Repository navigation
Closed
Labels
2026-07-28All issues and PRs related to the spec release 2026-07-28All issues and PRs related to the spec release 2026-07-28ServerIssues & PRs related to the Server componentIssues & PRs related to the Server componentbreaking changeBreaking the Backwards Compatibility PromiseBreaking the Backwards Compatibility PromiseenhancementRequest for a new feature that's not currently supportedRequest for a new feature that's not currently supportedimproves spec complianceImproves consistency with other SDKs such as TyepScriptImproves consistency with other SDKs such as TyepScriptneeds designValid issue but needs maintainer alignment on design or approachValid issue but needs maintainer alignment on design or approach
Description
Implements SEP-2567 for the MCP Spec 2026-07-28 release.
Tracked by umbrella #334.
Spec summary
Removes protocol-level sessions: no
session/create, nosession/destroy, noMcp-Session-Idheader.tools/list/resources/list/prompts/listMUST NOT depend on per-connection or prior-call state — list endpoints become cacheable at(deployment, auth)granularity. Stateful workflows use server-minted opaque handles passed as parameters.
PHP SDK changes
src/Server/Session/*— entire directory becomes optional/internal-only.SessionManager,InMemorySessionStore,FileSessionStore,Psr16SessionStore,SessionInterface— keep for back-compat with old clients but cannot drive list responses.src/Server/Transport/StreamableHttpTransport.php— stop minting/requiringMcp-Session-Id; downgrade to optional legacy header.src/Capability/Registry/Registry.phpand allList*Handler.php— must produce identical results regardless of session. Audit handlers that read from$session->get(...).RequestContext— sessions become optional, not guaranteed.- Documentation (
docs/server-builder.md,docs/transports.md) — guide users toward stateless tool design with explicit handles.
Breaking change. Coordinate with deprecation policy (SEP-2596, umbrella #339).
Related
- SEP-2575 (umbrella [2026-07-28] Stateless Core overhaul #334) — stateless protocol overhaul
Metadata
Metadata
Assignees
Labels
2026-07-28All issues and PRs related to the spec release 2026-07-28All issues and PRs related to the spec release 2026-07-28ServerIssues & PRs related to the Server componentIssues & PRs related to the Server componentbreaking changeBreaking the Backwards Compatibility PromiseBreaking the Backwards Compatibility PromiseenhancementRequest for a new feature that's not currently supportedRequest for a new feature that's not currently supportedimproves spec complianceImproves consistency with other SDKs such as TyepScriptImproves consistency with other SDKs such as TyepScriptneeds designValid issue but needs maintainer alignment on design or approachValid issue but needs maintainer alignment on design or approach
Type
Projects
- StatusShow more project fieldsDone
Activity
DevkumarPatel commentedon Jul 7, 2026
Re: honoring session optionality under the current (2025-11-25) spec, ahead of the breaking 2026-07-28 work
This SEP scopes the sessionless work to the 2026-07-28 release as a coordinated breaking change. I'd like to flag that the current 2025-11-25 spec already makes session management optional (
MAY), yet the transport hard-requires it today — so there's a smaller, non-breaking slice worth considering independently.Current behaviour (mcp/sdk 0.6.0, Streamable HTTP):
Protocol::resolveSession()always mints a session oninitialize(calling$transport->setSessionId(...), soMcp-Session-Idis always emitted), and hard-rejects every non-initialize request that lacks a stored session:if (!$sessionId)→ 400 "A valid session id is REQUIRED for non-initialize requests."if (!$this->sessionManager->exists($id))→ 404 "Session not found or has expired."Per the 2025-11-25 spec, session management is entirely
MAY— a server is free not to issue a session id and to treat each POST independently. There's currently no supported way to run a spec-compliant stateless server with the SDK.Why it matters: many deployments are stateless by nature — serverless/FaaS, autoscaled multi-instance apps, and MCP servers that just wrap an existing REST API (auth + params on every request, no subscriptions, no server-initiated messages). Because each HTTP request is a separate PHP process, the current design forces a persistent cross-request (and cross-node) session store purely to satisfy a handshake the spec says is optional.
Proposed non-breaking slice: an opt-in
Server::builder()->stateless()(or->withoutSessions()) that, when enabled:setSessionId()oninitialize, so noMcp-Session-Idheader is emitted, andresolveSession(), skips the!$sessionId/!exists()rejections and uses an ephemeral per-request session.Stateful stays the default; statelessness becomes a one-liner. This is aligned with #341's direction (making
Mcp-Session-Idoptional and decoupling handlers from session state) but could land ahead of, and independently from, the breaking 2026-07-28 overhaul in #334.Current workaround (for reference): supplying a non-persistent
SessionStoreInterface(exists()→true,read()→ fresh state,write()/save()→ no-op) makes each request self-contained without a real store — but the server still emits an unusedMcp-Session-Idand it relies onresolveSession()'s exact internals rather than a supported mode.Would a non-breaking opt-in flag under the current spec be in scope here, or would you prefer it tracked as its own issue?
chr-hertel commentedon Aug 19, 2026
Implemented via #444, #455.
StatelessProtocol::handle()builds a fresh, throwaway session per request, so list-endpoint output can't depend on prior calls.