Claude Code MCP Bridge Silently Coerces All Non-String Parameters to Strings
Claude Code MCP Bridge Silently Coerces All Non-String Parameters to Strings
What you expect
Claude Code’s MCP bridge is documented as a transparent pass-through layer: the tool call you define is the tool call that reaches the MCP server. Parameters of any JSON type — numbers, arrays, objects, booleans — should transit unmodified. This is the standard expectation for any protocol bridge.
What actually happens
The MCP bridge coerces every non-string parameter to its string representation before forwarding it to the MCP server. There is no error message, no type warning, and no log entry. From Claude Code’s perspective the tool call succeeds. The downstream tool silently receives the wrong types:
count: 5(number) arrives ascount: "5"(string)tags: ["a", "b"](array) arrives astags: "[\"a\",\"b\"]"(string)enabled: true(boolean) arrives asenabled: "true"(string)
Any MCP connector that uses strict Zod schema validation on input parameters will fail silently or produce undefined behavior. The only observable symptom is that the connector behaves incorrectly — no error propagates back to identify the root cause.
Two additional configuration failure modes compound the problem:
Wrong config file silently ignored. The intuitive location for user-level MCP config is ~/.claude/mcp.json. That file is silently ignored. The only honored location is ~/.claude.json. Tools configured in the wrong file never appear, with no warning. This is a confirmed open bug.
MCP servers load at session initialization only. Adding or modifying .mcp.json mid-session has no effect. The session must be restarted to pick up any config changes.
Subagent MCP constraints. Project-scoped MCP tools (registered via .mcp.json) are not accessible inside custom subagents — the failure surfaces as silent tool-not-found. Background agents (run_in_background: true) have no MCP access at all. The orchestrating session must handle all project-scoped MCP calls on behalf of subagents.
What this means for you
Any team building typed MCP connectors on top of Claude Code is operating with a type system that does not hold at the bridge layer. Strict Zod schemas will trigger failures that produce no diagnostic signal — the failure looks like a connector logic error, not a transport coercion problem. Debugging time is lost on the wrong layer.
Multi-agent architectures using project-scoped MCP servers must centralize all MCP tool calls in the orchestrating session. Subagents cannot be given MCP responsibilities without architecture changes. Teams that miss this constraint may build subagent workflows that silently do nothing rather than fail loudly.
What to do
- Treat every MCP parameter as potentially a string. In connector schema definitions, accept
string | Tunions and parse defensively on arrival. Do not rely on JSON type enforcement at the bridge. - Place user-level MCP config in
~/.claude.json, not~/.claude/mcp.json. Verify withclaude mcp listafter adding any tool — if it does not appear, the config is in the wrong location. - Restart sessions after
.mcp.jsonchanges. Mid-session modifications are not picked up. Treat Claude Code sessions as having an immutable MCP configuration from startup. - Centralize project-scoped MCP calls in the orchestrator. Subagents should not be designed to invoke project-scoped tools directly. Pass results through the orchestrator instead.
- Use
CLAUDE_CODE_REMOTE=trueto detect cloud-hosted web sessions (where this env var is set) vs. local CLI sessions (where it is unset) in hooks and conditional logic.
Falsification criterion: This finding would be disproved by a Claude Code release that correctly forwards typed JSON parameters to MCP servers (verifiable by sending a number-typed parameter and observing it arrive as a number in the server-side handler), or by documentation confirming that ~/.claude/mcp.json is a supported config path.
Evidence
| Tool | Version | Evidence | Result |
|---|---|---|---|
| Anthropic/Claude Code | validated 2026-05-03 | docs-reviewed | MCP bridge stringifies all non-string parameters; confirmed via Zod connector failures |
| Anthropic/Claude Code | validated 2026-05-03 | docs-reviewed | ~/.claude/mcp.json silently ignored; confirmed open bug |
| Anthropic/Claude Code | validated 2026-05-03 | docs-reviewed | Project-scoped MCP tools inaccessible to subagents and background agents |
Confidence: empirical — 3 environments reviewed (connector failure, config file path, subagent scoping).
Strongest case against: Claude Code’s tooling surface is actively developed. The parameter coercion behavior could be a bridge-layer normalization choice that changes silently in a patch release. The ~/.claude/mcp.json path issue is a confirmed open bug, suggesting it is on the fix list. Teams on auto-update policies may find this fixed before they encounter it. The subagent MCP constraint may be an intentional sandboxing decision rather than a bug, in which case it would not be “fixed” but instead formalized in documentation.
Open questions: Is the parameter coercion behavior intentional (normalization) or a bug? Is there a version of Claude Code where typed parameters are honored? Are there workaround flags or environment variables that preserve parameter types in transit?
Seen different? Contribute your evidence — share a repro or counter-example and we’ll review it against this finding. Reader evidence is what keeps these findings accurate.