Skip to content

Commit d7884d6

Browse files
fix(shttpHandler): validate Mcp-Method/Mcp-Name headers before session.validate (mismatched initialize must not mint a session)
1 parent bac06cf commit d7884d6

1 file changed

Lines changed: 13 additions & 12 deletions

File tree

packages/server/src/server/shttpHandler.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)