Skip to content

Commit 4cef394

Browse files
CopilotCopilot
andauthored
Add serialization roundtrip tests for all Protocol namespace types (#1289)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 392e47e commit 4cef394

73 files changed

Lines changed: 3222 additions & 475 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class AnnotationsTests
7+
{
8+
[Fact]
9+
public static void Annotations_SerializationRoundTrip_PreservesAllProperties()
10+
{
11+
var original = new Annotations
12+
{
13+
Audience = [Role.User, Role.Assistant],
14+
Priority = 0.75f,
15+
LastModified = new DateTimeOffset(2025, 6, 15, 10, 30, 0, TimeSpan.Zero)
16+
};
17+
18+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
19+
var deserialized = JsonSerializer.Deserialize<Annotations>(json, McpJsonUtilities.DefaultOptions);
20+
21+
Assert.NotNull(deserialized);
22+
Assert.NotNull(deserialized.Audience);
23+
Assert.Equal(2, deserialized.Audience.Count);
24+
Assert.Equal(Role.User, deserialized.Audience[0]);
25+
Assert.Equal(Role.Assistant, deserialized.Audience[1]);
26+
Assert.Equal(original.Priority, deserialized.Priority);
27+
Assert.Equal(original.LastModified, deserialized.LastModified);
28+
}
29+
30+
[Fact]
31+
public static void Annotations_SerializationRoundTrip_WithMinimalProperties()
32+
{
33+
var original = new Annotations();
34+
35+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
36+
var deserialized = JsonSerializer.Deserialize<Annotations>(json, McpJsonUtilities.DefaultOptions);
37+
38+
Assert.NotNull(deserialized);
39+
Assert.Null(deserialized.Audience);
40+
Assert.Null(deserialized.Priority);
41+
Assert.Null(deserialized.LastModified);
42+
}
43+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class ArgumentTests
7+
{
8+
[Fact]
9+
public static void Argument_SerializationRoundTrip_PreservesAllProperties()
10+
{
11+
var original = new Argument
12+
{
13+
Name = "temperature",
14+
Value = "72"
15+
};
16+
17+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
18+
var deserialized = JsonSerializer.Deserialize<Argument>(json, McpJsonUtilities.DefaultOptions);
19+
20+
Assert.NotNull(deserialized);
21+
Assert.Equal(original.Name, deserialized.Name);
22+
Assert.Equal(original.Value, deserialized.Value);
23+
}
24+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
using System.Text.Json.Nodes;
4+
5+
namespace ModelContextProtocol.Tests.Protocol;
6+
7+
public static class CallToolRequestParamsTests
8+
{
9+
[Fact]
10+
public static void CallToolRequestParams_SerializationRoundTrip_PreservesAllProperties()
11+
{
12+
var original = new CallToolRequestParams
13+
{
14+
Name = "get_weather",
15+
Arguments = new Dictionary<string, JsonElement>
16+
{
17+
["city"] = JsonDocument.Parse("\"Seattle\"").RootElement.Clone(),
18+
["units"] = JsonDocument.Parse("\"metric\"").RootElement.Clone()
19+
},
20+
Task = new McpTaskMetadata { TimeToLive = TimeSpan.FromHours(1) },
21+
Meta = new JsonObject { ["progressToken"] = "token-123" }
22+
};
23+
24+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
25+
var deserialized = JsonSerializer.Deserialize<CallToolRequestParams>(json, McpJsonUtilities.DefaultOptions);
26+
27+
Assert.NotNull(deserialized);
28+
Assert.Equal(original.Name, deserialized.Name);
29+
Assert.NotNull(deserialized.Arguments);
30+
Assert.Equal(2, deserialized.Arguments.Count);
31+
Assert.Equal("Seattle", deserialized.Arguments["city"].GetString());
32+
Assert.Equal("metric", deserialized.Arguments["units"].GetString());
33+
Assert.NotNull(deserialized.Task);
34+
Assert.Equal(original.Task.TimeToLive, deserialized.Task.TimeToLive);
35+
Assert.NotNull(deserialized.Meta);
36+
Assert.Equal("token-123", (string)deserialized.Meta["progressToken"]!);
37+
}
38+
39+
[Fact]
40+
public static void CallToolRequestParams_SerializationRoundTrip_WithMinimalProperties()
41+
{
42+
var original = new CallToolRequestParams
43+
{
44+
Name = "simple_tool"
45+
};
46+
47+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
48+
var deserialized = JsonSerializer.Deserialize<CallToolRequestParams>(json, McpJsonUtilities.DefaultOptions);
49+
50+
Assert.NotNull(deserialized);
51+
Assert.Equal(original.Name, deserialized.Name);
52+
Assert.Null(deserialized.Arguments);
53+
Assert.Null(deserialized.Task);
54+
Assert.Null(deserialized.Meta);
55+
}
56+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
using System.Text.Json.Nodes;
4+
5+
namespace ModelContextProtocol.Tests.Protocol;
6+
7+
public static class CallToolResultTests
8+
{
9+
[Fact]
10+
public static void CallToolResult_SerializationRoundTrip_PreservesAllProperties()
11+
{
12+
var original = new CallToolResult
13+
{
14+
Content = [new TextContentBlock { Text = "Result text" }],
15+
StructuredContent = JsonNode.Parse("""{"temperature":72}"""),
16+
IsError = false,
17+
Task = new McpTask
18+
{
19+
TaskId = "task-1",
20+
Status = McpTaskStatus.Completed,
21+
CreatedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
22+
LastUpdatedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero)
23+
},
24+
Meta = new JsonObject { ["key"] = "value" }
25+
};
26+
27+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
28+
var deserialized = JsonSerializer.Deserialize<CallToolResult>(json, McpJsonUtilities.DefaultOptions);
29+
30+
Assert.NotNull(deserialized);
31+
Assert.Single(deserialized.Content);
32+
var textBlock = Assert.IsType<TextContentBlock>(deserialized.Content[0]);
33+
Assert.Equal("Result text", textBlock.Text);
34+
Assert.NotNull(deserialized.StructuredContent);
35+
Assert.Equal(72, deserialized.StructuredContent["temperature"]!.GetValue<int>());
36+
Assert.False(deserialized.IsError);
37+
Assert.NotNull(deserialized.Task);
38+
Assert.Equal("task-1", deserialized.Task.TaskId);
39+
Assert.NotNull(deserialized.Meta);
40+
Assert.Equal("value", (string)deserialized.Meta["key"]!);
41+
}
42+
43+
[Fact]
44+
public static void CallToolResult_SerializationRoundTrip_WithMinimalProperties()
45+
{
46+
var original = new CallToolResult();
47+
48+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
49+
var deserialized = JsonSerializer.Deserialize<CallToolResult>(json, McpJsonUtilities.DefaultOptions);
50+
51+
Assert.NotNull(deserialized);
52+
Assert.Empty(deserialized.Content);
53+
Assert.Null(deserialized.StructuredContent);
54+
Assert.Null(deserialized.IsError);
55+
Assert.Null(deserialized.Task);
56+
Assert.Null(deserialized.Meta);
57+
}
58+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class CancelMcpTaskRequestParamsTests
7+
{
8+
[Fact]
9+
public static void CancelMcpTaskRequestParams_SerializationRoundTrip()
10+
{
11+
// Arrange
12+
var original = new CancelMcpTaskRequestParams
13+
{
14+
TaskId = "cancel-task-456"
15+
};
16+
17+
// Act
18+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
19+
var deserialized = JsonSerializer.Deserialize<CancelMcpTaskRequestParams>(json, McpJsonUtilities.DefaultOptions);
20+
21+
// Assert
22+
Assert.NotNull(deserialized);
23+
Assert.Equal(original.TaskId, deserialized.TaskId);
24+
}
25+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class CancelMcpTaskResultTests
7+
{
8+
[Fact]
9+
public static void CancelMcpTaskResult_SerializationRoundTrip()
10+
{
11+
// Arrange
12+
var original = new CancelMcpTaskResult
13+
{
14+
TaskId = "cancelled-789",
15+
Status = McpTaskStatus.Cancelled,
16+
StatusMessage = "Cancelled by user",
17+
CreatedAt = DateTimeOffset.UtcNow,
18+
LastUpdatedAt = DateTimeOffset.UtcNow,
19+
TimeToLive = null,
20+
PollInterval = null
21+
};
22+
23+
// Act
24+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
25+
var deserialized = JsonSerializer.Deserialize<CancelMcpTaskResult>(json, McpJsonUtilities.DefaultOptions);
26+
27+
// Assert
28+
Assert.NotNull(deserialized);
29+
Assert.Equal(original.TaskId, deserialized.TaskId);
30+
Assert.Equal(original.Status, deserialized.Status);
31+
Assert.Equal(original.StatusMessage, deserialized.StatusMessage);
32+
}
33+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
using System.Text.Json.Nodes;
4+
5+
namespace ModelContextProtocol.Tests.Protocol;
6+
7+
public static class CancelledNotificationParamsTests
8+
{
9+
[Fact]
10+
public static void CancelledNotificationParams_SerializationRoundTrip_PreservesAllProperties()
11+
{
12+
var original = new CancelledNotificationParams
13+
{
14+
RequestId = new RequestId(42),
15+
Reason = "User cancelled the operation",
16+
Meta = new JsonObject { ["key"] = "value" }
17+
};
18+
19+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
20+
var deserialized = JsonSerializer.Deserialize<CancelledNotificationParams>(json, McpJsonUtilities.DefaultOptions);
21+
22+
Assert.NotNull(deserialized);
23+
Assert.Equal(original.RequestId, deserialized.RequestId);
24+
Assert.Equal(original.Reason, deserialized.Reason);
25+
Assert.NotNull(deserialized.Meta);
26+
Assert.Equal("value", (string)deserialized.Meta["key"]!);
27+
}
28+
29+
[Fact]
30+
public static void CancelledNotificationParams_SerializationRoundTrip_WithMinimalProperties()
31+
{
32+
var original = new CancelledNotificationParams
33+
{
34+
RequestId = new RequestId("req-123")
35+
};
36+
37+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
38+
var deserialized = JsonSerializer.Deserialize<CancelledNotificationParams>(json, McpJsonUtilities.DefaultOptions);
39+
40+
Assert.NotNull(deserialized);
41+
Assert.Equal(original.RequestId, deserialized.RequestId);
42+
Assert.Null(deserialized.Reason);
43+
Assert.Null(deserialized.Meta);
44+
}
45+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class ClientCapabilitiesTests
7+
{
8+
[Fact]
9+
public static void ClientCapabilities_SerializationRoundTrip_PreservesAllProperties()
10+
{
11+
var original = new ClientCapabilities
12+
{
13+
Roots = new RootsCapability { ListChanged = true },
14+
Sampling = new SamplingCapability
15+
{
16+
Context = new SamplingContextCapability(),
17+
Tools = new SamplingToolsCapability()
18+
},
19+
Elicitation = new ElicitationCapability
20+
{
21+
Form = new FormElicitationCapability(),
22+
Url = new UrlElicitationCapability()
23+
},
24+
Tasks = new McpTasksCapability()
25+
};
26+
27+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
28+
var deserialized = JsonSerializer.Deserialize<ClientCapabilities>(json, McpJsonUtilities.DefaultOptions);
29+
30+
Assert.NotNull(deserialized);
31+
Assert.NotNull(deserialized.Roots);
32+
Assert.True(deserialized.Roots.ListChanged);
33+
Assert.NotNull(deserialized.Sampling);
34+
Assert.NotNull(deserialized.Sampling.Context);
35+
Assert.NotNull(deserialized.Sampling.Tools);
36+
Assert.NotNull(deserialized.Elicitation);
37+
Assert.NotNull(deserialized.Elicitation.Form);
38+
Assert.NotNull(deserialized.Elicitation.Url);
39+
Assert.NotNull(deserialized.Tasks);
40+
}
41+
42+
[Fact]
43+
public static void ClientCapabilities_SerializationRoundTrip_WithMinimalProperties()
44+
{
45+
var original = new ClientCapabilities();
46+
47+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
48+
var deserialized = JsonSerializer.Deserialize<ClientCapabilities>(json, McpJsonUtilities.DefaultOptions);
49+
50+
Assert.NotNull(deserialized);
51+
Assert.Null(deserialized.Experimental);
52+
Assert.Null(deserialized.Roots);
53+
Assert.Null(deserialized.Sampling);
54+
Assert.Null(deserialized.Elicitation);
55+
Assert.Null(deserialized.Tasks);
56+
}
57+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public static class CompleteContextTests
7+
{
8+
[Fact]
9+
public static void CompleteContext_SerializationRoundTrip_PreservesAllProperties()
10+
{
11+
var original = new CompleteContext
12+
{
13+
Arguments = new Dictionary<string, string>
14+
{
15+
["language"] = "en",
16+
["region"] = "us"
17+
}
18+
};
19+
20+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
21+
var deserialized = JsonSerializer.Deserialize<CompleteContext>(json, McpJsonUtilities.DefaultOptions);
22+
23+
Assert.NotNull(deserialized);
24+
Assert.NotNull(deserialized.Arguments);
25+
Assert.Equal(2, deserialized.Arguments.Count);
26+
Assert.Equal("en", deserialized.Arguments["language"]);
27+
Assert.Equal("us", deserialized.Arguments["region"]);
28+
}
29+
30+
[Fact]
31+
public static void CompleteContext_SerializationRoundTrip_WithMinimalProperties()
32+
{
33+
var original = new CompleteContext();
34+
35+
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
36+
var deserialized = JsonSerializer.Deserialize<CompleteContext>(json, McpJsonUtilities.DefaultOptions);
37+
38+
Assert.NotNull(deserialized);
39+
Assert.Null(deserialized.Arguments);
40+
}
41+
}

0 commit comments

Comments
 (0)