Skip to content

Consider type coercion for tool arguments #1361

@domdomegg

Description

@domdomegg

Problem

Models occasionally send tool arguments with incorrect JSON types - for example, numbers serialized as strings ({"thoughtNumber": "1"} instead of {"thoughtNumber": 1}). This causes Zod validation to reject otherwise valid requests.

This issue affects many MCP servers. For example, modelcontextprotocol/servers#2812 added a specific workaround to one part of the sequential-thinking server, but the maintainers noted this feels like the wrong layer to fix it.

The "proper" fix is probably smarter models, or as a consistent layer in the SDKs. This would avoid server authors either having to implement ad-hoc coercion logic OR suffer from these problems.

Proposal

The SDK could provide type coercion for tool arguments, either:

  1. Built-in coercion - automatically coerce string→number, string→boolean etc. when the schema expects a different primitive type (e.g. similar to https://ajv.js.org/coercion.html)
  2. Composable helper - export a coerceToolArgs(schema, args) utility that servers can use
  3. Documentation - guidance on how to handle this with Zod's .coerce or .preprocess (but doing so safely so that e.g. "thing" doesn't become true when coerced to bool)

Example

// Current: fails validation
const args1 = { thoughtNumber: "1" }  // model sent number string
const args2 = { thoughtNumber: "one" }  // model sent string
const schema = z.object({ thoughtNumber: z.number() })
schema.parse(args1)  // ZodError: Expected number, received string
schema.parse(args2)  // ZodError: Expected number, received string

// With coercion: works
const coercedSchema = z.object({ thoughtNumber: z.coerce.number() })
coercedSchema.parse(args1)  // { thoughtNumber: 1 }
coercedSchema.parse(args2)  // ZodError: Expected number, received string

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions