Skip to content

fix(server): handle ZodEffects in normalizeObjectSchema and getObjectShape#1865

Open
pch007 wants to merge 1 commit intomodelcontextprotocol:v1.xfrom
pch007:fix/zod-effects-normalize-object-schema
Open

fix(server): handle ZodEffects in normalizeObjectSchema and getObjectShape#1865
pch007 wants to merge 1 commit intomodelcontextprotocol:v1.xfrom
pch007:fix/zod-effects-normalize-object-schema

Conversation

@pch007
Copy link
Copy Markdown

@pch007 pch007 commented Apr 8, 2026

Summary

Schemas wrapped with .superRefine(), .refine(), or .transform() become ZodEffects (v3) or pipe types (v4) that lack .shape, causing normalizeObjectSchema() to return undefined and tools/list to fall back to EMPTY_OBJECT_JSON_SCHEMA.

Changes

  • Adds unwrapZodEffects() helper that walks _def.schema chains (v3 ZodEffects) with a depth bound of 10 to prevent infinite loops
  • Updates normalizeObjectSchema() to detect v3 ZodEffects and v4 pipe types wrapping ZodObjects, returning the original schema so zodToJsonSchema() / toJSONSchema() can extract correct JSON Schema
  • Updates getObjectShape() to extract shape through ZodEffects/pipe wrappers for both Zod versions

Tests

Adds 4 new tests verifying tools/list returns correct JSON Schema properties for .superRefine(), .refine(), .transform(), and nested ZodEffects chains. All tests run against both Zod v3 and v4.

All 1587 existing tests pass. Lint + Prettier clean.

Impact

Fixes: tools registered with refined/transformed schemas now correctly advertise their input properties to MCP clients. Without this fix, any tool using Zod refinements loses its schema information in the tools/list response, making it impossible for clients to know what parameters the tool accepts.

…Shape

Schemas wrapped with `.superRefine()`, `.refine()`, or `.transform()`
become ZodEffects (v3) or pipe types (v4) that lack `.shape`, causing
`normalizeObjectSchema()` to return `undefined` and `tools/list` to
fall back to `EMPTY_OBJECT_JSON_SCHEMA`.

This fix:
- Adds `unwrapZodEffects()` helper that walks `_def.schema` chains
  (v3 ZodEffects) with a depth bound of 10 to prevent infinite loops
- Updates `normalizeObjectSchema()` to detect v3 ZodEffects and v4
  pipe types wrapping ZodObjects, returning the original schema so
  `zodToJsonSchema()` / `toJSONSchema()` can extract correct JSON Schema
- Updates `getObjectShape()` to extract shape through ZodEffects/pipe
  wrappers for both Zod versions

Adds 4 new tests verifying `tools/list` returns correct JSON Schema
properties for `.superRefine()`, `.refine()`, `.transform()`, and
nested ZodEffects chains. All tests run against both Zod v3 and v4.

Fixes: tools registered with refined/transformed schemas now correctly
advertise their input properties to MCP clients.
@pch007 pch007 requested a review from a team as a code owner April 8, 2026 23:29
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

🦋 Changeset detected

Latest commit: ac01b14

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 8, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@1865

commit: ac01b14

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.

1 participant