Require the Mcp-Method header on the modern path - #492
Merged
koic merged 1 commit intoAug 8, 2026
Merged
Conversation
## Motivation and Context The modern Streamable HTTP path validated the SEP-2243 mirror headers only when present: an absent `Mcp-Method` or `Mcp-Name` was silently tolerated. The 2026-07-28 specification requires `Mcp-Method` on every request and `Mcp-Name` on `tools/call`, `resources/read`, and `prompts/get`, and lists a missing required standard header among the validation failures a server MUST reject; the TypeScript SDK enforces presence with `-32020` the same way. Tolerating absence also defeats the headers' purpose silently: they exist so intermediaries can route and inspect requests without parsing bodies. A modern POST without `Mcp-Method`, or a name-bearing modern POST whose body carries a target name without `Mcp-Name`, now answers HTTP 400 with `-32020` naming the missing header, exactly like a mismatch. `Mcp-Name` stays unrequired when the body carries no target name, matching the TypeScript SDK. The bundled `MCP::Client::HTTP` already sends both headers on every modern request, so SDK-to-SDK traffic is unaffected. ## How Has This Been Tested? New tests in `test/mcp/server/transports/streamable_http_transport_test.rb` cover the missing `Mcp-Method` and missing `Mcp-Name` rejections, asserting the `-32020` code and the header name in the message. The `modern_rack_request` helper now mirrors a conforming client by deriving `Mcp-Method` from the body (with `method_header: nil` to omit it), so the existing modern-path tests exercise the requirement on every request. ## Breaking Changes None for conforming clients, which must already send these headers. Hand-rolled modern clients that omitted them are now rejected with `-32020` instead of being served; add the headers, or use the legacy lifecycle, to proceed.
atesgoral
approved these changes
Aug 7, 2026
9 tasks
koic
added a commit
that referenced
this pull request
Aug 8, 2026
## Motivation and Context #490 and #492 merged independently green but broke each other on main: #492 made the modern path reject a name-bearing POST whose body carries a target name without `Mcp-Name` (-32020, HTTP 400) and taught the `modern_rack_request` helper to derive `Mcp-Method` from the body, while #490, merged in between, added five modern `tools/call` tests that build their requests through that helper and therefore send no `Mcp-Name`. Since the #492 merge every CI run on main fails those five tests with 400 where 200 is expected; the library behavior itself is correct. The helper now derives `Mcp-Name` the same way it derives `Mcp-Method`: from `params.name` or `params.uri` when the body's method is one of the name-bearing three. That is what a conforming client sends per the 2026-07-28 specification, and what the TypeScript SDK's client, the bundled `MCP::Client::HTTP`, and the conformance harness's standard headers all do, so tests built through the helper model a compliant client by default. `name_header: nil` omits the header for tests of the requirement itself, symmetric with `method_header: nil`, and an explicit `headers:` entry still overrides the derived value, which keeps the base64 mismatch tests exercising their divergent names. ## How Has This Been Tested? The five failing tests pass again without being touched, and the #492 requirement tests (missing `Mcp-Method`, missing `Mcp-Name`, header mismatches, base64 decoding) still pass: the transport test file reports 217 runs with zero failures. `bundle exec rake` is green, including RuboCop and the `--requirements 2025-11-25` conformance baseline. ## Breaking Changes None. The change is confined to a test helper; the shipped gem is untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
The modern Streamable HTTP path validated the SEP-2243 mirror headers only when present: an absent
Mcp-MethodorMcp-Namewas silently tolerated. The 2026-07-28 specification requiresMcp-Methodon every request andMcp-Nameontools/call,resources/read, andprompts/get, and lists a missing required standard header among the validation failures a server MUST reject; the TypeScript SDK enforces presence with-32020the same way. Tolerating absence also defeats the headers' purpose silently: they exist so intermediaries can route and inspect requests without parsing bodies.A modern POST without
Mcp-Method, or a name-bearing modern POST whose body carries a target name withoutMcp-Name, now answers HTTP 400 with-32020naming the missing header, exactly like a mismatch.Mcp-Namestays unrequired when the body carries no target name, matching the TypeScript SDK. The bundledMCP::Client::HTTPalready sends both headers on every modern request, so SDK-to-SDK traffic is unaffected.How Has This Been Tested?
New tests in
test/mcp/server/transports/streamable_http_transport_test.rbcover the missingMcp-Methodand missingMcp-Namerejections, asserting the-32020code and the header name in the message. Themodern_rack_requesthelper now mirrors a conforming client by derivingMcp-Methodfrom the body (withmethod_header: nilto omit it), so the existing modern-path tests exercise the requirement on every request.Breaking Changes
None for conforming clients, which must already send these headers. Hand-rolled modern clients that omitted them are now rejected with
-32020instead of being served; add the headers, or use the legacy lifecycle, to proceed.Types of changes
Checklist