fix(schemas): import from zod/v4 to match SDK's zod API (#548)
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
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1aa3c9c106
commit
eeb81c08bc
1 changed files with 20 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue