feat(codemod): manifest handling overhaul and fixes from migrating sample dependents (#2393)

This commit is contained in:
Felix Weinberger 2026-06-30 15:01:07 +01:00 • committed by GitHub
commit e4e8b22dff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
53 changed files with 4888 additions and 448 deletions

View file

@ -1,6 +1,6 @@
---
"@modelcontextprotocol/core-internal": minor
"@modelcontextprotocol/client": minor
'@modelcontextprotocol/core-internal': minor
'@modelcontextprotocol/client': minor
---
Add `SdkHttpError` subclass with typed `.status` / `.statusText` accessors for HTTP transport failures. `StreamableHTTPClientTransport` now throws `SdkHttpError` (which extends `SdkError`) for non-OK HTTP responses; `SSEClientTransport` throws `SdkHttpError` for 401-after-reauth (circuit breaker).

View file

@ -1,6 +1,6 @@
---
"@modelcontextprotocol/client": minor
"@modelcontextprotocol/server-legacy": minor
'@modelcontextprotocol/client': minor
'@modelcontextprotocol/server-legacy': minor
---
SEP-2468 follow-up: `transport.finishAuth()` gains a `URLSearchParams` overload (preferred) that extracts `code`/`iss`, validates `iss` first, and on mismatch throws a sanitized `IssuerMismatchError` (no callback `error_description` text); callers remain responsible for `state`. **Behavior change for `@modelcontextprotocol/server-legacy`:** `mcpAuthRouter` now advertises `authorization_response_iss_parameter_supported` (default `true`; `ProxyOAuthServerProvider` reports `false`) and the bundled authorize handler appends `iss` (RFC 9207) to every `res.redirect(...)` your `OAuthServerProvider.authorize()` issues to the client's `redirect_uri`. If your provider redirects another way (`res.writeHead`, a separate consent-page response, or a standalone `authorizationHandler({provider})` without `issuerUrl`), append `params.issuer` as `iss` yourself or set `authorizationResponseIssParameterSupported: false` — otherwise RFC 9207-compliant clients (including this SDK) will reject the callback.

View file

@ -1,6 +1,6 @@
---
"@modelcontextprotocol/core-internal": minor
"@modelcontextprotocol/client": minor
'@modelcontextprotocol/core-internal': minor
'@modelcontextprotocol/client': minor
---
Implement RFC 9207 / RFC 8414 §3.3 OAuth issuer validation (SEP-2468). `discoverAuthorizationServerMetadata()` now rejects metadata whose `issuer` does not match the discovery URL (opt out via `skipIssuerValidation` / `AuthOptions.skipIssuerMetadataValidation` — security-weakening). `auth()`, `exchangeAuthorization()`, `fetchToken()`, and `transport.finishAuth(code, iss?)` now validate the authorization-callback `iss` against the recorded issuer before redeeming the code; new `IssuerMismatchError` and `validateAuthorizationResponseIssuer()` are exported.

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': patch
---
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 stale `as ProtocolError`/`as McpError` casts bound to subjects whose assertions it moves to `SdkError`. 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).

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': patch
---
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 direct `McpServer` import 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`/`setNotificationHandler` with a schema _expression_ first argument get a marker pointing at the typed two-argument or custom three-argument form instead of being skipped silently, and `removeRequestHandler`/`removeNotificationHandler` with `Schema.shape.method.value` arguments 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.

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': minor
---
Three migration-sweep fixes. `completable()` calls whose first argument is an optional-wrapped schema are rewritten to apply `.optional()` to the `completable(...)` 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 of `Protocol` and `mergeCapabilities` from v1's `shared/protocol.js` are 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 (`fallbackRequestHandler` for 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 first `tools/list` depending on the imported zod entry point.

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': patch
---
Two long-standing intervention classes now migrate mechanically. `.code` reads on values an `instanceof SdkHttpError` check proves — in the same condition or the guarded block — rewrite to `.status` (v2 carries the HTTP status there; `.code` is an `SdkErrorCode` string); unprovable reads keep the existing warning. The context-property remap reaches three shapes the call-site scan missed: functions assigned to `fallbackRequestHandler`, 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.

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': minor
---
Migration-sweep batch. The ErrorCode split now coordinates with the surrounding check: an all-SDK condition's `instanceof ProtocolError`/`McpError` guard is rewritten to `SdkError`, a guard covering both enums gets a marker asking for a split, and an `ErrorCode` import 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 with `z.object()` adds `import { z } from 'zod'` when the file has no `z` value binding (a non-import `z` binding gets a marker instead). The context-parameter rewrite finds the trailing `extra` parameter, covering the three-argument `registerResource` template callback without flagging its `variables` argument. 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 rewritten `SdkHttpError` constructor site gets a marker, and single-argument `finishAuth(...)` calls in files the run changes get a run-log note (the one-argument `URLSearchParams` form 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".

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': minor
---
Overhaul manifest handling. The codemod now discovers workspace-member manifests (npm/yarn/bun `workspaces` and `pnpm-workspace.yaml`), writes only the nearest `package.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 (pnpm `node_modules` layouts contain cycles that previously aborted the run) and honors `--ignore` patterns during directory descent. Manifests whose `zod` range cannot satisfy the v2 floor get a warning describing the runtime failure mode. `RunnerResult.packageJsonChanges` is now an array of per-manifest changes with optional `warnings` and `notes`.

View file

@ -0,0 +1,5 @@
---
'@modelcontextprotocol/codemod': patch
---
The explicit-`undefined` result-schema removal now requires the same proof as the schema-identifier path: `request()` calls must carry a provably literal spec method, and `callTool()` 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 bespoke `end.request('ping', undefined, id)` helper), corrupting the call.

View file

@ -7,8 +7,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [
"@modelcontextprotocol/examples",
"@mcp-examples/*"
]
"ignore": ["@modelcontextprotocol/examples", "@mcp-examples/*"]
}

View file

@ -2,4 +2,4 @@
'@modelcontextprotocol/server': patch
---
fix(server): propagate negotiated protocol version to transport in _oninitialize
fix(server): propagate negotiated protocol version to transport in \_oninitialize

View file

@ -1,6 +1,6 @@
---
"@modelcontextprotocol/core-internal": minor
"@modelcontextprotocol/server": major
'@modelcontextprotocol/core-internal': minor
'@modelcontextprotocol/server': major
---
Fix error handling for unknown tools and resources per MCP spec.

View file

@ -1,5 +1,5 @@
---
"@modelcontextprotocol/client": patch
'@modelcontextprotocol/client': patch
---
fix(client): append custom Accept headers to spec-required defaults in StreamableHTTPClientTransport

View file

@ -1,106 +1,106 @@
{
"mode": "pre",
"tag": "alpha",
"initialVersions": {
"@modelcontextprotocol/eslint-config": "2.0.0",
"@modelcontextprotocol/tsconfig": "2.0.0",
"@modelcontextprotocol/vitest-config": "2.0.0",
"@modelcontextprotocol/examples": "2.0.0-alpha.0",
"@modelcontextprotocol/client": "2.0.0-alpha.0",
"@modelcontextprotocol/core-internal": "2.0.0-alpha.0",
"@modelcontextprotocol/express": "2.0.0-alpha.0",
"@modelcontextprotocol/fastify": "2.0.0-alpha.0",
"@modelcontextprotocol/hono": "2.0.0-alpha.0",
"@modelcontextprotocol/node": "2.0.0-alpha.0",
"@modelcontextprotocol/server": "2.0.0-alpha.0",
"@modelcontextprotocol/server-legacy": "2.0.0-alpha.0",
"@modelcontextprotocol/core": "2.0.0-alpha.0",
"@modelcontextprotocol/codemod": "2.0.0-alpha.0",
"@modelcontextprotocol/test-conformance": "2.0.0-alpha.0",
"@modelcontextprotocol/test-helpers": "2.0.0-alpha.0",
"@modelcontextprotocol/test-integration": "2.0.0-alpha.0",
"@modelcontextprotocol/test-e2e": "2.0.0-alpha.0"
},
"changesets": [
"abort-handlers-on-close",
"add-consumer-sse-e2e",
"add-core-public-package",
"add-e2e-test-suite",
"add-fastify-middleware",
"add-hono-peer-dep",
"add-resource-size-field",
"add-sdk-http-error",
"add-server-legacy-package",
"bound-resumability-version-gates",
"brave-lions-glow",
"busy-rice-smoke",
"busy-weeks-hang",
"cfworker-out-of-barrel",
"codemod-core-routing",
"codemod-infer-project-type",
"codemod-resolve-legacy-imports",
"codemod-streamablehttperror-sdkhttperror",
"codemod-task-handler-methods",
"custom-methods-minimal",
"cyan-cycles-pump",
"draft-spec-non-sep-conformance",
"drop-zod-peer-dep",
"export-inmemory-transport",
"expose-auth-server-discovery",
"expose-icons-on-tools-and-prompts",
"express-resource-server-auth",
"extract-task-manager",
"fast-dragons-lead",
"finish-sdkerror-capability",
"fix-abort-listener-leak",
"fix-conformance-server-leak",
"fix-oauth-5xx-discovery",
"fix-onerror-callbacks",
"fix-server-protocol-version",
"fix-session-status-codes",
"fix-stdio-epipe-crash",
"fix-stdio-windows-hide",
"fix-streamable-close-reentrant",
"fix-streamable-http-error-response",
"fix-task-session-isolation",
"fix-transport-exact-optional-property-types",
"fix-unknown-tool-protocol-error",
"fix-validate-client-metadata-url",
"funky-baths-attack",
"gentle-planets-rest",
"heavy-walls-swim",
"hono-peer-optional",
"idjag-spec-type-export",
"legacy-module-resolution-types",
"oauth-error-http200",
"odd-forks-enjoy",
"quick-islands-occur",
"reconnection-scheduler",
"register-rawshape-compat",
"remove-websocket-transport",
"respect-capability-negotiation",
"restore-task-wire-types",
"rich-hounds-report",
"schema-object-type-for-unions",
"sep-2577-deprecate-runtime-apis",
"sep-2663-tasks-removal",
"sep-414-trace-context-meta-keys",
"shy-times-learn",
"spec-reference-types-2026-07-28",
"spec-type-schema",
"spotty-cats-tickle",
"stdio-max-buffer-size",
"stdio-skip-non-json",
"stdio-subpath-export",
"support-standard-json-schema",
"tame-camels-greet",
"tender-snails-fold",
"token-provider-composable-auth",
"twelve-dodos-taste",
"use-scopes-supported-in-dcr",
"workerd-shim-vendors-cfworker",
"wraphandler-hook",
"zod-json-schema-compat",
"zod-jsonschema-fallback"
]
"mode": "pre",
"tag": "alpha",
"initialVersions": {
"@modelcontextprotocol/eslint-config": "2.0.0",
"@modelcontextprotocol/tsconfig": "2.0.0",
"@modelcontextprotocol/vitest-config": "2.0.0",
"@modelcontextprotocol/examples": "2.0.0-alpha.0",
"@modelcontextprotocol/client": "2.0.0-alpha.0",
"@modelcontextprotocol/core-internal": "2.0.0-alpha.0",
"@modelcontextprotocol/express": "2.0.0-alpha.0",
"@modelcontextprotocol/fastify": "2.0.0-alpha.0",
"@modelcontextprotocol/hono": "2.0.0-alpha.0",
"@modelcontextprotocol/node": "2.0.0-alpha.0",
"@modelcontextprotocol/server": "2.0.0-alpha.0",
"@modelcontextprotocol/server-legacy": "2.0.0-alpha.0",
"@modelcontextprotocol/core": "2.0.0-alpha.0",
"@modelcontextprotocol/codemod": "2.0.0-alpha.0",
"@modelcontextprotocol/test-conformance": "2.0.0-alpha.0",
"@modelcontextprotocol/test-helpers": "2.0.0-alpha.0",
"@modelcontextprotocol/test-integration": "2.0.0-alpha.0",
"@modelcontextprotocol/test-e2e": "2.0.0-alpha.0"
},
"changesets": [
"abort-handlers-on-close",
"add-consumer-sse-e2e",
"add-core-public-package",
"add-e2e-test-suite",
"add-fastify-middleware",
"add-hono-peer-dep",
"add-resource-size-field",
"add-sdk-http-error",
"add-server-legacy-package",
"bound-resumability-version-gates",
"brave-lions-glow",
"busy-rice-smoke",
"busy-weeks-hang",
"cfworker-out-of-barrel",
"codemod-core-routing",
"codemod-infer-project-type",
"codemod-resolve-legacy-imports",
"codemod-streamablehttperror-sdkhttperror",
"codemod-task-handler-methods",
"custom-methods-minimal",
"cyan-cycles-pump",
"draft-spec-non-sep-conformance",
"drop-zod-peer-dep",
"export-inmemory-transport",
"expose-auth-server-discovery",
"expose-icons-on-tools-and-prompts",
"express-resource-server-auth",
"extract-task-manager",
"fast-dragons-lead",
"finish-sdkerror-capability",
"fix-abort-listener-leak",
"fix-conformance-server-leak",
"fix-oauth-5xx-discovery",
"fix-onerror-callbacks",
"fix-server-protocol-version",
"fix-session-status-codes",
"fix-stdio-epipe-crash",
"fix-stdio-windows-hide",
"fix-streamable-close-reentrant",
"fix-streamable-http-error-response",
"fix-task-session-isolation",
"fix-transport-exact-optional-property-types",
"fix-unknown-tool-protocol-error",
"fix-validate-client-metadata-url",
"funky-baths-attack",
"gentle-planets-rest",
"heavy-walls-swim",
"hono-peer-optional",
"idjag-spec-type-export",
"legacy-module-resolution-types",
"oauth-error-http200",
"odd-forks-enjoy",
"quick-islands-occur",
"reconnection-scheduler",
"register-rawshape-compat",
"remove-websocket-transport",
"respect-capability-negotiation",
"restore-task-wire-types",
"rich-hounds-report",
"schema-object-type-for-unions",
"sep-2577-deprecate-runtime-apis",
"sep-2663-tasks-removal",
"sep-414-trace-context-meta-keys",
"shy-times-learn",
"spec-reference-types-2026-07-28",
"spec-type-schema",
"spotty-cats-tickle",
"stdio-max-buffer-size",
"stdio-skip-non-json",
"stdio-subpath-export",
"support-standard-json-schema",
"tame-camels-greet",
"tender-snails-fold",
"token-provider-composable-auth",
"twelve-dodos-taste",
"use-scopes-supported-in-dcr",
"workerd-shim-vendors-cfworker",
"wraphandler-hook",
"zod-json-schema-compat",
"zod-jsonschema-fallback"
]
}

View file

@ -1,7 +1,7 @@
---
"@modelcontextprotocol/core-internal": minor
"@modelcontextprotocol/server": major
"@modelcontextprotocol/client": minor
'@modelcontextprotocol/core-internal': minor
'@modelcontextprotocol/server': major
'@modelcontextprotocol/client': minor
---
`resources/read` for an unknown URI now answers with JSON-RPC error code `-32602`

View file

@ -3,4 +3,5 @@
'@modelcontextprotocol/server': major
'@modelcontextprotocol/client': major
---
SEP-2663: remove 2025-11 experimental tasks (TaskManager, experimental.tasks.* accessors). Tasks are now Extensions Track.
SEP-2663: remove 2025-11 experimental tasks (TaskManager, experimental.tasks.\* accessors). Tasks are now Extensions Track.

View file

@ -13,9 +13,13 @@ Tool and prompt registration now accepts any schema library that implements the
```typescript
import { type } from 'arktype';
server.registerTool('greet', {
inputSchema: type({ name: 'string' })
}, async ({ name }) => ({ content: [{ type: 'text', text: `Hello, ${name}!` }] }));
server.registerTool(
'greet',
{
inputSchema: type({ name: 'string' })
},
async ({ name }) => ({ content: [{ type: 'text', text: `Hello, ${name}!` }] })
);
```
For raw JSON Schema (e.g. TypeBox output), use the new `fromJsonSchema` adapter:
@ -23,12 +27,17 @@ For raw JSON Schema (e.g. TypeBox output), use the new `fromJsonSchema` adapter:
```typescript
import { fromJsonSchema } from '@modelcontextprotocol/server';
server.registerTool('greet', {
inputSchema: fromJsonSchema({ type: 'object', properties: { name: { type: 'string' } } })
}, handler);
server.registerTool(
'greet',
{
inputSchema: fromJsonSchema({ type: 'object', properties: { name: { type: 'string' } } })
},
handler
);
```
**Breaking changes:**
- `experimental.tasks.getTaskResult()` no longer accepts a `resultSchema` parameter. Returns `GetTaskPayloadResult` (a loose `Result`); cast to the expected type at the call site.
- Removed unused exports from `@modelcontextprotocol/core-internal`: `SchemaInput`, `schemaToJson`, `parseSchemaAsync`, `getSchemaShape`, `getSchemaDescription`, `isOptionalSchema`, `unwrapOptionalSchema`. Use the new `standardSchemaToJsonSchema` and `validateStandardSchema` instead.
- `completable()` remains Zod-specific (it relies on Zod's `.shape` introspection).

View file

@ -1,5 +1,5 @@
---
"@modelcontextprotocol/express": patch
'@modelcontextprotocol/express': patch
---
Add jsonLimit option to createMcpExpressApp

View file

@ -6,6 +6,9 @@ Codemods for migrating MCP TypeScript SDK code between major versions.
```bash
npx @modelcontextprotocol/codemod@alpha v1-to-v2 .
# or a single source file (manifest changes are reported, not applied)
npx @modelcontextprotocol/codemod@alpha v1-to-v2 src/server.ts
```
The codemod rewrites TypeScript and JavaScript source files
@ -33,8 +36,14 @@ raw shapes with `z.object()`), drop the result-schema argument from `client.requ
`@modelcontextprotocol/core`, rename
`StreamableHTTPError` → `SdkHttpError` / `IsomorphicHeaders` → `Headers`, rewrite
`SchemaInput<T>` → `StandardSchemaWithJSON.InferInput<T>`, route
`ErrorCode.{RequestTimeout,ConnectionClosed}` to `SdkErrorCode`, and rewrite `vi.mock`
/ `jest.mock` / dynamic `import()` paths.
`ErrorCode.{RequestTimeout,ConnectionClosed}` to `SdkErrorCode` (rewriting an
all-SDK condition's `instanceof ProtocolError` guard to `SdkError`, and marking
guards that mix the two enums), add `import { z } from 'zod'` when a wrap needs
it, rewrite `vi.mock`
/ `jest.mock` / dynamic `import()` paths, invert optional completable nesting
(`completable(schema.optional(), cb)` becomes `completable(schema, cb).optional()`),
and drop `Protocol` / `mergeCapabilities` (no v2 export) with an action-required
marker naming the replacement.
## `@mcp-codemod-error` markers
@ -54,7 +63,8 @@ grep -rn '@mcp-codemod-error' .
## What it does NOT cover
CJS→ESM / Node 20 pre-flight, `new Headers()` / `.get()` access rewrites, OAuth
CJS→ESM / Node 20 pre-flight, header **read** rewrites (`ctx.http?.req?.headers`
bracket access → `.get()`; sending plain-record headers keeps working), OAuth
error-class consolidation (`instanceof InvalidGrantError` → `OAuthError` +
`OAuthErrorCode`), per-scenario `SdkErrorCode` branch selection, `ctx.mcpReq.send()`
schema-arg drop, and behavioral adaptation are manual — see the

Some files were not shown because too many files have changed in this diff Show more