@@ -26,28 +26,13 @@ internal sealed class StreamableHttpHandler(
2626 private const string McpProtocolVersionHeaderName = "MCP-Protocol-Version" ;
2727 private const string LastEventIdHeaderName = "Last-Event-ID" ;
2828
29- /// <summary>All protocol versions supported by this implementation.</summary>
30- private static readonly HashSet < string > s_supportedProtocolVersions =
31- [
32- "2024-11-05" ,
33- "2025-03-26" ,
34- "2025-06-18" ,
35- "2025-11-25" ,
36- ] ;
37-
3829 private static readonly JsonTypeInfo < JsonRpcMessage > s_messageTypeInfo = GetRequiredJsonTypeInfo < JsonRpcMessage > ( ) ;
3930 private static readonly JsonTypeInfo < JsonRpcError > s_errorTypeInfo = GetRequiredJsonTypeInfo < JsonRpcError > ( ) ;
4031
4132 public HttpServerTransportOptions HttpServerTransportOptions => httpServerTransportOptions . Value ;
4233
4334 public async Task HandlePostRequestAsync ( HttpContext context )
4435 {
45- if ( ! ValidateProtocolVersionHeader ( context , out var errorMessage ) )
46- {
47- await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
48- return ;
49- }
50-
5136 // The Streamable HTTP spec mandates the client MUST accept both application/json and text/event-stream.
5237 // ASP.NET Core Minimal APIs mostly try to stay out of the business of response content negotiation,
5338 // so we have to do this manually. The spec doesn't mandate that servers MUST reject these requests,
@@ -67,6 +52,12 @@ await WriteJsonRpcErrorAsync(context,
6752 return ;
6853 }
6954
55+ if ( ! ValidateProtocolVersionHeader ( context , session . Server , out var errorMessage ) )
56+ {
57+ await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
58+ return ;
59+ }
60+
7061 await using var _ = await session . AcquireReferenceAsync ( context . RequestAborted ) ;
7162
7263 var message = await ReadJsonRpcMessageAsync ( context ) ;
@@ -90,12 +81,6 @@ await WriteJsonRpcErrorAsync(context,
9081
9182 public async Task HandleGetRequestAsync ( HttpContext context )
9283 {
93- if ( ! ValidateProtocolVersionHeader ( context , out var errorMessage ) )
94- {
95- await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
96- return ;
97- }
98-
9984 if ( ! context . Request . GetTypedHeaders ( ) . Accept . Any ( MatchesTextEventStreamMediaType ) )
10085 {
10186 await WriteJsonRpcErrorAsync ( context ,
@@ -111,6 +96,12 @@ await WriteJsonRpcErrorAsync(context,
11196 return ;
11297 }
11398
99+ if ( ! ValidateProtocolVersionHeader ( context , session . Server , out var errorMessage ) )
100+ {
101+ await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
102+ return ;
103+ }
104+
114105 var lastEventId = context . Request . Headers [ LastEventIdHeaderName ] . ToString ( ) ;
115106 if ( ! string . IsNullOrEmpty ( lastEventId ) )
116107 {
@@ -193,15 +184,15 @@ private static async Task HandleResumePostResponseStreamAsync(HttpContext contex
193184
194185 public async Task HandleDeleteRequestAsync ( HttpContext context )
195186 {
196- if ( ! ValidateProtocolVersionHeader ( context , out var errorMessage ) )
197- {
198- await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
199- return ;
200- }
201-
202187 var sessionId = context . Request . Headers [ McpSessionIdHeaderName ] . ToString ( ) ;
203188 if ( sessionManager . TryRemove ( sessionId , out var session ) )
204189 {
190+ if ( ! ValidateProtocolVersionHeader ( context , session . Server , out var errorMessage ) )
191+ {
192+ await WriteJsonRpcErrorAsync ( context , errorMessage ! , StatusCodes . Status400BadRequest ) ;
193+ return ;
194+ }
195+
205196 await session . DisposeAsync ( ) ;
206197 }
207198 }
@@ -422,11 +413,11 @@ internal static Task RunSessionAsync(HttpContext httpContext, McpServer session,
422413 /// Validates the MCP-Protocol-Version header if present. A missing header is allowed for backwards compatibility,
423414 /// but an invalid or unsupported value must be rejected with 400 Bad Request per the MCP spec.
424415 /// </summary>
425- private static bool ValidateProtocolVersionHeader ( HttpContext context , out string ? errorMessage )
416+ private static bool ValidateProtocolVersionHeader ( HttpContext context , McpServer server , out string ? errorMessage )
426417 {
427418 var protocolVersionHeader = context . Request . Headers [ McpProtocolVersionHeaderName ] . ToString ( ) ;
428419 if ( ! string . IsNullOrEmpty ( protocolVersionHeader ) &&
429- ! s_supportedProtocolVersions . Contains ( protocolVersionHeader ) )
420+ ! server . SupportedProtocolVersions . Contains ( protocolVersionHeader ) )
430421 {
431422 errorMessage = $ "Bad Request: The MCP-Protocol-Version header value '{ protocolVersionHeader } ' is not supported.";
432423 return false ;
0 commit comments