Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f636f4b
Initial plan
Copilot Nov 18, 2025
701597c
Remove internal usages of obsolete capability properties
Copilot Nov 18, 2025
d826cd3
Remove all obsolete API definitions and related tests
Copilot Nov 18, 2025
cd8f7ae
Merge main branch and resolve conflicts
Copilot Nov 19, 2025
3d20111
Merge remote-tracking branch 'origin/main' into copilot/remove-obsole…
Copilot Nov 19, 2025
eb31afb
Remove unused duplicate CreateSamplingHandler and helper methods from…
Copilot Nov 19, 2025
c7deb7f
Delete empty McpEndpointExtensions and McpServerExtensions classes
Copilot Nov 19, 2025
4d6fe0a
Remove obsolete IMcpEndpoint, IMcpClient, IMcpServer interfaces and M…
Copilot Nov 19, 2025
2decb2d
Remove extra newlines before closing braces in capability classes
Copilot Nov 19, 2025
4443cfc
Merge main branch and resolve conflicts (PR #976 integration)
Copilot Nov 20, 2025
44083aa
Revert "Merge main branch and resolve conflicts (PR #976 integration)"
MackinnonBuck Nov 20, 2025
cd9ce13
Merge remote-tracking branch 'origin/main' into copilot/remove-obsole…
MackinnonBuck Nov 20, 2025
93a6877
Remove remaining obsolete EnumSchema and LegacyTitledEnumSchema types…
Copilot Nov 21, 2025
186d85c
Restore EnumSchemaTests.cs and add back valid enum schema tests witho…
Copilot Nov 21, 2025
04e1326
Revert: "Remove remaining obsolete EnumSchema and LegacyTitledEnumSch…
jeffhandley Nov 26, 2025
40df946
Merge branch 'main' into copilot/remove-obsolete-apis
jeffhandley Nov 26, 2025
3c29253
Introduce Obsoletions/Experimentals pattern for custom diagnostics.
jeffhandley Nov 26, 2025
6fcf81c
Fix failing enum schema tests
jeffhandley Nov 26, 2025
981386e
Merge branch 'main' into copilot/remove-obsolete-apis
jeffhandley Nov 27, 2025
95708d6
Revise diagnostic ID ranges for analyzers, obsoletions, experimentals
jeffhandley Nov 27, 2025
7e074f8
Fix XML comment reference to RegisterNotificationHandler
jeffhandley Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 7 additions & 98 deletions src/ModelContextProtocol.Core/Protocol/ElicitRequestParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ public sealed class ElicitRequestParams
/// <remarks>
/// May be one of <see cref="StringSchema"/>, <see cref="NumberSchema"/>, <see cref="BooleanSchema"/>,
/// <see cref="UntitledSingleSelectEnumSchema"/>, <see cref="TitledSingleSelectEnumSchema"/>,
/// <see cref="UntitledMultiSelectEnumSchema"/>, <see cref="TitledMultiSelectEnumSchema"/>,
/// or <see cref="LegacyTitledEnumSchema"/> (deprecated).
/// <see cref="UntitledMultiSelectEnumSchema"/>, or <see cref="TitledMultiSelectEnumSchema"/>.
/// </remarks>
[JsonPropertyName("requestedSchema")]
[field: MaybeNull]
Expand Down Expand Up @@ -64,8 +63,7 @@ public IDictionary<string, PrimitiveSchemaDefinition> Properties
/// Represents restricted subset of JSON Schema:
/// <see cref="StringSchema"/>, <see cref="NumberSchema"/>, <see cref="BooleanSchema"/>,
/// <see cref="UntitledSingleSelectEnumSchema"/>, <see cref="TitledSingleSelectEnumSchema"/>,
/// <see cref="UntitledMultiSelectEnumSchema"/>, <see cref="TitledMultiSelectEnumSchema"/>,
/// or <see cref="LegacyTitledEnumSchema"/> (deprecated).
/// <see cref="UntitledMultiSelectEnumSchema"/>, or <see cref="TitledMultiSelectEnumSchema"/>.
/// </summary>
[JsonConverter(typeof(Converter))]
public abstract class PrimitiveSchemaDefinition
Expand Down Expand Up @@ -121,7 +119,6 @@ public class Converter : JsonConverter<PrimitiveSchemaDefinition>
string? defaultString = null;
IList<string>? defaultStringArray = null;
IList<string>? enumValues = null;
IList<string>? enumNames = null;
IList<EnumSchemaOption>? oneOf = null;
int? minItems = null;
int? maxItems = null;
Expand Down Expand Up @@ -207,10 +204,6 @@ public class Converter : JsonConverter<PrimitiveSchemaDefinition>
enumValues = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.IListString);
break;

case "enumNames":
enumNames = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.IListString);
break;

case "oneOf":
oneOf = DeserializeEnumOptions(ref reader);
break;
Expand Down Expand Up @@ -245,27 +238,12 @@ public class Converter : JsonConverter<PrimitiveSchemaDefinition>
}
else if (enumValues is not null)
{
if (enumNames is not null)
{
// EnumSchema for backward compatibility
#pragma warning disable CS0618 // Type or member is obsolete
psd = new EnumSchema
#pragma warning restore CS0618 // Type or member is obsolete
{
Enum = enumValues,
EnumNames = enumNames,
Default = defaultString,
};
}
else
// UntitledSingleSelectEnumSchema
psd = new UntitledSingleSelectEnumSchema
{
// UntitledSingleSelectEnumSchema
psd = new UntitledSingleSelectEnumSchema
{
Enum = enumValues,
Default = defaultString,
};
}
Enum = enumValues,
Default = defaultString,
};
}
else
{
Expand Down Expand Up @@ -558,25 +536,6 @@ public override void Write(Utf8JsonWriter writer, PrimitiveSchemaDefinition valu
}
break;

#pragma warning disable CS0618 // Type or member is obsolete
case LegacyTitledEnumSchema legacyEnum:
#pragma warning restore CS0618 // Type or member is obsolete
if (legacyEnum.Enum is not null)
{
writer.WritePropertyName("enum");
JsonSerializer.Serialize(writer, legacyEnum.Enum, McpJsonUtilities.JsonContext.Default.IListString);
}
if (legacyEnum.EnumNames is not null)
{
writer.WritePropertyName("enumNames");
JsonSerializer.Serialize(writer, legacyEnum.EnumNames, McpJsonUtilities.JsonContext.Default.IListString);
}
if (legacyEnum.Default is not null)
{
writer.WriteString("default", legacyEnum.Default);
}
break;

default:
throw new JsonException($"Unexpected schema type: {value.GetType().Name}");
}
Expand Down Expand Up @@ -740,49 +699,6 @@ public override string Type
public bool? Default { get; set; }
}

/// <summary>
/// Represents a legacy schema for an enum type with enumNames.
/// This schema is deprecated in favor of <see cref="TitledSingleSelectEnumSchema"/>.
/// </summary>
[Obsolete("Use TitledSingleSelectEnumSchema instead. This type will be removed in a future version.")]
public class LegacyTitledEnumSchema : PrimitiveSchemaDefinition
{
/// <inheritdoc/>
[JsonPropertyName("type")]
public override string Type
{
get => "string";
set
{
if (value is not "string")
{
throw new ArgumentException("Type must be 'string'.", nameof(value));
}
}
}

/// <summary>Gets or sets the list of allowed string values for the enum.</summary>
[JsonPropertyName("enum")]
[field: MaybeNull]
public IList<string> Enum
{
get => field ??= [];
set
{
Throw.IfNull(value);
field = value;
}
}

/// <summary>Gets or sets optional display names corresponding to the enum values.</summary>
[JsonPropertyName("enumNames")]
public IList<string>? EnumNames { get; set; }

/// <summary>Gets or sets the default value for the enum.</summary>
[JsonPropertyName("default")]
public string? Default { get; set; }
}

/// <summary>
/// Represents a schema for single-selection enumeration without display titles for options.
/// </summary>
Expand Down Expand Up @@ -967,11 +883,4 @@ public override string Type
public IList<string>? Default { get; set; }
}

/// <summary>
/// Represents a schema for an enum type. This is a compatibility alias for <see cref="LegacyTitledEnumSchema"/>.
/// </summary>
[Obsolete("Use UntitledSingleSelectEnumSchema or TitledSingleSelectEnumSchema instead. This type will be removed in a future version.")]
public sealed class EnumSchema : LegacyTitledEnumSchema
{
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using ModelContextProtocol.Protocol;
using System.Text.Json;

#pragma warning disable CS0618 // Type or member is obsolete

namespace ModelContextProtocol.Tests.Protocol;

public class ElicitationDefaultValuesTests
Expand Down Expand Up @@ -112,49 +110,6 @@ public void NumberSchema_Default_Null_DoesNotSerialize()
Assert.DoesNotContain("\"default\"", json);
}

[Fact]
public void EnumSchema_Default_Serializes_Correctly()
{
// Arrange
var schema = new ElicitRequestParams.EnumSchema
{
Title = "Priority",
Description = "Task priority",
Enum = ["low", "medium", "high"],
EnumNames = ["Low Priority", "Medium Priority", "High Priority"],
Default = "medium"
};

// Act - serialize as base type to use the converter
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);

// Assert
Assert.NotNull(deserialized);
var enumSchema = Assert.IsType<ElicitRequestParams.EnumSchema>(deserialized);
Assert.Equal("medium", enumSchema.Default);
Assert.Equal("Priority", enumSchema.Title);
Assert.Equal("Task priority", enumSchema.Description);
Assert.Contains("\"default\":\"medium\"", json);
}

[Fact]
public void EnumSchema_Default_Null_DoesNotSerialize()
{
// Arrange
var schema = new ElicitRequestParams.EnumSchema
{
Title = "Priority",
Enum = ["low", "medium", "high"]
};

// Act - serialize as base type to use the converter
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);

// Assert
Assert.DoesNotContain("\"default\"", json);
}

[Fact]
public void BooleanSchema_Default_True_Serializes_Correctly()
{
Expand Down Expand Up @@ -244,29 +199,6 @@ public void PrimitiveSchemaDefinition_NumberSchema_WithDefault_RoundTrips()
Assert.Equal(100, numberSchema.Maximum);
}

[Fact]
public void PrimitiveSchemaDefinition_EnumSchema_WithDefault_RoundTrips()
{
// Arrange
var schema = new ElicitRequestParams.EnumSchema
{
Title = "Status",
Enum = ["draft", "published", "archived"],
Default = "draft"
};

// Act - serialize as base type to test the converter
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);

// Assert
Assert.NotNull(deserialized);
// EnumSchema without enumNames deserializes as UntitledSingleSelectEnumSchema
var enumSchema = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(deserialized);
Assert.Equal("draft", enumSchema.Default);
Assert.Equal(["draft", "published", "archived"], enumSchema.Enum);
}

[Fact]
public void RequestSchema_WithAllDefaultTypes_Serializes_Correctly()
{
Expand Down Expand Up @@ -299,7 +231,7 @@ public void RequestSchema_WithAllDefaultTypes_Serializes_Correctly()
Title = "Active",
Default = true
},
["status"] = new ElicitRequestParams.EnumSchema
["status"] = new ElicitRequestParams.UntitledSingleSelectEnumSchema
{
Title = "Status",
Enum = ["active", "inactive"],
Expand Down
25 changes: 16 additions & 9 deletions tests/ModelContextProtocol.Tests/Protocol/ElicitationTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using System.Text.Json;

#pragma warning disable CS0618 // Type or member is obsolete

namespace ModelContextProtocol.Tests.Configuration;

public partial class ElicitationTests : ClientServerTestBase
Expand Down Expand Up @@ -46,10 +44,14 @@ protected override void ConfigureServices(ServiceCollection services, IMcpServer
Description = "description4",
Default = true,
},
["prop4"] = new ElicitRequestParams.EnumSchema
["prop4"] = new ElicitRequestParams.TitledSingleSelectEnumSchema
{
Enum = ["option1", "option2", "option3"],
EnumNames = ["Name1", "Name2", "Name3"],
OneOf =
[
new ElicitRequestParams.EnumSchemaOption { Const = "option1", Title = "Name1" },
new ElicitRequestParams.EnumSchemaOption { Const = "option2", Title = "Name2" },
new ElicitRequestParams.EnumSchemaOption { Const = "option3", Title = "Name3" }
],
},
},
},
Expand Down Expand Up @@ -104,9 +106,14 @@ public async Task Can_Elicit_Information()
break;

case "prop4":
var primitiveEnum = Assert.IsType<ElicitRequestParams.EnumSchema>(entry.Value);
Assert.Equal(["option1", "option2", "option3"], primitiveEnum.Enum);
Assert.Equal(["Name1", "Name2", "Name3"], primitiveEnum.EnumNames);
var primitiveEnum = Assert.IsType<ElicitRequestParams.TitledSingleSelectEnumSchema>(entry.Value);
Assert.Equal(3, primitiveEnum.OneOf.Count);
Assert.Equal("option1", primitiveEnum.OneOf[0].Const);
Assert.Equal("Name1", primitiveEnum.OneOf[0].Title);
Assert.Equal("option2", primitiveEnum.OneOf[1].Const);
Assert.Equal("Name2", primitiveEnum.OneOf[1].Title);
Assert.Equal("option3", primitiveEnum.OneOf[2].Const);
Assert.Equal("Name3", primitiveEnum.OneOf[2].Title);
break;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using System.Text.Json;
using System.Text.Json.Serialization;

#pragma warning disable CS0618 // Type or member is obsolete

namespace ModelContextProtocol.Tests.Configuration;

public partial class ElicitationTypedTests : ClientServerTestBase
Expand Down
Loading