Repository navigation
mcp: clear the caller's protocol version for the initialize handshake - #1165
Merged
guglielmo-san merged 2 commits intoOct 27, 2026
Conversation
gwyszynski-sa
force-pushed
the
fix/initialize-protocol-version-header
branch
from
August 13, 2026 12:19
9017736 to
babfbb3
Compare
The legacy initialize handshake pins params.protocolVersion but sends no Mcp-Protocol-Version header of its own: setMCPHeaders finds c.initializedResult still nil, since it is assigned a few lines later, and the message carries no _meta.protocolVersion, so the header falls to the request context. For a standalone client that context is empty and the header is absent; for a process that is both a server and a client it holds that process's inbound version, which contradicts the body it accompanies. This is the client-side mirror of modelcontextprotocol#963. No version is negotiated at that point, so the request has none of its own to state, and the caller's must not stand in for one. Clears it for the initialize send rather than sending the proposed version: a header the peer does not support fails the handshake outright, where the body would have negotiated down. Standalone clients are unaffected, the header having already been absent there. The fake server asserted wantProtocolVersion for other methods but for none of its sixteen initialize cases. Asserts centrally that initialize carries no protocol version header, and adds a Connect whose context already holds one, without which that assertion cannot fail. Requests after negotiation are left unchecked there, since which source wins once initializedResult is set is modelcontextprotocol#1162. Fixes modelcontextprotocol#1164
gwyszynski-sa
force-pushed
the
fix/initialize-protocol-version-header
branch
from
August 24, 2026 19:51
babfbb3 to
80f70c5
Compare
guglielmo-san
approved these changes
Oct 27, 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.
The legacy initialize handshake pins params.protocolVersion but sends no
Mcp-Protocol-Version header of its own: setMCPHeaders finds c.initializedResult
still nil, since it is assigned a few lines later, and the message carries no
_meta.protocolVersion, so the header falls to the request context. For a
standalone client that context is empty and the header is absent; for a process
that is both a server and a client it holds that process's inbound version,
which contradicts the body it accompanies. This is the client-side mirror of
#963.
No version is negotiated at that point, so the request has none of its own to
state, and the caller's must not stand in for one. Clears it for the initialize
send rather than sending the proposed version: a header the peer does not
support fails the handshake outright, where the body would have negotiated down.
Standalone clients are unaffected, the header having already been absent there.
The fake server asserted wantProtocolVersion for other methods but for none of
its sixteen initialize cases. Asserts centrally that initialize carries no
protocol version header, and adds a Connect whose context already holds one,
without which that assertion cannot fail. Requests after negotiation are left
unchecked there, since which source wins once initializedResult is set is #1162.
Fixes #1164