Tool call parameter closed with </content> instead of </parameter>, silently swallowing subsequent parameters
Summary
A tool call's string parameter is intermittently closed with a tag named after the parameter's name attribute value instead of </parameter>. Everything emitted after that point — including the remaining parameters — is swallowed into the string.
<parameter name="content">...long text...</content> <-- wrong closer
<parameter name="metadata">{"tags": "a,b"}</parameter> <-- swallowed into content
The call still succeeds. The receiving tool gets a content string with tool-call XML appended, and never receives metadata at all — so it silently applies defaults. Nothing errors, on either side.
Why this is worth a look
The failure is silent and lossy. In our case the swallowed parameter carried the tags used for retrieval, so affected records were stored untagged and effectively unfindable. It went unnoticed for roughly six weeks because a search over the corpus returns them looking perfectly normal — the damage is only visible if you inspect the tail of the stored string.
Any MCP tool with one long string parameter plus a smaller structured one is exposed to the same shape.
Evidence
Read-only analysis over a 21,682-row corpus of tool-call results accumulated 2026-04-30 → 2026-07-31.
27 genuine occurrences. The emitted closer is </content> in 27 of 27 — zero exceptions. Never </parameter>, never any other tag. The parameter in question is named content.
That invariant is the main thing I'd point at. A randomly hallucinated closer would produce variety across 27 samples spanning four months and multiple model versions; there is none. It is systematic, and the tag name matches the name attribute exactly.
Correlates with parameter length. Median length of the affected string was 2,899 characters vs 998 for unaffected calls in the same corpus. Roughly 27% of unaffected calls reach 1,600+ characters, so this is not simply "long calls are more common." Suggested reading: the further the closer is from the opening tag, the weaker the binding to the literal element name.
Not correlated with code fences — 0% of affected calls contained them, vs a 7.3% base rate. Worth stating because fenced content inside a parameter is the intuitive suspect and appears to be innocent here.
Four output shapes observed, differing only in how the next parameter got rendered after the closer went wrong — the initiating error is identical in all of them:
A </content> <parameter name="metadata">{json}</parameter>
B </content> <metadata>{json}</metadata>
C </content> <metadata><tags>a,b</tags><type>note</type></metadata>
D </content> </invoke>
Shapes B and C are notable: after the malformed closer, the model sometimes continues in an invented XML-element schema rather than the real parameter syntax.
Frequency note, stated carefully: raw counts per day rose over the period, but the days with the most occurrences are also the days with the most long calls. Conditioned on long calls the rate does not show a clean trend (ranging ~0–33% across days, most with single-digit denominators). I would not claim the rate is increasing — only that the failure is persistent and that length is a real per-call risk factor.
Reproduction
I do not have a deterministic repro, which is the main weakness of this report. It is intermittent and I can't trigger it on demand. What I can say is that it occurs at meaningful frequency on long string parameters — in our corpus, roughly 10–15% of calls above ~1,600 characters on the more recent sampled days.
Surfaces affected: it appears in stored results originating from multiple client surfaces, so it does not look specific to Claude Code's client.
The fix that would actually eliminate this
Accept </X> as a valid closer for <parameter name="X"> in the tool-call parser.
That is fully backward compatible — </parameter> keeps working — and it converts a silent, lossy, data-destroying failure into a correctly parsed call. Metadata would land, nothing would be lost, and no downstream repair would be needed.
Everything downstream can only mitigate. We ended up writing a server-side guard that detects the appended fragment, strips it, recovers the swallowed parameter, stores the record correctly, and flags it for review. It works, but it is a workaround for something only the parser can genuinely fix, and every other MCP server with a long string parameter would have to write its own.
Workaround for anyone hitting this
**Emit the small structured parameter before the long string one.** If the long parameter is last, a wrong closer has nothing after it to swallow but trailing machinery — the failure still occurs but becomes harmless. In the single observed case where the order was reversed, the other parameter survived intact.
Keeping individual calls shorter also reduces the rate, though that is a frequency mitigation rather than a fix.
Environment
- Claude Code CLI on Windows 11 (also observed in results originating from other surfaces)
- Receiving tool: a self-hosted MCP server (
memory_store-style: one longcontentstring, onemetadataobject) - Occurrences span 2026-04-30 → 2026-07-31 across multiple model versions
Happy to provide the shape-by-shape breakdown or per-day counts if useful. Corpus contents are personal so I can't share raw records, but the structural examples above are faithful to what was observed.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗