From cde46f231b22d23e47f5d6070fbc8452e253b648 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Mar 2026 18:36:52 +0000 Subject: [PATCH] fix(schemas): import from zod/v4 to match SDK's zod API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated schemas compose with schemas imported from @modelcontextprotocol/sdk/types.js (e.g. z.array(ContentBlockSchema)). The SDK constructs its schemas via `import * as z from 'zod/v4'`, but our generated schema.ts used `import { z } from "zod"` — which returns the v3 API when the consumer has zod 3.25.x installed. Mixing v3-created and v4-created schema instances throws at parse time with errors like `keyValidator._parse is not a function` because zod v4 dropped the `_parse` / `_parseSync` internals that v3 wrappers call. This was masked before #534 because zod was bundled — all schema creation shared the same inlined zod copy. Externalizing zod exposed the mismatch on consumers pinned to zod 3.x (e.g. anthropics/apps). The `zod/v4` subpath is exported by both zod 3.25+ and zod 4.x, so the existing peerDependency range `^3.25.0 || ^4.0.0` is preserved. https://claude.ai/code/session_013xQUegrvVGct5xpqeSL5av --- scripts/generate-schemas.ts | 24 ++++++++++++++++++------ src/generated/schema.test.ts | 2 +- src/generated/schema.ts | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/generate-schemas.ts b/scripts/generate-schemas.ts index 858ab914..109f3524 100644 --- a/scripts/generate-schemas.ts +++ b/scripts/generate-schemas.ts @@ -8,10 +8,15 @@ * * ts-to-zod is a powerful tool but has limitations that require post-processing: * - * ### 1. Zod Import Path (keep standard `"zod"` for version agnosticism) + * ### 1. Zod Import Path (`"zod"` → `"zod/v4"`) * - * ts-to-zod generates `import { z } from "zod"` which works with both - * Zod v3.25+ and v4. We keep this standard import to support both versions. + * ts-to-zod generates `import { z } from "zod"`. We rewrite this to + * `import { z } from "zod/v4"` because the generated schemas compose with + * schemas imported from `@modelcontextprotocol/sdk/types.js`, which the SDK + * constructs via `zod/v4`. Mixing schemas from the v3 and v4 APIs at runtime + * fails with errors like `keyValidator._parse is not a function` (v3 internals + * calling into v4 objects, or vice versa). The `zod/v4` subpath is exported by + * both zod 3.25+ and zod 4.x, so the peerDependency range is preserved. * * ### 2. External Type References (`z.any()` → actual schemas) * @@ -179,11 +184,13 @@ async function generateJsonSchema() { * Post-process generated schemas for project compatibility. */ function postProcess(content: string): string { - // 1. Add MCP SDK schema imports (keep standard zod import for v3/v4 compatibility) + // 1. Rewrite to zod/v4 and add MCP SDK schema imports. + // zod/v4 aligns with the SDK's own zod import — composing v3 and v4 + // schema instances throws at parse time. See header comment for details. const mcpImports = EXTERNAL_TYPE_SCHEMAS.join(",\n "); content = content.replace( 'import { z } from "zod";', - `import { z } from "zod"; + `import { z } from "zod/v4"; import { ${mcpImports}, } from "@modelcontextprotocol/sdk/types.js";`, @@ -257,7 +264,12 @@ function replaceRecordAndWithPassthrough(content: string): string { * Post-process generated integration tests. */ function postProcessTests(content: string): string { - // Keep standard zod import for v3/v4 compatibility + // Rewrite to zod/v4 so z.infer matches the v4 schemas in schema.ts. + content = content.replace( + 'import { z } from "zod";', + 'import { z } from "zod/v4";', + ); + content = content.replace( "// Generated by ts-to-zod", `// Generated by ts-to-zod diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index 47e59788..cebad70b 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -1,7 +1,7 @@ // Generated by ts-to-zod // Integration tests verifying schemas match TypeScript types // Run: npm run generate:schemas -import { z } from "zod"; +import { z } from "zod/v4"; import * as spec from "../spec.types.js"; import * as generated from "./schema.js"; diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 88797b50..8eb12b5a 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -1,7 +1,7 @@ // Generated by ts-to-zod // Post-processed for Zod v3/v4 compatibility and MCP SDK integration // Run: npm run generate:schemas -import { z } from "zod"; +import { z } from "zod/v4"; import { ContentBlockSchema, CallToolResultSchema,