Repository navigation
Conversation
A session is optional in the handshake era, but the SDK always created one on initialize and refused every later request without it. So a horizontally scaled server had to share a session store and lock only to serve those clients. Builder::withoutSessions() answers initialize without an Mcp-Session-Id, serves every later request on a session of its own, and answers GET and DELETE with 405. Requests to the client fail right away, as their answer cannot be matched without a session. Off by default; stdio and the 2026-07-28 era are not affected.
ruudk
requested review from
CodeWithKyrian,
Nyholm,
chr-hertel and
soyuka
as code owners
October 31, 2026 13:00
This branch has not been deployed
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 #644.
A session is optional in the handshake era: a server "MAY assign a session ID at initialization time". The SDK always creates one on
initializeand refuses every later request without it, so a horizontally scaled server has to share a session store and lock only to serve handshake-era clients.Builder::withoutSessions()turns that off for Streamable HTTP:initializeis answered withoutMcp-Session-Id, and a session id the client sends anyway is ignored;GETandDELETEare answered with405, which the spec allows for a server without a stream and for one that does not let clients end sessions.Requests to the client (elicitation, sampling,
roots/list) fail right away in this mode, since the client answers them in a POST of its own that cannot be matched without a session. Progress and other notifications sent during a request still reach the client. The TypeScript SDK serves handshake-era traffic the same way withsessionIdGenerator: undefined.The option is off by default, so existing servers behave exactly as before. The only API additions are
Builder::withoutSessions(), a trailing optional$sessionlessargument onProtocol::__construct()and an@internalStreamableHttpTransport::setSessionless(). stdio and the2026-07-28era are not affected.