DEV Community

Doriku
Doriku

Posted on

We collapsed 76 MCP tools into 12 — and cut per-session context cost by 60%

Every MCP server pays a hidden tax: the moment an AI agent connects, your entire tools/list gets injected into its context window. Every tool name, every description, every JSON schema — before the user has typed a single word.

Full disclosure up front: every mistake in this story is our own making — nobody handed us 76 tools, we grew them.

Doriku is a shared control plane for AI coding agents — Claude Code, Codex, Cursor, Gemini CLI, Windsurf, or any MCP-compatible tool talks to one task/memory/decision store. We grew fast and organically: task CRUD, dependency tracking, file locks, decisions, semantic memory, workflows, cost caps, approvals… Each feature politely added its own tools. One day we counted: 76 tools, 38,818 bytes of tools/list payload, loaded into every session of every agent, every day — before any work happened.

The problem isn't the number, it's the multiplication

38 KB doesn't sound like much until you multiply it: N agents × M sessions per day × every reconnect. For a heavy user we measured 6,298 API calls over 30 days across multiple daily sessions. That's megabytes of context per user per month spent on tool definitions — pure overhead that competes with actual working context and dilutes the model's attention across 76 choices.

There's a quality cost too. Agents pick tools by reading descriptions. With 76 near-neighbors (doriku_task_update vs doriku_task_progress_report vs doriku_work_status…), models mis-route. Fewer, sharper tools = better routing.

Design: verbs, not endpoints

The mistake we'd made was mirroring our REST API — one tool per endpoint. Agents don't think in endpoints; they think in intents. So we redesigned the surface around 12 verb-shaped tools:

task        — create / get / update / list / claim / complete / decompose …
memory      — set / get / search / delete
context     — capture / restore session context
decision    — record / list / update
agent       — register / heartbeat / message
project, workspace, search, lock, workflow, admin, capabilities
Enter fullscreen mode Exit fullscreen mode

Each compact tool takes an action parameter and routes internally to the same handlers the legacy tools used. One schema per domain instead of eight.

Result: 12 tools, 15,514 bytes — exactly 40.0% of the legacy payload. We locked that in with a regression test that fails the build if the compact surface ever creeps past 40% of legacy.

Breaking no one

76 tools were already in the wild — in MCP configs, in agent prompts, in muscle memory. So:

  • Every legacy tool name still works, permanently. The dispatcher resolves both surfaces regardless of which one is advertised.
  • Workspaces choose their surface (legacy / compact) in settings; new workspaces default to compact.
  • The regression suite asserts every routed legacy name is still dispatchable.

Migration cost for users: zero. They restart their MCP session and the agent simply sees 12 tools instead of 76.

A side quest: discovery without auth

MCP directories (Smithery, the official registry, mcp.so) scan servers by calling initialize and tools/list anonymously. Our server used to 401 those — directories listed us as "no capabilities." We now serve the compact surface to unauthenticated discovery while keeping tools/call behind auth. Listings fixed, security unchanged.

Numbers that mattered

Metric Legacy Compact
Tools 76 12
tools/list payload 38,818 B 15,514 B (40.0%)
Context saved per session ~23 KB
Breaking changes 0

If you run an MCP server with more than ~20 tools, you're probably paying this tax too. Count your tools/list bytes. Then think in verbs.


Doriku is a shared memory and coordination layer for AI coding agents — doriku.io. On the MCP Registry as io.doriku/task-manager. I'm a solo builder and honestly still figuring out whether this solves a problem beyond my own — if you run multiple agents on one repo, I'd be grateful if you tried it for a week (free, no card, every signup starts a 7-day full Pro trial) and told me what's broken.

Top comments (8)

Collapse
 
alexshev profile image
Alex Shev

Collapsing MCP tools is a strong pattern. Tool count is not capability; it is context surface area. Fewer, better-shaped tools usually make the model more reliable and the audit trail easier to read.

Collapse
 
dorikuio profile image
Doriku

"Context surface area" is exactly the right frame — wish I'd used that phrase in the post. The audit-trail point matters too: with 12 verb-shaped tools, reading an agent's call log actually tells you its intent, instead of scrolling through 76 near-identical names. Thanks for reading!

Collapse
 
alexshev profile image
Alex Shev

Yes, the call log readability is underrated. A smaller verb-shaped tool set makes the agent's intent legible after the fact, which is often where debugging and trust actually happen.

Thread Thread
 
dorikuio profile image
Doriku

Really well put — and it's turned out to be the more durable win of the two. The byte savings mattered on day one; the legible call log is the one that keeps paying off every time we've had to reconstruct what a multi-agent session actually did after the fact. Appreciate you pushing on this.

Thread Thread
 
alexshev profile image
Alex Shev

Exactly. The legible call log becomes an operations feature. When something fails, you can reconstruct intent from the verbs instead of reverse-engineering a pile of tiny tool names.

Thread Thread
 
dorikuio profile image
Doriku

That's the shift that's actually stuck with us. We didn't design the audit log as a support feature — it started as internal debug output because we got tired of guessing what a session did. But "operations feature" is the more accurate name for what it turned into: it's usually the first thing we open when a user says something behaved wrong, before we ever ask them to reproduce it.

It's part of why we committed to per-tool telemetry (call frequency, failure rate, retries, misrouted calls) as a beta feature in this thread with Edu — the verbs-not-tool-names readability you're describing gets more useful once it's attached to frequency data. Then you're not just reconstructing what one session did, you can see which tools get miscalled often enough to be a design problem before a user ever files a ticket about it.

Collapse
 
eduzsh profile image
Edu Peralta

This matches what I keep seeing running Claude and Codex side by side in different panes. The moment a project connects four or five MCP servers, the tool list eats enough context that the model starts guessing at flags instead of reading the schema. What worked better for me than manual consolidation was watching which tools actually got called across a week of real sessions, most servers expose ten tools for one that ever gets used. Curious if your 12 came from an audit of real usage or from redesigning the API surface upfront.

Collapse
 
dorikuio profile image
Doriku

Good catch — honest answer: the current 12 didn't come from a large-scale usage audit. We don't have enough external call data yet, so it's closer to an upfront API-surface redesign, aimed first at the context problem: exposing all 76 REST-mirrored endpoints as MCP tools made tools/list + schemas eat far too much of the window.

It wasn't arbitrary, though. We dogfooded with Claude Code, Codex, and Cursor connected, and folded the actions that kept recurring into verb-shaped primitives — task(action: claim), memory(action: search), decision(action: record), lock(action: acquire) — instead of CRUD-per-endpoint. That's what took 76 tools down to 12, and tools/list from 38.8KB to 15.5KB.

So the accurate claim is not "12 tools validated by usage audit" but "12 tools compressed against a context budget first — the usage audit is the next step." I agree with your approach: during the beta we plan to collect per-tool call frequency, failure rate, retries, missing arguments, and wrong-tool selections, then merge or demote what real traffic says is dead weight, and promote frequent flows into presets.

In other words, our 12 isn't the final answer — it's the first minimal surface for keeping context clean. Real usage data might shrink it further, or split specific workflows back out into dedicated tools.