Skip to content

fix(schemas): import from zod/v4 to match SDK's zod API#548

Merged
ochafik merged 1 commit intomainfrom
claude/bump-ext-apps-version-XAu7w
Mar 10, 2026
Merged

fix(schemas): import from zod/v4 to match SDK's zod API#548
ochafik merged 1 commit intomainfrom
claude/bump-ext-apps-version-XAu7w

Conversation

@ochafik
Copy link
Contributor

@ochafik ochafik commented Mar 10, 2026

Problem

After externalizing zod in #534, consumers on zod 3.25.x hit keyValidator._parse is not a function at runtime when parsing schemas that compose with SDK types.

Root cause

src/generated/schema.ts imports { z } from "zod" and then composes with schemas from @modelcontextprotocol/sdk/types.js:

import { z } from "zod";                              // ← v3 API when consumer has zod@3.x
import { ContentBlockSchema, ... } from "@modelcontextprotocol/sdk/types.js";  // ← v4 instances (SDK uses zod/v4)

// later: z.array(ContentBlockSchema), z.object({...params: CallToolResultSchema}), etc.
  • In zod 3.25.x, import { z } from "zod" returns the v3 API
  • In zod 4.x, the same import returns the v4 API
  • The SDK always uses import * as z from 'zod/v4'always v4 API

When a v3-created wrapper (z.array, z.object, z.record) parses a v4 schema instance, it tries to call the v3 internal ._parse() / ._parseSync() — which zod v4 removed. Result: TypeError: keyValidator._parse is not a function.

This was masked before #534 because zod was bundled — all schemas shared one inlined zod copy. Externalizing exposed the mismatch on zod-3.x consumers (e.g. anthropics/apps#27234).

Fix

Import from "zod/v4" in generated schemas. This subpath is exported by both zod 3.25+ and zod 4.x, so the existing peerDependencies.zod: "^3.25.0 || ^4.0.0" range is preserved.

Consumer zod "zod" import "zod/v4" import SDK schemas Compat
3.25.x v3 API v4 API v4 ✅ (after fix)
4.x v4 API v4 API v4

Testing

  • npm test — 121 pass
  • npx tsc --noEmit — typecheck clean (including schema.test.ts z.infer round-trip)
  • ✅ Verified dist loads and parses in apps repo context with zod@3.25.76 (previously crashed)
  • npm run build:all — all examples build (via pre-commit hook)

https://claude.ai/code/session_013xQUegrvVGct5xpqeSL5av

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
@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

Preview

Preview deployments for this PR have been cleaned up.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 10, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/@modelcontextprotocol/ext-apps@548

@modelcontextprotocol/server-basic-preact

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-preact@548

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-react@548

@modelcontextprotocol/server-basic-solid

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-solid@548

@modelcontextprotocol/server-basic-svelte

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-svelte@548

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vanillajs@548

@modelcontextprotocol/server-basic-vue

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vue@548

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/@modelcontextprotocol/server-budget-allocator@548

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/@modelcontextprotocol/server-cohort-heatmap@548

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/@modelcontextprotocol/server-customer-segmentation@548

@modelcontextprotocol/server-debug

npm i https://pkg.pr.new/@modelcontextprotocol/server-debug@548

@modelcontextprotocol/server-map

npm i https://pkg.pr.new/@modelcontextprotocol/server-map@548

@modelcontextprotocol/server-pdf

npm i https://pkg.pr.new/@modelcontextprotocol/server-pdf@548

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/@modelcontextprotocol/server-scenario-modeler@548

@modelcontextprotocol/server-shadertoy

npm i https://pkg.pr.new/@modelcontextprotocol/server-shadertoy@548

@modelcontextprotocol/server-sheet-music

npm i https://pkg.pr.new/@modelcontextprotocol/server-sheet-music@548

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/@modelcontextprotocol/server-system-monitor@548

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/@modelcontextprotocol/server-threejs@548

@modelcontextprotocol/server-transcript

npm i https://pkg.pr.new/@modelcontextprotocol/server-transcript@548

@modelcontextprotocol/server-video-resource

npm i https://pkg.pr.new/@modelcontextprotocol/server-video-resource@548

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/@modelcontextprotocol/server-wiki-explorer@548

commit: e746b73

@ochafik ochafik requested a review from antonpk1 March 10, 2026 19:09
@ochafik ochafik merged commit eeb81c0 into main Mar 10, 2026
22 checks passed
@ochafik ochafik deleted the claude/bump-ext-apps-version-XAu7w branch March 10, 2026 19:11
ochafik added a commit that referenced this pull request Mar 10, 2026
Changes since 1.2.1:
- fix(schemas): import from zod/v4 to match SDK's zod API (#548)
- test(e2e): fix no-op security injection test via frames[] traversal (#540)
ochafik added a commit that referenced this pull request Mar 10, 2026
Changes since 1.2.1:
- fix(schemas): import from zod/v4 to match SDK's zod API (#548)
- test(e2e): fix no-op security injection test via frames[] traversal (#540)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants