From f15f0fc28bfd9ad05b8b07183bdf336149a9bdc5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 03:56:59 +0000
Subject: [PATCH 1/3] Initial plan
From 750d0d1af34791582bb83f259085559b73ff26f6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 04:09:52 +0000
Subject: [PATCH 2/3] Seal public Protocol reference types to prevent external
inheritance
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Protocol/ContentBlock.cs | 2 +-
.../Protocol/ElicitRequestParams.cs | 61 +++++++++++++++++--
.../Protocol/JsonRpcMessageContext.cs | 2 +-
.../Protocol/ResourceContents.cs | 2 +-
4 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
index 04c98bc84..c85478772 100644
--- a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
+++ b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
@@ -69,7 +69,7 @@ private protected ContentBlock()
/// Provides a polymorphic converter for the class that doesn't require
/// setting explicitly.
[EditorBrowsable(EditorBrowsableState.Never)]
- public class Converter : JsonConverter
+ public sealed class Converter : JsonConverter
{
///
public override ContentBlock? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
diff --git a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
index 0203edd60..8449a0300 100644
--- a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
+++ b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
@@ -103,7 +103,7 @@ public string Mode
public McpTaskMetadata? Task { get; set; }
/// Represents a request schema used in a form mode elicitation request.
- public class RequestSchema
+ public sealed class RequestSchema
{
/// Gets the type of the schema.
/// This value is always "object".
@@ -161,7 +161,7 @@ protected private PrimitiveSchemaDefinition()
/// Provides a polymorphic converter for the class that doesn't require
/// setting explicitly.
[EditorBrowsable(EditorBrowsableState.Never)]
- public class Converter : JsonConverter
+ public sealed class Converter : JsonConverter
{
///
public override PrimitiveSchemaDefinition? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
@@ -647,6 +647,25 @@ public override void Write(Utf8JsonWriter writer, PrimitiveSchemaDefinition valu
}
break;
+#pragma warning disable MCP9001 // EnumSchema is deprecated but supported for backward compatibility
+ case EnumSchema enumSchema:
+#pragma warning restore MCP9001
+ if (enumSchema.Enum is not null)
+ {
+ writer.WritePropertyName("enum");
+ JsonSerializer.Serialize(writer, enumSchema.Enum, McpJsonUtilities.JsonContext.Default.IListString);
+ }
+ if (enumSchema.EnumNames is not null)
+ {
+ writer.WritePropertyName("enumNames");
+ JsonSerializer.Serialize(writer, enumSchema.EnumNames, McpJsonUtilities.JsonContext.Default.IListString);
+ }
+ if (enumSchema.Default is not null)
+ {
+ writer.WriteString("default", enumSchema.Default);
+ }
+ break;
+
default:
throw new JsonException($"Unexpected schema type: {value.GetType().Name}");
}
@@ -1002,8 +1021,42 @@ public override string Type
/// This schema is deprecated in favor of .
///
[Obsolete(Obsoletions.LegacyTitledEnumSchema_Message, DiagnosticId = Obsoletions.LegacyTitledEnumSchema_DiagnosticId, UrlFormat = Obsoletions.LegacyTitledEnumSchema_Url)]
- public sealed class EnumSchema : LegacyTitledEnumSchema
+ public sealed class EnumSchema : PrimitiveSchemaDefinition
{
+ ///
+ [JsonPropertyName("type")]
+ public override string Type
+ {
+ get => "string";
+ set
+ {
+ if (value is not "string")
+ {
+ throw new ArgumentException("Type must be 'string'.", nameof(value));
+ }
+ }
+ }
+
+ /// Gets or sets the list of allowed string values for the enum.
+ [JsonPropertyName("enum")]
+ [field: MaybeNull]
+ public IList Enum
+ {
+ get => field ??= [];
+ set
+ {
+ Throw.IfNull(value);
+ field = value;
+ }
+ }
+
+ /// Gets or sets optional display names corresponding to the enum values.
+ [JsonPropertyName("enumNames")]
+ public IList? EnumNames { get; set; }
+
+ /// Gets or sets the default value for the enum.
+ [JsonPropertyName("default")]
+ public string? Default { get; set; }
}
///
@@ -1013,7 +1066,7 @@ public sealed class EnumSchema : LegacyTitledEnumSchema
/// This schema is deprecated in favor of .
///
[Obsolete(Obsoletions.LegacyTitledEnumSchema_Message, DiagnosticId = Obsoletions.LegacyTitledEnumSchema_DiagnosticId, UrlFormat = Obsoletions.LegacyTitledEnumSchema_Url)]
- public class LegacyTitledEnumSchema : PrimitiveSchemaDefinition
+ public sealed class LegacyTitledEnumSchema : PrimitiveSchemaDefinition
{
///
[JsonPropertyName("type")]
diff --git a/src/ModelContextProtocol.Core/Protocol/JsonRpcMessageContext.cs b/src/ModelContextProtocol.Core/Protocol/JsonRpcMessageContext.cs
index 38d798dc4..b9c9a2483 100644
--- a/src/ModelContextProtocol.Core/Protocol/JsonRpcMessageContext.cs
+++ b/src/ModelContextProtocol.Core/Protocol/JsonRpcMessageContext.cs
@@ -12,7 +12,7 @@ namespace ModelContextProtocol.Protocol;
/// but is not serialized as part of the JSON-RPC payload. This includes transport references, execution context,
/// and authenticated user information.
///
-public class JsonRpcMessageContext
+public sealed class JsonRpcMessageContext
{
///
/// Gets or sets the transport the was received on or should be sent over.
diff --git a/src/ModelContextProtocol.Core/Protocol/ResourceContents.cs b/src/ModelContextProtocol.Core/Protocol/ResourceContents.cs
index 9c295a1f8..0948c4232 100644
--- a/src/ModelContextProtocol.Core/Protocol/ResourceContents.cs
+++ b/src/ModelContextProtocol.Core/Protocol/ResourceContents.cs
@@ -61,7 +61,7 @@ private protected ResourceContents()
/// Provides a for .
///
[EditorBrowsable(EditorBrowsableState.Never)]
- public class Converter : JsonConverter
+ public sealed class Converter : JsonConverter
{
///
public override ResourceContents? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
From cc194cd8227d685cd0e685c05eaa79b00825a343 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 04:30:27 +0000
Subject: [PATCH 3/3] Delete EnumSchema type and update references to use
LegacyTitledEnumSchema
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Protocol/ElicitRequestParams.cs | 71 +------------------
.../Protocol/EnumSchemaTests.cs | 14 ++--
.../PrimitiveSchemaDefinitionTests.cs | 2 +-
3 files changed, 10 insertions(+), 77 deletions(-)
diff --git a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
index 8449a0300..2e50824e1 100644
--- a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
+++ b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
@@ -315,11 +315,9 @@ public sealed class Converter : JsonConverter
{
if (enumNames is not null)
{
- // EnumSchema is deprecated but supported for backward compatibility.
- // Use the EnumSchema class, which is an alias for LegacyTitledEnumSchema,
- // to ensure backward compatibility with existing code relying on that type.
+ // LegacyTitledEnumSchema is deprecated but supported for backward compatibility.
#pragma warning disable MCP9001
- psd = new EnumSchema
+ psd = new LegacyTitledEnumSchema
#pragma warning restore MCP9001
{
Enum = enumValues,
@@ -647,25 +645,6 @@ public override void Write(Utf8JsonWriter writer, PrimitiveSchemaDefinition valu
}
break;
-#pragma warning disable MCP9001 // EnumSchema is deprecated but supported for backward compatibility
- case EnumSchema enumSchema:
-#pragma warning restore MCP9001
- if (enumSchema.Enum is not null)
- {
- writer.WritePropertyName("enum");
- JsonSerializer.Serialize(writer, enumSchema.Enum, McpJsonUtilities.JsonContext.Default.IListString);
- }
- if (enumSchema.EnumNames is not null)
- {
- writer.WritePropertyName("enumNames");
- JsonSerializer.Serialize(writer, enumSchema.EnumNames, McpJsonUtilities.JsonContext.Default.IListString);
- }
- if (enumSchema.Default is not null)
- {
- writer.WriteString("default", enumSchema.Default);
- }
- break;
-
default:
throw new JsonException($"Unexpected schema type: {value.GetType().Name}");
}
@@ -1013,52 +992,6 @@ public override string Type
public IList? Default { get; set; }
}
- ///
- /// Represents a legacy schema for an enum type with enumNames.
- /// This is a compatibility alias for .
- ///
- ///
- /// This schema is deprecated in favor of .
- ///
- [Obsolete(Obsoletions.LegacyTitledEnumSchema_Message, DiagnosticId = Obsoletions.LegacyTitledEnumSchema_DiagnosticId, UrlFormat = Obsoletions.LegacyTitledEnumSchema_Url)]
- public sealed class EnumSchema : PrimitiveSchemaDefinition
- {
- ///
- [JsonPropertyName("type")]
- public override string Type
- {
- get => "string";
- set
- {
- if (value is not "string")
- {
- throw new ArgumentException("Type must be 'string'.", nameof(value));
- }
- }
- }
-
- /// Gets or sets the list of allowed string values for the enum.
- [JsonPropertyName("enum")]
- [field: MaybeNull]
- public IList Enum
- {
- get => field ??= [];
- set
- {
- Throw.IfNull(value);
- field = value;
- }
- }
-
- /// Gets or sets optional display names corresponding to the enum values.
- [JsonPropertyName("enumNames")]
- public IList? EnumNames { get; set; }
-
- /// Gets or sets the default value for the enum.
- [JsonPropertyName("default")]
- public string? Default { get; set; }
- }
-
///
/// Represents a legacy schema for an enum type with enumNames.
///
diff --git a/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs b/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs
index f0addb9d7..95220d614 100644
--- a/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs
+++ b/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs
@@ -298,7 +298,7 @@ public void LegacyTitledEnumSchema_Serializes_Correctly()
// Assert
Assert.NotNull(deserialized);
- var result = Assert.IsType(deserialized);
+ var result = Assert.IsType(deserialized);
Assert.Equal("string", result.Type);
Assert.Equal("Environment", result.Title);
Assert.Equal("Deployment environment", result.Description);
@@ -309,10 +309,10 @@ public void LegacyTitledEnumSchema_Serializes_Correctly()
}
[Fact]
- public void EnumSchema_Serializes_Correctly()
+ public void LegacyTitledEnumSchema_Direct_Serializes_Correctly()
{
// Arrange
- var schema = new ElicitRequestParams.EnumSchema
+ var schema = new ElicitRequestParams.LegacyTitledEnumSchema
{
Title = "Environment",
Description = "Deployment environment",
@@ -327,7 +327,7 @@ public void EnumSchema_Serializes_Correctly()
// Assert
Assert.NotNull(deserialized);
- var result = Assert.IsType(deserialized);
+ var result = Assert.IsType(deserialized);
Assert.Equal("string", result.Type);
Assert.Equal("Environment", result.Title);
Assert.Equal("Deployment environment", result.Description);
@@ -338,9 +338,9 @@ public void EnumSchema_Serializes_Correctly()
}
[Fact]
- public void Enum_WithEnumNames_Deserializes_As_EnumSchema()
+ public void Enum_WithEnumNames_Deserializes_As_LegacyTitledEnumSchema()
{
- // Arrange - JSON with enumNames should deserialize as (deprecated) EnumSchema
+ // Arrange - JSON with enumNames should deserialize as (deprecated) LegacyTitledEnumSchema
string json = """
{
"type": "string",
@@ -356,7 +356,7 @@ public void Enum_WithEnumNames_Deserializes_As_EnumSchema()
// Assert
Assert.NotNull(deserialized);
- var result = Assert.IsType(deserialized);
+ var result = Assert.IsType(deserialized);
Assert.Equal("string", result.Type);
Assert.Equal("Environment", result.Title);
Assert.Equal("Deployment environment", result.Description);
diff --git a/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs b/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs
index fc83ee5ed..d7bea3f5f 100644
--- a/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs
+++ b/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs
@@ -283,7 +283,7 @@ public static void LegacyTitledEnumSchema_UnknownProperties_AreIgnored()
json,
McpJsonUtilities.DefaultOptions);
Assert.NotNull(result);
- var enumSchema = Assert.IsType(result);
+ var enumSchema = Assert.IsType(result);
Assert.Equal("string", enumSchema.Type);
Assert.Equal(2, enumSchema.Enum.Count);
Assert.Contains("option1", enumSchema.Enum);