Skip to content

fix(server): emit object schema for wrapped Zod inputs in tools/list#2159

Open
cogeor wants to merge 4 commits into
modelcontextprotocol:v1.xfrom
cogeor:fix/issue-2145-zod-effects-tools-list
Open

fix(server): emit object schema for wrapped Zod inputs in tools/list#2159
cogeor wants to merge 4 commits into
modelcontextprotocol:v1.xfrom
cogeor:fix/issue-2145-zod-effects-tools-list

Conversation

@cogeor
Copy link
Copy Markdown

@cogeor cogeor commented May 27, 2026

Fixes #2145

Summary

tools/list emits inputSchema: {} (and silently drops outputSchema) for tools whose schema is wrapped in ZodEffects / ZodPipeline (.refine, .superRefine, .transform, .pipe), because normalizeObjectSchema only walks unwrapped ZodObjects.

Fix: mirror the fallback validateToolInput already uses at the two emission sites, and widen toJsonSchemaCompat's first parameter from AnyObjectSchema to AnySchema. When normalizeObjectSchema can't unwrap, hand the original schema to the converter. zod-to-json-schema (v3) and z4mini.toJSONSchema (v4) walk those wrappers natively and drop the refinement body, so no wrapper-type list is maintained across zod versions. Validation isn't touched.

Scope is limited to tools/list emission. validateToolOutput has the same broken pattern (safeParseAsync(undefined, ...) crashes on a wrapped outputSchema) but is already covered by #2106 (#1308), so leaving it alone here to keep ownership clean.

Test plan

New tools/list with wrapped inputSchema (issue #2145) describe block in test/server/mcp.test.ts, parametrized over .refine / .superRefine / .transform / .pipe, under the existing zodTestMatrix (Zod v3 and v4):

  • For each wrapper: tools/list emits an inputSchema with type: "object" and properties containing both fields.
  • For each wrapper: tools/call with valid args passes; for .refine / .superRefine, args violating the rule still fail validation.
  • Regression: tool with no inputSchema still emits EMPTY_OBJECT_JSON_SCHEMA.
  • A tool with a wrapped outputSchema now has it emitted in tools/list (previously dropped).

20 new tests pass (10 per zod version). Typecheck and eslint clean on changed files.

…tools/list

normalizeObjectSchema doesn't unwrap ZodEffects / ZodPipeline (.refine,
.superRefine, .transform, .pipe), so the tools/list emission sites were
falling back to {} (input) or dropping outputSchema entirely. validateToolOutput
had the same shape and would crash on safeParseAsync(undefined, ...).

Mirror the fallback validateToolInput already uses: when normalizeObjectSchema
returns undefined, hand the original schema to the converter / parser.
zod-to-json-schema (v3) and z4mini.toJSONSchema (v4) walk those wrappers
natively and drop the refinement body, so the underlying object's properties
come through without us maintaining a wrapper-type list across zod versions.

Widens toJsonSchemaCompat's first parameter from AnyObjectSchema to AnySchema
so it accepts wrapped schemas. Validation against the wrapped schema is
unchanged (still parses the original) — only the JSON Schema emission and
output-validation parsing change.

Fixes modelcontextprotocol#2145

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cogeor cogeor requested a review from a team as a code owner May 27, 2026 08:50
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 27, 2026

🦋 Changeset detected

Latest commit: b54fd1a

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 May 27, 2026

Open in StackBlitz

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

commit: b54fd1a

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cogeor and others added 2 commits May 27, 2026 11:08
…ol#2106

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cogeor cogeor force-pushed the fix/issue-2145-zod-effects-tools-list branch from ba016fd to b54fd1a Compare May 27, 2026 09:38
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