SEP-2567: Sessionless MCP via Explicit State Handles changedseps/2567-sessionless-mcp
Upstream edited this page at 29 Jul 2026 22:46 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 28 Sep 2026 22:07 UTC.
Upstream edited
Recorded here
Lines+27added
Lines−27removed
From line
20
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits2to this page, all time
The whole hunk
from line 20, old and new numbered
/
from line 20
2020 requirements.
2121</Note>
2222
23| Field | Value |
24| ------------- | ------------------------------------------------------------------------------- |
25| **SEP** | 2567 |
26| **Title** | Sessionless MCP via Explicit State Handles |
27| **Status** | Final |
28| **Type** | Standards Track |
29| **Created** | 2026-03-11 |
30| **Author(s)** | Peter Alexander ([@pja-ant](https://github.com/pja-ant)) |
31| **Sponsor** | Peter Alexander ([@pja-ant](https://github.com/pja-ant)) |
32| **PR** | [#2567](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2567) |
23| Field | Value |
24| - | - |
25| **SEP** | 2567 |
26| **Title** | Sessionless MCP via Explicit State Handles |
27| **Status** | Final |
28| **Type** | Standards Track |
29| **Created** | 2026-03-11 |
30| **Author(s)** | Peter Alexander ([@pja-ant](https://github.com/pja-ant)) |
31| **Sponsor** | Peter Alexander ([@pja-ant](https://github.com/pja-ant)) |
32| **PR** | [#2567](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2567) |
3333
3434***
3535
from line 103
103103
104104No session boundary satisfies both:
105105
106| Session model | Cart (want: shared) | Browser (want: isolated) |
107| ------------------------ | :-----------------: | :----------------------: |
108| Subagents share parent's | ✓ shared | ✗ shared (clobbers) |
109| Subagents get their own | ✗ isolated | ✓ isolated |
106| Session model | Cart (want: shared) | Browser (want: isolated) |
107| - | :-: | :-: |
108| Subagents share parent's | ✓ shared | ✗ shared (clobbers) |
109| Subagents get their own | ✗ isolated | ✓ isolated |
110110
111111With explicit IDs the orchestrator calls `create_basket()` once, passes the resulting `basket_id` to each subagent, and each subagent separately calls `create_browser()` for its own `browser_id`. The model decides what is shared and what is isolated per piece of state, rather than having one scope imposed on everything.
112112
from line 156
156156
157157Nothing here is a protocol extension: `basket_id` is an ordinary string field in `structuredContent` and an ordinary string argument to subsequent tools. This pattern is already the norm in widely-deployed remote MCP servers that manage durable resources:
158158
159| Server (official, remote) | Create tool → returned ID | Operate tools taking that ID |
160| ----------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------- |
161| [Linear](https://linear.app/docs/mcp) | `create_issue` → issue id | `get_issue`, `update_issue`, `create_comment` |
162| [Notion](https://developers.notion.com/docs/mcp) | `notion-create-pages` → page id | `notion-update-page`, `notion-move-pages` |
159| Server (official, remote) | Create tool → returned ID | Operate tools taking that ID |
160| - | - | - |
161| [Linear](https://linear.app/docs/mcp) | `create_issue` → issue id | `get_issue`, `update_issue`, `create_comment` |
162| [Notion](https://developers.notion.com/docs/mcp) | `notion-create-pages` → page id | `notion-update-page`, `notion-move-pages` |
163163| [GitHub](https://github.com/github/github-mcp-server#tools) | `create_pull_request` → PR number | `pull_request_read`, `update_pull_request`, `merge_pull_request` |
164| [Stripe](https://docs.stripe.com/mcp) | `create_customer` → customer id | `create_invoice`, `list_subscriptions` |
164| [Stripe](https://docs.stripe.com/mcp) | `create_customer` → customer id | `create_invoice`, `list_subscriptions` |
165165
166166The approach can be adopted for less-persistent objects (a browser context, an in-progress cart) by giving the created object a limited lifetime, and/or limiting its discoverability to the principal that created it. The server owns the state, the client holds a name for it, and authorization is checked on every call.
167167
from line 246
246246
247247An automated survey of a 1000-repo random sample of open source MCP servers (classified by per-repo LLM analysis) found:
248248
249| Category | Share | Migration |
250| ------------------------------------------------------------- | ----: | ---------------------------------------------------- |
251| No application-level reference to MCP session ID | 90.0% | None |
252| `Map<sessionId, Transport>` routing (TS SDK boilerplate) | 3.5% | Removed by a sessionless SDK transport |
253| Transport setup only (`sessionIdGenerator`, never read) | 2.8% | Delete one constructor option |
254| **Session-keyed application state** | 2.5% | Migrate to explicit handles or auth principal |
255| **Proxy / gateway sticky routing** | 0.7% | Needs designed replacement |
256| **Auth binding** (JWT claims, PKCE verifier keyed on session) | 0.5% | Replace with server-generated nonce or token subject |
249| Category | Share | Migration |
250| - | -: | - |
251| No application-level reference to MCP session ID | 90.0% | None |
252| `Map<sessionId, Transport>` routing (TS SDK boilerplate) | 3.5% | Removed by a sessionless SDK transport |
253| Transport setup only (`sessionIdGenerator`, never read) | 2.8% | Delete one constructor option |
254| **Session-keyed application state** | 2.5% | Migrate to explicit handles or auth principal |
255| **Proxy / gateway sticky routing** | 0.7% | Needs designed replacement |
256| **Auth binding** (JWT claims, PKCE verifier keyed on session) | 0.5% | Replace with server-generated nonce or token subject |
257257
258258The bolded rows are the repos that use the session ID for application semantics. The hardest-hit category — gateways that spawn one upstream per session — needs a designed replacement rather than a mechanical edit; see [Backward Compatibility](#backward-compatibility).
259259
No line in this hunk matches that.