diff --git a/docs/concepts/elicitation/elicitation.md b/docs/concepts/elicitation/elicitation.md index b4d73a85d..056b0616a 100644 --- a/docs/concepts/elicitation/elicitation.md +++ b/docs/concepts/elicitation/elicitation.md @@ -32,7 +32,6 @@ For enum types, the SDK supports several schema formats: - **TitledSingleSelectEnumSchema**: A single-select enum with separate display titles for each option (using JSON Schema `oneOf` with `const` and `title`). - **UntitledMultiSelectEnumSchema**: A multi-select enum allowing multiple values to be selected. - **TitledMultiSelectEnumSchema**: A multi-select enum with display titles for each option. -- **LegacyTitledEnumSchema** (deprecated): The legacy enum schema using `enumNames` for backward compatibility. The server can request a single input or multiple inputs at once. To help distinguish multiple inputs, each input has a unique name. diff --git a/src/Common/Obsoletions.cs b/src/Common/Obsoletions.cs index ae7581997..d96eee69c 100644 --- a/src/Common/Obsoletions.cs +++ b/src/Common/Obsoletions.cs @@ -19,7 +19,5 @@ namespace ModelContextProtocol; /// internal static class Obsoletions { - public const string LegacyTitledEnumSchema_DiagnosticId = "MCP9001"; - public const string LegacyTitledEnumSchema_Message = "The EnumSchema and LegacyTitledEnumSchema APIs are deprecated as of specification version 2025-11-25 and will be removed in a future major version. See SEP-1330 for more information."; - public const string LegacyTitledEnumSchema_Url = "https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1330"; + // MCP9001 was used for LegacyTitledEnumSchema (removed) - do not reuse } diff --git a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs index 91cbb307d..976fb051b 100644 --- a/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs @@ -86,8 +86,7 @@ public string Mode /// /// Possible values are , , , /// , , - /// , , - /// and (deprecated). + /// , and . /// [JsonPropertyName("requestedSchema")] public RequestSchema? RequestedSchema { get; set; } @@ -132,8 +131,7 @@ public IDictionary Properties /// Represents a restricted subset of JSON Schema: /// , , , /// , , - /// , , - /// or (deprecated). + /// , or . /// [JsonConverter(typeof(Converter))] public abstract class PrimitiveSchemaDefinition @@ -153,9 +151,6 @@ protected private PrimitiveSchemaDefinition() TitledSingleSelectEnumSchema { Default: { } s } => JsonSerializer.SerializeToElement(s, McpJsonUtilities.JsonContext.Default.String), UntitledMultiSelectEnumSchema { Default: { } a } => JsonSerializer.SerializeToElement(a, McpJsonUtilities.JsonContext.Default.IListString), TitledMultiSelectEnumSchema { Default: { } a } => JsonSerializer.SerializeToElement(a, McpJsonUtilities.JsonContext.Default.IListString), -#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility - LegacyTitledEnumSchema { Default: { } s } => JsonSerializer.SerializeToElement(s, McpJsonUtilities.JsonContext.Default.String), -#pragma warning restore MCP9001 _ => null, }; @@ -329,27 +324,12 @@ public sealed class Converter : JsonConverter } else if (enumValues is not null) { - if (enumNames is not null) + // UntitledSingleSelectEnumSchema (enumNames is ignored if present) + psd = new UntitledSingleSelectEnumSchema { - // LegacyTitledEnumSchema is deprecated but supported for backward compatibility. -#pragma warning disable MCP9001 - psd = new LegacyTitledEnumSchema -#pragma warning restore MCP9001 - { - Enum = enumValues, - EnumNames = enumNames, - Default = defaultString, - }; - } - else - { - // UntitledSingleSelectEnumSchema - psd = new UntitledSingleSelectEnumSchema - { - Enum = enumValues, - Default = defaultString, - }; - } + Enum = enumValues, + Default = defaultString, + }; } else { @@ -642,25 +622,6 @@ public override void Write(Utf8JsonWriter writer, PrimitiveSchemaDefinition valu } break; -#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility - case LegacyTitledEnumSchema legacyTitledEnum: -#pragma warning restore MCP9001 - if (legacyTitledEnum.Enum is not null) - { - writer.WritePropertyName("enum"); - JsonSerializer.Serialize(writer, legacyTitledEnum.Enum, McpJsonUtilities.JsonContext.Default.IListString); - } - if (legacyTitledEnum.EnumNames is not null) - { - writer.WritePropertyName("enumNames"); - JsonSerializer.Serialize(writer, legacyTitledEnum.EnumNames, McpJsonUtilities.JsonContext.Default.IListString); - } - if (legacyTitledEnum.Default is not null) - { - writer.WriteString("default", legacyTitledEnum.Default); - } - break; - default: throw new JsonException($"Unexpected schema type: {value.GetType().Name}"); } @@ -1008,48 +969,4 @@ public override string Type public IList? Default { get; set; } } - /// - /// Represents a legacy schema for an enum type with enumNames. - /// - /// - /// This schema is deprecated in favor of . - /// - [Obsolete(Obsoletions.LegacyTitledEnumSchema_Message, DiagnosticId = Obsoletions.LegacyTitledEnumSchema_DiagnosticId, UrlFormat = Obsoletions.LegacyTitledEnumSchema_Url)] - public sealed class LegacyTitledEnumSchema : 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; } - } } diff --git a/tests/ModelContextProtocol.ConformanceServer/Tools/ConformanceTools.cs b/tests/ModelContextProtocol.ConformanceServer/Tools/ConformanceTools.cs index 8f1f017a2..6a223cc08 100644 --- a/tests/ModelContextProtocol.ConformanceServer/Tools/ConformanceTools.cs +++ b/tests/ModelContextProtocol.ConformanceServer/Tools/ConformanceTools.cs @@ -346,14 +346,6 @@ public static async Task ElicitationSep1330Enums( new() { Const = "value3", Title = "Third Option" } ] }, -#pragma warning disable MCP9001 - ["legacyEnum"] = new ElicitRequestParams.LegacyTitledEnumSchema() - { - Description = "Choose a legacy option", - Enum = ["opt1", "opt2", "opt3"], - EnumNames = ["Option One", "Option Two", "Option Three"] - }, -#pragma warning restore MCP9001 ["untitledMulti"] = new ElicitRequestParams.UntitledMultiSelectEnumSchema() { Description = "Choose multiple options", diff --git a/tests/ModelContextProtocol.Tests/Protocol/ElicitationDefaultValuesTests.cs b/tests/ModelContextProtocol.Tests/Protocol/ElicitationDefaultValuesTests.cs index e755f95b0..856b7c21b 100644 --- a/tests/ModelContextProtocol.Tests/Protocol/ElicitationDefaultValuesTests.cs +++ b/tests/ModelContextProtocol.Tests/Protocol/ElicitationDefaultValuesTests.cs @@ -282,26 +282,6 @@ public static void TitledMultiSelectEnumSchema_Default_Null_DoesNotSerialize() Assert.DoesNotContain("\"default\"", json); } -#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility - [Fact] - public static void LegacyTitledEnumSchema_Default_Null_DoesNotSerialize() - { - // Arrange - var schema = new ElicitRequestParams.LegacyTitledEnumSchema - { - Title = "Legacy Options", - Enum = ["option1", "option2"], - EnumNames = ["Option 1", "Option 2"] - }; - - // Act - serialize as base type to use the converter - string json = JsonSerializer.Serialize(schema, McpJsonUtilities.DefaultOptions); - - // Assert - Assert.DoesNotContain("\"default\"", json); - } -#pragma warning restore MCP9001 - [Fact] public static void RequestSchema_WithAllDefaultTypes_Serializes_Correctly() { diff --git a/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs b/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs index 95220d614..e130e7af8 100644 --- a/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs +++ b/tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs @@ -277,92 +277,4 @@ public void MultiSelectEnum_WithAnyOf_Deserializes_As_TitledMultiSelect() Assert.Equal("Administrator", result.Items.AnyOf[0].Title); Assert.Equal(["user"], result.Default); } - -#pragma warning disable MCP9001 // EnumSchema and LegacyTitledEnumSchema are deprecated but supported for backward compatibility - [Fact] - public void LegacyTitledEnumSchema_Serializes_Correctly() - { - // Arrange - var schema = new ElicitRequestParams.LegacyTitledEnumSchema - { - Title = "Environment", - Description = "Deployment environment", - Enum = ["dev", "staging", "prod"], - EnumNames = ["Development", "Staging", "Production"], - Default = "staging" - }; - - // Act - string json = JsonSerializer.Serialize(schema, McpJsonUtilities.DefaultOptions); - var deserialized = JsonSerializer.Deserialize(json, McpJsonUtilities.DefaultOptions); - - // Assert - Assert.NotNull(deserialized); - var result = Assert.IsType(deserialized); - Assert.Equal("string", result.Type); - Assert.Equal("Environment", result.Title); - Assert.Equal("Deployment environment", result.Description); - Assert.Equal(["dev", "staging", "prod"], result.Enum); - Assert.Equal(["Development", "Staging", "Production"], result.EnumNames); - Assert.Equal("staging", result.Default); - Assert.Contains("\"enumNames\":[\"Development\",\"Staging\",\"Production\"]", json); - } - - [Fact] - public void LegacyTitledEnumSchema_Direct_Serializes_Correctly() - { - // Arrange - var schema = new ElicitRequestParams.LegacyTitledEnumSchema - { - Title = "Environment", - Description = "Deployment environment", - Enum = ["dev", "staging", "prod"], - EnumNames = ["Development", "Staging", "Production"], - Default = "staging" - }; - - // Act - string json = JsonSerializer.Serialize(schema, McpJsonUtilities.DefaultOptions); - var deserialized = JsonSerializer.Deserialize(json, McpJsonUtilities.DefaultOptions); - - // Assert - Assert.NotNull(deserialized); - var result = Assert.IsType(deserialized); - Assert.Equal("string", result.Type); - Assert.Equal("Environment", result.Title); - Assert.Equal("Deployment environment", result.Description); - Assert.Equal(["dev", "staging", "prod"], result.Enum); - Assert.Equal(["Development", "Staging", "Production"], result.EnumNames); - Assert.Equal("staging", result.Default); - Assert.Contains("\"enumNames\":[\"Development\",\"Staging\",\"Production\"]", json); - } - - [Fact] - public void Enum_WithEnumNames_Deserializes_As_LegacyTitledEnumSchema() - { - // Arrange - JSON with enumNames should deserialize as (deprecated) LegacyTitledEnumSchema - string json = """ - { - "type": "string", - "title": "Environment", - "description": "Deployment environment", - "enum": ["dev", "staging", "prod"], - "enumNames": ["Development", "Staging", "Production"], - "default": "staging" - } - """; - // Act - var deserialized = JsonSerializer.Deserialize(json, McpJsonUtilities.DefaultOptions); - - // Assert - Assert.NotNull(deserialized); - var result = Assert.IsType(deserialized); - Assert.Equal("string", result.Type); - Assert.Equal("Environment", result.Title); - Assert.Equal("Deployment environment", result.Description); - Assert.Equal(["dev", "staging", "prod"], result.Enum); - Assert.Equal(["Development", "Staging", "Production"], result.EnumNames); - Assert.Equal("staging", result.Default); - } -#pragma warning restore MCP9001 } diff --git a/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs b/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs index d7bea3f5f..ebfb8abc5 100644 --- a/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs +++ b/tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs @@ -257,39 +257,4 @@ public static void TitledMultiSelectEnumSchema_UnknownProperties_AreIgnored() Assert.Contains("optionX", enumSchema.Default); Assert.Contains("optionZ", enumSchema.Default); } - -#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility - [Fact] - public static void LegacyTitledEnumSchema_UnknownProperties_AreIgnored() - { - const string json = """ - { - "type": "string", - "enum": ["option1", "option2"], - - "unknownNull": null, - "unknownEmptyObject": {}, - "unknownObject": {"a": 1}, - "unknownEmptyArray": [], - "unknownArray": [1, 2, 3], - "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, - - "enumNames": ["Option 1", "Option 2"], - "default": "option2" - } - """; - - var result = JsonSerializer.Deserialize( - json, - McpJsonUtilities.DefaultOptions); - Assert.NotNull(result); - var enumSchema = Assert.IsType(result); - Assert.Equal("string", enumSchema.Type); - Assert.Equal(2, enumSchema.Enum.Count); - Assert.Contains("option1", enumSchema.Enum); - Assert.Contains("option2", enumSchema.Enum); - Assert.Contains("Option 1", enumSchema.EnumNames!); - Assert.Contains("Option 2", enumSchema.EnumNames!); - } -#pragma warning restore MCP9001 }