Skip to content

Commit fd290ea

Browse files
Merge branch 'main' into fweinberger/extract-tasks-from-protocol
2 parents 2912f34 + 64f2782 commit fd290ea

File tree

6 files changed

+530
-11
lines changed

6 files changed

+530
-11
lines changed

CLAUDE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ pnpm --filter @modelcontextprotocol/core test -- path/to/file.test.ts
2222
pnpm --filter @modelcontextprotocol/core test -- -t "test name"
2323
```
2424

25+
## Breaking Changes
26+
27+
When making breaking changes, document them in **both**:
28+
29+
- `docs/migration.md` — human-readable guide with before/after code examples
30+
- `docs/migration-SKILL.md` — LLM-optimized mapping tables for mechanical migration
31+
32+
Include what changed, why, and how to migrate. Search for related sections and group
33+
related changes together rather than adding new standalone sections.
34+
2535
## Code Style Guidelines
2636

2737
- **TypeScript**: Strict type checking, ES modules, explicit return types

docs/migration-SKILL.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
name: migrate-v1-to-v2
3+
description: Migrate MCP TypeScript SDK code from v1 (@modelcontextprotocol/sdk) to v2 (@modelcontextprotocol/core, /client, /server). Use when a user asks to migrate, upgrade, or port their MCP TypeScript code from v1 to v2.
4+
---
5+
6+
# MCP TypeScript SDK: v1 → v2 Migration
7+
8+
Apply these changes in order: dependencies → imports → API calls → type aliases.
9+
10+
## 1. Environment
11+
12+
- Node.js 20+ required (v18 dropped)
13+
- ESM only (CJS dropped). If the project uses `require()`, convert to `import`/`export` or use dynamic `import()`.
14+
15+
## 2. Dependencies
16+
17+
Remove the old package and install only what you need:
18+
19+
```bash
20+
npm uninstall @modelcontextprotocol/sdk
21+
```
22+
23+
| You need | Install |
24+
|----------|---------|
25+
| Client only | `npm install @modelcontextprotocol/client` |
26+
| Server only | `npm install @modelcontextprotocol/server` |
27+
| Server + Node.js HTTP | `npm install @modelcontextprotocol/server @modelcontextprotocol/node` |
28+
| Server + Express | `npm install @modelcontextprotocol/server @modelcontextprotocol/express` |
29+
| Server + Hono | `npm install @modelcontextprotocol/server @modelcontextprotocol/hono` |
30+
31+
`@modelcontextprotocol/core` is installed automatically as a dependency.
32+
33+
## 3. Import Mapping
34+
35+
Replace all `@modelcontextprotocol/sdk/...` imports using this table.
36+
37+
### Client imports
38+
39+
| v1 import path | v2 package |
40+
|----------------|------------|
41+
| `@modelcontextprotocol/sdk/client/index.js` | `@modelcontextprotocol/client` |
42+
| `@modelcontextprotocol/sdk/client/auth.js` | `@modelcontextprotocol/client` |
43+
| `@modelcontextprotocol/sdk/client/streamableHttp.js` | `@modelcontextprotocol/client` |
44+
| `@modelcontextprotocol/sdk/client/sse.js` | `@modelcontextprotocol/client` |
45+
| `@modelcontextprotocol/sdk/client/stdio.js` | `@modelcontextprotocol/client` |
46+
| `@modelcontextprotocol/sdk/client/websocket.js` | `@modelcontextprotocol/client` |
47+
48+
### Server imports
49+
50+
| v1 import path | v2 package |
51+
|----------------|------------|
52+
| `@modelcontextprotocol/sdk/server/mcp.js` | `@modelcontextprotocol/server` |
53+
| `@modelcontextprotocol/sdk/server/index.js` | `@modelcontextprotocol/server` |
54+
| `@modelcontextprotocol/sdk/server/stdio.js` | `@modelcontextprotocol/server` |
55+
| `@modelcontextprotocol/sdk/server/streamableHttp.js` | `@modelcontextprotocol/node` (class renamed to `NodeStreamableHTTPServerTransport`) |
56+
| `@modelcontextprotocol/sdk/server/sse.js` | REMOVED (migrate to Streamable HTTP) |
57+
| `@modelcontextprotocol/sdk/server/auth/*` | REMOVED (use external auth library) |
58+
| `@modelcontextprotocol/sdk/server/middleware.js` | `@modelcontextprotocol/express` (signature changed, see section 8) |
59+
60+
### Types / shared imports
61+
62+
| v1 import path | v2 package |
63+
|----------------|------------|
64+
| `@modelcontextprotocol/sdk/types.js` | `@modelcontextprotocol/core` |
65+
| `@modelcontextprotocol/sdk/shared/protocol.js` | `@modelcontextprotocol/core` |
66+
| `@modelcontextprotocol/sdk/shared/transport.js` | `@modelcontextprotocol/core` |
67+
| `@modelcontextprotocol/sdk/shared/stdio.js` | `@modelcontextprotocol/core` |
68+
| `@modelcontextprotocol/sdk/shared/uriTemplate.js` | `@modelcontextprotocol/core` |
69+
| `@modelcontextprotocol/sdk/shared/auth.js` | `@modelcontextprotocol/core` |
70+
71+
Notes:
72+
- `@modelcontextprotocol/client` and `@modelcontextprotocol/server` both re-export everything from `@modelcontextprotocol/core`, so you can import types from whichever package you already depend on.
73+
- When multiple v1 imports map to the same v2 package, consolidate them into a single import statement.
74+
- If code imports from `sdk/client/...`, install `@modelcontextprotocol/client`. If from `sdk/server/...`, install `@modelcontextprotocol/server`. If from `sdk/types.js` or `sdk/shared/...` only, install `@modelcontextprotocol/core`.
75+
76+
## 4. Renamed Symbols
77+
78+
| v1 symbol | v2 symbol | v2 package |
79+
|-----------|-----------|------------|
80+
| `StreamableHTTPServerTransport` | `NodeStreamableHTTPServerTransport` | `@modelcontextprotocol/node` |
81+
82+
## 5. Removed / Renamed Type Aliases and Symbols
83+
84+
| v1 (removed) | v2 (replacement) |
85+
|--------------|------------------|
86+
| `JSONRPCError` | `JSONRPCErrorResponse` |
87+
| `JSONRPCErrorSchema` | `JSONRPCErrorResponseSchema` |
88+
| `isJSONRPCError` | `isJSONRPCErrorResponse` |
89+
| `isJSONRPCResponse` | `isJSONRPCResultResponse` |
90+
| `ResourceReference` | `ResourceTemplateReference` |
91+
| `ResourceReferenceSchema` | `ResourceTemplateReferenceSchema` |
92+
| `IsomorphicHeaders` | REMOVED (use Web Standard `Headers`) |
93+
| `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now in `@modelcontextprotocol/core`) |
94+
95+
All other symbols from `@modelcontextprotocol/sdk/types.js` retain their original names (e.g., `CallToolResultSchema`, `ListToolsResultSchema`, etc.).
96+
97+
**Unchanged APIs** (only import paths changed): `Client` constructor and methods, `McpServer` constructor, `server.connect()`, `server.close()`, all client transports (`StreamableHTTPClientTransport`, `SSEClientTransport`, `StdioClientTransport`), `StdioServerTransport`, all Zod schemas, all callback return types.
98+
99+
## 6. McpServer API Changes
100+
101+
The variadic `.tool()`, `.prompt()`, `.resource()` methods are removed. Use the `register*` methods with a config object.
102+
103+
### Tools
104+
105+
```typescript
106+
// v1: server.tool(name, schema, callback)
107+
server.tool('greet', { name: z.string() }, async ({ name }) => {
108+
return { content: [{ type: 'text', text: `Hello, ${name}!` }] };
109+
});
110+
111+
// v1: server.tool(name, description, schema, callback)
112+
server.tool('greet', 'Greet a user', { name: z.string() }, async ({ name }) => {
113+
return { content: [{ type: 'text', text: `Hello, ${name}!` }] };
114+
});
115+
116+
// v2: server.registerTool(name, config, callback)
117+
server.registerTool('greet', {
118+
description: 'Greet a user',
119+
inputSchema: { name: z.string() },
120+
}, async ({ name }) => {
121+
return { content: [{ type: 'text', text: `Hello, ${name}!` }] };
122+
});
123+
```
124+
125+
Config object fields: `title?`, `description?`, `inputSchema?`, `outputSchema?`, `annotations?`, `_meta?`
126+
127+
### Prompts
128+
129+
```typescript
130+
// v1: server.prompt(name, schema, callback)
131+
server.prompt('summarize', { text: z.string() }, async ({ text }) => {
132+
return { messages: [{ role: 'user', content: { type: 'text', text } }] };
133+
});
134+
135+
// v2: server.registerPrompt(name, config, callback)
136+
server.registerPrompt('summarize', {
137+
argsSchema: { text: z.string() },
138+
}, async ({ text }) => {
139+
return { messages: [{ role: 'user', content: { type: 'text', text } }] };
140+
});
141+
```
142+
143+
Config object fields: `title?`, `description?`, `argsSchema?`
144+
145+
### Resources
146+
147+
```typescript
148+
// v1: server.resource(name, uri, callback)
149+
server.resource('config', 'config://app', async (uri) => {
150+
return { contents: [{ uri: uri.href, text: '{}' }] };
151+
});
152+
153+
// v2: server.registerResource(name, uri, metadata, callback)
154+
server.registerResource('config', 'config://app', {}, async (uri) => {
155+
return { contents: [{ uri: uri.href, text: '{}' }] };
156+
});
157+
```
158+
159+
Note: the third argument (`metadata`) is required — pass `{}` if no metadata.
160+
161+
## 7. Headers API
162+
163+
Transport constructors and `RequestInfo.headers` now use the Web Standard `Headers` object instead of plain objects.
164+
165+
```typescript
166+
// v1: plain object, bracket access
167+
headers: { 'Authorization': 'Bearer token' }
168+
extra.requestInfo?.headers['mcp-session-id']
169+
170+
// v2: Headers object, .get() access
171+
headers: new Headers({ 'Authorization': 'Bearer token' })
172+
extra.requestInfo?.headers.get('mcp-session-id')
173+
```
174+
175+
## 8. Removed Server Features
176+
177+
### SSE server transport
178+
179+
`SSEServerTransport` removed entirely. Migrate to `NodeStreamableHTTPServerTransport` (from `@modelcontextprotocol/node`). Client-side `SSEClientTransport` still available for connecting to legacy servers.
180+
181+
### Server-side auth
182+
183+
All server OAuth exports removed: `mcpAuthRouter`, `OAuthServerProvider`, `OAuthTokenVerifier`, `requireBearerAuth`, `authenticateClient`, `ProxyOAuthServerProvider`, `allowedMethods`, and associated types. Use an external auth library (e.g., `better-auth`). See `examples/server/src/` for demos.
184+
185+
### Host header validation (Express)
186+
187+
`hostHeaderValidation()` and `localhostHostValidation()` moved from server package to `@modelcontextprotocol/express`. Signature changed: takes `string[]` instead of options object.
188+
189+
```typescript
190+
// v1
191+
import { hostHeaderValidation } from '@modelcontextprotocol/sdk/server/middleware.js';
192+
app.use(hostHeaderValidation({ allowedHosts: ['example.com'] }));
193+
194+
// v2
195+
import { hostHeaderValidation } from '@modelcontextprotocol/express';
196+
app.use(hostHeaderValidation(['example.com']));
197+
```
198+
199+
The server package now exports framework-agnostic alternatives: `validateHostHeader()`, `localhostAllowedHostnames()`, `hostHeaderValidationResponse()`.
200+
201+
## 9. Client Behavioral Changes
202+
203+
`Client.listPrompts()`, `listResources()`, `listResourceTemplates()`, `listTools()` now return empty results when the server lacks the corresponding capability (instead of sending the request). Set `enforceStrictCapabilities: true` in `ClientOptions` to throw an error instead.
204+
205+
## 10. Migration Steps (apply in this order)
206+
207+
1. Update `package.json`: `npm uninstall @modelcontextprotocol/sdk`, install the appropriate v2 packages
208+
2. Replace all imports from `@modelcontextprotocol/sdk/...` using the import mapping tables (sections 3-4), including `StreamableHTTPServerTransport``NodeStreamableHTTPServerTransport`
209+
3. Replace removed type aliases (`JSONRPCError``JSONRPCErrorResponse`, etc.) per section 5
210+
4. Replace `.tool()` / `.prompt()` / `.resource()` calls with `registerTool` / `registerPrompt` / `registerResource` per section 6
211+
5. Replace plain header objects with `new Headers({...})` and bracket access (`headers['x']`) with `.get()` calls per section 7
212+
6. If using `hostHeaderValidation` from server, update import and signature per section 8
213+
7. If using server SSE transport, migrate to Streamable HTTP
214+
8. If using server auth from the SDK, migrate to an external auth library
215+
9. If relying on `listTools()`/`listPrompts()`/etc. throwing on missing capabilities, set `enforceStrictCapabilities: true`
216+
10. Verify: build with `tsc` / run tests

0 commit comments

Comments
 (0)