Install
$ agentstack add skill-yigitkonur-skills-by-yigitkonur-convert-mcp-sdk-v1-to-v2 ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Convert MCP Server (SDK v1 → v2)
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.
When to use this skill
Trigger on actual migration intent applied to an existing v1 codebase. Italicized phrases below are concrete tells:
- "port my MCP server to v2", "upgrade @modelcontextprotocol/sdk to the new split packages"
- "replace
@modelcontextprotocol/sdk/server/mcp.jsimports with@modelcontextprotocol/server" - "my handlers use
extra.signal/extra.authInfoand I need the v2 equivalent" - "convert
inputSchema: { name: z.string() }raw shapes to v2", "upgrade Zod v3 to v4 in MCP tools" - "replace
mcpAuthRouter/requireBearerAuth/OAuthServerProvider" - "swap
StreamableHTTPServerTransportforNodeStreamableHTTPServerTransport" - "
McpError/ErrorCode→ProtocolError/ProtocolErrorCoderename" - "
setRequestHandler(CallToolRequestSchema, ...)→ method-string keys"
Detection signals (all should be true)
package.jsoncontains@modelcontextprotocol/sdk(the v1 single package).- The user states intent to migrate, upgrade, port, or convert — not just maintain v1.
- There is existing handler/transport/auth code to transform — not a greenfield build.
Do NOT use this skill for
- New v1 server (no existing code) → use
build-mcp-server-sdk-v1. - New v2 server (greenfield on v2 alpha) → use
build-mcp-server-sdk-v2. - Maintaining or bug-fixing a v1 server with no migration intent → use
build-mcp-server-sdk-v1. - Already on v2 and just need to extend it → use
build-mcp-server-sdk-v2. - Using the
mcp-usewrapper (not the official SDK) → usebuild-mcp-use-server.
Core rules — load-bearing
- Pick a strategy before touching files. Full rewrite, meta-package shim (only if the target alpha actually publishes one), HTTP-layer auth transition, or stay on v1. Verify package availability on npm before committing.
- Never mix v1 and v2 packages in the same module graph except deliberately during a staged migration. Two
McpServerclasses from two packages do not interoperate; types silently diverge andinstanceofchecks break at runtime. - Pin to exact alpha versions (
@modelcontextprotocol/server@2.0.0-alpha.2).^ranges across alphas surface breaking changes mid-migration. Always use--save-exact(or pnpm/yarn equivalents). - Migrate handler context (
extra → ctx) and schemas (ZodRawShape → z.object) together for any tool you touch. Half-migrated handlers are the single biggest source of runtime errors. - Replace OAuth deliberately. Server-side OAuth (
mcpAuthRouter,requireBearerAuth,OAuthServerProvider) is removed from v2. If@modelcontextprotocol/server-auth-legacyis 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 viareq.auth. - Upgrade Node to 20+ and add
"type": "module"topackage.json. v2 is ESM-only — CommonJS dual-publish is unsupported. - Keep a working v1 branch alive until v2 graduates from alpha. v2 is a delivery target; v1 is the running production until then.
v1 → v2 surface map
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) |
extra → ctx (most-frequent moves)
| 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.
Workflow
1 — Inventory the v1 server
Read package.json, tsconfig.json, and every file under src/. Record:
- Every
@modelcontextprotocol/sdk/*import path (subpath exports are the migration unit). - Every
extra.*field accessed in handlers. - Every transport class instantiated.
- Every Zod schema shape: raw-object shorthand vs full
z.object(). - Every
McpError(ErrorCode.X, …)call site and the codes used. - Every
setRequestHandler(SomeRequestSchema, …)call. - Every framework wiring point:
createMcpExpressApp,requireBearerAuth,mcpAuthRouter, custom middleware that depends on the SDK.
For a deterministic first pass, run bash scripts/check-v2-feasibility.sh 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.
2 — Choose the migration strategy
| 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.
3 — Rewrite packages and imports
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 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.
4 — Rewrite schemas
Per references/guides/schema-and-errors.md.
import { z } from "zod"→import * as z from "zod/v4"- Raw shape
{ name: z.string() }→ full schemaz.object({ name: z.string() }). v2 rejects raw shapes outright. - Drop
zod-to-json-schema— v2 emits JSON Schema 2020-12 natively viaz.toJSONSchema().
5 — Rewrite handlers (extra → ctx)
Per references/guides/handler-context-mapping.md. Use the mapping table above. No-args tool handler: (extra) => … becomes (ctx) => … — same shape, renamed.
6 — Rewrite errors and request-handler keys
Per references/guides/schema-and-errors.md. McpError / ErrorCode → ProtocolError / ProtocolErrorCode. setRequestHandler(CallToolRequestSchema, …) → setRequestHandler("tools/call", …).
7 — Replace auth
Per references/guides/auth-replacements.md.
- If using
mcpAuthRouterand 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. - If integrating fresh: do auth at the HTTP layer (Express/Hono middleware) and forward identity into
authInfoviareq.auth. The Express adapter passesreq.auththrough toctx.http?.authInfoautomatically. - The
better-authMCP plugin currently targets v1 import paths and is flagged for deprecation — do not adopt it new.
8 — Replace transports and adapters
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).
9 — Validate and stage rollout
Per references/patterns/validation-and-rollback.md.
- Add
"type": "module"topackage.json. Bump engines to Node 20+. - Run type-check first, then the existing unit/integration test suite.
- Smoke-test with
npx @anthropic-ai/mcp-inspectorfor browser/manual coverage. - Use
test-by-mcpc-clifor headless CLI smoke/regression checks whenmcpcis available. - Connect at least one real MCP client before production rollout.
- Stage in a non-prod environment for at least one week before flipping production traffic.
- Keep the v1 branch deployable until v2 reaches stable — alpha versions can break.
Quick diff — minimal hello-world before/after
// 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());
Decision rules
- Prefer the meta-package shim only when the target alpha actually publishes it; otherwise direct packages or stay on v1.
- Prefer separating auth migration from the SDK port — auth is high-stakes; only use a verified transition package.
- Prefer pinned alpha versions over
^ranges — alphas can publish breaking changes between any two patches. - Prefer migrating one handler end-to-end (imports + schema + ctx + errors) over one concern across all handlers — bounds the test surface per PR.
- Treat
ctx.http?as nullable everywhere — stdio leaves itundefined.
Guardrails
- Never run an alpha SDK in production before staging it in a non-prod environment with realistic traffic for at least one week.
- Never mix
@modelcontextprotocol/sdkand@modelcontextprotocol/serverin the same compiled bundle without the meta-package shim — TypeScript accepts duplicate types butinstanceofchecks and class identity break at runtime. - Never assume
req.authpropagates without explicitly wiring HTTP-layer auth middleware — v2 has no server-side OAuth router. - Never delete the v1 branch or
package-lock.jsonuntil v2 has been stable in production for at least one full release cycle. - Never
npm installv2 packages without--save-exact. - Never adopt the
better-authMCP plugin as a new dependency in a v2 migration — flagged for deprecation, currently targets v1 import paths.
Output contract
When a port finishes, report:
- migration strategy chosen and why
- package/version changes, exact alpha pins, and whether the meta-package shim remains
- handlers/tools migrated, especially schema and
ctxrewrites - auth path chosen: stay on v1, verified transition package, HTTP-layer auth, or no auth
- transports/adapters changed
- validation rung reached: type-check, unit tests, Inspector,
test-by-mcpc-cli, real client, staging/canary - rollback status: v1 branch/image/lockfile preserved, or blocker if not verified
- residual risks from v2 alpha status
After the port lands, hand off to build-mcp-server-sdk-v2 for ongoing v2 maintenance.
Reference routing
Use the smallest set relevant to the migration step.
Plan and decide
| Reference | When to read | |---|---| | references/guides/migration-strategy.md | Choosing between full rewrite, meta-package shim, HTTP-layer auth transition, "stay on v1" |
Rewrite mechanics
| 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 |
Validate and ship
| Reference | When to read | |---|---| | references/patterns/validation-and-rollback.md | Migration test plan, dual-version coexistence, rollback playbook, alpha-pinning |
Compatibility note
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.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: yigitkonur
- Source: yigitkonur/skills-by-yigitkonur
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.