MCP error results drop structuredContent, leaving the model with an unactionable string

Status Open
Maintainer reply None cached
Activity 1 comment · opened Aug 12, 2026

Summary

When an MCP tool returns isError: true, Claude Code renders only content[0].text and does not surface structuredContent. For servers that put their diagnostic detail in structuredContent — the field names that failed validation, the offending key, the constraint violated — that detail never reaches the model.

The model is left with a single opaque string and no way to ask a follow-up question.

What I observed

An MCP server (obsidian-tc) formats tool errors like this:

content: [{ type: "text", text: `Error [${error.code}]: ${error.message}` }],
structuredContent: error,   // full Zod issues live here
isError: true,

Every error surfaced in Claude Code as exactly:

Error [validation_error]: input validation failed

The server had computed the field-level detail and attached it. It was not rendered.

Impact

This is not cosmetic. In one session the missing detail cost hours: the actual cause was a single misspelled envelope key (arguments instead of args). With no field name to work from, the model reasoned forward from the opaque string and produced three confident wrong diagnoses in sequence — a permissions problem, then a broken server, then an architectural workaround built on top of both — each reported to the user as a finding before the real cause was found by reading the server's source.

Every one of those wrong turns was preventable by one line of text the server had already generated.

Agents cannot interrogate an error. Whatever is rendered is the entire diagnostic surface, so dropping the structured half is disproportionately expensive compared to a human hitting the same message in a GUI.

Note on the spec

I want to be fair about this: structuredContent is specified as the counterpart to a tool's outputSchema, so ignoring it for a tool that declares no outputSchema may well be intentional and spec-compliant. Servers arguably should duplicate critical detail into the text block, and I have filed that suggestion upstream too.

But given how many servers put error detail there, and how costly the loss is specifically for an agent, it seems worth surfacing on the client side regardless — even as a fallback that only applies when isError is true.

Suggested behaviour

When isError: true and structuredContent is present, render it (or a compact summary) alongside the text block, rather than dropping it. A fallback scoped to error results would avoid changing anything about the normal outputSchema path.

Environment

  • Claude Code, in the Claude Desktop app (macOS 15, arm64)
  • MCP server over stdio

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗