[BUG] MCP tool parameters with type: number are sent as strings to MCP servers

Resolved 💬 11 comments Opened Mar 9, 2026 by kamalsingh11 Closed Jul 3, 2026

Environment

  • Claude Code version: 2.1.71
  • OS: macOS (Darwin 25.3.0)
  • MCP Server: @mobilenext/mobile-mcp v0.0.46 (MCP SDK v1.26.0)

Description

When Claude Code calls an MCP tool that declares parameters with "type": "number" in its JSON Schema, the values are sent as strings in the JSON-RPC call. MCP servers using strict Zod validation (z.number()) rightfully reject these with "expected number, received string".

Root Cause Analysis

The issue is in the XML-to-JSON-RPC pipeline:

  1. MCP server exposes tools/list with JSON Schema declaring "type": "number" for parameters
  2. Claude Code presents the schema to the Claude model
  3. Claude model generates tool calls in XML format: <parameter name="x">330</parameter>
  4. Claude Code parses the XML and sends JSON-RPC to the MCP server

The problem is at step 4. Everything in XML is inherently a string — there's no type distinction. Claude Code needs to use the JSON Schema from step 1 to coerce parameter values to their declared types before sending the JSON-RPC request. Currently, it passes raw strings through without coercion.

Reproduction

  1. Configure @mobilenext/mobile-mcp in .mcp.json:
{
  "mobile-mcp": {
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@mobilenext/mobile-mcp@latest"]
  }
}
  1. Call mobile_click_on_screen_at_coordinates with any numeric x/y values
  1. Expected: Parameters sent as JSON numbers ({"x": 330, "y": 200})
  2. Actual: Parameters sent as JSON strings ({"x": "330", "y": "200"})

Error from MCP Server

MCP error -32602: Input validation error: Invalid arguments for tool mobile_click_on_screen_at_coordinates: [
  {
    "expected": "number",
    "code": "invalid_type",
    "path": ["x"],
    "message": "Invalid input: expected number, received string"
  },
  {
    "expected": "number",
    "code": "invalid_type",
    "path": ["y"],
    "message": "Invalid input: expected number, received string"
  }
]

MCP Server Schema

The server uses Zod (z.number()) which converts to JSON Schema {"type": "number"} via zodToJsonSchema. The schema is correct — the server properly declares these as numbers.

// From mobile-mcp server.ts
x: z.number().describe("The x coordinate to click on the screen, in pixels"),
y: z.number().describe("The y coordinate to click on the screen, in pixels"),

Suggested Fix

When constructing the JSON-RPC arguments object for an MCP tool call, Claude Code should walk the tool's JSON Schema and coerce values to their declared types:

  • "type": "number"parseFloat(value)
  • "type": "integer"parseInt(value, 10)
  • "type": "boolean"value === "true"
  • "type": "string" → no change (default)
  • "type": "array" / "type": "object"JSON.parse(value)

This is similar to how the existing $ref serialization bug (#18260) manifests, but affects plain primitive types.

Impact

This breaks any MCP tool that uses z.number(), z.boolean(), or z.integer() for parameters, which is extremely common. Affected tools include coordinate-based interactions (click, swipe, long press), pagination parameters, numeric configuration values, etc.

Workaround

MCP server authors can use z.coerce.number() instead of z.number() to accept both strings and numbers, but this shouldn't be necessary — the client should honor the schema.

View original on GitHub ↗

This issue has 11 comments on GitHub. Read the full discussion on GitHub ↗