Skip to content

feat: cap individual tool response sizes#1029

Draft
jmikitova wants to merge 1 commit into
masterfrom
feat/cap-tool-response-size
Draft

feat: cap individual tool response sizes#1029
jmikitova wants to merge 1 commit into
masterfrom
feat/cap-tool-response-size

Conversation

@jmikitova

@jmikitova jmikitova commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

Several MCP tools returned unbounded output, so a single tool call could blow the AI-chat context budget (e.g. get-dataset-items reaching ~236k tokens). This caps per-call output so no single response is unbounded, and every truncated response tells the model how to get the rest (paginate / fetch full record / fetch full schema).

Changes

Tool Cap
get-dataset-items Clamp effective limit to MAX_DATASET_ITEMS_LIMIT (100) pre-fetch, then a DATASET_ITEMS_MAX_BYTES (50 KB) byte cap on the encoded payload, dropping trailing items and steering to offset pagination from the actually-returned count (lossless resume).
get-key-value-store-record Cap inlined text/JSON values at KV_RECORD_MAX_INLINE_TEXT_BYTES (50 KB) → truncate + link to the full record (mirrors the existing 256 KB binary cap).
search-apify-docs Clip per-snippet content to DOCS_SNIPPET_MAX_LENGTH (1000), with a pointer to fetch-apify-docs for the full page.
call-actor Stop dumping the full input schema on input-validation / missing-input errors (could be ~30k chars for complex Actors). Return the AJV validation errors + a fetch-actor-details pointer instead.

Measured on what the model actually receives: the chat serializes MCP results via mcpToModelOutput (schemas: "automatic"), which forwards only content and drops structuredContent, so the caps measure the content payload.

Tests

New/extended unit tests in tests/unit/ for each cap (over-cap input stays bounded, truncation/pointer present, pagination offset resumes from the returned count). Full unit suite green (68 files, 973 pass / 2 skip).

Out of scope (follow-up)

The model paginating through an entire dataset (many capped calls) is a separate prompt/behavior lever, not a per-call size fix — worth its own change.

🤖 Generated with Claude Code

Bound per-call output for the tools that could blow the context budget:
- get-dataset-items: clamp effective limit to MAX_DATASET_ITEMS_LIMIT (100)
  pre-fetch, then a DATASET_ITEMS_MAX_BYTES (50KB) byte cap on the encoded
  payload, dropping trailing items and paginating via offset.
- get-key-value-store-record: cap inlined text/JSON at
  KV_RECORD_MAX_INLINE_TEXT_BYTES (50KB), truncate + link to the full record.
- search-apify-docs: clip per-snippet content to DOCS_SNIPPET_MAX_LENGTH (1000).
- call-actor: stop dumping the full input schema on validation/missing-input
  errors; return the AJV errors + a fetch-actor-details pointer instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants