fix(server): bound mcp tool payloads on the wire - #5481
Conversation
MCP tool call payloads skipped the wire projection entirely, so `item.result.content` shipped whole tool results — a single connector fetch reaches 1MB, and one MCP-heavy thread ships 11.7MB of mcp_tool_call payloads out of 17.8MB total. Project them like every other tool payload instead: keep the call descriptor (tool, server, status, arguments, appContext, error, durationMs, type, id) and collapse `result` to the same one-line preview regular tool output already gets. Full payloads stay in SQLite. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved 2ede711 Straightforward performance fix that bounds MCP tool result payloads (which can reach megabytes) to prevent oversized wire payloads. Self-contained change with comprehensive test coverage, authored by the file's original creator. You can customize Macroscope's approvability policy. Learn more. |
|
Superseded by #5482, which merged the same MCP payload bounding. Closing in favor of the merged implementation. |
Problem
MCP tool call payloads were the one activity type that skipped the wire projection —
projectActivityPayloadearly-returned onitemType === "mcp_tool_call", sopayload.data.item.result.contentshipped the entire tool result. A single connector call (e.g. fetching a whole GitHub PR) reaches 1MB+, and one real MCP-heavy thread ships 11.7MB of mcp_tool_call payloads out of 17.8MB total wire size.Fix
Run MCP payloads through the projection like every other tool payload.
data.itemis retained with a bounded shape: the call descriptor (tool,server,status,arguments,appContext,error,durationMs,type,id) survives intact, anditem.resultcollapses to the same one-line preview that regular tool output already gets viasummarizeToolTextOutput.data.toolCallId/data.kindare retained as before.Both clients render
data.itemas JSON in the expanded work-log row and gate that row ondata.item !== undefined, so an item record always projects to a record — the descriptor plus a result preview still renders.tool.startedMCP rows go through the same path for consistency. Full payloads are untouched in SQLite and the event store; this only affects the wire.Tests
Added to
apps/server/test/ActivityPayloadProjection.test.ts: a 1MB+ result projects under 500 bytes while keeping tool/server/arguments/status, a small call keeps its fields, a failing call keepserrorandisError, and an in-flight call with no result still renders. Full server suite green (1873 passed).Changes made by Claude Fable 5 via Claude Code, running as a subagent of a planning session.
🤖 Generated with Claude Code
Note
Medium Risk
Changes orchestration wire payloads for a high-volume activity type; clients still get descriptors but lose full MCP result text in expanded work-log JSON unless they read persistence elsewhere.
Overview
MCP tool call activities are no longer exempt from wire projection.
projectActivityPayloadused to return them unchanged, so megabyte-scaleresult.contentshipped on thread snapshots and activity events.MCP rows now go through
projectMcpToolCallData: call metadata (tool,server,status,arguments,error,durationMs, etc.) stays ondata.item, whileresultis flattened from string or MCP text blocks (capped at 4KB) and collapsed to the same one-line preview other tools use viasummarizeToolTextOutput.isErroron failed tool results is preserved. In-flight calls without a result still expose a descriptor-onlyitemso clients’data.item !== undefinedchecks keep working.Tests cover bounded megabyte payloads, failures, and in-progress calls; the web/mobile parity loop now excludes MCP because expanded work-log JSON will show the summarized result instead of the full blob. Persistence and the event store are unchanged—only API projection is affected.
Reviewed by Cursor Bugbot for commit 2ede711. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Bound MCP tool call payloads on the wire by projecting and summarizing large results
ActivityPayloadProjection.tsto strip large result payloads down to a bounded summary.extractMcpResultText, then passed throughsummarizeToolTextOutput.type,id,tool,server,status,arguments,appContext,error,durationMs) are retained on the projected item;resultis replaced with{ content: summary }plusisErrorif the call failed.Macroscope summarized 2ede711.