Use TryAddEnumerable for McpServerOptionsSetup (#252)
This commit is contained in:
parent
cae5dff318
commit
b3a5a82544
2 changed files with 53 additions and 1 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using ModelContextProtocol.Server;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ public static class McpServerServiceCollectionExtensions
|
|||
public static IMcpServerBuilder AddMcpServer(this IServiceCollection services, Action<McpServerOptions>? configureOptions = null)
|
||||
{
|
||||
services.AddOptions();
|
||||
services.AddTransient<IConfigureOptions<McpServerOptions>, McpServerOptionsSetup>();
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<McpServerOptions>, McpServerOptionsSetup>());
|
||||
if (configureOptions is not null)
|
||||
{
|
||||
services.Configure(configureOptions);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using ModelContextProtocol.Protocol.Transport;
|
|||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Tests.Utils;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using TestServerWithHosting.Tools;
|
||||
|
||||
namespace ModelContextProtocol.Tests;
|
||||
|
||||
|
|
@ -95,6 +96,56 @@ public class SseIntegrationTests(ITestOutputHelper outputHelper) : KestrelInMemo
|
|||
Assert.Equal("Hello from server!", message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddMcpServer_CanBeCalled_MultipleTimes()
|
||||
{
|
||||
var firstOptionsCallbackCallCount = 0;
|
||||
var secondOptionsCallbackCallCount = 0;
|
||||
|
||||
Builder.Services.AddMcpServer(options =>
|
||||
{
|
||||
Interlocked.Increment(ref firstOptionsCallbackCallCount);
|
||||
})
|
||||
.WithTools<EchoTool>();
|
||||
|
||||
Builder.Services.AddMcpServer(options =>
|
||||
{
|
||||
Interlocked.Increment(ref secondOptionsCallbackCallCount);
|
||||
})
|
||||
.WithTools<SampleLlmTool>();
|
||||
|
||||
|
||||
await using var app = Builder.Build();
|
||||
app.MapMcp();
|
||||
await app.StartAsync(TestContext.Current.CancellationToken);
|
||||
|
||||
using var httpClient = CreateHttpClient();
|
||||
await using var mcpClient = await ConnectMcpClient(httpClient);
|
||||
|
||||
// Options can be lazily initialized, but they must be instantiated by the time an MCP client can finish connecting.
|
||||
// Callbacks can be called multiple times if configureOptionsAsync is configured, because that uses the IOptionsFactory,
|
||||
// but that's not the case in this test.
|
||||
Assert.Equal(1, firstOptionsCallbackCallCount);
|
||||
Assert.Equal(1, secondOptionsCallbackCallCount);
|
||||
|
||||
var tools = await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, tools.Count);
|
||||
Assert.Contains(tools, tools => tools.Name == "Echo");
|
||||
Assert.Contains(tools, tools => tools.Name == "sampleLLM");
|
||||
|
||||
var echoResponse = await mcpClient.CallToolAsync(
|
||||
"Echo",
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["message"] = "from client!"
|
||||
},
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
var textContent = Assert.Single(echoResponse.Content, c => c.Type == "text");
|
||||
|
||||
Assert.Equal("hello from client!", textContent.Text);
|
||||
}
|
||||
|
||||
private static void MapAbsoluteEndpointUriMcp(IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
|
||||
|
|
|
|||
Loading…
Reference in a new issue