@@ -244,6 +244,19 @@ export function shttpHandler(
244244 return jsonError ( 400 , - 32_700 , 'Parse error: Invalid JSON-RPC message' ) ;
245245 }
246246
247+ const requests = messages . filter ( m => isJSONRPCRequest ( m ) ) ;
248+
249+ // SEP-2243: reject if Mcp-Method/Mcp-Name headers (when present) don't match the body.
250+ // Runs BEFORE session.validate so a mismatched initialize cannot mint a session
251+ // (session.validate has side effects: it inserts the entry and fires onsessioninitialized).
252+ if ( ! isBatch && requests . length === 1 ) {
253+ const headerMismatch = validateMcpHeaders ( req , requests [ 0 ] ! ) ;
254+ if ( headerMismatch ) {
255+ onerror ?.( new Error ( headerMismatch ) ) ;
256+ return jsonError ( 400 , - 32_001 , `Bad Request: ${ headerMismatch } ` ) ;
257+ }
258+ }
259+
247260 let sessionId : string | undefined ;
248261 let isInitialize = false ;
249262 if ( session ) {
@@ -257,18 +270,6 @@ export function shttpHandler(
257270 if ( protoErr ) return protoErr ;
258271 }
259272
260- const requests = messages . filter ( m => isJSONRPCRequest ( m ) ) ;
261-
262- // SEP-2243: reject if Mcp-Method/Mcp-Name headers (when present) don't match the body.
263- // Prevents header/body source-of-truth split between intermediaries and the handler.
264- if ( ! isBatch && requests . length === 1 ) {
265- const headerMismatch = validateMcpHeaders ( req , requests [ 0 ] ! ) ;
266- if ( headerMismatch ) {
267- onerror ?.( new Error ( headerMismatch ) ) ;
268- return jsonError ( 400 , - 32_001 , `Bad Request: ${ headerMismatch } ` ) ;
269- }
270- }
271-
272273 const notifications = messages . filter ( m => isJSONRPCNotification ( m ) ) ;
273274 const responses = messages . filter (
274275 ( m ) : m is JSONRPCResultResponse | JSONRPCErrorResponse => isJSONRPCResultResponse ( m ) || isJSONRPCErrorResponse ( m )
0 commit comments