Context
Measured 2026-08-09 during the pro30 flatrate-drain investigation (operator's figures: 6% of the weekly budget in 68 minutes across the two kimi seats; 34% of the 5-hour session window in 1h8m). Turn volume × context size is the established root cause of the drain; this ticket is the largest mechanical amplifier found inside that root cause.
The Problem
Every MCP tool response from the fleet's servers (github-workflow, memory-core, knowledge-base) is delivered to the harness twice: once as the tool-result content and again as <mcp-structured-result> (structuredContent). For large responses the duplication is the dominant term — a 50-message list_messages unread dump is ~35 KB of payload and ~70 KB of context. Once in context, both copies ride along as input on every subsequent model call for the rest of the session.
Concrete session receipt (Kimi Code CLI seat, session d05afdba-d7f9-4733-b9da-e1a8a7946777): a boot-time mailbox triage, two list_issues board scans, and three get_conversation fetches together carried an estimated ~100+ KB of duplicate payload — every byte of it re-billed as input on each following turn. Both kimi seats (Kimi Code CLI and OpenCode) attach the same MCP servers, so the amplifier is harness-independent and fleet-wide.
The Architectural Reality
- MCP
CallToolResult allows both content and structuredContent; servers that populate both leave the rendering choice to the client. The fleet's MCP servers appear to populate both with the same JSON for every tool.
- The harness serializes the tool result into the model's context — both copies — so the cost is not per-fetch, it is per-fetch × every-subsequent-turn (context accumulation).
- The drain forensics to date (seat-cost reporter,
#16707/#16709/#16784) measured turn cadence and cache warmth; the per-response payload shape is an orthogonal multiplier nothing currently audits.
The Fix
Direction, not premature mechanism — the right owner may be the servers, the harness adapters, or both:
- Measure first: one instrumented turn per harness logging bytes-in-context per MCP tool, content-copy vs structured-copy — a one-hour experiment that sizes the amplifier honestly before any surgery.
- Server side: populate
structuredContent only where a client genuinely consumes it (or gate it behind a negotiated capability), so the default response carries the payload once.
- Harness side: where stripping is not possible, elide or truncate the duplicate at the adapter boundary for known fleet servers (the way the diff tool already pages large output to a file instead of into context).
Acceptance Criteria
Out of Scope
- Turn-cadence and cache-TTL work (the
WARM_WINDOWS / wake-poll economics) — measured elsewhere; this ticket is strictly the per-response payload shape.
- Non-fleet MCP servers.
Avoided Traps
- Do NOT estimate-and-fix. The two copies exist for a compatibility reason until measured otherwise; the probe in AC-1 precedes any surgery.
- Do NOT break structured consumers. Stripping
structuredContent where a client depends on it trades token savings for silent schema loss — the capability negotiation is the check.
Related
#16682 (context-budget / flatrate-drain parent thread) · #16707 / #16709 / #16784 (seat-cost reporter chain — the cadence half) · #16677 (MCP surface stability)
Decision Record impact: none.
Origin Session ID: d05afdba-d7f9-4733-b9da-e1a8a7946777
Retrieval Hint: MCP structuredContent duplicate payload double billing context amplifier flatrate drain list_messages
Context
Measured 2026-08-09 during the pro30 flatrate-drain investigation (operator's figures: 6% of the weekly budget in 68 minutes across the two kimi seats; 34% of the 5-hour session window in 1h8m). Turn volume × context size is the established root cause of the drain; this ticket is the largest mechanical amplifier found inside that root cause.
The Problem
Every MCP tool response from the fleet's servers (
github-workflow,memory-core,knowledge-base) is delivered to the harness twice: once as the tool-result content and again as<mcp-structured-result>(structuredContent). For large responses the duplication is the dominant term — a 50-messagelist_messagesunread dump is ~35 KB of payload and ~70 KB of context. Once in context, both copies ride along as input on every subsequent model call for the rest of the session.Concrete session receipt (Kimi Code CLI seat, session
d05afdba-d7f9-4733-b9da-e1a8a7946777): a boot-time mailbox triage, twolist_issuesboard scans, and threeget_conversationfetches together carried an estimated ~100+ KB of duplicate payload — every byte of it re-billed as input on each following turn. Both kimi seats (Kimi Code CLI and OpenCode) attach the same MCP servers, so the amplifier is harness-independent and fleet-wide.The Architectural Reality
CallToolResultallows bothcontentandstructuredContent; servers that populate both leave the rendering choice to the client. The fleet's MCP servers appear to populate both with the same JSON for every tool.#16707/#16709/#16784) measured turn cadence and cache warmth; the per-response payload shape is an orthogonal multiplier nothing currently audits.The Fix
Direction, not premature mechanism — the right owner may be the servers, the harness adapters, or both:
structuredContentonly where a client genuinely consumes it (or gate it behind a negotiated capability), so the default response carries the payload once.Acceptance Criteria
list_messages,list_issues,get_conversation) occupy context exactly once per harness, or the harness-side elision is documented as the chosen fix with the server shape left intact.Out of Scope
WARM_WINDOWS/ wake-poll economics) — measured elsewhere; this ticket is strictly the per-response payload shape.Avoided Traps
structuredContentwhere a client depends on it trades token savings for silent schema loss — the capability negotiation is the check.Related
#16682(context-budget / flatrate-drain parent thread) ·#16707/#16709/#16784(seat-cost reporter chain — the cadence half) ·#16677(MCP surface stability)Decision Record impact: none.
Origin Session ID: d05afdba-d7f9-4733-b9da-e1a8a7946777
Retrieval Hint:
MCP structuredContent duplicate payload double billing context amplifier flatrate drain list_messages