feat(mcp-server): output shaping & truncation framework (MCP Prompt 16)#4017
feat(mcp-server): output shaping & truncation framework (MCP Prompt 16)#4017gilgardosh wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a centralized output shaping and truncation utility (shapeListResult) to enforce payload size limits on list-producing tools, updating the charges, lookups, and reports tools to use it. The review feedback suggests spreading params.extra first in the structured output to prevent accidental key overrides, and improving the lookup tools' summaries to explicitly show the number of returned items when truncated.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
7dc10a7 to
2ef1248
Compare
Add a centralized formatter enforcing bounded, valid tool output (spec §9.3). - src/tools/output.ts: shapeListResult caps the serialized payload (MAX_TOOL_RESULT_BYTES) by dropping whole trailing items via binary search (never invalid JSON), reports returnedCount/totalCount/truncated, and adds a continuation hint (payload_size vs result_cap) when not all results are shown - retrofit all three tools (charges, tags/tax-categories, balance report) to build their results through the shared formatter; per-tool ad-hoc truncated flags removed in favor of the unified fields - unit tests for within-limit, result-cap continuation, payload-size guard (whole-item drops, valid JSON, prefix preserved, zero-fit), plus updated tool tests for the new output shape Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SPMszz9gdZFhNjobRm6Ndo
26a3413 to
6aa7d4f
Compare
There was a problem hiding this comment.
Pull request overview
Adds a centralized output shaping/truncation helper for MCP list-style tools, enforcing a byte cap by dropping whole trailing items (preserving valid JSON) and standardizing returnedCount/totalCount/truncated plus a continuation hint.
Changes:
- Introduced
shapeListResult(src/tools/output.ts) implementing byte-based truncation via whole-item drops and consistent metadata fields. - Retrofitted list-producing tools (
charges,lookups(tags/tax categories),balance_report) to use the shared formatter and updated their structured output shape. - Added/updated tests to validate within-limit behavior, result-cap truncation, payload-size truncation, and updated tool output assertions.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/mcp-server/src/tools/reports.ts | Uses shapeListResult for balance report rows and unified truncation metadata. |
| packages/mcp-server/src/tools/output.ts | New shared output shaping/truncation framework with byte cap + continuation hint. |
| packages/mcp-server/src/tools/lookups.ts | Refactors tag/tax-category tools to return shaped list results with unified counts/truncation. |
| packages/mcp-server/src/tools/charges.ts | Routes charge search output through the shared shaper; moves total count to totalCount. |
| packages/mcp-server/src/tools/tests/reports.test.ts | Updates balance report expectations to the new structured shape (totalCount, etc.). |
| packages/mcp-server/src/tools/tests/output.test.ts | Adds unit tests for shapeListResult (result cap + payload-size guard). |
| packages/mcp-server/src/tools/tests/lookups.test.ts | Updates lookups tests to assert totalCount and continuation reason semantics. |
| packages/mcp-server/src/tools/tests/charges.test.ts | Updates charges test assertions for totalCount/truncated and pagination shape. |
| packages/mcp-server/README.md | Documents the new shared formatter and unified truncation semantics for list tools. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review feedback on output.ts: - Normalize `total` to never be less than `items.length`, so a caller passing a too-small `total` can't produce `totalCount < returnedCount` or a wrong `truncated` flag. - Spread `extra` before the framework-owned keys so a colliding `extra` key can never overwrite the items array or the counts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SPMszz9gdZFhNjobRm6Ndo
Summary
Implements Prompt 16 – Output shaping and truncation framework (see
docs/mcp/spec.md§9.3). Adds a centralizedformatter that all list-producing tools use.
Changes
src/tools/output.ts—shapeListResult:MAX_TOOL_RESULT_BYTESby dropping whole trailing items (binary search over prefix length) so output is always valid JSON — never a structure cut mid-object.returnedCount/totalCount/truncated, and attaches acontinuationhint (payload_sizevsresult_cap) whenever not all results were returned.charges,list_tags,list_tax_categories, andbalance_reportnow build results through the shared formatter; the per-tool ad-hoctruncated/totalfields are unified intoreturnedCount/totalCount/truncated/continuation.Validation
yarn workspace @accounter/mcp-server test→ 173 passedyarn workspace @accounter/mcp-server lint/typecheck/build→ passNotes
truncated = returnedCount < totalCount, so both an upstream row cap and the byte guard surface the same way with a continuation hint. Tools pass the true upstream total (e.g.pageInfo.totalRecords, filtered count) so pagination "more available" is reflected.🤖 Generated with Claude Code
Generated by Claude Code