Support stateless MCP Streamable HTTP - #509
Merged
Merged
Conversation
imran-siddique
marked this pull request as ready for review
August 14, 2026 22:31
imran-siddique
pushed a commit
that referenced
this pull request
Aug 17, 2026
* fix(mcp): negotiate a handshake-era revision at initialize #509 replaced the hardcoded `2024-11-05` in the `initialize` result with `PROTOCOL_VERSION`, addressing "stop hardcoding the downstream protocol version" from #496. That constant is `2026-07-28`, the revision that removed `initialize` altogether, so the gateway answered every handshake by naming a protocol in which the request just made does not exist, and in which each later request must carry `_meta` plus the mirrored MCP-Protocol-Version / Mcp-Method headers a handshake-era client has no way to know it should send. Confirmed against every revision a real client offers: asked 2025-06-18, 2025-03-26 or 2024-11-05, the gateway answered 2026-07-28 in all three cases. The direction of the swap is the defect. PROTOCOL_VERSION is correct on the outbound leg, where the gateway is the client and #509 got it right, and wrong on the inbound one, where reaching `initialize` is itself proof the caller is handshake-era. Negotiate over _LEGACY_PROTOCOL_VERSIONS instead, echoing the client's request when the gateway speaks it. A client asking for 2026-07-28 at a handshake is deliberately not humoured. server.py no longer imports PROTOCOL_VERSION; #509 added that import solely for this misuse. Verified by mutation: reverting only the `initialize` line while keeping the new constant fails 9 of the 10 new tests. Full unit suite 1076 passed, with the 8 pre-existing agent_manifest SDK failures unchanged from main. Signed-off-by: Mohammed Zoheb Shaik <zoheb.shaik7@gmail.com> * fix(mcp): support 2025-11-25 and reject non-object initialize params Review feedback on #513. 1. _LEGACY_PROTOCOL_VERSIONS omitted 2025-11-25, the newest revision that still defines `initialize`. A client offering the latest handshake revision was therefore answered 2025-06-18. The lifecycle spec requires a server to echo a requested version it supports, and says a client that does not support the server's answer SHOULD disconnect, so a needless downgrade is the same class of defect this branch already fixes, one revision over. 2025-11-25 now heads the tuple. Echo and fallback are covered twice over. The parametrized echo test walks _LEGACY_PROTOCOL_VERSIONS, and two further tests name 2025-11-25 literally: one that it is echoed rather than downgraded, one that an unknown version falls back to it. The literal pair matters because a test parametrized over the constant under test loses its own case when that constant is wrong, which is exactly the regression being fixed. 2. test_unnegotiable_params_fall_back_to_the_newest_legacy_revision asserted that array-shaped `initialize` params negotiate successfully, turning an existing validation gap into an asserted contract. InitializeRequestParams is an object with required protocolVersion, capabilities and clientInfo, so a non-object is now rejected with -32600, matching how #500 already rejects non-object tools/call params. Absent params stays legal and negotiates the newest revision. The array case moves to a negative test alongside a string and an integer. Verified by mutation, each fix independently: dropping 2025-11-25 fails three tests, re-blessing non-object params fails three more. Full unit suite 1082 passed, with the 8 pre-existing agent_manifest SDK failures unchanged from main. Ruff and mypy clean. Signed-off-by: Mohammed Zoheb Shaik <zoheb.shaik7@gmail.com> --------- Signed-off-by: Mohammed Zoheb Shaik <zoheb.shaik7@gmail.com> Co-authored-by: Mohammed Zoheb Shaik <zoheb.shaik7@gmail.com>
This was referenced Aug 17, 2026
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.
Closes #496.
Implements the MCP 2026-07-28 stateless Streamable HTTP request contract for network upstreams: per-request protocol metadata, mirrored headers, JSON and request-scoped SSE responses, and x-mcp-header parameter mirroring. Invalid streams, content types, annotations, and unimplemented WebSocket catalogs fail closed.
The issue comment proposed initialize and Mcp-Session-Id, but those belong to 2025-era compatibility. The 2026-07-28 protocol explicitly removes both; this PR follows the current official contract and documents that decision.
Evidence: