diff --git a/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs b/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs index bb96356b3..891408d01 100644 --- a/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs +++ b/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.DependencyInjection; @@ -39,7 +40,7 @@ public static IEndpointConventionBuilder MapMcp(this IEndpointRouteBuilder endpo var requestAborted = context.RequestAborted; response.Headers.ContentType = "text/event-stream"; - response.Headers.CacheControl = "no-store"; + response.Headers.CacheControl = "no-cache,no-store"; var sessionId = MakeNewSessionId(); await using var transport = new SseResponseStreamTransport(response.Body, $"/message?sessionId={sessionId}"); @@ -50,6 +51,10 @@ public static IEndpointConventionBuilder MapMcp(this IEndpointRouteBuilder endpo try { + // Make sure we disable all response buffering for SSE + context.Response.Headers.ContentEncoding = "identity"; + context.Features.GetRequiredFeature().DisableBuffering(); + var transportTask = transport.RunAsync(cancellationToken: requestAborted); await using var server = McpServerFactory.Create(transport, mcpServerOptions.Value, loggerFactory, endpoints.ServiceProvider); diff --git a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs index b73a9c06e..5dffad9e9 100644 --- a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs +++ b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs @@ -280,6 +280,21 @@ public async Task CallTool_Sse_EchoServer_Concurrently() } } + [Fact] + public async Task EventSourceResponse_Includes_ExpectedHeaders() + { + using var httpClient = GetHttpClient(); + using var sseResponse = await httpClient.GetAsync("", HttpCompletionOption.ResponseHeadersRead, TestContext.Current.CancellationToken); + + sseResponse.EnsureSuccessStatusCode(); + + Assert.Equal("text/event-stream", sseResponse.Content.Headers.ContentType?.MediaType); + Assert.Equal("identity", sseResponse.Content.Headers.ContentEncoding.ToString()); + Assert.NotNull(sseResponse.Headers.CacheControl); + Assert.True(sseResponse.Headers.CacheControl.NoStore); + Assert.True(sseResponse.Headers.CacheControl.NoCache); + } + [Fact] public async Task EventSourceStream_Includes_MessageEventType() {