diff --git a/src/ModelContextProtocol.Core/AIContentExtensions.cs b/src/ModelContextProtocol.Core/AIContentExtensions.cs index affb8b20a..03e7e9366 100644 --- a/src/ModelContextProtocol.Core/AIContentExtensions.cs +++ b/src/ModelContextProtocol.Core/AIContentExtensions.cs @@ -434,7 +434,7 @@ public static ContentBlock ToContentBlock(this AIContent content, JsonSerializer Content = resultContent.Result is AIContent c ? [c.ToContentBlock(options)] : resultContent.Result is IEnumerable ec ? [.. ec.Select(c => c.ToContentBlock(options))] : - [new TextContentBlock { Text = JsonSerializer.Serialize(content, options.GetTypeInfo()) }], + [new TextContentBlock { Text = JsonSerializer.Serialize(resultContent.Result, options.GetTypeInfo(typeof(object))) }], StructuredContent = resultContent.Result is JsonElement je ? je : null, }, diff --git a/tests/ModelContextProtocol.Tests/AIContentExtensionsTests.cs b/tests/ModelContextProtocol.Tests/AIContentExtensionsTests.cs index 77be2f922..c20a8e759 100644 --- a/tests/ModelContextProtocol.Tests/AIContentExtensionsTests.cs +++ b/tests/ModelContextProtocol.Tests/AIContentExtensionsTests.cs @@ -151,6 +151,43 @@ public void ToAIContent_ToolResultToFunctionResultRoundTrip() Assert.NotNull(functionResult.Result); } + [Fact] + public void ToContentBlock_FunctionResultWithStringResult_TextIsTheResult() + { + FunctionResultContent functionResult = new("call_123", "Weather in Paris: sunny"); + + var toolResult = Assert.IsType(functionResult.ToContentBlock()); + + Assert.Equal("call_123", toolResult.ToolUseId); + var text = Assert.IsType(Assert.Single(toolResult.Content)); + Assert.Equal("\"Weather in Paris: sunny\"", text.Text); + } + + [Fact] + public void ToContentBlock_FunctionResultWithJsonElementResult_TextIsTheResult() + { + JsonElement value = JsonSerializer.SerializeToElement(new Dictionary { ["temperature"] = 22 }, McpJsonUtilities.DefaultOptions); + FunctionResultContent functionResult = new("call_123", value); + + var toolResult = Assert.IsType(functionResult.ToContentBlock()); + + var text = Assert.IsType(Assert.Single(toolResult.Content)); + Assert.Equal("""{"temperature":22}""", text.Text); + Assert.NotNull(toolResult.StructuredContent); + Assert.Equal(22, toolResult.StructuredContent.Value.GetProperty("temperature").GetInt32()); + } + + [Fact] + public void ToContentBlock_FunctionResultWithAIContentResult_ConvertsTheContent() + { + FunctionResultContent functionResult = new("call_123", new TextContent("Weather in Paris: sunny")); + + var toolResult = Assert.IsType(functionResult.ToContentBlock()); + + var text = Assert.IsType(Assert.Single(toolResult.Content)); + Assert.Equal("Weather in Paris: sunny", text.Text); + } + // Tests for anonymous types in AdditionalProperties (sampling pipeline regression fix) // These tests require reflection-based serialization and will be skipped when reflection is disabled. diff --git a/tests/ModelContextProtocol.Tests/Client/McpClientTests.cs b/tests/ModelContextProtocol.Tests/Client/McpClientTests.cs index 053245909..24de94814 100644 --- a/tests/ModelContextProtocol.Tests/Client/McpClientTests.cs +++ b/tests/ModelContextProtocol.Tests/Client/McpClientTests.cs @@ -653,6 +653,7 @@ public async Task EndToEnd_SamplingWithTools_ServerUsesIChatClientWithFunctionIn string resultText = toolResult.Result?.ToString() ?? string.Empty; Assert.Contains("Weather in Paris: sunny", resultText); + Assert.DoesNotContain("callId", resultText); return Task.FromResult(new([ new ChatMessage(ChatRole.User, messages.First().Contents),