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 { ["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(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(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(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(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(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 { ["key"] = JsonDocument.Parse("\"value\"").RootElement.Clone() } }; var inputResponse = InputResponse.FromElicitResult(elicitResult); string json = JsonSerializer.Serialize(inputResponse, McpJsonUtilities.DefaultOptions); var deserialized = JsonSerializer.Deserialize(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(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 requests = new Dictionary { ["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>(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 responses = new Dictionary { ["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>(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"]); } }