convert-mcp-sdk-v1-to-v2
Use if porting an MCP TypeScript server from @modelcontextprotocol/sdk v1.x to the v2 SDK.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use if porting an MCP TypeScript server from @modelcontextprotocol/sdk v1.x to the v2 SDK.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use skill if you are exhaustively testing or release-gating martool CLI commands in a source checkout or deployed Coolify container over SSH, without local Docker or provider spend.
Use if driving agent-browser for Chrome/CDP automation, @ref snapshots, tabs, or verification.
Use if testing or debugging an iOS app via agent-device CLI — simulator flows, evidence, bug triage.
Use if supervising Jean agents through MCP and Computer Use for monitoring, recovery, or closure.
Use if auditing or designing a CLI for agent/LLM use — JSON output, exit codes, non-interactive.
Use if auditing or designing an MCP server for agent-readiness — framework, security, context.
| name | convert-mcp-sdk-v1-to-v2 |
| description | Use if porting an MCP TypeScript server from @modelcontextprotocol/sdk v1.x to the v2 SDK. |
Port an existing MCP TypeScript server from @modelcontextprotocol/sdk v1.x (single package) to the v2 split-package SDK: @modelcontextprotocol/server, /client, /node, /express, /hono. The v2 surface changes are package split, extra → ctx handler-context mapping, Zod v3→v4 with raw-shape removal, McpError → ProtocolError, method-string request-handler keys, framework adapter packages, and OAuth-router removal.
v2 is currently a pre-release alpha. Latest published: 2.0.0-alpha.2 (verified on npm, 2026-05-09). Most production servers should stay on @modelcontextprotocol/sdk@^1.x and use this skill to plan, test, and stage the migration — not to flip a production switch.
Trigger on actual migration intent applied to an existing v1 codebase. Italicized phrases below are concrete tells:
@modelcontextprotocol/sdk/server/mcp.js imports with @modelcontextprotocol/server"extra.signal/extra.authInfo and I need the v2 equivalent"inputSchema: { name: z.string() } raw shapes to v2", "upgrade Zod v3 to v4 in MCP tools"mcpAuthRouter / requireBearerAuth / OAuthServerProvider"StreamableHTTPServerTransport for NodeStreamableHTTPServerTransport"McpError/ErrorCode → ProtocolError/ProtocolErrorCode rename"setRequestHandler(CallToolRequestSchema, ...) → method-string keys"package.json contains @modelcontextprotocol/sdk (the v1 single package).build-mcp-server-sdk-v1.build-mcp-server-sdk-v2.build-mcp-server-sdk-v1.build-mcp-server-sdk-v2.mcp-use wrapper (not the official SDK) → use build-mcp-use-server.McpServer classes from two packages do not interoperate; types silently diverge and instanceof checks break at runtime.@modelcontextprotocol/server@2.0.0-alpha.2). ^ ranges across alphas surface breaking changes mid-migration. Always use --save-exact (or pnpm/yarn equivalents).extra → ctx) and schemas (ZodRawShape → z.object) together for any tool you touch. Half-migrated handlers are the single biggest source of runtime errors.mcpAuthRouter, requireBearerAuth, OAuthServerProvider) is removed from v2. If @modelcontextprotocol/server-auth-legacy is published for the target alpha, use it as a transition; otherwise stay on v1 or move auth to the HTTP layer (Bearer middleware, Passport, jose) and forward identity via req.auth."type": "module" to package.json. v2 is ESM-only — CommonJS dual-publish is unsupported.The most-used renames at a glance. Detailed per-area guides linked below.
| Area | v1 | v2 |
|---|---|---|
| Server class import | @modelcontextprotocol/sdk/server/mcp.js | @modelcontextprotocol/server |
| Stdio transport | @modelcontextprotocol/sdk/server/stdio.js | @modelcontextprotocol/server |
| HTTP transport | StreamableHTTPServerTransport from …/server/streamableHttp.js | NodeStreamableHTTPServerTransport from @modelcontextprotocol/node |
| SSE transport | SSEServerTransport | removed (clients must move to Streamable HTTP first) |
| Express adapter | createMcpExpressApp from SDK subpath | createMcpExpressApp from @modelcontextprotocol/express |
| Hono adapter | (none) | createMcpHonoApp from @modelcontextprotocol/hono |
| Client | @modelcontextprotocol/sdk/client/index.js | @modelcontextprotocol/client |
| Errors | McpError / ErrorCode from …/types.js | ProtocolError / ProtocolErrorCode from @modelcontextprotocol/server |
| Request-handler key | setRequestHandler(CallToolRequestSchema, …) | setRequestHandler("tools/call", …) |
| Zod | import { z } from "zod" (v3) | import * as z from "zod/v4" |
| Tool input schema | inputSchema: { name: z.string() } raw shape | inputSchema: z.object({ name: z.string() }) full schema |
| Handler signature | (args, extra) => … | (args, ctx) => … |
| Auth router | mcpAuthRouter, requireBearerAuth, OAuthServerProvider | removed (HTTP-layer auth or transition package) |
| v1 | v2 |
|---|---|
extra.signal | ctx.mcpReq.signal |
extra.requestId | ctx.mcpReq.id |
extra.sendNotification(n) | ctx.mcpReq.notify(n) |
extra.sendRequest(r, s) | ctx.mcpReq.send(r, s) |
extra.authInfo | ctx.http?.authInfo |
extra.requestInfo | ctx.http?.req |
extra.closeSSEStream?.() | ctx.http?.closeSSE?.() |
extra.sessionId | ctx.sessionId (top-level, unchanged) |
ctx.http? is nullable — stdio transport leaves it undefined. Any code that assumed extra.authInfo was always defined needs an explicit branch.
Read package.json, tsconfig.json, and every file under src/. Record:
@modelcontextprotocol/sdk/* import path (subpath exports are the migration unit).extra.* field accessed in handlers.z.object().McpError(ErrorCode.X, …) call site and the codes used.setRequestHandler(SomeRequestSchema, …) call.createMcpExpressApp, requireBearerAuth, mcpAuthRouter, custom middleware that depends on the SDK.For a deterministic first pass, run bash scripts/check-v2-feasibility.sh <project-dir> from this skill directory and read scripts/check-v2-feasibility.md. Use the report to focus the manual inventory; do not treat it as a substitute for reading the code.
| Strategy | When | Effort | Trade-off |
|---|---|---|---|
| Full rewrite | Small server (≤200 LOC tools, ≤2 transports, no OAuth router) | Hours | Cleanest end state, full v2 API access |
| Meta-package shim | Medium server, many subpath imports, target alpha publishes the shim | Hours | Keeps v1 import paths working under v2; defer rewrites tool-by-tool |
| HTTP-layer auth transition | Production OAuth server using mcpAuthRouter | Days | Replace SDK OAuth with app/framework middleware in a separate auth migration |
| Stay on v1 | OAuth-heavy, large, or alpha-allergic | Zero | No code change; revisit when v2 reaches stable |
Read references/guides/migration-strategy.md before committing. Record the choice in the change description.
Per references/guides/package-and-imports.md. Smallest unit: one import line at a time.
For direct-package migrations, preview the mechanical import portion with bash scripts/migrate-imports.sh <project-dir> and read scripts/migrate-imports.md. Rerun with --write only after reviewing the dry-run. Do not use it for schema, ctx, auth-router, request-handler-key, or transport-lifecycle rewrites — those need hand edits.
Per references/guides/schema-and-errors.md.
import { z } from "zod" → import * as z from "zod/v4"{ name: z.string() } → full schema z.object({ name: z.string() }). v2 rejects raw shapes outright.zod-to-json-schema — v2 emits JSON Schema 2020-12 natively via z.toJSONSchema().Per references/guides/handler-context-mapping.md. Use the mapping table above. No-args tool handler: (extra) => … becomes (ctx) => … — same shape, renamed.
Per references/guides/schema-and-errors.md. McpError / ErrorCode → ProtocolError / ProtocolErrorCode. setRequestHandler(CallToolRequestSchema, …) → setRequestHandler("tools/call", …).
Per references/guides/auth-replacements.md.
mcpAuthRouter and the target alpha publishes @modelcontextprotocol/server-auth-legacy, keep the v1 router through that transition package; otherwise stay on v1 until auth can move out of the SDK.authInfo via req.auth. The Express adapter passes req.auth through to ctx.http?.authInfo automatically.better-auth MCP plugin currently targets v1 import paths and is flagged for deprecation — do not adopt it new.Per references/guides/transports-and-adapters.md. Use the surface map table above. Hono is new in v2 via @modelcontextprotocol/hono (the official SDK package, not the unrelated community @hono/mcp package).
Per references/patterns/validation-and-rollback.md.
"type": "module" to package.json. Bump engines to Node 20+.npx @anthropic-ai/mcp-inspector for browser/manual coverage.test-by-mcpc-cli for headless CLI smoke/regression checks when mcpc is available.// v1
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.registerTool("greet", {
inputSchema: { name: z.string() }, // raw shape
}, async ({ name }, extra) => { // (args, extra)
await extra.sendNotification({ method: "...", params: {} });
return { content: [{ type: "text", text: `Hi ${name}` }] };
});
await server.connect(new StdioServerTransport());
// v2
import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server";
import * as z from "zod/v4";
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.registerTool("greet", {
inputSchema: z.object({ name: z.string() }), // full schema
}, async ({ name }, ctx) => { // (args, ctx)
await ctx.mcpReq.notify({ method: "...", params: {} });
return { content: [{ type: "text" as const, text: `Hi ${name}` }] };
});
await server.connect(new StdioServerTransport());
^ ranges — alphas can publish breaking changes between any two patches.ctx.http? as nullable everywhere — stdio leaves it undefined.@modelcontextprotocol/sdk and @modelcontextprotocol/server in the same compiled bundle without the meta-package shim — TypeScript accepts duplicate types but instanceof checks and class identity break at runtime.req.auth propagates without explicitly wiring HTTP-layer auth middleware — v2 has no server-side OAuth router.package-lock.json until v2 has been stable in production for at least one full release cycle.npm install v2 packages without --save-exact.better-auth MCP plugin as a new dependency in a v2 migration — flagged for deprecation, currently targets v1 import paths.When a port finishes, report:
ctx rewritestest-by-mcpc-cli, real client, staging/canaryAfter the port lands, hand off to build-mcp-server-sdk-v2 for ongoing v2 maintenance.
Use the smallest set relevant to the migration step.
| Reference | When to read |
|---|---|
references/guides/migration-strategy.md | Choosing between full rewrite, meta-package shim, HTTP-layer auth transition, "stay on v1" |
| Reference | When to read |
|---|---|
references/guides/package-and-imports.md | Package split table, import-by-import rewriter, meta-package shim usage |
references/guides/schema-and-errors.md | Zod v3→v4, raw shapes, JSON Schema dialect, error class rename, request-handler key strings |
references/guides/handler-context-mapping.md | Full extra → ctx field mapping, no-args handlers, http nullability, new ctx-only methods |
references/guides/transports-and-adapters.md | Transport renames, Express/Hono adapters, DNS rebinding, hostHeaderValidation |
references/guides/auth-replacements.md | OAuth-router replacement, custom Bearer/Passport/jose patterns, why not better-auth |
| Reference | When to read |
|---|---|
references/patterns/validation-and-rollback.md | Migration test plan, dual-version coexistence, rollback playbook, alpha-pinning |
Source-verified against the v1.x branch (latest stable: @modelcontextprotocol/sdk@^1.x) and the v2 alpha packages (@modelcontextprotocol/server@2.0.0-alpha.2, /client@2.0.0-alpha.2, /node@2.0.0-alpha.2, /express@2.0.0-alpha.2, /hono@2.0.0-alpha.2). npm verification on 2026-05-09 found no published @modelcontextprotocol/core, @modelcontextprotocol/sdk@2.0.0-alpha.2, or @modelcontextprotocol/server-auth-legacy; re-check the v2 changelog and npm package availability before each migration sprint.