Skip to content

Implement SEP-2567: Sessionless MCP via Explicit State Handles #870

@alexhancock

Description

@alexhancock

SEP-2567: Sessionless MCP via Explicit State Handles — rust-sdk implementation

Spec PR: modelcontextprotocol/modelcontextprotocol#2567
Track: Specification · Stage: final · Priority: P0 · Theme: Transport Evolution and Scalability
Needs code changes: Yes (Large)

Summary

Removes protocol-level sessions, replacing implicit session-scoped state with explicit,
server-minted state handles. Builds on SEP-1442 (stateless-by-default) but argues the opt-in
stateful path should not exist at all.

What changes:

  • No session/create, session/destroy, or Mcp-Session-Id header.
  • tools/list / resources/list / prompts/list MUST NOT depend on per-connection or prior-tool-call state (so list endpoints become cacheable at (deployment, auth) granularity).
  • Stateful workflows use create_*() -> handle + threaded parameters (guidance, not a protocol construct).

Why this needs code changes in rust-sdk

The streamable HTTP transport mints and threads a session id today, but a disable path already
exists:

  • Server: StreamableHttpServerConfig.stateful_mode (default true); when false the server "disables sessions entirely (stateless mode)" per the doc comment, backed by the SessionManager/SessionStore trait (session.rs, with Local…/Never… stores and RestoreOutcome/SessionRestoreMarker). The session id rides on HEADER_SESSION_ID.
  • Client: streamable_http_client.rs carries session_id: Arc<str> through requests and SSE reconnects.
  • List handlers live behind service/server.rs + handler/server/router.rs.

So "no sessions" is partly reachable via stateful_mode = false. The remaining work is: making that
path the default/clean one for V_2026_07_28, ensuring list endpoints are state-independent, and
removing the client's hard dependency on a session id.

Proposed work

  • Ensure the stateful_mode = false server path neither requires nor emits HEADER_SESSION_ID, and verify the Never…-store path is the one selected.
  • Audit tools/list / resources/list / prompts/list handlers (handler/server/router.rs) so results don't depend on per-connection or prior-call state in the sessionless path (precondition for the SEP-2549 caching story).
  • Make the client's session_id optional (Option<Arc<str>>) so it can operate without one when the negotiated version is V_2026_07_28; keep sending it for older negotiated versions.
  • Keep HEADER_SESSION_ID handling for back-compat behind older protocol versions.
  • Add an example demonstrating the create_*() -> handle pattern (state handles are app-level, not a protocol construct).

Affected areas

transport/streamable_http_server/session.rs, transport/streamable_http_server/tower.rs,
transport/streamable_http_client.rs, service/server.rs, handler/server/router.rs.

Notes / risks

  • Overlaps heavily with SEP-2575. Treat as one transport-statelessness workstream; this SEP is the application-state half, 2575 is the handshake half.
  • Making client session_id optional touches several Arc<str> call sites in streamable_http_client.rs (reconnect/get-stream paths) — mechanical but broad.

Related existing issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High: significant functionality gap or spec violationT-coreCore library changesT-enhancementNew features and enhancementsT-transportTransport layer changes

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions