using ModelContextProtocol.Protocol; using System.Text.Json; namespace ModelContextProtocol.Tests.Protocol; public static class PrimitiveSchemaDefinitionTests { [Fact] public static void StringSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "string", "title": "Test", "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "minLength": 5, "maxLength": 50, "format": "email" } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var stringSchema = Assert.IsType(result); Assert.Equal("string", stringSchema.Type); Assert.Equal("Test", stringSchema.Title); Assert.Equal(5, stringSchema.MinLength); Assert.Equal(50, stringSchema.MaxLength); Assert.Equal("email", stringSchema.Format); } [Fact] public static void NumberSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "number", "description": "Test Number", "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "minimum": 0, "maximum": 1000 } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var numberSchema = Assert.IsType(result); Assert.Equal("number", numberSchema.Type); Assert.Equal("Test Number", numberSchema.Description); Assert.Equal(0, numberSchema.Minimum); Assert.Equal(1000, numberSchema.Maximum); } [Fact] public static void BooleanSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "boolean", "title": "Test Boolean", "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "default": false } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var boolSchema = Assert.IsType(result); Assert.Equal("boolean", boolSchema.Type); Assert.Equal("Test Boolean", boolSchema.Title); Assert.False(boolSchema.Default); } [Fact] public static void UntitledSingleSelectEnumSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "string", "enum": ["option1", "option2", "option3"], "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "default": "option1" } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var enumSchema = Assert.IsType(result); Assert.Equal("string", enumSchema.Type); Assert.Equal(3, enumSchema.Enum.Count); Assert.Contains("option1", enumSchema.Enum); Assert.Contains("option2", enumSchema.Enum); Assert.Contains("option3", enumSchema.Enum); Assert.Equal("option1", enumSchema.Default); } [Fact] public static void TitledSingleSelectEnumSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "string", "oneOf": [ {"const": "option1", "title": "Option 1"}, {"const": "option2", "title": "Option 2"} ], "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "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.OneOf.Count); Assert.Contains(enumSchema.OneOf, option => option.Const == "option1" && option.Title == "Option 1"); Assert.Contains(enumSchema.OneOf, option => option.Const == "option2" && option.Title == "Option 2"); Assert.Equal("option2", enumSchema.Default); } [Fact] public static void UntitledMultiSelectEnumSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "array", "items": { "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "enum": ["optionA", "optionB", "optionC"] }, "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "default": ["optionA", "optionC"] } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var enumSchema = Assert.IsType(result); Assert.Equal("array", enumSchema.Type); Assert.Equal(3, enumSchema.Items.Enum.Count); Assert.Contains("optionA", enumSchema.Items.Enum); Assert.Contains("optionB", enumSchema.Items.Enum); Assert.Contains("optionC", enumSchema.Items.Enum); Assert.Equal(2, enumSchema.Default!.Count); Assert.Contains("optionA", enumSchema.Default); Assert.Contains("optionC", enumSchema.Default); } [Fact] public static void TitledMultiSelectEnumSchema_UnknownProperties_AreIgnored() { const string json = """ { "type": "array", "items": { "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "anyOf": [ {"const": "optionX", "title": "Option X"}, {"const": "optionY", "title": "Option Y"}, {"const": "optionZ", "title": "Option Z"} ] }, "unknownNull": null, "unknownEmptyObject": {}, "unknownObject": {"a": 1}, "unknownEmptyArray": [], "unknownArray": [1, 2, 3], "unknownNestedObject": {"b": {"c": "d", "e": ["f"]}}, "default": ["optionX", "optionZ"] } """; var result = JsonSerializer.Deserialize( json, McpJsonUtilities.DefaultOptions); Assert.NotNull(result); var enumSchema = Assert.IsType(result); Assert.Equal("array", enumSchema.Type); Assert.Equal(3, enumSchema.Items.AnyOf.Count); Assert.Contains(enumSchema.Items.AnyOf, option => option.Const == "optionX" && option.Title == "Option X"); Assert.Contains(enumSchema.Items.AnyOf, option => option.Const == "optionY" && option.Title == "Option Y"); Assert.Contains(enumSchema.Items.AnyOf, option => option.Const == "optionZ" && option.Title == "Option Z"); Assert.Equal(2, enumSchema.Default!.Count); 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 }