[BUG] MCP tool wrapper concatenates parameter XML into one string field instead of serializing structured args
Environment
- Claude Code 2.1.150
- Model: Claude Opus 4.7 (1M context) —
claude-opus-4-7[1m] - MCP server: any server advertising an
additionalProperties: trueinput_schema for a tool with multiple parameters (one long-text, one object-shaped), reachable over Streamable HTTP.
What's wrong
When Claude Code's MCP wrapper calls a tool whose input_schema is permissive ({"type": "object", "additionalProperties": true}) and the model emits a tool_use block with multiple parameters — one with multi-line string content, another with object content — the on-the-wire JSON-RPC payload concatenates ALL parameters as text into the FIRST parameter's slot, with the subsequent parameters appearing as literal XML tag wrapping inside that string. The structured non-first parameters arrive empty.
Minimal reproduction
Any MCP server advertising:
{
"name": "example_tool",
"inputSchema": { "type": "object", "additionalProperties": true }
}
Invoke this tool with:
body= a multi-line string of proseattributes= a JSON object like{"key1": "value1", "key2": "value2"}
The MCP server receives a JSON-RPC tools/call with:
{
"name": "example_tool",
"arguments": {
"body": "...the prose...</body>\n<parameter name=\"attributes\">{\"key1\": \"value1\", ...}</parameter>",
"attributes": {}
}
}
Two consecutive corrupted records were observed in this state, each with:
bodycontaining a literal</body>\n<parameter name=\"attributes\">{...JSON...}</parameter>suffixattributesfield arriving as empty object{}
Direct curl POST to the same endpoint with the same tool call content (structured JSON arguments in JSON-RPC) lands cleanly. The MCP server parses JSON-RPC correctly. The corruption is upstream of the wire — in how Claude Code's wrapper serializes the tool_use XML into JSON-RPC arguments.
Hypothesis
When the input_schema is open (additionalProperties: true), the wrapper's tool-arg serializer appears to fall back to concatenating the emitted parameter XML as text instead of parsing each <parameter name=\"..\">value</parameter> block into a structured arguments field. Tight-typed schemas (e.g. properties: {body: {type: \"string\"}}) likely route through the correct code path; permissive schemas trigger the broken path.
Why it matters
- MCP 2026-07-28 (release candidate locked 2026-05-21) allows servers to advertise permissive schemas during transition. Servers that have not yet derived per-command schemas are uncallable from Claude Code's MCP wrapper for any tool with complex args.
- Consumer-side workaround: bypass the wrapper and POST JSON-RPC directly via
curl. Works, but defeats the integration ergonomics MCP is supposed to provide.
Expected behavior
Claude Code's wrapper should serialize each <parameter> block's value as a structured JSON-RPC argument, regardless of how permissive the server's input_schema is. The schema's role is validation, not serialization control.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗