Codemod CLI Commands

Purpose and Scope

@modelcontextprotocol/codemod is the migration package for projects moving MCP TypeScript SDK code from the v1 monolithic package surface to the v2 split packages. It is intentionally narrower than a general migration assistant: it performs mechanical source rewrites, reports package manifest changes, and marks code that needs human judgment. Use it when a codebase still imports v1 paths such as @modelcontextprotocol/sdk/... and you want a repeatable first pass before doing behavioral review, runtime checks, and protocol-revision adoption work.

Sources: packages/codemod/README.md, packages/codemod/package.json

The executable name is mcp-codemod, exposed by the package bin map and normally invoked through npx @modelcontextprotocol/codemod@beta. The package requires Node >=20, is published as an ES module package, and depends on commander, fast-glob, and ts-morph, which matches its role as a command-line AST rewrite tool. The README shows the primary command as v1-to-v2, run either against a directory or a single source file. Directory runs can rewrite source files in place and report manifest changes; single-file runs focus on the source target and report, rather than apply, manifest changes.

Sources: packages/codemod/README.md, packages/codemod/package.json

Relevant Source Files

  • packages/codemod/README.md — user-facing CLI usage, migration coverage, action-required marker format, and manual follow-up boundaries.
  • packages/codemod/package.json — package name, Node engine, executable name, published entry points, scripts, and runtime dependencies.
  • packages/codemod/src/cli.tscommander program definition, command options, target validation, manifest-change printing, formatter guidance, and migration dispatch.
  • packages/codemod/src/bin/batchTest.ts — internal batch-test entrypoint and report/config types for running the codemod against real repositories.
  • packages/codemod/src/runner.ts — programmatic execution engine that analyzes projects, selects transforms, edits files, updates manifests, and inserts diagnostic comments.

Command Reference

The public command group is generated from the migration registry: the CLI iterates over listMigrations() and adds one subcommand for each migration name. In the current package documentation, the supported public migration is v1-to-v2. The command accepts an optional-looking [target-dir] in the Commander declaration, but the action explicitly treats the target as required unless --list is used. If no target is provided, it prints an error for the missing <target-dir> and sets a nonzero exit code. The target may be a directory or a single source file whose extension matches the source-file filter.

Sources: packages/codemod/README.md, packages/codemod/src/cli.ts

npx @modelcontextprotocol/codemod@beta v1-to-v2 .
npx @modelcontextprotocol/codemod@beta v1-to-v2 src/server.ts
mcp-codemod v1-to-v2 .

The visible CLI options are deliberately small. --dry-run previews changes without writing files, --transforms <ids> restricts execution to a comma-separated set of transform identifiers, --verbose shows detailed per-change output, --ignore <patterns...> adds glob patterns to ignore, and --list prints the available transforms for the selected migration. --list is the discovery mode to use before narrowing a run with --transforms; the runner validates requested IDs and throws an error that names unknown IDs and lists available IDs, which prevents a mistyped transform list from silently doing partial work.

Sources: packages/codemod/src/cli.ts, packages/codemod/src/runner.ts

Command or optionMeaningNotes
mcp-codemodExecutable nameDeclared in packages/codemod/package.json as ./dist/cli.mjs.
v1-to-v2 <target-dir>Run the v1 to v2 migrationTarget can be a project directory or a recognized source file.
--dry-runPreview without writingUse before touching a large tree.
--transforms <ids>Run selected transform IDsIDs are validated against the migration registry.
--verbosePrint detailed per-change outputUseful when reviewing why a file changed.
--ignore <patterns...>Add ignored glob patternsCombine with repo-specific generated-output exclusions.
--listList available transformsDoes not require a target.

Target Selection and File Rewrites

The codemod rewrites TypeScript and JavaScript source files with extensions .ts, .tsx, .mts, .cts, .js, .jsx, .mjs, and .cjs. Run it from a clean working tree because the normal mode edits files in place and the intended review workflow is to inspect the resulting diff. The CLI checks that the target exists and is either a directory or a supported source file, which catches common mistakes such as pointing at a missing path or an unsupported artifact. Its formatter guidance is also explicit: the codemod changes ASTs, but it does not reformat output.

Sources: packages/codemod/README.md, packages/codemod/src/cli.ts

Formatter guidance is part of the command contract rather than an afterthought. After a run, the CLI detects a formatter for the target directory and prints a command for the changed files, falling back to an example prettier --write invocation when it cannot identify one. This matters because several transforms intentionally create syntactically correct but not necessarily style-compliant output: wrapped schemas, generated string-literal method names, and import rewrites may violate a repository’s configured formatting. Treat formatting as the step after mechanical migration and before typechecking.

Sources: packages/codemod/src/cli.ts

What v1-to-v2 Changes

The README defines the migration’s coverage around source-of-truth mapping tables and transform directories. Import mappings route old @modelcontextprotocol/sdk/... paths to the v2 package split; symbol mappings handle renames such as McpError to ProtocolError; schema-to-method mappings rewrite request handlers from schema constants to method strings; and context-property mappings move extra.* usages toward ctx.mcpReq.* or ctx.http?.*. The transform layer goes beyond direct renames by rewriting tool registration, schema wrapping, spec schema imports, mock paths, dynamic imports, selected error-code references, and completable optional nesting.

Sources: packages/codemod/README.md

A useful mental model is that v1-to-v2 updates the SDK surface area, not the application architecture. It can convert many imports, calls, and type references because those changes have deterministic mappings. It cannot decide how your product should adopt new protocol behavior, redesign auth flows, or choose a transport strategy for removed APIs. The README explicitly calls out manual areas including CJS to ESM preparation, Node 20 readiness, some header read rewrites, OAuth error-class consolidation, scenario-specific SdkErrorCode branches, ctx.mcpReq.send() schema-argument drops, and behavioral adaptation.

Sources: packages/codemod/README.md

Diagnostics and Action-Required Markers

When the codemod recognizes a v1 pattern but cannot safely rewrite it, it leaves the code unchanged and inserts a comment beginning with @mcp-codemod-error. These markers are generated for ambiguous contexts, removed APIs without a mechanical replacement, or signature changes that require developer judgment. The README shows a marker for WebSocketClientTransport being removed in v2 and recommends searching the repository after the run with grep -rn '@mcp-codemod-error' .. That grep should be part of every migration checklist, because a clean command exit does not mean every semantic decision has been completed.

Sources: packages/codemod/README.md, packages/codemod/src/runner.ts

The runner implements marker insertion carefully. It gathers diagnostics that request inserted comments, sorts them in descending line order, merges multiple diagnostics on the same line, preserves indentation, sanitizes the message so it cannot prematurely close the block comment, and avoids inserting inside literal-like syntax nodes. This design keeps diagnostics close to the affected code while minimizing the chance that the diagnostic comment itself changes program meaning. For migration review, keep the comments until the associated code has been manually updated, then remove them as part of the same patch.

Sources: packages/codemod/src/runner.ts

Batch Testing and Regression Signals

The package includes a batch-test script and a separate executable source file for maintainers validating the codemod across real repositories. The batch-test source defines configuration for where the SDK packages come from, where the codemod comes from, version specs for published runs, and result directories. It also defines report structures with baseline check results, post-codemod check results, files changed, total changes, diagnostics, and optional CLI stdout/stderr when the published CLI path is used. This is not the everyday migration command, but it explains how the project measures codemod safety.

Sources: packages/codemod/package.json, packages/codemod/src/bin/batchTest.ts

For users, the important lesson from the batch-test design is to compare before and after. Establish a baseline with your existing typecheck, build, test, and lint commands before running the migration. Then run the codemod, install the v2 packages it reports or applies, format changed files, and repeat the same checks. Any new errors are migration regressions or manual follow-up items. The codemod’s own diagnostics are not the only signal; compiler and test failures often reveal behavioral changes that are outside the safe mechanical rewrite boundary.

Sources: packages/codemod/src/bin/batchTest.ts, packages/codemod/README.md

Start by creating a branch and confirming the working tree is clean. Run mcp-codemod v1-to-v2 --list to see the available transform IDs, then run npx @modelcontextprotocol/codemod@beta v1-to-v2 . --dry-run for a preview. If the preview is plausible, run the command without --dry-run, apply the manifest changes reported for your packages, and run the formatter command printed by the CLI. For very large codebases, use --ignore to skip generated directories and --transforms only when isolating a problem or bisecting a transform.

Sources: packages/codemod/src/cli.ts, packages/codemod/README.md

After the mechanical run, search for action-required markers, review the diff file by file, and run your normal checks. Do not treat this command as an adoption path for the 2026-07-28 protocol revision: the README states that changes such as createMcpHandler, multi-round-trip requests, and versionNegotiation are architectural and not codemod-automatable. Once the v1-to-v2 surface upgrade is stable, continue with the migration guide and protocol-revision documentation, especially if the application needs to opt into newer 2026-era behavior rather than simply compiling against the v2 package split.

Sources: packages/codemod/README.md