From 650df631947f9026b5c65d6f1fc0f6f3dd9a77ad Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 23 Jul 2025 19:52:45 +0300 Subject: [PATCH] Fix ResourceLinkBlock deserialization by adding missing "name" case (#645) * Initial plan * Initial analysis and plan for ResourceLinkBlock deserialization fix Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> * Fix ResourceLinkBlock deserialization by adding missing "name" case Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> * Remove unnecessary dotnet-install.sh file Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> * Use const for JSON string variables and improve indentation Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Remove temporary backup file Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Change JSON variable names to use PascalCase (Json) as requested Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../Protocol/ContentBlock.cs | 4 + .../Protocol/ContentBlockTests.cs | 83 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 tests/ModelContextProtocol.Tests/Protocol/ContentBlockTests.cs diff --git a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs index 516ea24..04de39d 100644 --- a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs +++ b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs @@ -103,6 +103,10 @@ public abstract class ContentBlock text = reader.GetString(); break; + case "name": + name = reader.GetString(); + break; + case "data": data = reader.GetString(); break; diff --git a/tests/ModelContextProtocol.Tests/Protocol/ContentBlockTests.cs b/tests/ModelContextProtocol.Tests/Protocol/ContentBlockTests.cs new file mode 100644 index 0000000..c5ab88b --- /dev/null +++ b/tests/ModelContextProtocol.Tests/Protocol/ContentBlockTests.cs @@ -0,0 +1,83 @@ +using System.Text.Json; +using ModelContextProtocol.Protocol; + +namespace ModelContextProtocol.Tests.Protocol; + +public class ContentBlockTests +{ + [Fact] + public void ResourceLinkBlock_SerializationRoundTrip_PreservesAllProperties() + { + // Arrange + var original = new ResourceLinkBlock + { + Uri = "https://example.com/resource", + Name = "Test Resource", + Description = "A test resource for validation", + MimeType = "text/plain", + Size = 1024 + }; + + // Act - Serialize to JSON + string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions); + + // Act - Deserialize back from JSON + var deserialized = JsonSerializer.Deserialize(json, McpJsonUtilities.DefaultOptions); + + // Assert + Assert.NotNull(deserialized); + var resourceLink = Assert.IsType(deserialized); + + Assert.Equal(original.Uri, resourceLink.Uri); + Assert.Equal(original.Name, resourceLink.Name); + Assert.Equal(original.Description, resourceLink.Description); + Assert.Equal(original.MimeType, resourceLink.MimeType); + Assert.Equal(original.Size, resourceLink.Size); + Assert.Equal("resource_link", resourceLink.Type); + } + + [Fact] + public void ResourceLinkBlock_DeserializationWithMinimalProperties_Succeeds() + { + // Arrange - JSON with only required properties + const string Json = """ + { + "type": "resource_link", + "uri": "https://example.com/minimal", + "name": "Minimal Resource" + } + """; + + // Act + var deserialized = JsonSerializer.Deserialize(Json, McpJsonUtilities.DefaultOptions); + + // Assert + Assert.NotNull(deserialized); + var resourceLink = Assert.IsType(deserialized); + + Assert.Equal("https://example.com/minimal", resourceLink.Uri); + Assert.Equal("Minimal Resource", resourceLink.Name); + Assert.Null(resourceLink.Description); + Assert.Null(resourceLink.MimeType); + Assert.Null(resourceLink.Size); + Assert.Equal("resource_link", resourceLink.Type); + } + + [Fact] + public void ResourceLinkBlock_DeserializationWithoutName_ThrowsJsonException() + { + // Arrange - JSON missing the required "name" property + const string Json = """ + { + "type": "resource_link", + "uri": "https://example.com/missing-name" + } + """; + + // Act & Assert + var exception = Assert.Throws(() => + JsonSerializer.Deserialize(Json, McpJsonUtilities.DefaultOptions)); + + Assert.Contains("Name must be provided for 'resource_link' type", exception.Message); + } +} \ No newline at end of file