---
title: structuredContent or Text? What the Model Sees in MCP
description: Does the model see structuredContent or text from your MCP tool? Two-marker test: Claude Code structured only, OpenCode text only, Codex both. What to send.
canonical: https://spiritroom.app/blog/mcp-structuredcontent-vs-text/
published: 2026-10-21
updated: 2026-10-21
---

> Markdown version of https://spiritroom.app/blog/mcp-structuredcontent-vs-text/ for agents. Index: /llms.txt

[Blog](/blog/) / [Tool results and errors](/guides/tool-results-and-errors-for-agents/)

# structuredContent or text? Which half of your MCP result the model actually sees

The MCP spec lets a tool return its result twice: once as text and once as structuredContent, and recommends sending both for compatibility. So many servers do. But the model doesn't get both. Each agent app picks a half, and they don't pick the same one.

Leonid Bugaev · Published 21 Oct 2026

**TL;DR**

- **Each app shows the model one half, and not the same half.** In a two-marker test, Claude Code passed only the `structuredContent` marker (2 of 2 runs), OpenCode only the text marker (2 of 2), and Codex both (2 of 2).
- **Same result on 16 and 21 October**, across Claude Code 2.1.301 and 2.1.304.
- **Sending both doubles the payload on the wire.** On a 99-tool production server, 27 of 34 read tools sent the same data twice; one default result was 21,547 tokens of text plus 18,039 of structured JSON.
- **Codex can pay for both.** When the model printed a raw result in code mode, both halves were serialized: 67,251 tokens, then truncated.
- **Fix:** put the full data in `structuredContent` and a short summary with next steps in the text, so every app gets something useful and nobody gets the data twice.
[The two-marker test](#test)[What each app passed to the model](#results)[What duplication costs](#cost)[What to send instead](#send)[How we measured](#how-we-measured)[FAQ](#faq)

## The two-marker test

To see which half reaches the model, you need the halves to differ. Our test server has one tool. Its text content carries the marker `TXT-7Q4`; its `structuredContent` carries `STR-9Z2`. We ask each app to call the tool once and report every marker it can see, without guessing. Then we check the app's transcript for what it passed on.

```
{"content": [{"type": "text", "text": "TEXT_PART: marker TXT-7Q4"}],
 "structuredContent": {"part": "STRUCTURED_PART", "marker": "STR-9Z2"}}
```

A model can't report a marker it never saw, so this is a clean read on what each app does with a dual result.

## What each app passed to the model

Two-marker test, 21 Oct 2026 (2 runs per app)

| App | Text marker | Structured marker | What the transcript holds |
| --- | --- | --- | --- |
| Claude Code 2.1.304 | 0/2 | **2/2** | Structured JSON only |
| Codex 0.161.0 | **2/2** | **2/2** | Both halves |
| OpenCode 1.18.34 | **2/2** | 0/2 | Text only |

Server sends text + structured**→**Claude Code: structured**/**Codex: both**/**OpenCode: text

We ran the same test on 16 October with Claude Code 2.1.301 and OpenCode 1.18.34 and got the same result for both. It matches public reports: Claude Code users have noticed text being hidden when structured content is present ([#9962](https://github.com/anthropics/claude-code/issues/9962), [#45575](https://github.com/anthropics/claude-code/issues/45575)), and Codex made structuredContent the preferred function output ([PR #2594](https://github.com/openai/codex/pull/2594)), with users reporting dropped content blocks ([#10334](https://github.com/openai/codex/issues/10334)). In our runs Codex's model still saw both, because in code mode it gets the whole result object.

The practical consequence: if your text says something the structured half doesn't, such as “call get\_item next” or “results are truncated, use offset”, Claude Code's model never reads it. If your structured half has fields the text lacks, OpenCode's model never sees them.

**Find out what the model really sees from your tools.**

We run your users' jobs through Claude Code, Codex and the other apps they use, capture what each one passes to the model, and show where your results are dropped, duplicated or cut.

[Test your MCP →](/#contact)

## What duplication costs

On the wire, sending both halves sends the data twice. We measured a 99-tool production server where 27 of 34 read tools did exactly that, with no `outputSchema` on any tool:

Activity feed, text half*21,547*

Activity feed, structured half*18,039*

Item list, text half*25,806*

Item list, structured half*20,550*

Because each app picks one half, most runs don't pay double in the model's context. But the client still receives both, and Codex can pay for both: when its model printed a raw result in code mode, both halves were serialized, “original token count: 67,251”, and the output was truncated. Large results have their own limits per app; see [MCP output limits by agent](/blog/mcp-tool-output-limits-by-agent/).

## What to send instead

1. **Full data in `structuredContent`**, with an `outputSchema` so clients know its shape.
2. **A short text summary**: what was returned, how many, whether there's more, and the next useful call. Not the same data serialized again.
3. **Put anything the model must read in both**, briefly. A “truncated, use offset=10” note belongs in the structured half too, for Claude Code.
4. **Test it with markers** in your own server, per app, after each client update. Behaviour has changed between versions before.

```
{"content": [{"type": "text", "text": "12 tasks blocked in Mobile app (showing 10). Next: offset=10."}],
 "structuredContent": {"items": [...], "total": 12, "next_offset": 10}}
```

Small, summarised results helped every model in our tests: see [should your MCP server look different to each model?](/blog/per-model-mcp-tool-surfaces/) For the wider question of which MCP channels agents use, see [MCP prompts, resources and tools](/blog/mcp-prompts-resources-tools-which-agents-use/).

**Go deeper:** [Tool results for AI agents](/guides/tool-results-and-errors-for-agents/), [Pagination for agents](/blog/reduce-mcp-tool-response-size/), [Error messages for AI agents](/blog/error-messages-for-ai-agents/).

## How we measured

- **Two-marker server:** a 12-line stdio MCP server with one read-only tool whose text and structured halves carry different markers.
- **Runs:** 2 per app on 21 Oct 2026, about 21:40 (UTC+3): Claude Code 2.1.304 and Codex CLI 0.161.0 with default models, OpenCode 1.18.34 with a small free model. Each isolated from other servers. Earlier capture: 16 Oct 2026, Claude Code 2.1.301 and OpenCode 1.18.34; Codex's raw-print figure is from a live run the same day.
- **Evidence:** the marker the model reported, checked against the tool result recorded in each app's transcript.
- **Production sizes:** recorded default results from a 99-tool production server, counted in `o200k_base`, 16 Oct 2026.
- **Limits:** 2 runs per app is enough for a yes/no on a deterministic behaviour, not for rates. Grok Build and OpenCode 2 weren't re-tested.

## FAQ

### Does Claude Code show the model structuredContent or text?

structuredContent. When a tool result had both, Claude Code passed only the structured JSON to the model and dropped the text, in 2 of 2 runs on 21 October 2026 (version 2.1.304) and in the same test on 16 October (2.1.301).

### Does Codex use structuredContent from MCP tools?

Codex's model reported both the text and the structured marker in 2 of 2 runs. Codex's own code prefers structuredContent for the function output, but in code mode the model gets the whole result object, so a raw print serializes both halves.

### Does OpenCode show structuredContent?

No. OpenCode 1.18.34 passed only the text content to the model in 2 of 2 runs; the structured marker never reached it.

### Should my MCP tool return text, structuredContent or both?

Both, but not the same data twice. Put the full data in structuredContent, declare an outputSchema, and make the text a short summary with the next step. Apps that show only text still get the gist; apps that show only structured get the data.

### Why are my MCP tool results so large?

Often because the same data is sent twice, as text and as structuredContent. On one production server that was true for 27 of 34 read tools. Check the raw result size, and see which half each app actually uses.

**Find out what the model really sees from your tools.**

We run your users' jobs through Claude Code, Codex and the other apps they use, capture what each one passes to the model, and show where your results are dropped, duplicated or cut.

[Test your MCP →](/#contact)

## Keep reading

- Up[Tool results and errors for AI agents (guide)](/guides/tool-results-and-errors-for-agents/)
- Related[How to reduce MCP tool response size: measured before and after](/blog/reduce-mcp-tool-response-size/)
- Related[MCP prompts vs resources vs tools: which ones agents actually see (tested in 5 agent apps)](/blog/mcp-prompts-resources-tools-which-agents-use/)
- Related[MCP output limits by agent: Claude Code, Codex, OpenCode and Grok Build compared](/blog/mcp-tool-output-limits-by-agent/)
