csharp-sdk/tests/ModelContextProtocol.Tests/Protocol/MrtrSerializationTests.cs
2026-06-03 16:19:31 -07:00

298 lines
11 KiB
C#

using ModelContextProtocol.Protocol;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace ModelContextProtocol.Tests.Protocol;
public static class MrtrSerializationTests
{
[Fact]
public static void IncompleteResult_SerializationRoundTrip_PreservesAllProperties()
{
var original = new InputRequiredResult
{
InputRequests = new Dictionary<string, InputRequest>
{
["input_1"] = InputRequest.ForElicitation(new ElicitRequestParams
{
Message = "What is your name?",
RequestedSchema = new()
}),
["input_2"] = InputRequest.ForSampling(new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = [new TextContentBlock { Text = "Hello" }] }],
MaxTokens = 100
})
},
RequestState = "correlation-123",
};
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputRequiredResult>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal("input_required", deserialized.ResultType);
Assert.Equal("correlation-123", deserialized.RequestState);
Assert.NotNull(deserialized.InputRequests);
Assert.Equal(2, deserialized.InputRequests.Count);
Assert.True(deserialized.InputRequests.ContainsKey("input_1"));
Assert.True(deserialized.InputRequests.ContainsKey("input_2"));
}
[Fact]
public static void IncompleteResult_HasResultTypeIncomplete()
{
var result = new InputRequiredResult();
Assert.Equal("input_required", result.ResultType);
}
[Fact]
public static void IncompleteResult_ResultType_AppearsInJson()
{
var result = new InputRequiredResult
{
RequestState = "abc",
};
string json = JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
Assert.NotNull(node);
Assert.Equal("input_required", (string?)node["resultType"]);
Assert.Equal("abc", (string?)node["requestState"]);
}
[Fact]
public static void InputRequest_ForElicitation_SerializesCorrectly()
{
var inputRequest = InputRequest.ForElicitation(new ElicitRequestParams
{
Message = "Enter name",
RequestedSchema = new()
});
string json = JsonSerializer.Serialize(inputRequest, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
Assert.NotNull(node);
Assert.Equal("elicitation/create", (string?)node["method"]);
Assert.NotNull(node["params"]);
Assert.Equal("Enter name", (string?)node["params"]!["message"]);
}
[Fact]
public static void InputRequest_ForSampling_SerializesCorrectly()
{
var inputRequest = InputRequest.ForSampling(new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = [new TextContentBlock { Text = "Prompt" }] }],
MaxTokens = 50
});
string json = JsonSerializer.Serialize(inputRequest, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
Assert.NotNull(node);
Assert.Equal("sampling/createMessage", (string?)node["method"]);
Assert.NotNull(node["params"]);
Assert.Equal(50, (int?)node["params"]!["maxTokens"]);
}
[Fact]
public static void InputRequest_ForRootsList_SerializesCorrectly()
{
var inputRequest = InputRequest.ForRootsList(new ListRootsRequestParams());
string json = JsonSerializer.Serialize(inputRequest, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
Assert.NotNull(node);
Assert.Equal("roots/list", (string?)node["method"]);
}
[Fact]
public static void InputRequest_Elicitation_RoundTrip()
{
var original = InputRequest.ForElicitation(new ElicitRequestParams
{
Message = "test message",
RequestedSchema = new()
});
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputRequest>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal("elicitation/create", deserialized.Method);
Assert.NotNull(deserialized.ElicitationParams);
Assert.Equal("test message", deserialized.ElicitationParams.Message);
}
[Fact]
public static void InputRequest_Sampling_RoundTrip()
{
var original = InputRequest.ForSampling(new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = [new TextContentBlock { Text = "Hello" }] }],
MaxTokens = 200
});
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputRequest>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal("sampling/createMessage", deserialized.Method);
Assert.NotNull(deserialized.SamplingParams);
Assert.Equal(200, deserialized.SamplingParams.MaxTokens);
}
[Fact]
public static void InputRequest_RootsList_RoundTrip()
{
var original = InputRequest.ForRootsList(new ListRootsRequestParams());
string json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputRequest>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal("roots/list", deserialized.Method);
Assert.NotNull(deserialized.RootsParams);
}
[Fact]
public static void InputResponse_FromSamplingResult_RoundTrip()
{
var samplingResult = new CreateMessageResult
{
Content = [new TextContentBlock { Text = "Response text" }],
Model = "test-model"
};
var inputResponse = InputResponse.FromSamplingResult(samplingResult);
// Serialize → deserialize
string json = JsonSerializer.Serialize(inputResponse, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputResponse>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
var sampling = deserialized.Deserialize(InputResponse.CreateMessageResultJsonTypeInfo);
Assert.NotNull(sampling);
Assert.Equal("test-model", sampling.Model);
}
[Fact]
public static void InputResponse_FromElicitResult_RoundTrip()
{
var elicitResult = new ElicitResult
{
Action = "confirm",
Content = new Dictionary<string, JsonElement>
{
["key"] = JsonDocument.Parse("\"value\"").RootElement.Clone()
}
};
var inputResponse = InputResponse.FromElicitResult(elicitResult);
string json = JsonSerializer.Serialize(inputResponse, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputResponse>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
var elicit = deserialized.Deserialize(InputResponse.ElicitResultJsonTypeInfo);
Assert.NotNull(elicit);
Assert.Equal("confirm", elicit.Action);
}
[Fact]
public static void InputResponse_FromRootsResult_RoundTrip()
{
var rootsResult = new ListRootsResult
{
Roots = [new Root { Uri = "file:///test", Name = "Test" }]
};
var inputResponse = InputResponse.FromRootsResult(rootsResult);
string json = JsonSerializer.Serialize(inputResponse, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<InputResponse>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
var roots = deserialized.Deserialize(InputResponse.ListRootsResultJsonTypeInfo);
Assert.NotNull(roots);
Assert.Single(roots.Roots);
Assert.Equal("file:///test", roots.Roots[0].Uri);
}
[Fact]
public static void InputRequestDictionary_SerializationRoundTrip()
{
IDictionary<string, InputRequest> requests = new Dictionary<string, InputRequest>
{
["a"] = InputRequest.ForElicitation(new ElicitRequestParams { Message = "q1", RequestedSchema = new() }),
["b"] = InputRequest.ForSampling(new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = [new TextContentBlock { Text = "q2" }] }],
MaxTokens = 50
}),
};
string json = JsonSerializer.Serialize(requests, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<IDictionary<string, InputRequest>>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal(2, deserialized.Count);
Assert.Equal("elicitation/create", deserialized["a"].Method);
Assert.Equal("sampling/createMessage", deserialized["b"].Method);
}
[Fact]
public static void InputResponseDictionary_SerializationRoundTrip()
{
IDictionary<string, InputResponse> responses = new Dictionary<string, InputResponse>
{
["a"] = InputResponse.FromElicitResult(new ElicitResult { Action = "confirm" }),
["b"] = InputResponse.FromSamplingResult(new CreateMessageResult
{
Content = [new TextContentBlock { Text = "AI" }],
Model = "m1"
}),
};
string json = JsonSerializer.Serialize(responses, McpJsonUtilities.DefaultOptions);
var deserialized = JsonSerializer.Deserialize<IDictionary<string, InputResponse>>(json, McpJsonUtilities.DefaultOptions);
Assert.NotNull(deserialized);
Assert.Equal(2, deserialized.Count);
}
[Fact]
public static void Result_ResultType_DefaultsToNull()
{
var result = new CallToolResult
{
Content = [new TextContentBlock { Text = "test" }]
};
string json = JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
// result_type should not appear for normal results
Assert.Null(node?["resultType"]);
}
[Fact]
public static void RequestParams_InputResponses_NotSerializedByDefault()
{
var callParams = new CallToolRequestParams
{
Name = "test-tool",
};
string json = JsonSerializer.Serialize(callParams, McpJsonUtilities.DefaultOptions);
var node = JsonNode.Parse(json);
// inputResponses and requestState should not appear when null
Assert.Null(node?["inputResponses"]);
Assert.Null(node?["requestState"]);
}
}