Repository navigation
Description
Summary
Claude Code appears to serialize integer-typed MCP tool parameters as JSON strings, breaking servers that strict-validate the type with typeof !== 'number'. The most reproducible failure is mcp__MCP_DOCKER__sequentialthinking, where every call rejects thoughtNumber as not-a-number even when the model emits it as an integer.
Reproduction
Call mcp__MCP_DOCKER__sequentialthinking with parameters that match its schema (thoughtNumber: integer ≥ 1, totalThoughts: integer ≥ 1, nextThoughtNeeded: boolean, thought: string):
mcp__MCP_DOCKER__sequentialthinking(
thought: "first thought",
thoughtNumber: 1,
totalThoughts: 1,
nextThoughtNeeded: false
)
Expected: success — server returns the next-thought response.
Actual:
{"error": "Invalid thoughtNumber: must be a number", "status": "failed"}Reproduces 3-for-3 in the same session, varying thought content. Confirmed against both npm @modelcontextprotocol/[email protected] (latest published) and the Docker bundle.
Evidence the parameters are stringified by the client
modelcontextprotocol/servers#2905 (now closed as a duplicate of #2792) contains a verbatim repro from another user where Claude Code's tool call line shows the integers as strings:
next_thought_needed: "true", thought_number: "1", total_thoughts: "10", is_revision: "false"
That user's diagnosis matches ours: "It attempts to use strings like \"1\" instead of integer value 1". The pattern is consistent with the symptom we observe.
Asymmetry / partial coercion
In our reproductions, nextThoughtNeeded (boolean) passed through fine while integers failed. The booleans-as-strings case in #2905 (is_revision: "false") suggests the same root cause hits booleans too on some code paths, but on our path booleans escape the defect. Worth narrowing whether the serialization differs by parameter position, by depth, or by model output formatting.
Server-side context
The strict validator on the server side at modelcontextprotocol/servers/src/sequentialthinking/index.ts (commit ec91421) is:
if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') {
throw new Error('Invalid thoughtNumber: must be a number');
}This was already softened to z.coerce.number().int().min(1) in PR modelcontextprotocol/servers#3533 (merged 2026-03-15, commit 1cdf806d21c3afdeb203c04705e8892d0f9d832f), but the fix has not been published — npm latest is still 2025.12.18. Tracked upstream in modelcontextprotocol/servers#3856. Once that release ships, the server will absorb the stringified params and this bug will become invisible — but the client-side stringification would remain a defect for any future MCP server that strict-validates types.
Impact
Blocks the canonical sequentialthinking branching/revision/synthesis pattern in our framework's skills (/audit-framework, /codify-issue, any new skill that adopts it). Workaround is inline-RCA in the main thread, which loses the auditable thought-by-thought reasoning trace.
Cross-references
modelcontextprotocol/servers#2905(closed, dup of Save session based on git branch #2792, contains the verbatim stringified repro)modelcontextprotocol/servers#2792(open, parent issue)modelcontextprotocol/servers#3856(open, awaiting npm release of the coercion fix)modelcontextprotocol/servers#3533(merged, the coercion fix)
Environment
- Claude Code on
darwin 25.5.0 - Model: Opus 4.7 (1M context)
- MCP server:
@modelcontextprotocol/[email protected](Docker bundle)
Activity
github-actions commentedon May 6, 2026
Found 2 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
github-actions commentedon May 9, 2026
This issue has been automatically closed as a duplicate of #32524.
If this is incorrect, please re-open this issue or create a new one.
🤖 Generated with Claude Code
github-actions commentedon Jun 28, 2026
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.