Document MCP SDK v1.25.2 upgrade and new features
Some checks failed
/ Publish Preview (push) Has been cancelled

- Add documentation for new WorkerTransport options:
  - onsessionclosed callback for session cleanup
  - eventStore for resumability support
  - retryInterval for polling behavior
  - closeSSEStream() method for triggering reconnections
- Add section on using MCP SDK directly with WebStandardStreamableHTTPServerTransport
- Document new mcp-server example showing zero-config MCP server setup
- Update WorkerTransportOptions interface documentation

Syncs documentation with PR #752 (Upgrade MCP SDK to v1.25.1)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
github-actions[bot] 2026-01-09 14:59:33 +00:00
parent 145d6df3c0
commit 6f3f783058

View file

@ -61,8 +61,11 @@ interface CreateMcpHandlerOptions extends WorkerTransportOptions {
sessionIdGenerator?: () => string;
enableJsonResponse?: boolean;
onsessioninitialized?: (sessionId: string) => void;
onsessionclosed?: (sessionId: string) => void;
corsOptions?: CORSOptions;
storage?: MCPStorageApi;
eventStore?: EventStore;
retryInterval?: number;
}
```
@ -112,9 +115,76 @@ const handler = createMcpHandler(server, { transport });
</TypeScriptExample>
## Using the MCP SDK Directly
For the simplest possible stateless MCP server, you can use the `@modelcontextprotocol/sdk` package directly with `WebStandardStreamableHTTPServerTransport`. This approach does not use the `agents` package and provides zero-config MCP server functionality that works on Cloudflare Workers. View the [complete example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-server).
<TypeScriptExample>
```ts title="src/index.ts"
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { z } from "zod";
const server = new McpServer({
name: "Hello MCP Server",
version: "1.0.0",
});
server.registerTool(
"hello",
{
description: "Returns a greeting message",
inputSchema: { name: z.string().optional() },
},
async ({ name }) => {
return {
content: [
{
text: `Hello, ${name ?? "World"}!`,
type: "text",
},
],
};
},
);
const transport = new WebStandardStreamableHTTPServerTransport();
server.connect(transport);
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
"Access-Control-Allow-Headers":
"Content-Type, Accept, mcp-session-id, mcp-protocol-version",
"Access-Control-Expose-Headers": "mcp-session-id",
"Access-Control-Max-Age": "86400",
};
function withCors(response: Response): Response {
for (const [key, value] of Object.entries(corsHeaders)) {
response.headers.set(key, value);
}
return response;
}
export default {
fetch: async (request: Request) => {
if (request.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
return withCors(await transport.handleRequest(request));
},
};
```
</TypeScriptExample>
This approach is recommended when you need a simple, stateless MCP server without additional features like authentication, state management, or agent capabilities. The server handles CORS automatically and works with any MCP client that supports the `streamable-http` transport.
## Stateless MCP Servers
Many MCP Servers are stateless, meaning they don't maintain any session state between requests. The `createMcpHandler` function is a lightweight alternative to the `McpAgent` class that can be used to serve an MCP server straight from a Worker. View the [complete example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker).
Many MCP Servers are stateless, meaning they do not maintain any session state between requests. The `createMcpHandler` function is a lightweight alternative to the `McpAgent` class that can be used to serve an MCP server straight from a Worker. View the [complete example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker).
<TypeScriptExample>
@ -259,6 +329,7 @@ class WorkerTransport implements Transport {
): Promise<void>;
async start(): Promise<void>;
async close(): Promise<void>;
closeSSEStream(requestId: RequestId): void;
}
```
@ -285,6 +356,11 @@ interface WorkerTransportOptions {
*/
onsessioninitialized?: (sessionId: string) => void;
/**
* Callback fired when a session is closed via DELETE request.
*/
onsessionclosed?: (sessionId: string) => void;
/**
* CORS configuration for cross-origin requests.
* Configures Access-Control-* headers.
@ -297,6 +373,18 @@ interface WorkerTransportOptions {
* so it survives hibernation/restart.
*/
storage?: MCPStorageApi;
/**
* Event store for resumability support.
* If provided, enables clients to reconnect and resume messages using Last-Event-ID.
*/
eventStore?: EventStore;
/**
* Retry interval in milliseconds to suggest to clients in SSE retry field.
* Controls client reconnection timing for polling behavior.
*/
retryInterval?: number;
}
```
@ -344,6 +432,23 @@ const transport = new WorkerTransport({
</TypeScriptExample>
#### onsessionclosed
A callback that fires when a session is closed via DELETE request. Use this to clean up resources or log session closures.
<TypeScriptExample>
```ts
const transport = new WorkerTransport({
onsessionclosed: (sessionId) => {
console.log(`MCP session closed: ${sessionId}`);
// Clean up any resources associated with this session
},
});
```
</TypeScriptExample>
#### corsOptions
Configure CORS headers for cross-origin requests.
@ -409,6 +514,90 @@ const transport = new WorkerTransport({
</TypeScriptExample>
#### eventStore
Optional event store for resumability support. When provided, enables clients to reconnect and resume receiving messages using the `Last-Event-ID` header. This is useful for implementing reliable delivery in long-running operations.
```ts
interface EventStore {
storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;
replayEventsAfter(
lastEventId: EventId,
options: {
send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;
},
): Promise<StreamId>;
getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;
}
```
<TypeScriptExample>
```ts
const transport = new WorkerTransport({
eventStore: {
storeEvent: async (streamId, message) => {
const eventId = crypto.randomUUID();
await env.EVENTS.put(`${streamId}:${eventId}`, JSON.stringify(message));
return eventId;
},
replayEventsAfter: async (lastEventId, { send }) => {
// Fetch and replay events after lastEventId
// Return the stream ID
},
},
});
```
</TypeScriptExample>
#### retryInterval
Retry interval in milliseconds to suggest to clients in the SSE `retry` field. Controls how often clients should attempt to reconnect when connections are lost. Useful for implementing polling behavior during long-running operations.
<TypeScriptExample>
```ts
const transport = new WorkerTransport({
retryInterval: 5000, // Clients will reconnect every 5 seconds
});
```
</TypeScriptExample>
#### Methods
##### closeSSEStream
Close an SSE stream for a specific request, triggering client reconnection. Use this to implement polling behavior during long-running operations. The client will reconnect after the retry interval specified in the priming event.
```ts
closeSSEStream(requestId: RequestId): void;
```
<TypeScriptExample>
```ts
const transport = new WorkerTransport({
retryInterval: 3000, // Client will reconnect every 3 seconds
});
// In your MCP tool handler:
server.tool("longOperation", "Start a long-running operation", {}, async () => {
// Start async work
const requestId = getCurrentRequestId(); // Get from context
// Close the stream to trigger client reconnection
transport.closeSSEStream(requestId);
return {
content: [{ type: "text", text: "Operation started, polling for updates..." }],
};
});
```
</TypeScriptExample>
## Authentication Context
When using [OAuth authentication](/agents/model-context-protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available.