You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- AJV (Node.js): `import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server';`
523
526
- CF Worker: `import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';`
524
527
525
-
## 15. Migration Steps (apply in this order)
528
+
## 15. 2026-06 Stateless Support (SEP-2575/2567/2322)
529
+
530
+
`Server`/`Client` are the same classes (still extend `Protocol`); 2026-06 support is additive. `Client.connect()` auto-probes `server/discover` and falls back to legacy `initialize`. `setRequestHandler` is unchanged.
531
+
532
+
**Prefer `ctx.mcpReq.*` inside handlers** (works under both protocols). Inside tool/prompt/resource handler bodies where `ctx` (the handler's second argument) is in scope, replace `<expr>.server.X()` (or `server.X()` on a low-level `Server`) with `ctx.mcpReq.X()`. The `<expr>` prefix varies (`mcpServer.server`, `this.server`, just `server`), so search for `.X(` and rewrite by hand:
All five rows are the **both-protocols** path, not 2026-only: `ctx.mcpReq.listRoots()` and `ctx.clientCapabilities` work identically against pre-2026 and 2026-06 clients.
543
+
544
+
Add `ctx` to the handler signature if not already present. For tools with an `inputSchema`: `async (args) =>` → `async (args, ctx) =>`. For tools WITHOUT an `inputSchema`: `async () =>` → `async ctx =>` (single parameter).
545
+
546
+
The top-level `server.createMessage()` etc. still work with a connected pre-2026 client; this migration is recommended but not required.
547
+
548
+
`ctx.mcpReq.requestSampling` keeps the same overload narrowing as `server.createMessage`: when `params.tools` is statically present the result type is `CreateMessageResultWithTools`; when statically absent it is `CreateMessageResult`. If `tools` is conditional at the call site, the result is the union; add a runtime `Array.isArray(result.content)` check before indexing.
549
+
550
+
MRTR via `InputRequiredError` works for handlers registered via `setRequestHandler`; `fallbackRequestHandler` is not wrapped by middleware (matches pre-existing behavior).
551
+
552
+
For tests that exercise pre-2026 connection-model behavior, construct the test client with `supportedProtocolVersions` filtered to pre-2026 versions only.
2. Replace all imports from `@modelcontextprotocol/sdk/...` using the import mapping tables (sections 3-4), including `StreamableHTTPServerTransport` → `NodeStreamableHTTPServerTransport`
@@ -534,4 +563,5 @@ Access validators explicitly:
534
563
8. If using server SSE transport, migrate to Streamable HTTP
535
564
9. If using server auth from the SDK: RS helpers (`requireBearerAuth`, `mcpAuthMetadataRouter`) → `@modelcontextprotocol/express`; AS helpers → external IdP/OAuth library
536
565
10. If relying on `listTools()`/`listPrompts()`/etc. throwing on missing capabilities, set `enforceStrictCapabilities: true`
537
-
11. Verify: build with `tsc` / run tests
566
+
11. Inside tool/prompt/resource handlers, replace `server.createMessage`/`elicitInput`/`listRoots`/`sendLoggingMessage` with `ctx.mcpReq.*` per section 15
These replace the pattern of calling `server.sendLoggingMessage()`, `server.createMessage()`, and `server.elicitInput()` from within handlers.
648
+
These replace the pattern of calling `server.sendLoggingMessage()`, `server.createMessage()`, `server.elicitInput()`, and `server.listRoots()` from within handlers. `ctx.clientCapabilities` likewise replaces `server.getClientCapabilities()`.
649
649
650
650
### Error hierarchy refactoring
651
651
@@ -869,6 +869,48 @@ The 2025-11 experimental tasks side-channel woven through `Protocol` has been re
869
869
870
870
There is no migration path for the removed surface; it was always `@experimental`. Under SEP-2663, tasks reattach via a `DispatchMiddleware` (`mcp.use(tasksPlugin({ store }))`) and handlers read task context from `ctx.ext.task` instead of `ctx.task`.
871
871
872
+
## 2026-06 Stateless Protocol Support (SEP-2575, SEP-2567, SEP-2322)
873
+
874
+
`Server` and `Client` now support the 2026-06 stateless connection model alongside the existing pre-2026 model. They remain the same classes (still extending `Protocol`); the new behavior is additive.
875
+
876
+
### What changed
877
+
878
+
-**`Client.connect()` auto-probes.** On connect, the client sends `server/discover` via the transport's `sendAndReceive` path. If the server responds, the client operates in stateless mode; typed methods (`callTool`, `listTools`, etc.) route via `sendAndReceive` and the MRTR loop. If discover fails (server doesn't support it, transport doesn't have `sendAndReceive`), the client falls back to the legacy `initialize` handshake. Existing code works unchanged.
879
+
-**`Server` gained a stateless dispatch path.**`server.statelessHandlers()` returns `{dispatch, listen}` for transports to call. `connect(transport)` wires this automatically via `transport.setStatelessHandlers?.()`. Handlers registered with `setRequestHandler` serve both paths.
880
+
-**`handleHttp(server, opts)`** is a new Fetch-API entry point: one shared `Server` instance, no `Transport`, no `connect()`. Returns `(Request) => Promise<Response>`. See `examples/server/src/honoWebStandardStreamableHttp.ts`.
881
+
-**`client.subscribe(filter)`** opens a `subscriptions/listen` stream for list-changed and resource-updated notifications (the 2026-06 replacement for unsolicited notifications and `resources/subscribe`).
882
+
-**`Transport` interface gained two optional methods:**`setStatelessHandlers?(handlers)` (server side) and `sendAndReceive?(req, opts?)` (client side). Implement these in custom transports to support 2026-06.
883
+
884
+
### Prefer `ctx.mcpReq.*` for server-to-client interactions
885
+
886
+
Inside a tool/prompt/resource handler, use `ctx.mcpReq.{elicitInput, requestSampling, listRoots, log}` instead of the top-level `server.elicitInput()` / `server.createMessage()` / `server.listRoots()` / `server.sendLoggingMessage()`. The `ctx.mcpReq.*` form works under **both** protocols: with a pre-2026 client it sends a real request; with a 2026-06 client it returns an `input_required` result and the client retries with the response embedded (SEP-2322 MRTR).
`ctx.mcpReq.listRoots()` and `ctx.clientCapabilities` work under **both** protocols, not just 2026-06.
897
+
898
+
The top-level methods still exist and work when a pre-2026 client is connected. They are not removed.
899
+
900
+
MRTR via `InputRequiredError` works for handlers registered via `setRequestHandler`; `fallbackRequestHandler` is not wrapped by middleware (matches pre-existing behavior).
901
+
902
+
### Tests pinning pre-2026
903
+
904
+
If a test exercises pre-2026 connection-model behavior (e.g., `oninitialized`, server-initiated requests, in-band logging) and breaks because the auto-probe now succeeds, construct the client with `supportedProtocolVersions` filtered to pre-2026 versions only, or use a fixture like `LegacyTestClient` that does so. The probe falls back to legacy when no mutual stateless version exists.
905
+
906
+
### Shared instances
907
+
908
+
A single `Server` instance can safely serve many concurrent 2026-06 clients via `handleHttp` or a connected transport's per-message router. For pre-2026 clients, the existing per-instance isolation guidance still applies (the legacy path's `_clientCapabilities` is per-connection state): either per-session (a transport map keyed by session ID) or a fresh server per request.
909
+
910
+
### Dual-mode endpoint
911
+
912
+
To serve both protocol eras from one HTTP endpoint, use `WebStandardStreamableHTTPServerTransport`'s per-message router for both eras, or compose `handleHttp` with a legacy transport behind your own router (e.g. branch on `MCP-Protocol-Version` / `isInitializeRequest` to send pre-2026 traffic to a per-session transport and everything else to the shared `handleHttp` handler). The shared `Server` instance handles 2026-06 traffic; pre-2026 traffic gets per-instance isolation as above.
913
+
872
914
## Enhancements
873
915
874
916
### Automatic JSON Schema validator selection by runtime
Copy file name to clipboardExpand all lines: docs/server.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -478,7 +478,7 @@ For runnable examples, see [`elicitationFormExample.ts`](https://github.com/mode
478
478
479
479
### Roots
480
480
481
-
Roots let a tool handler discover the client's workspace directories — for example, to scope a file search or identify project boundaries (see [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) in the MCP overview). Call {@linkcode@modelcontextprotocol/server!server/server.Server#listRoots | server.server.listRoots()} (requires the client to declare the `roots` capability):
481
+
Roots let a tool handler discover the client's workspace directories — for example, to scope a file search or identify project boundaries (see [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) in the MCP overview). Call `ctx.mcpReq.listRoots()` inside the handler (requires the client to declare the `roots` capability). This works under both the pre-2026 connection model and the 2026 stateless model:
@@ -572,7 +572,7 @@ If you use `NodeStreamableHTTPServerTransport` directly with your own HTTP frame
572
572
573
573
| Feature | Description | Example |
574
574
|---------|-------------|---------|
575
-
|Web Standard transport | Deploy on Cloudflare Workers, Deno, or Bun |[`honoWebStandardStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/honoWebStandardStreamableHttp.ts)|
575
+
|2026-06 stateless `handleHttp()` (Hono) | One shared server, no Transport, no `connect()` — runs on Cloudflare Workers, Deno, or Bun |[`honoWebStandardStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/honoWebStandardStreamableHttp.ts)|
576
576
| Session management | Per-session transport routing, initialization, and cleanup |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
577
577
| Resumability | Replay missed SSE events via an event store |[`inMemoryEventStore.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/inMemoryEventStore.ts)|
578
578
| CORS | Expose MCP headers for browser clients |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
0 commit comments