Skip to content

fix: negotiate protocol version in handler#930

Open
actsalan wants to merge 2 commits into
modelcontextprotocol:mainfrom
actsalan:fix/protocol-version-negotiation
Open

fix: negotiate protocol version in handler#930
actsalan wants to merge 2 commits into
modelcontextprotocol:mainfrom
actsalan:fix/protocol-version-negotiation

Conversation

@actsalan

Copy link
Copy Markdown

Summary

Fixes #916 - ensures context.protocol_version() returns the negotiated version in all transports and modes.

Motivation and Context

Three related bugs existed in protocol version handling:

  1. Stateless HTTP: serve_directly passed None as peer_info, so context.protocol_version() was always None in handlers
  2. Stateful/stdio: serve_server negotiated the version in the initialize response but never updated peer_info to match, so handlers saw the client's raw requested version instead of the negotiated one
  3. Default handler: The default ServerHandler::initialize didn't apply negotiation logic, so the response could echo an unnegotiated version

How Has This Been Tested?

  • Added tests for both stdio (test_protocol_version_negotiation.rs) and stateless HTTP (test_stateless_protocol_version.rs) transports
  • Tests verify that all KNOWN_VERSIONS are correctly echoed back to clients
  • Tests verify that unknown versions fall back to LATEST
  • All existing tests continue to pass

Breaking Changes

None. This fix maintains backward compatibility while ensuring correct protocol version negotiation.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Changes made:

  • tower.rs: Reconstruct peer_info per-request from MCP-Protocol-Version header for stateless mode
  • service/server.rs: Update peer_info after negotiation so subsequent handlers see the negotiated version
  • handler/server.rs: Apply negotiate_protocol_version in default initialize response

@actsalan actsalan requested a review from a team as a code owner June 26, 2026 17:02
@github-actions github-actions Bot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-handler Handler implementation changes T-service Service layer changes T-transport Transport layer changes labels Jun 26, 2026
@actsalan actsalan force-pushed the fix/protocol-version-negotiation branch from 83708af to 0f12a96 Compare June 26, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-config Configuration file changes T-core Core library changes T-dependencies Dependencies related changes T-handler Handler implementation changes T-service Service layer changes T-test Testing related changes T-transport Transport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

streamable_http transport does not perform MCP protocol version negotiation

1 participant