<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Doriku</title>
    <description>The latest articles on DEV Community by Doriku (@dorikuio).</description>
    <link>https://dev.to/dorikuio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4017900%2Fd553a347-6b4d-47d3-bf04-3793772a39f0.png</url>
      <title>DEV Community: Doriku</title>
      <link>https://dev.to/dorikuio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dorikuio"/>
    <language>en</language>
    <item>
      <title>We collapsed 76 MCP tools into 12 — and cut per-session context cost by 60%</title>
      <dc:creator>Doriku</dc:creator>
      <pubDate>Mon, 06 Jul 2026 13:56:45 +0000</pubDate>
      <link>https://dev.to/dorikuio/we-collapsed-76-mcp-tools-into-12-and-cut-per-session-context-cost-by-60-do</link>
      <guid>https://dev.to/dorikuio/we-collapsed-76-mcp-tools-into-12-and-cut-per-session-context-cost-by-60-do</guid>
      <description>&lt;p&gt;Every MCP server pays a hidden tax: the moment an AI agent connects, your entire &lt;code&gt;tools/list&lt;/code&gt; gets injected into its context window. Every tool name, every description, every JSON schema — before the user has typed a single word.&lt;/p&gt;

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

&lt;p&gt;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: &lt;strong&gt;76 tools, 38,818 bytes of &lt;code&gt;tools/list&lt;/code&gt; payload&lt;/strong&gt;, loaded into every session of every agent, every day — before any work happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem isn't the number, it's the multiplication
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;tool definitions&lt;/em&gt; — pure overhead that competes with actual working context and dilutes the model's attention across 76 choices.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Design: verbs, not endpoints
&lt;/h2&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each compact tool takes an &lt;code&gt;action&lt;/code&gt; parameter and routes internally to the same handlers the legacy tools used. One schema per domain instead of eight.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Breaking no one
&lt;/h2&gt;

&lt;p&gt;76 tools were already in the wild — in MCP configs, in agent prompts, in muscle memory. So:&lt;/p&gt;

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

&lt;p&gt;Migration cost for users: zero. They restart their MCP session and the agent simply sees 12 tools instead of 76.&lt;/p&gt;

&lt;h2&gt;
  
  
  A side quest: discovery without auth
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  Numbers that mattered
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Legacy&lt;/th&gt;
&lt;th&gt;Compact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tools&lt;/td&gt;
&lt;td&gt;76&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;tools/list&lt;/code&gt; payload&lt;/td&gt;
&lt;td&gt;38,818 B&lt;/td&gt;
&lt;td&gt;15,514 B (40.0%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context saved per session&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;~23 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breaking changes&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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




&lt;p&gt;&lt;em&gt;Doriku is a shared memory and coordination layer for AI coding agents — &lt;a href="https://doriku.io" rel="noopener noreferrer"&gt;doriku.io&lt;/a&gt;. On the &lt;a href="https://registry.modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP Registry&lt;/a&gt; as &lt;code&gt;io.doriku/task-manager&lt;/code&gt;. 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.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
