From f9dec13660fb7052cf65bff4e72d85945d38615c Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 29 Jan 2026 23:04:51 -0500 Subject: [PATCH] Fix race condition in SSE GET request initialization (#1212) --- .../StreamableHttpHandler.cs | 5 ----- .../Server/StreamableHttpServerTransport.cs | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs b/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs index 6e11b9b..c50e513 100644 --- a/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs +++ b/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs @@ -154,11 +154,6 @@ internal sealed class StreamableHttpHandler( { await using var _ = await session.AcquireReferenceAsync(cancellationToken); InitializeSseResponse(context); - - // We should flush headers to indicate a 200 success quickly, because the initialization response - // will be sent in response to a different POST request. It might be a while before we send a message - // over this response body. - await context.Response.Body.FlushAsync(cancellationToken); await session.Transport.HandleGetRequestAsync(context.Response.Body, cancellationToken); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) diff --git a/src/ModelContextProtocol.Core/Server/StreamableHttpServerTransport.cs b/src/ModelContextProtocol.Core/Server/StreamableHttpServerTransport.cs index 6307726..55b6650 100644 --- a/src/ModelContextProtocol.Core/Server/StreamableHttpServerTransport.cs +++ b/src/ModelContextProtocol.Core/Server/StreamableHttpServerTransport.cs @@ -125,6 +125,12 @@ public sealed class StreamableHttpServerTransport : ITransport var primingItem = await _storeSseWriter.WriteEventAsync(SseItem.Prime(), cancellationToken).ConfigureAwait(false); await _httpSseWriter.WriteAsync(primingItem, cancellationToken).ConfigureAwait(false); } + else + { + // If there's no priming write, flush the stream to ensure HTTP response headers are + // sent to the client now that the transport is ready to accept messages via SendMessageAsync. + await sseResponseStream.FlushAsync(cancellationToken).ConfigureAwait(false); + } } // Wait for the response to be written before returning from the handler.