Skip to content

Numeric ID issue #18

Description

@climberg-san

Update tools fail when Claude Desktop sends numeric IDs (e.g. deal_id) as strings

Description

When using this server with Claude Desktop on Windows, update calls (e.g. update_deal, update_organization) consistently fail with a type validation error on the ID parameter. The error occurs regardless of how the ID is formatted on the model's side (plain number, quoted string, with/without leading zeros) — the request is rejected before it reaches the handler logic.

Read and create operations work fine (occasionally need a retry), but update operations fail every time, across multiple entity types.

Root cause

This is a known, documented behavior in Claude Desktop / Claude Code, not specific to this server. Claude builds tool calls internally as XML, where every value is inherently a string. When that gets converted into the JSON-RPC call sent to the MCP server, the originally declared parameter type from the tool's JSON Schema isn't used to coerce the value — so a numeric ID declared as number/integer (or expected as a numeric string) can still arrive in a form that fails strict validation.

This has been independently confirmed in at least two other places:

Anthropic's own Claude Code repo: anthropics/claude-code#32524 — "MCP tool parameters with type: number are sent as strings to MCP servers."
GitHub's official MCP server: github/github-mcp-server#2044 — explicitly reproduces this with Claude Desktop sending "5812" instead of 5812 for a pullNumber parameter, causing Expected number, received string.

Existing fix to model this on

GitHub already shipped a fix for this exact issue in their MCP server: github/github-mcp-server#2130. Summary of the approach:

Replaced strict Decode with WeakDecode to coerce numeric values passed as strings.
Updated required-int validation to convert string → int before validating.

The equivalent fix here would likely be using Zod's coercion schema (z.coerce.number() / z.coerce.string() as appropriate) instead of strict z.number() / z.string() for ID-like parameters on update/write tools, so that a numeric ID arriving as either a string or a number is accepted.

Suggested solutions (from the GitHub issue discussion)

Accept both types in the schema (e.g. oneOf: [{type: "number"}, {type: "string", pattern: "^\d+$"}]).
Pre-validation coercion — normalize string-encoded numbers to actual numbers before schema validation runs (this is what the merged GitHub PR does, and what z.coerce.number() achieves in Zod).

Environment

OS: Windows 11
Client: Claude Desktop
Server: comma-compliance/pipedrive-mcp (latest main, stdio transport)

Happy to test a fix if useful — this currently blocks all update operations for our team.

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