Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ public class Converter : JsonConverter<ContentBlock>
break;

default:
reader.Skip();
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public class Converter : JsonConverter<PrimitiveSchemaDefinition>
break;

default:
reader.Skip();
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public sealed class Converter : JsonConverter<ProgressNotificationParams>
case "_meta":
meta = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.JsonObject);
break;

default:
reader.Skip();
break;
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/ModelContextProtocol.Core/Protocol/Reference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,16 @@ public sealed class Converter : JsonConverter<Reference>
name = reader.GetString();
break;

case "title":
title = reader.GetString();
break;

case "uri":
uri = reader.GetString();
break;

default:
reader.Skip();
break;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ModelContextProtocol.Core/Protocol/ResourceContents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public class Converter : JsonConverter<ResourceContents>
break;

default:
reader.Skip();
break;
}
}
Expand Down
47 changes: 46 additions & 1 deletion tests/ModelContextProtocol.Tests/Protocol/ContentBlockTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Protocol;
using System.Text.Json;

namespace ModelContextProtocol.Tests.Protocol;

Expand Down Expand Up @@ -80,4 +81,48 @@ public void ResourceLinkBlock_DeserializationWithoutName_ThrowsJsonException()

Assert.Contains("Name must be provided for 'resource_link' type", exception.Message);
}

[Fact]
public void Deserialize_IgnoresUnknownArrayProperty()
{
// This is a regression test where a server returned an unexpected response with
// `structuredContent` as an array nested inside a content block. This should be
// permitted with the `structuredContent` gracefully ignored in that location.
string responseJson = @"{
""type"": ""text"",
""text"": ""[\n {\n \""Data\"": \""1234567890\""\n }\n]"",
""structuredContent"": [
{
""Data"": ""1234567890""
}
]
}";

var contentBlock = JsonSerializer.Deserialize<ContentBlock>(responseJson, McpJsonUtilities.DefaultOptions);
Assert.NotNull(contentBlock);

var textBlock = Assert.IsType<TextContentBlock>(contentBlock);
Assert.Contains("1234567890", textBlock.Text);
}

[Fact]
public void Deserialize_IgnoresUnknownObjectProperties()
{
string responseJson = @"{
""type"": ""text"",
""text"": ""Sample text"",
""unknownObject"": {
""nestedProp1"": ""value1"",
""nestedProp2"": {
""deeplyNested"": true
}
}
}";

var contentBlock = JsonSerializer.Deserialize<ContentBlock>(responseJson, McpJsonUtilities.DefaultOptions);
Assert.NotNull(contentBlock);

var textBlock = Assert.IsType<TextContentBlock>(contentBlock);
Assert.Contains("Sample text", textBlock.Text);
}
}
Loading
Loading