Files
Max Isbey 801095acad Flag removed modules, update dependency files, add a batch-test harness
Three additions to mcp-codemod, closing the gaps a comparison with the
TypeScript codemod surfaced:

Imports of module namespaces v2 deleted outright (the experimental tasks
namespaces, the WebSocket transports, `mcp.shared.progress`) are now
marked with replacement guidance. A new ratchet test freezes the 107
public modules v1 shipped and asserts every one imports on v2, is
renamed, or is in the removed table, so the whole v1 module namespace is
provably accounted for.

The codemod now also updates the `mcp` requirement in `pyproject.toml`
(PEP 621 tables and dependency groups) and `requirements*.txt` to
`>=2,<3` -- only where the current constraint cannot accept any v2
release, and only the version specifier: name, extras, environment
marker, and spacing keep the user's spelling. Poetry tables and the
removed `ws` extra are marked instead of guessed at, under the same
`# mcp-codemod:` contract as source markers.

`scripts/codemod-batch-test/` runs the codemod against pinned real
repositories and audits the marker contract end to end: it type-checks
the pristine clone against the latest v1 and the migrated copy against
this workspace's v2 with identical pyright settings, then requires every
error that exists only on the migrated side to sit next to a marker.
Across the four repos in the manifest every migration-surface error is
covered, and the audit caught two real bugs now fixed here: `Context`
imported from the old `.server` submodule is rehomed to the package (the
submodule holds the name at runtime, but a type checker treats a
non-re-exported name as private), and `request_context` on a receiver
the pre-pass proved holds a lowlevel `Server` is flagged again --
receiver-matched, so the live `ctx.request_context` idiom stays
untouched.
2026-07-01 12:08:22 +00:00

1.8 KiB

Codemod batch test

Runs the mcp-codemod v1 -> v2 migration against real, pinned repositories and audits the result with pyright, to find silent misses the unit tests and the in-repo example corpus cannot.

How it works

For each repository in repos.json:

  1. Clone the pinned commit (shallow).
  2. Run the codemod (sources and dependency files) over a copy.
  3. Type-check the pristine clone against an environment holding the latest v1 SDK, and the migrated copy against this workspace's v2 environment, with identical pyright settings.
  4. Diff the two error sets. Errors only on the migrated side are the migration surface; baseline noise (the repo's own issues, missing third-party stubs) appears on both sides and cancels out.
  5. Correlate each new error with the inserted # mcp-codemod: markers.

The codemod's contract is that the markers are the complete list of remaining manual work, so every new error should sit on or next to a marker. A new error with no nearby marker is a silent miss -- those are printed, written to work/results/<slug>.json, and make the run exit 1.

Usage

From the repository root (the v1 environment is created on first run):

uv run --frozen python scripts/codemod-batch-test/run.py            # all repos
uv run --frozen python scripts/codemod-batch-test/run.py --repo mcp-obsidian
uv run --frozen python scripts/codemod-batch-test/run.py --fresh    # re-clone

Adding a repository

Add an entry to repos.json with a pinned sha (never a branch), an include list when only part of the repository uses the SDK (empty means the whole tree), and a one-line note. Prefer repositories that depend on the mcp package directly; servers built on the external FastMCP library exercise that library's surface, not this SDK's.