Don't let MCP eat it
Your Agent's Context
199 tools, 40K tokens in schema overhead per round—until we slashed that by 90% using a five-layer architecture.
Service → SDK → CLI → MCP → Skill, allowing AI Agent to do the most with the fewest tokens.
What problems have we encountered?
Three real pain points led to the development of this five-layer architecture: an overwhelming number of tokens, an explosion in MCP processes, and too many tools to choose from.
Token Surge
Each call to Playwright MCP consumes a large number of tokens. Even when it is not in use, the "tool" schema still occupies the context window. Every round pays for it.
After switching to the Playwright CLI:
Token Cost Comparison
MCP processes 1,600 tokens per round, while the CLI processes 0 (excluding actual I/O).
Schema overhead (tokens) per round
Schema overhead (tokens) per round
Total waste in unused schemas
The entire IDE uses only two tools
What is each of the five layers used for?
The five layers from top to bottom are Skill (intent routing), MCP (write operations), CLI (read operations), SDK (the only encapsulation layer that touches HTTP), and Service (the core business logic itself), with upper layers strictly importing lower layers.
Core Principles: Bug Fix Auto-Propagation—Fix one SDK bug, and both the CLI and MCP are fixed at the same time. Without the SDK layer, each consumer implementing HTTP + auth + error handling on their own = maintenance hell.
Skill ──invoke──► CLI (Read) / MCP (Written by)
MCP ──import──► SDK ──HTTP──► Service
CLI ──import──► SDK ──HTTP──► Service
// The SDK is the only place that interacts with HTTP
// Change SDK = All upstream consumers are updated simultaneously
Why can't we do it with one less layer?
| Consumers | Best Access Layer | Reason |
|---|---|---|
| Other Core Modules | Service | Call `services.py` directly within the same process, with zero overhead |
| Python Script / Notebook | SDK | Programmatic Access, Comprehensive Error Handling |
| Person (End User) | CLI | --help Discoverable, pipe-composable |
| AI Coding Agent Claude Code / Codex CLI / Gemini CLI |
CLI (Read) / MCP (Written by) | Reading Bash commands requires no schema; writing them requires typed input. |
| Scheduling System | CLI | Shell commands are the universal language of scheduling. |
| AI Workflows | Skill | Advanced Intent Routing: Automatically Select CLI or MCP |
"The CLI is a zero-overhead, universal interface—anything that can run a shell can use it,
while MCP can only be used by clients that support the MCP protocol."
How did we end up here?
This architecture wasn't designed all at once—each of the four phases addressed the pain points we were facing at the time, and it wasn't until they were pieced together that it took its current form.
The First Lesson from the Token Surge
The Playwright MCP has a massive tool schema that is injected into the system prompt on every turn of the conversation. Even when the browser isn't used in that turn, it still consumes tokens. After replacing it with the Playwright CLI, token usage dropped by 98%.
Insight: If you can use the CLI, you shouldn't use MCP.
The Multiplicative Disaster of Multiple Sessions
Once the number of MCP servers grew to 23, opening each additional Claude Code session proportionally duplicates all processes. 3 sessions = 69 resident processes. The solution is mcpproxy aggregation + offloading read operations to the CLI.
Insight: It is necessary to reduce the number of MCP servers and tools.
The industry's most extreme tool compression
Cloudflare's Code Mode MCP exposes only 2 tools: search() and execute(). All other operations are written in real time within the sandbox. This proves that the number of tools is inversely proportional to their capabilities.
Insight: We don't take it to such extremes, but the same principle applies—the fewer tools, the better.
The new module has successfully completed all five levels.
Backend → SDK → CLI → MCP → Skill, missing a single layer causes downstream integration to break. With the BaseClient DRY pattern, the marginal cost of adding new modules decreases, but the composability gained with each added layer is a permanent benefit.
Insight: Five layers aren't a burden—they're compound interest.
Disposable Tools — Filling in for Sandbox
Not all operations require a permanent tool. Inspired by Cloudflare Code Mode, batch operations are written in real time within the sandbox and do not take up an MCP tool slot.
Cloudflare: 2 permanent tools + sandbox: Log all operations in real time
Pragmatists: ≤10 permanent tools/server + sandbox to cover low-frequency operations
// General rule: Permanent tools are a scarce resource; if something isn't worth taking up space, use the sandbox instead.
Criteria: Is a single operation worth becoming a permanent tool?
→ Used ≥ 3 times per week + complex parameter combinations + requires discoverability → Five-layer coverage
→ Otherwise → sandbox: write in real time, use and discard
What if we don't use five layers?
| Alternatives | Question | Consequences |
|---|---|---|
| Only Service | HTTP calls only | AI agents, cron jobs, and CLI users all have to write their own HTTP clients. |
| Service + MCP | Token overhead + process explosion | 23 servers × 3 sessions = 69 processes; the schema consumes a token per round |
| Service + CLI | Write operation missing typed schema | LLM passed incorrect parameters; no input validation |
| Go with MCP across the board | CLI users are excluded | Codex CLI, Gemini CLI, and cron are all unable to connect |
| Each layer implements HTTP independently | No unified SDK | Fix one thing, miss another: The “Ghost Parameter” anti-pattern runs rampant |
Use the Agent SDK to Control Tool Injection Yourself
If you're building your own client using the Agent SDK, you can fully control, at the application layer, which tool schemas are included in the LLM's context—no need to wait for platform support. Speakeasy's Dynamic Toolset Solution uses the same approach to filter tools, cutting token usage by 96%.
all_tools = mcp_server.tools_list() # Received 199 (protocol layer)
relevant = bm25_filter(all_tools, query) # You've narrowed it down to 5 yourself
response = client.messages.create(
tools=relevant, # Only 5 to be given to LLM
)
Key Distinctions: At the MCP protocol layer, tools/list returns all tools—there's no changing that.
But it's up to your client to decide what to put into the API's tools[] — that's completely under your control.
Use an off-the-shelf client like Claude Code? It handles everything for you. Build your own client? You have to filter the data yourself.
The implementation costs are actually quite low.
"Diminishing marginal costs and scalability offer long-term benefits—but maintenance costs are also long-term."
⚠ The Cost of a Five-Tier Architecture
Maintain three additional packaging sets
The SDK, CLI, and MCP all contain the same logic. When the API changes, all three layers must be updated accordingly. This is manageable when the team is small, but as the team grows, automated testing becomes essential to ensure consistency.
A Shift in the OpenCLI Community's Sentiment
The open-source community is adopting the CLI as the default interface, not the direction we ourselves are calling for.
OpenCLI converts websites and desktop apps into a standardized CLI; CLI-Anything wants to ensure that all software can be controlled by the Agent via the CLI. More and more developers are asking, “Is there a CLI?” rather than “Is there an API?”
The reason is simple: The New Stack's 2025 report already said as much—the entire industry is entering the era of the Agentic CLI. When all AI coding tools can run shell commands, the CLI naturally becomes the greatest common denominator across tools.
It’s not a CLI revival—it’s the rediscovery of the CLI’s value in the age of AI.
199 Tools, One Set of Logic
Read via the CLI, write via MCP—these 199 tools all operate based on this single distinction, People, Scripts, AI, to each his own.
From the surge in token volume to the validation of community sentiment, every step was driven by pain points—change one place, and it updates everywhere.
Pain Point 1: Playwright MCP Token Surges in Volume
→ CLI Save 98% token
Pain Point 2: Running multiple instances of CC → Processes increase proportionally
→ mcpproxy Aggregation + CLI Unload Read Operations
Pain Point 3: There are too many LLM tools to choose from
→ ≤10 tools/server + sandbox Fill-in
Verification 1: Running the Entire IDE with Just 2 Cloudflare Tools
→ Following the same principle, we further Pragmatic
Verification 2: The OpenCLI community is shifting toward a CLI-first approach
→ In the Age of AI, CLI is Greatest Common Divisor Across Tools
// Induction
Service → SDK → CLI → MCP → Skill
199 Tools, One Logic, Three Types of Consumers
First, calculate your own schema bill
The 40K tokens mentioned above are based on my setup; if you substitute your own numbers, the results will be completely different. Fill in three fields and calculate your per-round overhead and resident process count using the two constants cited in this text (approximately 200 tokens per tool schema, industry recommendation of ≤ 10 tools per MCP server). Everything is calculated entirely in the browser with no data sent out.
The sources for all constants are in this text: 200 tokens/schema comes from the linear relationship of "8 tools × 200 tokens/schema = 1,600 tokens/turn," the number of processes comes from "3 sessions × 23 MCP servers = 69 resident processes," and 10 tools/server is the industry recommendation cited in the text. This figure only accounts for the overhead associated with the schema; it does not include actual I/O.—The actual usage depends on how you make the calls.
Copy this to your AI Agent
The MCP tool schema consumes tokens every round, but most of your tools are actually “read” operations—they don’t need the schema at all. Once you have too many tools, the schemas alone consume tens of thousands of tokens, and with more than 10 tools, the probability of the LLM making the wrong choice increases. The five-tier architecture in this article relegates "reading" away from the CLI and leaves only "writing" for MCP.
Send the text below to your AI, have it conduct an on-site inventory of your current MCP configuration, and then use this five-tier framework to determine which elements can be migrated:
Further Reading
I’ve actually read all of the articles below, and they’ve genuinely influenced my decisions—this isn’t just a random list I put together.
| Article | Why It Matters |
|---|---|
| Code Mode: Give Agents an Entire API in 1,000 Tokens | Cloudflare's real-world test showed that running the entire IDE with just two tools reduced token overhead by 81%. This validated the principle that "the fewer tools, the better." |
| Your MCP Server Is Consuming Your Context Window | Apideck analyzes how MCP schema eats up context, and proposes CLI as an alternative—80 tokens prompt vs tens of thousands of tokens schema |
| Advanced Tool Use — Anthropic Engineering | Anthropic has officially acknowledged the issue of the tool schema consuming context and has introduced the Tool Search mechanism to achieve an 85% reduction in context usage. |
| How We Reduced Token Usage by a Factor of 100: Dynamic Toolsets | Speakeasy's dynamic toolkit solution achieves a 96% reduction in input tokens |
| MCPProxy — MCP Gateway | Open-source MCP aggregation gateway that uses BM25 to index dynamic discovery tools, supporting hundreds of servers and thousands of tools |
| Welcome to the Agentic CLI Era | The New Stack Reports on the Industry Trend of AI Coding Tools Shifting Entirely to the CLI |
| OpenCLI — Universal CLI Hub | A universal CLI hub designed specifically for AI agents, transforming websites and desktop applications into standardized CLIs |
| CLI-Anything — Making ALL Software Agent-Native | University of Hong Kong Study: Enabling AI Agents to Operate All Software via the CLI |