[BUG] MCP stdio encoder glues following parameter's tag fragment onto previous string parameter (likely root cause for #895, #51962)

Resolved 💬 3 comments Opened Apr 25, 2026 by machdat Closed Apr 28, 2026

Preflight Checklist

  • [x] I have searched existing issues
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

When Claude Code calls an MCP tool via the stdio bridge with multiple parameters, the closing tag of one parameter and the opening markup of the next can be literally glued onto the previous string parameter's value. The tool engine then sees the next parameter as missing — which is the symptom reported in #895 and #51962 ("required parameter X is missing"), but the root cause is parameter-value contamination upstream in the encoder, not a missing parameter.

This was caught directly because the receiving MCP server (KanPrompt, https://github.com/machdat/kanprompt-v2) added a server-side validator (parameter_tag_pollution, HTTP 422) after observing silent data corruption: payloads from a Claude Code session were arriving with the next parameter's tag fragment appended to a previous parameter's value, and the actual target field arriving as NULL.

What Should Happen?

Each parameter's value must arrive at the tool exactly as Claude emitted it, without being merged with neighbouring parameter markup. If a string ends with a closing-like substring (e.g. punctuation, a paragraph break, or a verbatim </tag> reference inside a code block), the encoder must still terminate the parameter cleanly.

Repro (deterministic at server side)

  1. Configure any MCP tool that accepts at least two string parameters where the first parameter is a multi-line summary/description.
  2. From Claude Code (stdio MCP bridge), call the tool with a multi-line first parameter ending in a period or newline, followed by additional string parameters.
  3. Server-side validators that inspect the raw arguments JSON observe that the first parameter's string ends with </firstparam>\n<parameter name="secondparam">VALUE appended verbatim, and secondparam is absent from the arguments object.

Concrete example we hit (KanPrompt finalize_card, server v2.28.0+):

{
  "type": "value_error",
  "loc": ["body"],
  "msg": "Field 'summary' contains a tool-call/parameter-tag fragment ('</summary>') at offset 370. ... [code=parameter_tag_pollution]",
  "input": {
    "summary": "<...intended summary text...>...ändert.</summary>\n<parameter name=\"changed_files\">streams/events.py (NEU), ...",
    "deviations": "Keine.",
    "open_issues": "..."
  }
}

changed_files is missing from input entirely — its value got concatenated onto summary.

Why I think this is the same root cause as #895 / #51962

  • #895 ("Write failed: required parameter content is missing"): if the encoder glues content's value onto file_path, the engine sees a Write call with only file_path. Symptom matches exactly.
  • #51962: same symptom in Write, sporadic, "session-state dependent or timing-dependent". The KanPrompt repro suggests it's actually content-shape dependent: a multi-line first parameter ending with trailing punctuation is one trigger.

Workaround

Keep first parameter values short and single-line. We confirmed this in our session: a long multi-line summary reproduced the bug; a short ASCII single-line summary did not.

Claude Model

Claude Opus 4.7 (1M context), claude-opus-4-7[1m].

Claude Code Version

2.1.120

MCP Server Version

KanPrompt MCP server 2.30.0 (validator added in 2.28.0).

Platform / OS

Windows 11 Pro 22621, Git Bash.

Additional Information

The receiving MCP server is open-source: https://github.com/machdat/kanprompt-v2

The validator that catches this lives at src/services/escape_normalizer.py::check_parameter_tag_pollution. There is an internal bug card documenting the exact server-side behaviour (110ca293-7832-41e3-9c0d-0ce8c22ec4e2 in the kanprompt-v2 board); happy to share more concrete logs / fixtures on request.

Related issues: #895, #51962, #47189, #46528, #50184 — all show the "silent parameter drop" symptom from different angles.

View original on GitHub ↗

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