Skip to content

Commit 5ad9db3

Browse files
Copilotjeffhandley
andcommitted
Remove LegacyTitledEnumSchema obsolete API
BREAKING CHANGE: Removed the [Obsolete] LegacyTitledEnumSchema API and related Obsoletions constants. The LegacyTitledEnumSchema class used enumNames for titled enums and has been replaced by TitledSingleSelectEnumSchema using oneOf with const/title. JSON with enumNames will now deserialize as UntitledSingleSelectEnumSchema (ignoring enumNames). - Removed LegacyTitledEnumSchema class from ElicitRequestParams.cs - Removed LegacyTitledEnumSchema from JSON converter (deserialization now ignores enumNames) - Removed LegacyTitledEnumSchema from GetDefaultAsJsonElement method - Removed obsoletions constants and added comment that MCP9001 cannot be reused - Removed LegacyTitledEnumSchema tests from EnumSchemaTests.cs - Removed LegacyTitledEnumSchema tests from ElicitationDefaultValuesTests.cs - Removed LegacyTitledEnumSchema tests from PrimitiveSchemaDefinitionTests.cs - Removed LegacyTitledEnumSchema usage from ConformanceTools.cs - Updated documentation in elicitation.md - Updated XML documentation comments to remove references Co-authored-by: jeffhandley <1031940+jeffhandley@users.noreply.github.com>
1 parent b7f9be2 commit 5ad9db3

7 files changed

Lines changed: 8 additions & 245 deletions

File tree

docs/concepts/elicitation/elicitation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ For enum types, the SDK supports several schema formats:
3232
- **TitledSingleSelectEnumSchema**: A single-select enum with separate display titles for each option (using JSON Schema `oneOf` with `const` and `title`).
3333
- **UntitledMultiSelectEnumSchema**: A multi-select enum allowing multiple values to be selected.
3434
- **TitledMultiSelectEnumSchema**: A multi-select enum with display titles for each option.
35-
- **LegacyTitledEnumSchema** (deprecated): The legacy enum schema using `enumNames` for backward compatibility.
3635

3736
The server can request a single input or multiple inputs at once.
3837
To help distinguish multiple inputs, each input has a unique name.

src/Common/Obsoletions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,5 @@ namespace ModelContextProtocol;
1919
/// </remarks>
2020
internal static class Obsoletions
2121
{
22-
public const string LegacyTitledEnumSchema_DiagnosticId = "MCP9001";
23-
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.";
24-
public const string LegacyTitledEnumSchema_Url = "https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1330";
22+
// MCP9001 was used for LegacyTitledEnumSchema (removed) - do not reuse
2523
}

src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs

Lines changed: 7 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ public string Mode
8686
/// <value>
8787
/// Possible values are <see cref="StringSchema"/>, <see cref="NumberSchema"/>, <see cref="BooleanSchema"/>,
8888
/// <see cref="UntitledSingleSelectEnumSchema"/>, <see cref="TitledSingleSelectEnumSchema"/>,
89-
/// <see cref="UntitledMultiSelectEnumSchema"/>, <see cref="TitledMultiSelectEnumSchema"/>,
90-
/// and <see cref="LegacyTitledEnumSchema"/> (deprecated).
89+
/// <see cref="UntitledMultiSelectEnumSchema"/>, and <see cref="TitledMultiSelectEnumSchema"/>.
9190
/// </value>
9291
[JsonPropertyName("requestedSchema")]
9392
public RequestSchema? RequestedSchema { get; set; }
@@ -132,8 +131,7 @@ public IDictionary<string, PrimitiveSchemaDefinition> Properties
132131
/// Represents a restricted subset of JSON Schema:
133132
/// <see cref="StringSchema"/>, <see cref="NumberSchema"/>, <see cref="BooleanSchema"/>,
134133
/// <see cref="UntitledSingleSelectEnumSchema"/>, <see cref="TitledSingleSelectEnumSchema"/>,
135-
/// <see cref="UntitledMultiSelectEnumSchema"/>, <see cref="TitledMultiSelectEnumSchema"/>,
136-
/// or <see cref="LegacyTitledEnumSchema"/> (deprecated).
134+
/// <see cref="UntitledMultiSelectEnumSchema"/>, or <see cref="TitledMultiSelectEnumSchema"/>.
137135
/// </summary>
138136
[JsonConverter(typeof(Converter))]
139137
public abstract class PrimitiveSchemaDefinition
@@ -153,9 +151,6 @@ protected private PrimitiveSchemaDefinition()
153151
TitledSingleSelectEnumSchema { Default: { } s } => JsonSerializer.SerializeToElement(s, McpJsonUtilities.JsonContext.Default.String),
154152
UntitledMultiSelectEnumSchema { Default: { } a } => JsonSerializer.SerializeToElement(a, McpJsonUtilities.JsonContext.Default.IListString),
155153
TitledMultiSelectEnumSchema { Default: { } a } => JsonSerializer.SerializeToElement(a, McpJsonUtilities.JsonContext.Default.IListString),
156-
#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility
157-
LegacyTitledEnumSchema { Default: { } s } => JsonSerializer.SerializeToElement(s, McpJsonUtilities.JsonContext.Default.String),
158-
#pragma warning restore MCP9001
159154
_ => null,
160155
};
161156

@@ -329,27 +324,12 @@ public sealed class Converter : JsonConverter<PrimitiveSchemaDefinition>
329324
}
330325
else if (enumValues is not null)
331326
{
332-
if (enumNames is not null)
327+
// UntitledSingleSelectEnumSchema (enumNames is ignored if present)
328+
psd = new UntitledSingleSelectEnumSchema
333329
{
334-
// LegacyTitledEnumSchema is deprecated but supported for backward compatibility.
335-
#pragma warning disable MCP9001
336-
psd = new LegacyTitledEnumSchema
337-
#pragma warning restore MCP9001
338-
{
339-
Enum = enumValues,
340-
EnumNames = enumNames,
341-
Default = defaultString,
342-
};
343-
}
344-
else
345-
{
346-
// UntitledSingleSelectEnumSchema
347-
psd = new UntitledSingleSelectEnumSchema
348-
{
349-
Enum = enumValues,
350-
Default = defaultString,
351-
};
352-
}
330+
Enum = enumValues,
331+
Default = defaultString,
332+
};
353333
}
354334
else
355335
{
@@ -642,25 +622,6 @@ public override void Write(Utf8JsonWriter writer, PrimitiveSchemaDefinition valu
642622
}
643623
break;
644624

645-
#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility
646-
case LegacyTitledEnumSchema legacyTitledEnum:
647-
#pragma warning restore MCP9001
648-
if (legacyTitledEnum.Enum is not null)
649-
{
650-
writer.WritePropertyName("enum");
651-
JsonSerializer.Serialize(writer, legacyTitledEnum.Enum, McpJsonUtilities.JsonContext.Default.IListString);
652-
}
653-
if (legacyTitledEnum.EnumNames is not null)
654-
{
655-
writer.WritePropertyName("enumNames");
656-
JsonSerializer.Serialize(writer, legacyTitledEnum.EnumNames, McpJsonUtilities.JsonContext.Default.IListString);
657-
}
658-
if (legacyTitledEnum.Default is not null)
659-
{
660-
writer.WriteString("default", legacyTitledEnum.Default);
661-
}
662-
break;
663-
664625
default:
665626
throw new JsonException($"Unexpected schema type: {value.GetType().Name}");
666627
}
@@ -1008,48 +969,4 @@ public override string Type
1008969
public IList<string>? Default { get; set; }
1009970
}
1010971

1011-
/// <summary>
1012-
/// Represents a legacy schema for an enum type with enumNames.
1013-
/// </summary>
1014-
/// <remarks>
1015-
/// This schema is deprecated in favor of <see cref="TitledSingleSelectEnumSchema"/>.
1016-
/// </remarks>
1017-
[Obsolete(Obsoletions.LegacyTitledEnumSchema_Message, DiagnosticId = Obsoletions.LegacyTitledEnumSchema_DiagnosticId, UrlFormat = Obsoletions.LegacyTitledEnumSchema_Url)]
1018-
public sealed class LegacyTitledEnumSchema : PrimitiveSchemaDefinition
1019-
{
1020-
/// <inheritdoc/>
1021-
[JsonPropertyName("type")]
1022-
public override string Type
1023-
{
1024-
get => "string";
1025-
set
1026-
{
1027-
if (value is not "string")
1028-
{
1029-
throw new ArgumentException("Type must be 'string'.", nameof(value));
1030-
}
1031-
}
1032-
}
1033-
1034-
/// <summary>Gets or sets the list of allowed string values for the enum.</summary>
1035-
[JsonPropertyName("enum")]
1036-
[field: MaybeNull]
1037-
public IList<string> Enum
1038-
{
1039-
get => field ??= [];
1040-
set
1041-
{
1042-
Throw.IfNull(value);
1043-
field = value;
1044-
}
1045-
}
1046-
1047-
/// <summary>Gets or sets optional display names corresponding to the enum values.</summary>
1048-
[JsonPropertyName("enumNames")]
1049-
public IList<string>? EnumNames { get; set; }
1050-
1051-
/// <summary>Gets or sets the default value for the enum.</summary>
1052-
[JsonPropertyName("default")]
1053-
public string? Default { get; set; }
1054-
}
1055972
}

tests/ModelContextProtocol.ConformanceServer/Tools/ConformanceTools.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,6 @@ public static async Task<string> ElicitationSep1330Enums(
346346
new() { Const = "value3", Title = "Third Option" }
347347
]
348348
},
349-
#pragma warning disable MCP9001
350-
["legacyEnum"] = new ElicitRequestParams.LegacyTitledEnumSchema()
351-
{
352-
Description = "Choose a legacy option",
353-
Enum = ["opt1", "opt2", "opt3"],
354-
EnumNames = ["Option One", "Option Two", "Option Three"]
355-
},
356-
#pragma warning restore MCP9001
357349
["untitledMulti"] = new ElicitRequestParams.UntitledMultiSelectEnumSchema()
358350
{
359351
Description = "Choose multiple options",

tests/ModelContextProtocol.Tests/Protocol/ElicitationDefaultValuesTests.cs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -282,26 +282,6 @@ public static void TitledMultiSelectEnumSchema_Default_Null_DoesNotSerialize()
282282
Assert.DoesNotContain("\"default\"", json);
283283
}
284284

285-
#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility
286-
[Fact]
287-
public static void LegacyTitledEnumSchema_Default_Null_DoesNotSerialize()
288-
{
289-
// Arrange
290-
var schema = new ElicitRequestParams.LegacyTitledEnumSchema
291-
{
292-
Title = "Legacy Options",
293-
Enum = ["option1", "option2"],
294-
EnumNames = ["Option 1", "Option 2"]
295-
};
296-
297-
// Act - serialize as base type to use the converter
298-
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
299-
300-
// Assert
301-
Assert.DoesNotContain("\"default\"", json);
302-
}
303-
#pragma warning restore MCP9001
304-
305285
[Fact]
306286
public static void RequestSchema_WithAllDefaultTypes_Serializes_Correctly()
307287
{

tests/ModelContextProtocol.Tests/Protocol/EnumSchemaTests.cs

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -277,92 +277,4 @@ public void MultiSelectEnum_WithAnyOf_Deserializes_As_TitledMultiSelect()
277277
Assert.Equal("Administrator", result.Items.AnyOf[0].Title);
278278
Assert.Equal(["user"], result.Default);
279279
}
280-
281-
#pragma warning disable MCP9001 // EnumSchema and LegacyTitledEnumSchema are deprecated but supported for backward compatibility
282-
[Fact]
283-
public void LegacyTitledEnumSchema_Serializes_Correctly()
284-
{
285-
// Arrange
286-
var schema = new ElicitRequestParams.LegacyTitledEnumSchema
287-
{
288-
Title = "Environment",
289-
Description = "Deployment environment",
290-
Enum = ["dev", "staging", "prod"],
291-
EnumNames = ["Development", "Staging", "Production"],
292-
Default = "staging"
293-
};
294-
295-
// Act
296-
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
297-
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
298-
299-
// Assert
300-
Assert.NotNull(deserialized);
301-
var result = Assert.IsType<ElicitRequestParams.LegacyTitledEnumSchema>(deserialized);
302-
Assert.Equal("string", result.Type);
303-
Assert.Equal("Environment", result.Title);
304-
Assert.Equal("Deployment environment", result.Description);
305-
Assert.Equal(["dev", "staging", "prod"], result.Enum);
306-
Assert.Equal(["Development", "Staging", "Production"], result.EnumNames);
307-
Assert.Equal("staging", result.Default);
308-
Assert.Contains("\"enumNames\":[\"Development\",\"Staging\",\"Production\"]", json);
309-
}
310-
311-
[Fact]
312-
public void LegacyTitledEnumSchema_Direct_Serializes_Correctly()
313-
{
314-
// Arrange
315-
var schema = new ElicitRequestParams.LegacyTitledEnumSchema
316-
{
317-
Title = "Environment",
318-
Description = "Deployment environment",
319-
Enum = ["dev", "staging", "prod"],
320-
EnumNames = ["Development", "Staging", "Production"],
321-
Default = "staging"
322-
};
323-
324-
// Act
325-
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
326-
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
327-
328-
// Assert
329-
Assert.NotNull(deserialized);
330-
var result = Assert.IsType<ElicitRequestParams.LegacyTitledEnumSchema>(deserialized);
331-
Assert.Equal("string", result.Type);
332-
Assert.Equal("Environment", result.Title);
333-
Assert.Equal("Deployment environment", result.Description);
334-
Assert.Equal(["dev", "staging", "prod"], result.Enum);
335-
Assert.Equal(["Development", "Staging", "Production"], result.EnumNames);
336-
Assert.Equal("staging", result.Default);
337-
Assert.Contains("\"enumNames\":[\"Development\",\"Staging\",\"Production\"]", json);
338-
}
339-
340-
[Fact]
341-
public void Enum_WithEnumNames_Deserializes_As_LegacyTitledEnumSchema()
342-
{
343-
// Arrange - JSON with enumNames should deserialize as (deprecated) LegacyTitledEnumSchema
344-
string json = """
345-
{
346-
"type": "string",
347-
"title": "Environment",
348-
"description": "Deployment environment",
349-
"enum": ["dev", "staging", "prod"],
350-
"enumNames": ["Development", "Staging", "Production"],
351-
"default": "staging"
352-
}
353-
""";
354-
// Act
355-
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
356-
357-
// Assert
358-
Assert.NotNull(deserialized);
359-
var result = Assert.IsType<ElicitRequestParams.LegacyTitledEnumSchema>(deserialized);
360-
Assert.Equal("string", result.Type);
361-
Assert.Equal("Environment", result.Title);
362-
Assert.Equal("Deployment environment", result.Description);
363-
Assert.Equal(["dev", "staging", "prod"], result.Enum);
364-
Assert.Equal(["Development", "Staging", "Production"], result.EnumNames);
365-
Assert.Equal("staging", result.Default);
366-
}
367-
#pragma warning restore MCP9001
368280
}

tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -257,39 +257,4 @@ public static void TitledMultiSelectEnumSchema_UnknownProperties_AreIgnored()
257257
Assert.Contains("optionX", enumSchema.Default);
258258
Assert.Contains("optionZ", enumSchema.Default);
259259
}
260-
261-
#pragma warning disable MCP9001 // LegacyTitledEnumSchema is deprecated but supported for backward compatibility
262-
[Fact]
263-
public static void LegacyTitledEnumSchema_UnknownProperties_AreIgnored()
264-
{
265-
const string json = """
266-
{
267-
"type": "string",
268-
"enum": ["option1", "option2"],
269-
270-
"unknownNull": null,
271-
"unknownEmptyObject": {},
272-
"unknownObject": {"a": 1},
273-
"unknownEmptyArray": [],
274-
"unknownArray": [1, 2, 3],
275-
"unknownNestedObject": {"b": {"c": "d", "e": ["f"]}},
276-
277-
"enumNames": ["Option 1", "Option 2"],
278-
"default": "option2"
279-
}
280-
""";
281-
282-
var result = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(
283-
json,
284-
McpJsonUtilities.DefaultOptions);
285-
Assert.NotNull(result);
286-
var enumSchema = Assert.IsType<ElicitRequestParams.LegacyTitledEnumSchema>(result);
287-
Assert.Equal("string", enumSchema.Type);
288-
Assert.Equal(2, enumSchema.Enum.Count);
289-
Assert.Contains("option1", enumSchema.Enum);
290-
Assert.Contains("option2", enumSchema.Enum);
291-
Assert.Contains("Option 1", enumSchema.EnumNames!);
292-
Assert.Contains("Option 2", enumSchema.EnumNames!);
293-
}
294-
#pragma warning restore MCP9001
295260
}

0 commit comments

Comments
 (0)