diff --git a/samples/AspNetCoreSseServer/Properties/launchSettings.json b/samples/AspNetCoreSseServer/Properties/launchSettings.json index d1d337072..3b6f145d2 100644 --- a/samples/AspNetCoreSseServer/Properties/launchSettings.json +++ b/samples/AspNetCoreSseServer/Properties/launchSettings.json @@ -4,7 +4,6 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, "applicationUrl": "http://localhost:3001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -13,7 +12,6 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, "applicationUrl": "https://localhost:7133;http://localhost:3001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs b/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs index b0ba472cb..c556db63c 100644 --- a/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs +++ b/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using ModelContextProtocol.Hosting; using ModelContextProtocol.Protocol.Transport; @@ -348,17 +349,8 @@ public static IMcpServerBuilder WithStdioServerTransport(this IMcpServerBuilder { Throw.IfNull(builder); + AddSingleSessionServerDependencies(builder.Services); builder.Services.AddSingleton(); - builder.Services.AddHostedService(); - - builder.Services.AddSingleton(services => - { - ITransport serverTransport = services.GetRequiredService(); - IOptions options = services.GetRequiredService>(); - ILoggerFactory? loggerFactory = services.GetService(); - - return McpServerFactory.Create(serverTransport, options.Value, loggerFactory, services); - }); return builder; } @@ -378,19 +370,22 @@ public static IMcpServerBuilder WithStreamServerTransport( Throw.IfNull(inputStream); Throw.IfNull(outputStream); + AddSingleSessionServerDependencies(builder.Services); builder.Services.AddSingleton(new StreamServerTransport(inputStream, outputStream)); - builder.Services.AddHostedService(); - builder.Services.AddSingleton(services => + return builder; + } + + private static void AddSingleSessionServerDependencies(IServiceCollection services) + { + services.AddHostedService(); + services.TryAddSingleton(services => { ITransport serverTransport = services.GetRequiredService(); IOptions options = services.GetRequiredService>(); ILoggerFactory? loggerFactory = services.GetService(); - return McpServerFactory.Create(serverTransport, options.Value, loggerFactory, services); }); - - return builder; } #endregion } diff --git a/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs b/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs index 8fe8e91c1..63b86a4a6 100644 --- a/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs +++ b/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs @@ -148,7 +148,7 @@ public async Task SendMessageAsync_Handles_Accepted_Json_RPC_Response() var eventSourcePipe = new Pipe(); var eventSourceData = "event: endpoint\r\ndata: /sseendpoint\r\n\r\n"u8; - Assert.True(eventSourceData.TryCopyTo(eventSourcePipe.Writer.GetSpan())); + eventSourceData.CopyTo(eventSourcePipe.Writer.GetSpan(eventSourceData.Length)); eventSourcePipe.Writer.Advance(eventSourceData.Length); await eventSourcePipe.Writer.FlushAsync(TestContext.Current.CancellationToken); diff --git a/tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs b/tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs index d641d8760..d0f1036d1 100644 --- a/tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs +++ b/tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs @@ -43,9 +43,10 @@ public override ValueTask DisposeAsync() // completes the other half of these pipes. _serverToClientPipe.Writer.Complete(); _serverToClientPipe.Reader.Complete(); - // Disposing the CTS without waiting for the client would be problematic - // except we always dispose the HttpClient before Kestrel in our tests. - _connectionClosedCts.Dispose(); + + // Don't bother disposing the _connectionClosedCts, since this is just for testing, + // and it's annoying to synchronize with DuplexStream. + return base.DisposeAsync(); }