Skip to content

fix(server): serve draft-version requests statelessly per SEP-2567#999

Merged
DaleSeo merged 4 commits into
mainfrom
alexhancock/sep-2567
Jul 20, 2026
Merged

fix(server): serve draft-version requests statelessly per SEP-2567#999
DaleSeo merged 4 commits into
mainfrom
alexhancock/sep-2567

Conversation

@alexhancock

Copy link
Copy Markdown
Contributor

Motivation and Context

Per modelcontextprotocol/modelcontextprotocol#2567 protocol-level sessions (and the Mcp-Session-Id header) are removed from the Streamable HTTP transport as of the draft protocol version (2026-07-28); servers speaking that version MUST serve requests statelessly.

The rust-sdk server assigned an Mcp-Session-Id in its default stateful_mode even when the negotiated protocol version was 2026-07-28. This gates the session code path on the negotiated version: sessions are used only for pre-draft versions (< 2026-07-28), and draft-version requests are served statelessly even in stateful_mode. Older versions retain full session behavior.

How Has This Been Tested?

No dedicated SEP-2567 conformance scenario exists (the conformance PR that would add one was closed unmerged); per the maintainer, every existing draft (2026-07-28) scenario already sends sessionless requests. Verified against the existing draft server suite:

cargo build -p mcp-conformance
STATELESS= ./target/debug/conformance-server &   # default stateful_mode
npx -y @modelcontextprotocol/conformance@0.2.0-alpha.9 server --url http://127.0.0.1:8001/mcp --suite draft -o results

The default (stateful) server now produces results byte-for-byte identical to an explicit stateless server (48 passed / 31 failed; the 31 remaining failures are pre-existing SEP-2575 server/discover gaps, out of scope). rmcp lib unit tests (232) and streamable-HTTP integration tests (session store, stale session, protocol version, JSON response — 19) pass locally.

Breaking Changes

None. The session code path is unchanged for all pre-2026-07-28 versions; only the draft version changes behavior, bringing it into spec compliance.

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

SEP-2575 (also in progress) removes the initialize handshake for the draft version. Once that lands, the version detection here can be simplified to a lifecycle check (an initialize request implies the pre-draft/stateful lifecycle; draft requests never carry initialize).

@alexhancock
alexhancock requested a review from a team as a code owner July 16, 2026 18:35
@github-actions github-actions Bot added T-core Core library changes T-transport Transport layer changes labels Jul 16, 2026
Comment thread crates/rmcp/src/transport/streamable_http_server/tower.rs Outdated
Comment thread crates/rmcp/src/transport/streamable_http_server/tower.rs
Comment thread crates/rmcp/src/transport/streamable_http_server/tower.rs
@alexhancock
alexhancock force-pushed the alexhancock/sep-2567 branch from 78e4e11 to d27b509 Compare July 17, 2026 17:56
@github-actions github-actions Bot added T-documentation Documentation improvements T-test Testing related changes labels Jul 17, 2026
Comment thread crates/rmcp/src/transport/streamable_http_server/tower.rs Outdated
Comment thread crates/rmcp/src/transport/streamable_http_server/tower.rs Outdated
pub sse_retry: Option<Duration>,
/// If true, the server will create a session for each request and keep it alive.
/// When enabled, SSE priming events are sent to enable client reconnection.
pub stateful_mode: bool,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a breaking change, the commit message should contains ! to pass CI like refactor!: rename stateful_mode to legacy_session_mode.

@DaleSeo DaleSeo linked an issue Jul 18, 2026 that may be closed by this pull request
5 tasks
@alexhancock
alexhancock force-pushed the alexhancock/sep-2567 branch from 754929b to d6eb140 Compare July 20, 2026 17:44
@alexhancock
alexhancock requested a review from DaleSeo July 20, 2026 17:54
@DaleSeo
DaleSeo merged commit a5bb51c into main Jul 20, 2026
21 checks passed
@DaleSeo
DaleSeo deleted the alexhancock/sep-2567 branch July 20, 2026 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-core Core library changes T-documentation Documentation improvements T-test Testing related changes T-transport Transport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement SEP-2567: Sessionless MCP via Explicit State Handles

2 participants