Skip to content

fix: accept null arguments in tools/call and return -32602 for validation errors#2013

Open
blackwell-systems wants to merge 3 commits intomodelcontextprotocol:mainfrom
blackwell-systems:fix/null-arguments-internal-error
Open

fix: accept null arguments in tools/call and return -32602 for validation errors#2013
blackwell-systems wants to merge 3 commits intomodelcontextprotocol:mainfrom
blackwell-systems:fix/null-arguments-internal-error

Conversation

@blackwell-systems
Copy link
Copy Markdown

Summary

  • CallToolRequestParamsSchema rejects null arguments with -32603 (InternalError) and a raw Zod error message. Fixed by adding z.preprocess() to coerce null to undefined before validation, preserving the existing type signature.
  • The protocol request handler uses schema.parse() which throws on validation failure. The thrown ZodError lacks a numeric code, so the error handler defaults to -32603. Changed to schema.safeParse() with an explicit ProtocolError(InvalidParams) on failure, returning -32602 as the JSON-RPC spec requires.

Motivation

Clients that serialize missing fields as null (common in Go, Java, and C# JSON libraries) get an opaque internal error when calling any tool without arguments. Tested against @modelcontextprotocol/server-everything: all 13 tools fail this way.

Changes

File Change
schemas.ts:1420 z.preprocess(val => val ?? undefined, ...) on arguments field
protocol.ts:390-397 schema.parse()schema.safeParse() + ProtocolError(InvalidParams)
types.test.ts 4 new tests: null, undefined, empty, and normal arguments

Test plan

  • pnpm run test:all passes (1,536 tests, 0 failures)
  • pnpm -r typecheck passes (no type changes, preprocess preserves existing signature)
  • pnpm -r lint passes (prettier formatting applied)
  • Verified against @modelcontextprotocol/server-everything over raw stdio: null arguments now accepted

Fixes #2012

…tion errors

Two issues:

1. CallToolRequestParamsSchema uses .optional() on the arguments field,
   which accepts undefined but rejects null. Clients that serialize
   missing fields as null (common in Go, Java, C# JSON libraries)
   get an internal error. Fixed with z.preprocess() to coerce null to
   undefined before validation, preserving the existing type signature.

2. The protocol request handler uses schema.parse() which throws on
   validation failure. The thrown ZodError lacks a numeric "code"
   property, so the error handler defaults to -32603 (InternalError).
   Changed to schema.safeParse() with an explicit ProtocolError
   using -32602 (InvalidParams) on failure.

Before: null arguments → -32603 with raw Zod error message.
After: null arguments → accepted (coerced to undefined).
Any remaining validation errors → -32602 with structured message.
@blackwell-systems blackwell-systems requested a review from a team as a code owner May 2, 2026 12:11
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 2, 2026

🦋 Changeset detected

Latest commit: b33d687

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

This PR includes changesets to release 1 package
Name Type
@modelcontextprotocol/core Patch

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 2, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2013

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2013

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2013

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2013

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2013

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2013

commit: b33d687

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.

tools/call with null arguments returns -32603 (InternalError) instead of being accepted

1 participant