EnorexaEnorexa
Back to blog

AI

MCP Tool Bloat: Why 40+ Schemas Tank Agent Accuracy in Production

October 28, 20264 min readBy Enorexa Team

Pass forty-five Model Context Protocol (MCP) tool definitions into an agent's context window and watch what happens to your p95 latency. It spikes past 4.2 seconds before the first token even renders. Worse, your payload quietly burns 16,500 input tokens on every single turn just re-transmitting JSON Schema boilerplate for Jira, Slack, Postgres, and Stripe tools the user never asked to run.

Most engineering teams treat MCP servers like free plugins. They spin up five internal connectors, register every available CRUD endpoint, and dump the combined tools array straight into the model request. Everything looks fine during a three-turn localhost demo. Then production traffic hits, multi-turn tool loops compound those schema tokens five times per user message, and the model starts hallucinating required fields or picking update_customer_billing when it needed get_invoice_status.

The 25-Tool Cliff Where Function Selection Breaks Down

LLMs do not read a 1,400-line JSON Schema array the way a compiler reads a type file. Every nested anyOf, additionalProperties: false, and enum description competes for attention weight across the context window. In our internal benchmarks across production workflow agents, tool selection accuracy stays above 94% when the model chooses from 8 or fewer distinct schemas. Push that list past 30 tools—especially when multiple endpoints share overlapping parameter names like user_id, account_id, and org_id—and strict parameter adherence drops to 63%.

You also hit hard validator walls. OpenAI and Anthropic strict-mode compilers reject or heavily penalize deeply nested schemas that exceed token or recursion budgets, throwing 400 Bad Request: Invalid schema for function when a third-party MCP server exposes an untamed OpenAPI spec. And even when the request succeeds, prompt caching only saves you if the exact tool array order and system prefix remain byte-for-byte identical across calls.

Flattening Schemas and Trimming Verbose Enum Descriptions

Your first fix has nothing to do with model routing. Audit the raw JSON payload your MCP client actually serializes over the wire. Third-party MCP servers routinely attach 300-word markdown essays to every parameter description and expose twenty optional filter flags that an autonomous workflow never touches.

We wrap every external MCP server behind an internal sanitization proxy before its tools ever reach the orchestrator. If an ops agent only needs to look up an order and issue a refund, we strip the other fourteen Stripe webhook and subscription endpoints at registration time. Next, we flatten deeply nested input objects into top-level primitive parameters and replace sprawling free-text fields with strict string enums. Cutting a bloated 420-token tool definition down to 85 tokens immediately drops Time to First Token (TTFT) by 35% and eliminates SyntaxError: Unexpected end of JSON input from truncated tool-call streams.

Two-Stage Dynamic Tool Retrieval Without the Extra LLM Hop

When an enterprise platform genuinely requires access to 120 different operational tools, static registration is dead on arrival. You need dynamic tool injection, but using a second LLM call just to classify which tools to load adds 800ms of serial latency you cannot afford.

Instead, we index every sanitized tool description and five synthetic example queries into an in-memory vector store—or directly inside PostgreSQL using pgvector and BM25 hybrid search. When a user prompt or webhook payload arrives, a sub-15ms embedding lookup retrieves only the top 5 most relevant tool schemas for that specific intent. We pin 2 core utility tools (such as ask_human_clarification and fetch_entity_context) permanently in the cached prefix, and dynamically append the 5 retrieved domain tools at the tail of the prompt.

Keeping Prompt Caches Warm During Multi-Step Execution

Dynamic tool loading introduces one subtle trap: if you swap the tools array on every step of a five-turn agent loop, you invalidate the provider's KV prompt cache on every iteration. That turns a 90% cache-read discount into full-price input billing.

To keep the cache warm, lock the retrieved toolset for the duration of a single task execution graph. Once the router selects the 6 tools needed for an invoice reconciliation run, keep that exact tool array fixed in the same deterministic alphabetical order until the run terminates or explicitly requests a capability escalation via a meta-tool like request_additional_tools(domain). This preserves your cached prefix across all intermediate tool-result turns while keeping the active schema count under ten.

Where Lean AI Architecture Fits

Before you upgrade to a slower, more expensive reasoning model to fix flaky agent behavior, inspect your raw API request logs and count how many kilobytes of unused JSON Schema you are shipping on every turn. If your team is fighting brittle MCP integrations, runaway token bills, or hallucinated tool calls, explore how Enorexa architects production-grade AI workflows—or talk to us to audit your agent pipeline before your next release.