Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/migration-SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ npm uninstall @modelcontextprotocol/sdk
| Server + Express | `npm install @modelcontextprotocol/server @modelcontextprotocol/express` |
| Server + Hono | `npm install @modelcontextprotocol/server @modelcontextprotocol/hono` |

`@modelcontextprotocol/core` is installed automatically as a dependency.
`@modelcontextprotocol/core` is an internal package — never install or import it directly. Both `@modelcontextprotocol/client` and `@modelcontextprotocol/server` re-export everything you need.

## 3. Import Mapping

Expand Down Expand Up @@ -373,6 +373,9 @@ Schema to method string mapping:
| `PromptListChangedNotificationSchema` | `'notifications/prompts/list_changed'` |
| `ProgressNotificationSchema` | `'notifications/progress'` |
| `CancelledNotificationSchema` | `'notifications/cancelled'` |
| `GetTaskRequestSchema` | `'tasks/get'` |
| `GetTaskPayloadRequestSchema` | `'tasks/result'` |
| `ElicitationCompleteNotificationSchema` | `'notifications/elicitation/complete'` |
| `InitializedNotificationSchema` | `'notifications/initialized'` |

Request/notification params remain fully typed. Remove unused schema imports after migration.
Expand Down Expand Up @@ -407,9 +410,9 @@ Request/notification params remain fully typed. Remove unused schema imports aft
| `ctx.mcpReq.elicitInput(params, options?)` | Elicit user input (form or URL) | `server.elicitInput(...)` from within handler |
| `ctx.mcpReq.requestSampling(params, options?)` | Request LLM sampling from client | `server.createMessage(...)` from within handler |

## 11. Schema parameter removed from `request()`, `send()`, and `callTool()`
## 11. Schema parameter removed from `request()`, `send()`, `callTool()`, and `callToolStream()`

`Protocol.request()`, `BaseContext.mcpReq.send()`, and `Client.callTool()` no longer take a Zod result schema argument. The SDK resolves the schema internally from the method name.
`Protocol.request()`, `BaseContext.mcpReq.send()`, `Client.callTool()`, and `client.experimental.tasks.callToolStream()` no longer take a Zod result schema argument. The SDK resolves the schema internally from the method name.

```typescript
// v1: schema required
Expand All @@ -428,6 +431,7 @@ const tool = await client.callTool({ name: 'my-tool', arguments: {} });
| ------------------------------------------------------------ | ---------------------------------- |
| `client.request(req, ResultSchema)` | `client.request(req)` |
| `client.request(req, ResultSchema, options)` | `client.request(req, options)` |
| `client.experimental.tasks.callToolStream(params, ResultSchema, options?)` | `client.experimental.tasks.callToolStream(params, options?)` |
| `ctx.mcpReq.send(req, ResultSchema)` | `ctx.mcpReq.send(req)` |
| `ctx.mcpReq.send(req, ResultSchema, options)` | `ctx.mcpReq.send(req, options)` |
| `client.callTool(params, CompatibilityCallToolResultSchema)` | `client.callTool(params)` |
Expand Down
66 changes: 58 additions & 8 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,36 @@ const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: ()

The SSE transport has been removed from the server. Servers should migrate to Streamable HTTP. The client-side SSE transport remains available for connecting to legacy SSE servers.

**Before (v1):**

```typescript
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';

let transport: SSEServerTransport;

app.get('/sse', async (req, res) => {
transport = new SSEServerTransport('/messages', res);
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
await transport.handlePostMessage(req, res);
});
```

**After (v2, stateless):**

```typescript
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';

app.all('/mcp', async (req, res) => {
const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);
await transport.handleRequest(req, res);
});
```

With `sessionIdGenerator: undefined` the transport runs in stateless mode, so creating a fresh instance per request is correct. For stateful sessions, the transport must be created once per session and stored in a `Map<string, NodeStreamableHTTPServerTransport>` keyed by session ID — see `examples/server/src/simpleStreamableHttp.ts` for the full pattern.

### `WebSocketClientTransport` removed

`WebSocketClientTransport` has been removed. WebSocket is not a spec-defined MCP transport, and keeping it in the SDK encouraged transport proliferation without a conformance baseline.
Expand Down Expand Up @@ -381,10 +411,14 @@ Common method string replacements:
| `ToolListChangedNotificationSchema` | `'notifications/tools/list_changed'` |
| `ResourceListChangedNotificationSchema` | `'notifications/resources/list_changed'` |
| `PromptListChangedNotificationSchema` | `'notifications/prompts/list_changed'` |
| `GetTaskRequestSchema` | `'tasks/get'` |
| `GetTaskPayloadRequestSchema` | `'tasks/result'` |
| `ElicitationCompleteNotificationSchema` | `'notifications/elicitation/complete'` |
| `InitializedNotificationSchema` | `'notifications/initialized'` |

### `Protocol.request()`, `ctx.mcpReq.send()`, and `Client.callTool()` no longer take a schema parameter

The public `Protocol.request()`, `BaseContext.mcpReq.send()`, and `Client.callTool()` methods no longer accept a Zod result schema argument. The SDK now resolves the correct result schema internally based on the method name. This means you no longer need to import result schemas
The public `Protocol.request()`, `BaseContext.mcpReq.send()`, `Client.callTool()`, and `client.experimental.tasks.callToolStream()` methods no longer accept a Zod result schema argument. The SDK now resolves the correct result schema internally based on the method name. This means you no longer need to import result schemas
like `CallToolResultSchema` or `ElicitResultSchema` when making requests.

**`client.request()` — Before (v1):**
Expand Down Expand Up @@ -440,6 +474,24 @@ const result = await client.callTool({ name: 'my-tool', arguments: {} }, Compati
const result = await client.callTool({ name: 'my-tool', arguments: {} });
```

**`client.experimental.tasks.callToolStream()` — Before (v1):**

```typescript
import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';

for await (const event of client.experimental.tasks.callToolStream({ name: 'my-tool', arguments: {} }, CallToolResultSchema)) {
// ...
}
```

**After (v2):**

```typescript
for await (const event of client.experimental.tasks.callToolStream({ name: 'my-tool', arguments: {} })) {
// ...
}
```

The return type is now inferred from the method name via `ResultTypeMap`. For example, `client.request({ method: 'tools/call', ... })` returns `Promise<CallToolResult | CreateTaskResult>`.

### Client list methods return empty results for missing capabilities
Expand All @@ -457,21 +509,19 @@ const client = new Client(
);
```

### `InMemoryTransport` removed from public API

`InMemoryTransport` has been removed from the public API surface. It was previously used for in-process client-server connections and testing.
### `InMemoryTransport` import path

For **testing**, import it directly from the internal core package:
`InMemoryTransport` is used for testing client/server interactions within a single process. It is re-exported from both `@modelcontextprotocol/server` and `@modelcontextprotocol/client`.

```typescript
// v1
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';

// v2 (testing only — @modelcontextprotocol/core is internal, not for production use)
import { InMemoryTransport } from '@modelcontextprotocol/core';
// v2
import { InMemoryTransport } from '@modelcontextprotocol/server';
```

For **production in-process connections**, use `StreamableHTTPClientTransport` with a local server URL, or connect client and server via paired streams.
For **production in-process connections**, prefer `StreamableHTTPClientTransport` with a local server URL.

### Removed type aliases and deprecated exports

Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/exports/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ export { deserializeMessage, ReadBuffer, serializeMessage } from '../../shared/s

// Transport types (NOT normalizeHeaders)
export type { FetchLike, Transport, TransportSendOptions } from '../../shared/transport.js';

// In-memory transport (for testing client/server in the same process)
export { InMemoryTransport } from '../../util/inMemory.js';
export { createFetchWithInit } from '../../shared/transport.js';

// URI Template
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/util/inMemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ interface QueuedMessage {

/**
* In-memory transport for creating clients and servers that talk to each other within the same process.
*
* Intended for testing and development. For production in-process connections, prefer
* `StreamableHTTPClientTransport` against a local server URL.
*/
export class InMemoryTransport implements Transport {
private _otherTransport?: InMemoryTransport;
Expand Down
Loading