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,