Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
17 KiB
@modelcontextprotocol/codemod
2.0.0-beta.2
Patch Changes
-
#2405
f172626Thanks @mattzcarey! - Ship CommonJS builds alongside ESM. Each package now emits both.mjs/.d.mtsand.cjs/.d.cts(via tsdownformat: ['esm', 'cjs']), and itsexportsmap adds arequirecondition sorequire('@modelcontextprotocol/…')works from CommonJS consumers. Output extensions are normalized across all packages (@modelcontextprotocol/coremoves from.js/.d.tsto.mjs/.d.mts); the public import paths are unchanged. -
#2412
ef120b2Thanks @felixweinberger! - v1-to-v2 migration fixes from continued real-world migrations (codemod iterations 5).
2.0.0-beta.1
Patch Changes
- #2402
a400259Thanks @felixweinberger! - First beta release of SDK v2 with support for the MCP 2026-07-28 specification revision. See the migration guides for upgrading from v1 (docs/migration/upgrade-to-v2.md) and adopting the 2026-07-28 revision (docs/migration/support-2026-07-28.md).
2.0.0-alpha.2
Minor Changes
-
#2393
e4e8b22Thanks @felixweinberger! - Three migration-sweep fixes.completable()calls whose first argument is an optional-wrapped schema are rewritten to apply.optional()to thecompletable(...)result — v2 resolves completion metadata after unwrapping an outer optional wrapper, so the v1 nesting produced empty completion lists without an error; wrapper shapes the codemod cannot invert get an action-required marker instead. Imports ofProtocolandmergeCapabilitiesfrom v1'sshared/protocol.jsare no longer rewritten to a member the v2 packages do not export: the symbols are dropped from the rewritten import and an action-required marker explains the replacement (fallbackRequestHandlerfor unrouted inbound requests; a plain object spread for capability merging). The manifest zod-range warning now describes the symptom by vintage — zod 4.0–4.1 ranges fail type-checking (TS2769), while zod-3 ranges fail type-checking or at the firsttools/listdepending on the imported zod entry point. -
#2393
e4e8b22Thanks @felixweinberger! - Migration-sweep batch. The ErrorCode split now coordinates with the surrounding check: an all-SDK condition'sinstanceof ProtocolError/McpErrorguard is rewritten toSdkError, a guard covering both enums gets a marker asking for a split, and anErrorCodeimport with no rewritable member access on a v2 specifier is dropped with a marker instead of failing at module link time. Wrapping a raw shape withz.object()addsimport { z } from 'zod'when the file has nozvalue binding (a non-importzbinding gets a marker instead). The context-parameter rewrite finds the trailingextraparameter, covering the three-argumentregisterResourcetemplate callback without flagging itsvariablesargument. Resource-server auth helpers routed to the frozen server-legacy copy get a marker on value imports and barrel re-exports (an info note for type-only imports), every rewrittenSdkHttpErrorconstructor site gets a marker, and single-argumentfinishAuth(...)calls in files the run changes get a run-log note (the one-argumentURLSearchParamsform is valid v2, so the note never re-fires on already-migrated trees). The codemod accepts a single source file as target — source rewrites scope to that file and manifest changes are reported, not applied — and the no-changes summary distinguishes "already on the v2 packages", "still on the v1 SDK under a transform subset", and "no MCP SDK imports found". -
#2393
e4e8b22Thanks @felixweinberger! - Overhaul manifest handling. The codemod now discovers workspace-member manifests (npm/yarn/bunworkspacesandpnpm-workspace.yaml), writes only the nearestpackage.json, and reports the exact dependency changes every other affected manifest needs, so you can apply them deliberately. The v2 additions are computed from the post-transform import state of the files each manifest owns, so already-migrated packages still receive the packages their imports need when the v1 dependency is removed; in hoisted monorepos, member usage counts toward the manifest that declares the SDK dependency, with a note naming the contributing members. File collection no longer follows symbolic links (pnpmnode_moduleslayouts contain cycles that previously aborted the run) and honors--ignorepatterns during directory descent. Manifests whosezodrange cannot satisfy the v2 floor get a warning describing the runtime failure mode.RunnerResult.packageJsonChangesis now an array of per-manifest changes with optionalwarningsandnotes.
Patch Changes
-
#2393
e4e8b22Thanks @felixweinberger! - Backlog fixes. When the zod import injection fires in a package that declares no zod, the manifest pass adds it (devDependencies when only tests import it) so strict node_modules layouts install cleanly. The ErrorCode-split pairing re-points staleas ProtocolError/as McpErrorcasts bound to subjects whose assertions it moves toSdkError. Handler registration resolves one same-file variable hop (const S = ListToolsRequestSchema) before declaring a schema custom. Shorthand and aliased destructures of SDK dynamic imports rename with the static-import pass. Call-shape assertions pinning a registration schema (expect.objectContaining({ inputSchema: … })) get an advisory. The guide covers dist-text pins (no CJS-resolvable subpaths, content-hashed chunks, changed quote style, ESM-only output). -
#2393
e4e8b22Thanks @felixweinberger! - Fixes from migrating two large consumers. Registrations nested inside another handler's body no longer crash the transform with a whole-file rollback (calls process inner-first). Legacy.tool()/.prompt()/.resource()calls migrate without a directMcpServerimport when their shape matches the v1 signature AND the receiver is named like an MCP server (server,harness.mcp,this.mockServer); other receivers are left alone, without hard markers, since their type is unknown to the codemod.setRequestHandler/setNotificationHandlerwith a schema expression first argument get a marker pointing at the typed two-argument or custom three-argument form instead of being skipped silently, andremoveRequestHandler/removeNotificationHandlerwithSchema.shape.method.valuearguments rewrite to the method string. Destructured trailing callback parameters only count as the context when their keys look like context members, so template-variable destructures stop collecting false markers. The manifest zod note only appears for manifests that actually take part in the migration. -
#2393
e4e8b22Thanks @felixweinberger! - Two long-standing intervention classes now migrate mechanically..codereads on values aninstanceof SdkHttpErrorcheck proves — in the same condition or the guarded block — rewrite to.status(v2 carries the HTTP status there;.codeis anSdkErrorCodestring); unprovable reads keep the existing warning. The context-property remap reaches three shapes the call-site scan missed: functions assigned tofallbackRequestHandler, parameters annotated with a context type directly or via a same-file alias (accesses remap in place, the parameter keeps its name), and contexts forwarded wholesale to helpers, which get an advisory naming the callee. -
#2286
1823aaeThanks @felixweinberger! - The v1→v2 codemod no longer rewritestaskStore/taskMessageQueueMcpServer constructor options intocapabilities.tasks— that target does not exist in v2 (the experimental tasks runtime was removed, SEP-2663). The codemod now leaves the code untouched and emits an action-required diagnostic telling migrators to remove the option, matching the removal guidance already given forexperimental/tasksimports and the migration guide. -
#2386
36055d5Thanks @KKonstantinov! - Preserve a leading#!shebang (and the blank lines after it) when migrating a file. Some transforms drop the shebang because it is leading trivia of the first import they rewrite; the codemod now captures it before transforms and restores it before saving, so CLI packages whosebinpoints at the migrated entry keep working. -
#2393
e4e8b22Thanks @felixweinberger! - The explicit-undefinedresult-schema removal now requires the same proof as the schema-identifier path:request()calls must carry a provably literal spec method, andcallTool()calls whose first argument is a primitive are left alone. Previously, any file importing an MCP package could have the middle argument deleted from an unrelated.request()/.callTool()member call on a non-SDK receiver (e.g. a bespokeend.request('ping', undefined, id)helper), corrupting the call. -
#2286
1823aaeThanks @felixweinberger! - v1-to-v2: now wrapsoutputSchemaraw shapes withz.object(); importMap coverssdk/server/express.js,sdk/server/middleware/hostHeaderValidation.js, andsdk/client/auth-extensions.js. The unreachableexpressMiddlewaretransform is removed. -
#2383
9f8ba61Thanks @felixweinberger! - Keep the result-schema argument onrequest()calls unless the method is a literal spec method, and keep the generic passthroughResultSchemaeven then. Schema-less v2request()enforces the spec result schema for spec methods and throws aTypeErrorfor non-spec methods, so dropping the schema from a dynamic-method call site (the proxy/forwarder shape,request({ method, params }, ResultSchema)) or from a custom-method call broke the call.callTool()is unaffected — v2callTool()has no schema parameter.
2.0.0-alpha.1
Minor Changes
-
#2354
0fb8406Thanks @KKonstantinov! - Route v1@modelcontextprotocol/sdk/types.jsschema imports to the new@modelcontextprotocol/corepackage. The*SchemaZod constants now migrate as a behavior-preserving import-path swap —<Name>Schema.parse(value)/.safeParse(value)keep working — while spec types, error classes, enums, and guards continue to resolve to@modelcontextprotocol/client/@modelcontextprotocol/serverby context. A singleimport { CallToolResult, CallToolResultSchema } from '.../types.js'is split accordingly. The v1 OAuth/OpenID*Schemaconstants imported from@modelcontextprotocol/sdk/shared/auth.jsare routed to@modelcontextprotocol/corethe same way (their auth TYPES keep resolving toclient/server). The previousspecSchemaAccesstransform (which rewrote.parse()intospecTypeSchemas.X['~standard'].validate(...)) is removed. -
#2206
e03bca9Thanks @KKonstantinov! - Codemod now resolves SSE server and OAuth auth imports to @modelcontextprotocol/server-legacy sub-paths instead of removing them. An info diagnostic suggests eventual migration to v2 equivalents.
Patch Changes
-
#2354
0fb8406Thanks @KKonstantinov! - Infer client/server project type from source for v1 projects. A project being migrated still declares the single v1@modelcontextprotocol/sdkdependency, so detecting the project type frompackage.jsoncame back "unknown" and every file importing only shared protocol symbols defaulted to@modelcontextprotocol/serverwith an action-required warning. The codemod now scans the source for quoted@modelcontextprotocol/sdk/client/…and…/server/…import specifiers to infer the type (both → "both", one → that side, neither → "unknown"), routing shared symbols to the installed package and replacing the spurious warnings with at most an info note for genuinely ambiguous "both" projects. -
#2137
542d5c9Thanks @KKonstantinov! - The v1→v2 codemod now migrates the removedStreamableHTTPErrortoSdkHttpError(instead of the baseSdkError), matching the shipped error type and the migration guide. Diagnostics now point at the typederror.status/error.statusTextaccessors and note that unexpected-content-type responses are thrown as the baseSdkError. -
#2354
0fb8406Thanks @KKonstantinov! - Map the task request/notification schemas to their v2 method strings in the handler-registration transform.setRequestHandler(GetTaskRequestSchema, …),setNotificationHandler(TaskStatusNotificationSchema, …), and the other task handlers (tasks/get,tasks/result,tasks/list,tasks/cancel,notifications/tasks/status) now rewrite to the v2 two-argument method-string form instead of falling through to the generic "use the 3-argument form" manual-migration diagnostic. -
#2252
8d55531Thanks @felixweinberger! - Add per-revision spec reference types (2025-11-25 and 2026-07-28) with split comparison tests, and the 2026-07-28 wire contract surface: request-meta key constants,RequestMetaEnvelopeSchema,server/discovershapes, the typed-32004error, the-32003code constant, and aresultTypepassthrough on the base result. Types and constants only — no behavior changes.