typescript-sdk/.changeset/require-protocol-version-header-on-modern-post.md
David Pavlovschii 75dc7ea6e2
fix(server): reject a modern POST without the required MCP-Protocol-Version header (#2590)
Co-authored-by: Konstantin Konstantinov <konstantin@mach5technology.com>
Co-authored-by: Konstantin Konstantinov <KKonstantinov@users.noreply.github.com>
2026-08-17 09:31:47 +03:00

1.9 KiB

@modelcontextprotocol/core-internal @modelcontextprotocol/server
patch patch

Reject a modern (2026-07-28) POST that omits the required MCP-Protocol-Version header.

createMcpHandler accepted a request whose body carried a valid per-request _meta envelope but whose MCP-Protocol-Version header was absent: the request was classified modern, dispatched, and answered 200 — tool handlers ran. Only the mismatch case (header present, disagreeing with the body) was rejected, so of the standard headers SEP-2243 requires on a modern POST, presence was enforced for Mcp-Method (and for Mcp-Name on the methods that mirror params.name / params.uri) but not for MCP-Protocol-Version.

Such a request is now refused with 400 Bad Request and JSON-RPC -32020 (HeaderMismatch), matching the shape the sibling missing-header cells already emit and echoing the request id — per the Streamable HTTP spec, which requires the header on every POST and lists a missing required standard header as a HeaderMismatch failure. The spec's allowance to treat a header-less request as 2025-03-26 is available only to a server that also serves pre-2025-06-18 clients, and permits routing it to legacy handling — never serving it as 2026-07-28; under legacy: 'reject' the requirement is unconditional.

Era classification is deliberately unchanged and stays body-primary: a proxy that strips the header still must not change the era, so such a request is still classified modern and is refused one rung later, at standard-header-validation — the same rung that already answers a missing Mcp-Method. Legacy-era traffic is untouched, notifications are unaffected, body-less GET / DELETE session operations are method-routed before any header validation, and stdio serving (which has no HTTP headers) is not involved.

Clients built with this SDK always send the header, so no first-party client is affected; hand-rolled clients that omitted it must add it.