claude-code - 💡(How to fix) Fix MCP: tool result content[].text dropped from model when structuredContent is also present [1 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#55677Fetched 2026-05-03 04:47:19
View on GitHub
Comments
2
Participants
2
Timeline
6
Reactions
0
Author
Timeline (top)
labeled ×4commented ×2

When an MCP tool returns BOTH a content[].text part and structuredContent, Claude Code (CLI) appears to forward only structuredContent to the model. The text content is observable in the iframe-host machinery (so the host receives it) but the model never sees it.

This breaks tools that intentionally use the text part to give the model a human-presentable rendering of the data — e.g. a numbered candidate list with markdown links — while keeping structuredContent as a typed payload.

The same response shape works on Claude.ai web and on ChatGPT.

Root Cause

When an MCP tool returns BOTH a content[].text part and structuredContent, Claude Code (CLI) appears to forward only structuredContent to the model. The text content is observable in the iframe-host machinery (so the host receives it) but the model never sees it.

This breaks tools that intentionally use the text part to give the model a human-presentable rendering of the data — e.g. a numbered candidate list with markdown links — while keeping structuredContent as a typed payload.

The same response shape works on Claude.ai web and on ChatGPT.

Fix Action

Workaround

Duplicate model-targeted prose into structuredContent (e.g. as an agent_instructions string) until the filter is fixed. Live in our PR: https://github.com/sidis405/stashed.live/pull/111

Code Example

{
     "content": [
       { "type": "text", "text": "Found 6 candidates ...\n1. [link] 3ff8t — [The Unwritten Laws of Software Engineering](https://...) ...\n2. ..." }
     ],
     "structuredContent": {
       "status": "candidates_ready",
       "hit_count": 6,
       "fallback_used": false,
       "query": "engineering",
       "type": null,
       "hits": [...],
       "agent_instructions": "Present this list to the user ... Do not auto-pick."
     }
   }
RAW_BUFFERClick to expand / collapse

Summary

When an MCP tool returns BOTH a content[].text part and structuredContent, Claude Code (CLI) appears to forward only structuredContent to the model. The text content is observable in the iframe-host machinery (so the host receives it) but the model never sees it.

This breaks tools that intentionally use the text part to give the model a human-presentable rendering of the data — e.g. a numbered candidate list with markdown links — while keeping structuredContent as a typed payload.

The same response shape works on Claude.ai web and on ChatGPT.

Environment

  • Claude Code v2.1.126 (Opus 4.7, claude-opus-4-7)
  • macOS 25.4.0
  • Streamable HTTP MCP transport
  • Server: Laravel 13 / laravel/mcp v0

Reproduction

I have a working MCP server that emits a tool result with both content blocks. The server's behavior is verifiable from the wire side:

  1. Tool: find_in_stash_picker (search-and-pick over a personal stash).
  2. The tool returns:
    {
      "content": [
        { "type": "text", "text": "Found 6 candidates ...\n1. [link] 3ff8t — [The Unwritten Laws of Software Engineering](https://...) ...\n2. ..." }
      ],
      "structuredContent": {
        "status": "candidates_ready",
        "hit_count": 6,
        "fallback_used": false,
        "query": "engineering",
        "type": null,
        "hits": [...],
        "agent_instructions": "Present this list to the user ... Do not auto-pick."
      }
    }
  3. Server-side log of the wire response confirms BOTH content[0].text and structuredContent are sent. (Verified via the server's tool-call log table.)
  4. In Claude Code:
    • ctrl+o to expand the tool result shows ONLY the structuredContent JSON. The content[0].text is not visible in the expanded transcript.
    • The model paraphrases from structuredContent only ("The picker returned X hits, but the numbered list isn't showing in the response I got back — only the structured status payload"). The model literally tells the user it didn't receive the text part.
  5. Same response from the same server, same authenticated session, viewed in:
    • Claude.ai (web): the model receives both parts and presents the markdown-linked numbered list. ✅
    • ChatGPT (with MCP enabled): the model receives both parts and presents the list. ✅
    • Claude Code CLI: only structuredContent makes it to the model. ❌

Why it matters

Several MCP App / picker patterns put the user-facing prose in content[].text and the typed payload in structuredContent (per the MCP Apps spec on visibility: content and structuredContent are model-visible; _meta is iframe-only). When a host filters one of the two model-visible channels, tools have to duplicate everything into structuredContent. That works around it but is a real spec deviation.

In our case, after observing this, we ended up duplicating hits into structuredContent.hits and adding an agent_instructions string so models on Claude Code can still present the list. Worked, but the text content is the natural channel for that.

Possible cause

Inferred only — would need confirmation from the Claude Code team. Two hypotheses:

  1. The host filters out content[].text whenever the tool's tools/list entry declares _meta.ui.resourceUri (i.e. has a RendersApp annotation). We saw the filter persist even after we removed RendersApp and reconnected, so it may be tools/list cache stickiness OR a broader filter.
  2. The host always prefers structuredContent over content[].text when both are present and only forwards the structured part, regardless of RendersApp.

The behavior is consistent across Disconnect/Reconnect of the MCP connector and across new ccc sessions on a given install.

Expected

Per MCP spec / ext-apps#380, both content[].text and structuredContent should reach the model. Hosts may render content as the user-visible channel and structuredContent as the typed channel, but neither should be silently dropped from the model's transcript when both are present.

Cross-references

Workaround

Duplicate model-targeted prose into structuredContent (e.g. as an agent_instructions string) until the filter is fixed. Live in our PR: https://github.com/sidis405/stashed.live/pull/111

extent analysis

TL;DR

The issue can be worked around by duplicating the model-targeted prose into structuredContent, but the root cause appears to be Claude Code filtering out content[].text when structuredContent is present.

Guidance

  • Verify that the issue persists across different tools and MCP servers to rule out tool-specific or server-side issues.
  • Test with different types of content in content[].text to see if the filtering is content-agnostic.
  • Investigate the Claude Code documentation and source code to confirm the filtering behavior and potential workarounds.
  • Consider reaching out to the Claude Code team for confirmation of the issue and potential fixes.

Example

No code example is provided as the issue is more related to the behavior of the Claude Code CLI rather than a specific code snippet.

Notes

The issue seems to be specific to the Claude Code CLI, as the same response works on Claude.ai web and ChatGPT. The workaround of duplicating model-targeted prose into structuredContent is already implemented in the provided PR.

Recommendation

Apply the workaround of duplicating model-targeted prose into structuredContent until the root cause is confirmed and fixed by the Claude Code team. This ensures that the model receives the necessary information, even if it's not the ideal solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix MCP: tool result content[].text dropped from model when structuredContent is also present [1 pull requests, 2 comments, 2 participants]