Disable STJ reflection for testing. (#266)
* Disable STJ reflection for testing. * Remove params method and redundant overload. --------- Co-authored-by: Stephen Toub <stoub@microsoft.com>
This commit is contained in:
parent
45dcfe07ca
commit
e3aa54eb3c
18 changed files with 155 additions and 75 deletions
|
|
@ -8,6 +8,7 @@ using ModelContextProtocol.Server;
|
|||
using ModelContextProtocol.Utils;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// <summary>Adds <see cref="McpServerTool"/> instances to the service collection backing <paramref name="builder"/>.</summary>
|
||||
/// <typeparam name="TToolType">The tool type.</typeparam>
|
||||
/// <param name="builder">The builder instance.</param>
|
||||
/// <param name="serializerOptions">The serializer options governing tool parameter marshalling.</param>
|
||||
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
|
|
@ -35,7 +37,8 @@ public static partial class McpServerBuilderExtensions
|
|||
DynamicallyAccessedMemberTypes.PublicMethods |
|
||||
DynamicallyAccessedMemberTypes.NonPublicMethods |
|
||||
DynamicallyAccessedMemberTypes.PublicConstructors)] TToolType>(
|
||||
this IMcpServerBuilder builder)
|
||||
this IMcpServerBuilder builder,
|
||||
JsonSerializerOptions? serializerOptions = null)
|
||||
{
|
||||
Throw.IfNull(builder);
|
||||
|
||||
|
|
@ -44,8 +47,8 @@ public static partial class McpServerBuilderExtensions
|
|||
if (toolMethod.GetCustomAttribute<McpServerToolAttribute>() is not null)
|
||||
{
|
||||
builder.Services.AddSingleton((Func<IServiceProvider, McpServerTool>)(toolMethod.IsStatic ?
|
||||
services => McpServerTool.Create(toolMethod, options: new() { Services = services }) :
|
||||
services => McpServerTool.Create(toolMethod, typeof(TToolType), new() { Services = services })));
|
||||
services => McpServerTool.Create(toolMethod, options: new() { Services = services, SerializerOptions = serializerOptions }) :
|
||||
services => McpServerTool.Create(toolMethod, typeof(TToolType), new() { Services = services, SerializerOptions = serializerOptions })));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +58,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// <summary>Adds <see cref="McpServerTool"/> instances to the service collection backing <paramref name="builder"/>.</summary>
|
||||
/// <param name="builder">The builder instance.</param>
|
||||
/// <param name="toolTypes">Types with marked methods to add as tools to the server.</param>
|
||||
/// <param name="serializerOptions">The serializer options governing tool parameter marshalling.</param>
|
||||
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="toolTypes"/> is <see langword="null"/>.</exception>
|
||||
|
|
@ -64,7 +68,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// instance for each. For instance methods, an instance will be constructed for each invocation of the tool.
|
||||
/// </remarks>
|
||||
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
|
||||
public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, params IEnumerable<Type> toolTypes)
|
||||
public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, IEnumerable<Type> toolTypes, JsonSerializerOptions? serializerOptions = null)
|
||||
{
|
||||
Throw.IfNull(builder);
|
||||
Throw.IfNull(toolTypes);
|
||||
|
|
@ -78,8 +82,8 @@ public static partial class McpServerBuilderExtensions
|
|||
if (toolMethod.GetCustomAttribute<McpServerToolAttribute>() is not null)
|
||||
{
|
||||
builder.Services.AddSingleton((Func<IServiceProvider, McpServerTool>)(toolMethod.IsStatic ?
|
||||
services => McpServerTool.Create(toolMethod, options: new() { Services = services }) :
|
||||
services => McpServerTool.Create(toolMethod, toolType, new() { Services = services })));
|
||||
services => McpServerTool.Create(toolMethod, options: new() { Services = services , SerializerOptions = serializerOptions }) :
|
||||
services => McpServerTool.Create(toolMethod, toolType, new() { Services = services , SerializerOptions = serializerOptions })));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,6 +96,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// Adds types marked with the <see cref="McpServerToolTypeAttribute"/> attribute from the given assembly as tools to the server.
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder instance.</param>
|
||||
/// <param name="serializerOptions">The serializer options governing tool parameter marshalling.</param>
|
||||
/// <param name="toolAssembly">The assembly to load the types from. If <see langword="null"/>, the calling assembly will be used.</param>
|
||||
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
|
||||
|
|
@ -116,7 +121,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// </para>
|
||||
/// </remarks>
|
||||
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
|
||||
public static IMcpServerBuilder WithToolsFromAssembly(this IMcpServerBuilder builder, Assembly? toolAssembly = null)
|
||||
public static IMcpServerBuilder WithToolsFromAssembly(this IMcpServerBuilder builder, Assembly? toolAssembly = null, JsonSerializerOptions? serializerOptions = null)
|
||||
{
|
||||
Throw.IfNull(builder);
|
||||
|
||||
|
|
@ -125,7 +130,8 @@ public static partial class McpServerBuilderExtensions
|
|||
return builder.WithTools(
|
||||
from t in toolAssembly.GetTypes()
|
||||
where t.GetCustomAttribute<McpServerToolTypeAttribute>() is not null
|
||||
select t);
|
||||
select t,
|
||||
serializerOptions);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
Name = options?.Name ?? method.GetCustomAttribute<McpServerToolAttribute>()?.Name,
|
||||
Description = options?.Description,
|
||||
MarshalResult = static (result, _, cancellationToken) => new ValueTask<object?>(result),
|
||||
SerializerOptions = options?.SerializerOptions ?? McpJsonUtilities.DefaultOptions,
|
||||
ConfigureParameterBinding = pi =>
|
||||
{
|
||||
if (pi.ParameterType == typeof(RequestContext<CallToolRequestParams>))
|
||||
|
|
@ -314,7 +315,7 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
{
|
||||
Content = [new()
|
||||
{
|
||||
Text = JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object))),
|
||||
Text = JsonSerializer.Serialize(result, AIFunction.JsonSerializerOptions.GetTypeInfo(typeof(object))),
|
||||
Type = "text"
|
||||
}]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using ModelContextProtocol.Utils.Json;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ModelContextProtocol.Server;
|
||||
|
||||
|
|
@ -122,11 +124,19 @@ public sealed class McpServerToolCreateOptions
|
|||
/// </remarks>
|
||||
public bool? ReadOnly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the JSON serializer options to use when marshalling data to/from JSON.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Defaults to <see cref="McpJsonUtilities.DefaultOptions"/> if left unspecified.
|
||||
/// </remarks>
|
||||
public JsonSerializerOptions? SerializerOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a shallow clone of the current <see cref="McpServerToolCreateOptions"/> instance.
|
||||
/// </summary>
|
||||
internal McpServerToolCreateOptions Clone() =>
|
||||
new McpServerToolCreateOptions()
|
||||
new McpServerToolCreateOptions
|
||||
{
|
||||
Services = Services,
|
||||
Name = Name,
|
||||
|
|
@ -135,6 +145,7 @@ public sealed class McpServerToolCreateOptions
|
|||
Destructive = Destructive,
|
||||
Idempotent = Idempotent,
|
||||
OpenWorld = OpenWorld,
|
||||
ReadOnly = ReadOnly
|
||||
ReadOnly = ReadOnly,
|
||||
SerializerOptions = SerializerOptions,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
<RootNamespace>ModelContextProtocol.AspNetCore.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<!-- For better test coverage, only disable reflection in one of the targets -->
|
||||
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Without this, tests are currently not showing results until all tests complete
|
||||
https://xunit.net/docs/getting-started/v3/microsoft-testing-platform
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ using ModelContextProtocol.Protocol.Transport;
|
|||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Tests.Utils;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using TestServerWithHosting.Tools;
|
||||
|
||||
namespace ModelContextProtocol.Tests;
|
||||
|
||||
public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemoryTest(outputHelper)
|
||||
public partial class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemoryTest(outputHelper)
|
||||
{
|
||||
private SseClientTransportOptions DefaultTransportOptions = new()
|
||||
{
|
||||
|
|
@ -41,7 +42,7 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
await using var mcpClient = await ConnectMcpClient(httpClient);
|
||||
|
||||
// Send a test message through POST endpoint
|
||||
await mcpClient.SendNotificationAsync("test/message", new { message = "Hello, SSE!" }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
await mcpClient.SendNotificationAsync("test/message", new Envelope { Message = "Hello, SSE!" }, serializerOptions: JsonContext.Default.Options, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(true);
|
||||
}
|
||||
|
|
@ -57,7 +58,7 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
await using var mcpClient = await ConnectMcpClient(httpClient);
|
||||
|
||||
// Send a test message through POST endpoint
|
||||
await mcpClient.SendNotificationAsync("test/message", new { message = "Hello, SSE!" }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
await mcpClient.SendNotificationAsync("test/message", new Envelope { Message = "Hello, SSE!" }, serializerOptions: JsonContext.Default.Options, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(true);
|
||||
}
|
||||
|
|
@ -73,7 +74,7 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
mcpServer.RegisterNotificationHandler("test/notification", async (notification, cancellationToken) =>
|
||||
{
|
||||
Assert.Equal("Hello from client!", notification.Params?["message"]?.GetValue<string>());
|
||||
await mcpServer.SendNotificationAsync("test/notification", new { message = "Hello from server!" }, cancellationToken: cancellationToken);
|
||||
await mcpServer.SendNotificationAsync("test/notification", new Envelope { Message = "Hello from server!" }, serializerOptions: JsonContext.Default.Options, cancellationToken: cancellationToken);
|
||||
});
|
||||
return mcpServer.RunAsync(cancellationToken);
|
||||
});
|
||||
|
|
@ -90,7 +91,7 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
});
|
||||
|
||||
// Send a test message through POST endpoint
|
||||
await mcpClient.SendNotificationAsync("test/notification", new { message = "Hello from client!" }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
await mcpClient.SendNotificationAsync("test/notification", new Envelope { Message = "Hello from client!" }, serializerOptions: JsonContext.Default.Options, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
var message = await receivedNotification.Task.WaitAsync(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken);
|
||||
Assert.Equal("Hello from server!", message);
|
||||
|
|
@ -205,4 +206,13 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
await context.Response.WriteAsync("Accepted");
|
||||
});
|
||||
}
|
||||
|
||||
public class Envelope
|
||||
{
|
||||
public required string Message { get; set; }
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
|
||||
[JsonSerializable(typeof(Envelope))]
|
||||
partial class JsonContext : JsonSerializerContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Microsoft.AspNetCore.Connections;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using Serilog;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
|
@ -124,7 +125,7 @@ public class Program
|
|||
},
|
||||
"required": ["message"]
|
||||
}
|
||||
"""),
|
||||
""", McpJsonUtilities.DefaultOptions),
|
||||
},
|
||||
new Tool()
|
||||
{
|
||||
|
|
@ -145,7 +146,7 @@ public class Program
|
|||
},
|
||||
"required": ["prompt", "maxTokens"]
|
||||
}
|
||||
"""),
|
||||
""", McpJsonUtilities.DefaultOptions),
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using Moq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
|
|
@ -379,7 +380,7 @@ public class McpClientExtensionsTests : ClientServerTestBase
|
|||
await using (client.RegisterNotificationHandler(NotificationMethods.LoggingMessageNotification,
|
||||
(notification, cancellationToken) =>
|
||||
{
|
||||
Assert.True(channel.Writer.TryWrite(JsonSerializer.Deserialize<LoggingMessageNotificationParams>(notification.Params)));
|
||||
Assert.True(channel.Writer.TryWrite(JsonSerializer.Deserialize<LoggingMessageNotificationParams>(notification.Params, McpJsonUtilities.DefaultOptions)));
|
||||
return Task.CompletedTask;
|
||||
}))
|
||||
{
|
||||
|
|
@ -398,7 +399,7 @@ public class McpClientExtensionsTests : ClientServerTestBase
|
|||
|
||||
Assert.Equal("TestLogger", m.Logger);
|
||||
|
||||
string ? s = JsonSerializer.Deserialize<string>(m.Data.Value);
|
||||
string ? s = JsonSerializer.Deserialize<string>(m.Data.Value, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(s);
|
||||
|
||||
if (s.Contains("Information"))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Protocol.Transport;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using Moq;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Channels;
|
||||
|
|
@ -107,7 +108,7 @@ public class McpClientFactoryTests
|
|||
Name = "NopTransport",
|
||||
Version = "1.0.0"
|
||||
},
|
||||
}),
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@ using ModelContextProtocol.Protocol.Messages;
|
|||
using ModelContextProtocol.Protocol.Transport;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Tests.Utils;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using OpenAI;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Tests;
|
||||
|
||||
public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegrationTestFixture>
|
||||
public partial class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegrationTestFixture>
|
||||
{
|
||||
private static readonly string? s_openAIKey = Environment.GetEnvironmentVariable("AI:OpenAI:ApiKey");
|
||||
|
||||
|
|
@ -261,7 +263,7 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
|||
[
|
||||
new(NotificationMethods.ResourceUpdatedNotification, (notification, cancellationToken) =>
|
||||
{
|
||||
var notificationParams = JsonSerializer.Deserialize<ResourceUpdatedNotificationParams>(notification.Params);
|
||||
var notificationParams = JsonSerializer.Deserialize<ResourceUpdatedNotificationParams>(notification.Params, McpJsonUtilities.DefaultOptions);
|
||||
tcs.TrySetResult(true);
|
||||
return Task.CompletedTask;
|
||||
})
|
||||
|
|
@ -291,7 +293,7 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
|||
[
|
||||
new(NotificationMethods.ResourceUpdatedNotification, (notification, cancellationToken) =>
|
||||
{
|
||||
var notificationParams = JsonSerializer.Deserialize<ResourceUpdatedNotificationParams>(notification.Params);
|
||||
var notificationParams = JsonSerializer.Deserialize<ResourceUpdatedNotificationParams>(notification.Params, McpJsonUtilities.DefaultOptions);
|
||||
receivedNotification.TrySetResult(true);
|
||||
return Task.CompletedTask;
|
||||
})
|
||||
|
|
@ -442,13 +444,18 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
|||
|
||||
// Verify we can send notifications without errors
|
||||
await client.SendNotificationAsync(NotificationMethods.RootsUpdatedNotification, cancellationToken: TestContext.Current.CancellationToken);
|
||||
await client.SendNotificationAsync("test/notification", new { test = true }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
await client.SendNotificationAsync("test/notification", new TestNotification { Test = true }, cancellationToken: TestContext.Current.CancellationToken, serializerOptions: JsonContext3.Default.Options);
|
||||
|
||||
// assert
|
||||
// no response to check, if no exception is thrown, it's a success
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
class TestNotification
|
||||
{
|
||||
public required bool Test { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CallTool_Stdio_MemoryServer()
|
||||
{
|
||||
|
|
@ -557,7 +564,7 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
|||
[
|
||||
new(NotificationMethods.LoggingMessageNotification, (notification, cancellationToken) =>
|
||||
{
|
||||
var loggingMessageNotificationParameters = JsonSerializer.Deserialize<LoggingMessageNotificationParams>(notification.Params);
|
||||
var loggingMessageNotificationParameters = JsonSerializer.Deserialize<LoggingMessageNotificationParams>(notification.Params, McpJsonUtilities.DefaultOptions);
|
||||
if (loggingMessageNotificationParameters is not null)
|
||||
{
|
||||
receivedNotification.TrySetResult(true);
|
||||
|
|
@ -574,4 +581,7 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
|||
// assert
|
||||
await receivedNotification.Task;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(TestNotification))]
|
||||
partial class JsonContext3 : JsonSerializerContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ using ModelContextProtocol.Protocol.Messages;
|
|||
using ModelContextProtocol.Protocol.Transport;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Channels;
|
||||
|
||||
|
|
@ -18,7 +20,7 @@ using System.Threading.Channels;
|
|||
|
||||
namespace ModelContextProtocol.Tests.Configuration;
|
||||
|
||||
public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
||||
public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
||||
{
|
||||
public McpServerBuilderExtensionsToolsTests(ITestOutputHelper testOutputHelper)
|
||||
: base(testOutputHelper)
|
||||
|
|
@ -47,7 +49,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
"""),
|
||||
""", McpJsonUtilities.DefaultOptions),
|
||||
}],
|
||||
};
|
||||
|
||||
|
|
@ -65,7 +67,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
"""),
|
||||
""", McpJsonUtilities.DefaultOptions),
|
||||
}],
|
||||
};
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
"""),
|
||||
""", McpJsonUtilities.DefaultOptions),
|
||||
}],
|
||||
};
|
||||
|
||||
|
|
@ -107,7 +109,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
throw new Exception($"Unknown tool '{request.Params?.Name}'");
|
||||
}
|
||||
})
|
||||
.WithTools<EchoTool>();
|
||||
.WithTools<EchoTool>(serializerOptions: JsonContext.Default.Options);
|
||||
|
||||
services.AddSingleton(new ObjectWithId());
|
||||
}
|
||||
|
|
@ -430,7 +432,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
public void Register_Tools_From_Current_Assembly()
|
||||
{
|
||||
ServiceCollection sc = new();
|
||||
sc.AddMcpServer().WithToolsFromAssembly();
|
||||
sc.AddMcpServer().WithToolsFromAssembly(serializerOptions: JsonContext.Default.Options);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "Echo");
|
||||
|
|
@ -446,17 +448,17 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
{
|
||||
sc.AddSingleton(new ComplexObject());
|
||||
}
|
||||
sc.AddMcpServer().WithTools(typeof(EchoTool));
|
||||
sc.AddMcpServer().WithTools([typeof(EchoTool)], JsonContext.Default.Options);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "EchoComplex");
|
||||
if (parameterInServices)
|
||||
{
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Contains("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.Contains("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -483,17 +485,17 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
break;
|
||||
}
|
||||
|
||||
sc.AddMcpServer().WithToolsFromAssembly();
|
||||
sc.AddMcpServer().WithToolsFromAssembly(serializerOptions: JsonContext.Default.Options);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "EchoComplex");
|
||||
if (lifetime is not null)
|
||||
{
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Contains("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.Contains("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,9 +528,9 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
{
|
||||
ServiceCollection sc = new();
|
||||
sc.AddMcpServer()
|
||||
.WithTools<EchoTool>()
|
||||
.WithTools<AnotherToolType>()
|
||||
.WithTools(typeof(ToolTypeWithNoAttribute));
|
||||
.WithTools<EchoTool>(serializerOptions: JsonContext.Default.Options)
|
||||
.WithTools<AnotherToolType>(serializerOptions: JsonContext.Default.Options)
|
||||
.WithTools([typeof(ToolTypeWithNoAttribute)], JsonContext.Default.Options);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "double_echo");
|
||||
|
|
@ -584,7 +586,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
ConcurrentQueue<ProgressNotification> notifications = new();
|
||||
await using (client.RegisterNotificationHandler(NotificationMethods.ProgressNotification, (notification, cancellationToken) =>
|
||||
{
|
||||
ProgressNotification pn = JsonSerializer.Deserialize<ProgressNotification>(notification.Params)!;
|
||||
ProgressNotification pn = JsonSerializer.Deserialize<ProgressNotification>(notification.Params, McpJsonUtilities.DefaultOptions)!;
|
||||
notifications.Enqueue(pn);
|
||||
return Task.CompletedTask;
|
||||
}))
|
||||
|
|
@ -598,7 +600,7 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
},
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Contains("done", JsonSerializer.Serialize(result));
|
||||
Assert.Contains("done", JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions));
|
||||
SpinWait.SpinUntil(() => notifications.Count == 10, TimeSpan.FromSeconds(10));
|
||||
}
|
||||
|
||||
|
|
@ -765,4 +767,16 @@ public class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString("N");
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(bool))]
|
||||
[JsonSerializable(typeof(int))]
|
||||
[JsonSerializable(typeof(long))]
|
||||
[JsonSerializable(typeof(double))]
|
||||
[JsonSerializable(typeof(string))]
|
||||
[JsonSerializable(typeof(DateTime))]
|
||||
[JsonSerializable(typeof(DateTimeOffset))]
|
||||
[JsonSerializable(typeof(ComplexObject))]
|
||||
[JsonSerializable(typeof(string[]))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
partial class JsonContext : JsonSerializerContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@ public static class McpJsonUtilitiesTests
|
|||
public static void DefaultOptions_UseReflectionWhenEnabled()
|
||||
{
|
||||
var options = McpJsonUtilities.DefaultOptions;
|
||||
bool isReflectionEnabled = JsonSerializer.IsReflectionEnabledByDefault;
|
||||
Type anonType = new { Id = 42 }.GetType();
|
||||
|
||||
Assert.True(isReflectionEnabled); // To be disabled once https://github.com/dotnet/extensions/pull/6241 is incorporated
|
||||
Assert.Equal(isReflectionEnabled, options.TryGetTypeInfo(anonType, out _));
|
||||
Assert.Equal(JsonSerializer.IsReflectionEnabledByDefault, options.TryGetTypeInfo(anonType, out _));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
<RootNamespace>ModelContextProtocol.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<!-- For better test coverage, only disable reflection in one of the targets -->
|
||||
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Without this, tests are currently not showing results until all tests complete
|
||||
https://xunit.net/docs/getting-started/v3/microsoft-testing-platform
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Protocol;
|
||||
|
|
@ -57,7 +58,7 @@ public static class ProtocolTypeTests
|
|||
[InlineData(Role.Assistant, "\"assistant\"")]
|
||||
public static void SerializeRole_ShouldBeCamelCased(Role role, string expectedValue)
|
||||
{
|
||||
var actualValue = JsonSerializer.Serialize(role);
|
||||
var actualValue = JsonSerializer.Serialize(role, McpJsonUtilities.DefaultOptions);
|
||||
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
|
@ -73,7 +74,7 @@ public static class ProtocolTypeTests
|
|||
[InlineData(LoggingLevel.Emergency, "\"emergency\"")]
|
||||
public static void SerializeLoggingLevel_ShouldBeCamelCased(LoggingLevel level, string expectedValue)
|
||||
{
|
||||
var actualValue = JsonSerializer.Serialize(level);
|
||||
var actualValue = JsonSerializer.Serialize(level, McpJsonUtilities.DefaultOptions);
|
||||
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
|
@ -84,7 +85,7 @@ public static class ProtocolTypeTests
|
|||
[InlineData(ContextInclusion.AllServers, "\"allServers\"")]
|
||||
public static void ContextInclusion_ShouldBeCamelCased(ContextInclusion level, string expectedValue)
|
||||
{
|
||||
var actualValue = JsonSerializer.Serialize(level);
|
||||
var actualValue = JsonSerializer.Serialize(level, McpJsonUtilities.DefaultOptions);
|
||||
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Protocol;
|
||||
|
|
@ -10,14 +11,14 @@ public class RequestIdTests
|
|||
{
|
||||
RequestId id = new("test-id");
|
||||
Assert.Equal("test-id", id.ToString());
|
||||
Assert.Equal("\"test-id\"", JsonSerializer.Serialize(id));
|
||||
Assert.Equal("\"test-id\"", JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions));
|
||||
Assert.Same("test-id", id.Id);
|
||||
|
||||
Assert.True(id.Equals(new("test-id")));
|
||||
Assert.False(id.Equals(new("tEst-id")));
|
||||
Assert.Equal("test-id".GetHashCode(), id.GetHashCode());
|
||||
|
||||
Assert.Equal(id, JsonSerializer.Deserialize<RequestId>(JsonSerializer.Serialize(id)));
|
||||
Assert.Equal(id, JsonSerializer.Deserialize<RequestId>(JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions), McpJsonUtilities.DefaultOptions));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -25,7 +26,7 @@ public class RequestIdTests
|
|||
{
|
||||
RequestId id = new(42);
|
||||
Assert.Equal("42", id.ToString());
|
||||
Assert.Equal("42", JsonSerializer.Serialize(id));
|
||||
Assert.Equal("42", JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions));
|
||||
Assert.Equal(42, Assert.IsType<long>(id.Id));
|
||||
|
||||
Assert.True(id.Equals(new(42)));
|
||||
|
|
@ -33,6 +34,6 @@ public class RequestIdTests
|
|||
Assert.False(id.Equals(new("42")));
|
||||
Assert.Equal(42L.GetHashCode(), id.GetHashCode());
|
||||
|
||||
Assert.Equal(id, JsonSerializer.Deserialize<RequestId>(JsonSerializer.Serialize(id)));
|
||||
Assert.Equal(id, JsonSerializer.Deserialize<RequestId>(JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions), McpJsonUtilities.DefaultOptions));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using ModelContextProtocol.Protocol.Messages;
|
|||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Tests.Utils;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
|
@ -185,7 +186,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<InitializeResult>(response);
|
||||
var result = JsonSerializer.Deserialize<InitializeResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("ModelContextProtocol.Tests", result.ServerInfo.Name);
|
||||
Assert.Equal("1.0.0.0", result.ServerInfo.Version);
|
||||
|
|
@ -217,7 +218,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<CompleteResult>(response);
|
||||
var result = JsonSerializer.Deserialize<CompleteResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result?.Completion);
|
||||
Assert.Equal(["test"], result.Completion.Values);
|
||||
Assert.Equal(2, result.Completion.Total);
|
||||
|
|
@ -254,7 +255,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<ListResourceTemplatesResult>(response);
|
||||
var result = JsonSerializer.Deserialize<ListResourceTemplatesResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result?.ResourceTemplates);
|
||||
Assert.NotEmpty(result.ResourceTemplates);
|
||||
Assert.Equal("test", result.ResourceTemplates[0].UriTemplate);
|
||||
|
|
@ -283,7 +284,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<ListResourcesResult>(response);
|
||||
var result = JsonSerializer.Deserialize<ListResourcesResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result?.Resources);
|
||||
Assert.NotEmpty(result.Resources);
|
||||
Assert.Equal("test", result.Resources[0].Uri);
|
||||
|
|
@ -318,7 +319,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<ReadResourceResult>(response);
|
||||
var result = JsonSerializer.Deserialize<ReadResourceResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result?.Contents);
|
||||
Assert.NotEmpty(result.Contents);
|
||||
|
||||
|
|
@ -355,7 +356,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<ListPromptsResult>(response);
|
||||
var result = JsonSerializer.Deserialize<ListPromptsResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result?.Prompts);
|
||||
Assert.NotEmpty(result.Prompts);
|
||||
Assert.Equal("test", result.Prompts[0].Name);
|
||||
|
|
@ -384,7 +385,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<GetPromptResult>(response);
|
||||
var result = JsonSerializer.Deserialize<GetPromptResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("test", result.Description);
|
||||
});
|
||||
|
|
@ -418,7 +419,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<ListToolsResult>(response);
|
||||
var result = JsonSerializer.Deserialize<ListToolsResult>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(result.Tools);
|
||||
Assert.Equal("test", result.Tools[0].Name);
|
||||
|
|
@ -453,7 +454,7 @@ public class McpServerTests : LoggedTest
|
|||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<CallToolResponse>(response);
|
||||
var result = JsonSerializer.Deserialize<CallToolResponse>(response, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(result.Content);
|
||||
Assert.Equal("test", result.Content[0].Text);
|
||||
|
|
@ -581,7 +582,7 @@ public class McpServerTests : LoggedTest
|
|||
|
||||
public Task<JsonRpcResponse> SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
CreateMessageRequestParams? rp = JsonSerializer.Deserialize<CreateMessageRequestParams>(request.Params);
|
||||
CreateMessageRequestParams? rp = JsonSerializer.Deserialize<CreateMessageRequestParams>(request.Params, McpJsonUtilities.DefaultOptions);
|
||||
|
||||
Assert.NotNull(rp);
|
||||
Assert.Equal(0.75f, rp.Temperature);
|
||||
|
|
@ -608,7 +609,7 @@ public class McpServerTests : LoggedTest
|
|||
return Task.FromResult(new JsonRpcResponse
|
||||
{
|
||||
Id = new RequestId("0"),
|
||||
Result = JsonSerializer.SerializeToNode(result),
|
||||
Result = JsonSerializer.SerializeToNode(result, McpJsonUtilities.DefaultOptions),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -658,11 +659,11 @@ public class McpServerTests : LoggedTest
|
|||
Total = 100,
|
||||
Message = "Progress message",
|
||||
},
|
||||
}),
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
}, TestContext.Current.CancellationToken);
|
||||
|
||||
var notification = await notificationReceived.Task;
|
||||
var progress = JsonSerializer.Deserialize<ProgressNotification>(notification.Params);
|
||||
var progress = JsonSerializer.Deserialize<ProgressNotification>(notification.Params, McpJsonUtilities.DefaultOptions);
|
||||
Assert.NotNull(progress);
|
||||
Assert.Equal("abc", progress.ProgressToken.ToString());
|
||||
Assert.Equal(50, progress.Progress.Progress);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using Moq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
|
@ -9,7 +10,7 @@ using System.Text.Json.Serialization;
|
|||
|
||||
namespace ModelContextProtocol.Tests.Server;
|
||||
|
||||
public class McpServerToolTests
|
||||
public partial class McpServerToolTests
|
||||
{
|
||||
[Fact]
|
||||
public void Create_InvalidArgs_Throws()
|
||||
|
|
@ -36,7 +37,7 @@ public class McpServerToolTests
|
|||
return "42";
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("server", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.DoesNotContain("server", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, McpJsonUtilities.DefaultOptions));
|
||||
|
||||
var result = await tool.InvokeAsync(
|
||||
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
|
||||
|
|
@ -86,7 +87,7 @@ public class McpServerToolTests
|
|||
|
||||
McpServerTool tool = services.GetRequiredService<McpServerTool>();
|
||||
|
||||
Assert.DoesNotContain("actualMyService", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema));
|
||||
Assert.DoesNotContain("actualMyService", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, McpJsonUtilities.DefaultOptions));
|
||||
|
||||
Mock<IMcpServer> mockServer = new();
|
||||
|
||||
|
|
@ -127,9 +128,11 @@ public class McpServerToolTests
|
|||
[Fact]
|
||||
public async Task SupportsDisposingInstantiatedDisposableTargets()
|
||||
{
|
||||
McpServerToolCreateOptions options = new() { SerializerOptions = JsonContext2.Default.Options };
|
||||
McpServerTool tool1 = McpServerTool.Create(
|
||||
typeof(DisposableToolType).GetMethod(nameof(DisposableToolType.InstanceMethod))!,
|
||||
typeof(DisposableToolType));
|
||||
typeof(DisposableToolType),
|
||||
options);
|
||||
|
||||
var result = await tool1.InvokeAsync(
|
||||
new RequestContext<CallToolRequestParams>(null!, null),
|
||||
|
|
@ -140,9 +143,11 @@ public class McpServerToolTests
|
|||
[Fact]
|
||||
public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableTargets()
|
||||
{
|
||||
McpServerToolCreateOptions options = new() { SerializerOptions = JsonContext2.Default.Options };
|
||||
McpServerTool tool1 = McpServerTool.Create(
|
||||
typeof(AsyncDisposableToolType).GetMethod(nameof(AsyncDisposableToolType.InstanceMethod))!,
|
||||
typeof(AsyncDisposableToolType));
|
||||
typeof(AsyncDisposableToolType),
|
||||
options);
|
||||
|
||||
var result = await tool1.InvokeAsync(
|
||||
new RequestContext<CallToolRequestParams>(null!, null),
|
||||
|
|
@ -153,9 +158,11 @@ public class McpServerToolTests
|
|||
[Fact]
|
||||
public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableAndDisposableTargets()
|
||||
{
|
||||
McpServerToolCreateOptions options = new() { SerializerOptions = JsonContext2.Default.Options };
|
||||
McpServerTool tool1 = McpServerTool.Create(
|
||||
typeof(AsyncDisposableAndDisposableToolType).GetMethod(nameof(AsyncDisposableAndDisposableToolType.InstanceMethod))!,
|
||||
typeof(AsyncDisposableAndDisposableToolType));
|
||||
typeof(AsyncDisposableAndDisposableToolType),
|
||||
options);
|
||||
|
||||
var result = await tool1.InvokeAsync(
|
||||
new RequestContext<CallToolRequestParams>(null!, null),
|
||||
|
|
@ -432,4 +439,10 @@ public class McpServerToolTests
|
|||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
|
||||
[JsonSerializable(typeof(DisposableToolType))]
|
||||
[JsonSerializable(typeof(AsyncDisposableToolType))]
|
||||
[JsonSerializable(typeof(AsyncDisposableAndDisposableToolType))]
|
||||
partial class JsonContext2 : JsonSerializerContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ public class StdioServerTransportTests : LoggedTest
|
|||
var chineseResult = Encoding.UTF8.GetString(output.ToArray()).Trim();
|
||||
var expectedChinese = JsonSerializer.Serialize(chineseMessage, McpJsonUtilities.DefaultOptions);
|
||||
Assert.Equal(expectedChinese, chineseResult);
|
||||
Assert.Contains(JsonSerializer.Serialize(chineseText), chineseResult);
|
||||
Assert.Contains(JsonSerializer.Serialize(chineseText, McpJsonUtilities.DefaultOptions), chineseResult);
|
||||
|
||||
// Test 2: Emoji (non-BMP Unicode using surrogate pairs)
|
||||
var emojiText = "🔍 🚀 👍"; // Magnifying glass, rocket, thumbs up
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Protocol.Transport;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Channels;
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ public class TestServerTransport : ITransport
|
|||
Result = JsonSerializer.SerializeToNode(new ListRootsResult
|
||||
{
|
||||
Roots = []
|
||||
}),
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ public class TestServerTransport : ITransport
|
|||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = new(), Model = "model", Role = Role.User }),
|
||||
Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = new(), Model = "model", Role = Role.User }, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue