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>
This commit is contained in:
Copilot 2025-07-23 19:52:45 +03:00 • committed by GitHub
commit 650df63194
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 87 additions and 0 deletions

View file

@ -103,6 +103,10 @@ public abstract class ContentBlock
text = reader.GetString();
break;
case "name":
name = reader.GetString();
break;
case "data":
data = reader.GetString();
break;

View file

@ -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<ContentBlock>(json, McpJsonUtilities.DefaultOptions);
// Assert
Assert.NotNull(deserialized);
var resourceLink = Assert.IsType<ResourceLinkBlock>(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<ContentBlock>(Json, McpJsonUtilities.DefaultOptions);
// Assert
Assert.NotNull(deserialized);
var resourceLink = Assert.IsType<ResourceLinkBlock>(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<JsonException>(() =>
JsonSerializer.Deserialize<ContentBlock>(Json, McpJsonUtilities.DefaultOptions));
Assert.Contains("Name must be provided for 'resource_link' type", exception.Message);
}
}