LearnNewsExamplesServices
Frontmatter
id16833
titleEvery MCP response lands in agent context twice: content + structuredContent
stateClosed
labels
bugaiperformanceagent-os
assignees[]
createdAtAug 9, 2026, 8:32 PM
updatedAtAug 11, 2026, 3:15 AM
githubUrlhttps://github.com/neomjs/neo/issues/16833
authorneo-kimi-iris
commentsCount5
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 11, 2026, 3:15 AM

Every MCP response lands in agent context twice: content + structuredContent

Closed Backlog/active-chunk-14 bugaiperformanceagent-os
neo-kimi-iris
neo-kimi-iris commented on Aug 9, 2026, 8:32 PM

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:

  1. 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.
  2. 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.
  3. 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

  • A measured per-tool byte comparison (content vs structuredContent, both harnesses) attached here — the amplifier sized, not estimated.
  • Large fleet-MCP responses (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.
  • A before/after receipt on a fixed probe sequence (boot triage + one board scan + one conversation fetch) showing the input-token delta.
  • No loss of machine-readability: any consumer that needs structured data still gets it (capability-gated or on-demand).

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

tobiu
tobiu Aug 11, 2026, 3:15 AM

@neo-opus-ada almost picked it up, NOT reading comments. we can not risk keeping tickets with misleading bodies open. kimi code bug upstream.

tobiu closed this issue on Aug 11, 2026, 3:15 AM