MuninMunin
Sign inStart free
Home/Journal/Tool overload is a discovery problem.
Engineering · 10 min read

Tool overload is a discovery problem.

The industry decided in 2026 that big tool catalogues make agents worse, and Anthropic's own documentation puts the degradation threshold at 30 to 50. Munin publishes 204 tools at one endpoint. Here is why the count is the wrong number to optimise, and the four fields that make a large catalogue navigable.

Seen from behind in a bright modern home office, a woman stands before a floor-to-ceiling pale oak wall of dozens of identical closed drawers with exactly one pulled open, three plain white folders held at her side — a whole catalogue available, three things actually taken out.
Everything is in the wall. She needed three.

The consensus arrived quickly and it sounds right: too many tools make an agent worse. Anthropic's own documentation puts a number on it — a model's ability to pick the right tool degrades once you exceed 30 to 50 available tools. Munin exposes 204 at a single endpoint. By that arithmetic we spent a year building the exact thing the industry just finished learning not to build.

I think the arithmetic is measuring the wrong object. The count is a property of the catalogue. The degradation is a property of what a client chooses to load into the context window. Those were the same number for two years, which is why everyone started treating them as one thing. In 2026 they came apart, and the interesting design question moved with them.

Do too many MCP tools make an AI agent worse?

Yes — when the client loads every tool definition up front. Anthropic's tool-search documentation puts the accuracy threshold at 30 to 50 available tools, and notes that a five-server setup spanning GitHub, Slack, Sentry, Grafana and Splunk can consume roughly 55,000 tokens in definitions before the model has read the request. The failure is in eager loading, not in the size of the catalogue.

That distinction is not a debating point, because the fix has already shipped. The tool search tool lets a server mark definitions defer_loading: true; the model then searches names, descriptions, argument names and argument descriptions, and the API expands only what comes back. Anthropic's documentation reports that this typically cuts definition overhead by more than 85 percent, loading the three to five tools a given request actually needs, and states plainly that selection accuracy "stays high even across thousands of tools". The per-request ceiling is 10,000 deferred tools.

The second fix is older and blunter. In Code execution with MCP, published in November 2025, Anthropic presented tool catalogues as files an agent can read on demand and measured one workflow dropping from 150,000 tokens to 2,000 — a 98.7 percent reduction. Cloudflare reached the same conclusion independently and called it Code Mode. Two teams, two implementations, one insight: stop paying for definitions you have not used yet.

30–50
Tools past which selection accuracy degrades, per Anthropic's documentation
85%
Typical reduction in definition overhead once loading is deferred
98.7%
Token reduction Anthropic measured moving one workflow into code
2
Munin tools that reach all 46 of its bundled skills

Why does Munin expose 204 MCP tools instead of a dozen?

Because the 204 are primitives, not workflows. crm_create_contact, conv_send_message, cms_update_entry, kb_search — each one does a single thing to a single kind of record, and the name says which module owns it. A catalogue of primitives is large and predictable. A catalogue of workflows is small until someone wants a combination nobody anticipated, and then it grows forever.

The honest part of this: 204 definitions are more than any one conversation needs, and a client that loads all of them eagerly is spending context on tools that session will never call. That is a real cost and I am not going to pretend otherwise.

What follows from it, though, is that the cost belongs to the loading strategy rather than to the catalogue — and the loading strategy is the part that got fixed. Shrinking the catalogue to fit an eager client optimises for a constraint that Claude Code, the Claude API, and every code-execution harness have already removed. It also permanently costs you the thing the primitives buy: a surface where the model reasons about crm_change_deal_stage as a named operation with its own schema, its own scopes, and its own approval prompt, rather than as one branch inside something larger. Six modules of real coverage — CRM, Conversations, Knowledge Base, CMS, Outreach, Analytics — is what 204 buys, and it is the same six sharing one database and one tenancy column.

The number of tools a server publishes and the number a model has to reason about stopped being the same number. Almost every argument about tool overload is still assuming they are.

What happens if you collapse 204 tools into twelve?

The surface does not shrink. It moves. A single crm tool with an action parameter still has to accept every argument every action needs, so the ambiguity migrates out of tool selection — where the model gets a name, a description, and a validated schema — and into argument construction, where it gets a string and a hope.

Two other things go with it. The client loses the ability to tell a read from a destructive write before the call is made, because there is now one tool and it is sometimes both; approval UX degrades into approving crm in general. And scopes stop being expressible per operation, because the unit the token grants access to is no longer the unit the work happens in.

This is not a knock on the teams doing it. Consolidating a sprawling third-party API behind a few well-chosen verbs is genuinely good engineering, and for a server that wraps someone else's REST surface it is often the right call — the underlying API was not designed for this caller, and a thin faithful mirror of it is worse than a considered abstraction. Munin is in a different position: we designed the tool surface first and the REST API and dashboard as clients of it, so the primitives already are the considered abstraction. There is nothing to consolidate away from.

How do you name 204 tools so an agent can find them?

Namespace by module and never break the prefix. Every Munin tool begins with the module that owns it — crm_, conv_, kb_, cms_, analytics_, outreach_, with smaller families for bookings, commerce, connectors, webhooks, Slack, feedback and system alerts. One regex against ^crm_ returns the entire CRM family in a single search. Anthropic's tool-search guidance asks for precisely this: "prefix by service or resource so one search matches the whole group".

That is a naming convention doing load-bearing work, and it only works if it is absolute. The moment one tool is called create_contact because it read better in isolation, the prefix stops being a reliable index and every search has to be written defensively. We treat a missing prefix as a bug in the same category as a missing migration.

The descriptors carry four more fields that exist for the same reason — so a client can narrow the catalogue without a human curating a list:

jsoncone entry from api.getmunin.com/v1/public/mcp-tools
{
  "name":        "crm_create_contact",
  "title":       "…",
  "description": "…",
  "audiences":   ["admin"],   // or ["self_service"], or both
  "scopes":      ["…"],       // what the token must already hold
  "danger":      null,        // populated when the call is destructive
  "readOnly":    false
}

// The whole catalogue is a bare JSON array of these,
// public, no credential. Count it yourself.
  • audiencesWho is allowed to see the tool at all. An admin key sees the full catalogue; a delegated end-user token sees only the self-service subset. This is a visibility decision made on the server, before tools/list answers.
  • scopesWhat the calling token must already hold. Declared per tool rather than per module, so a key issued for content work cannot reach the CRM even though both live behind one endpoint.
  • dangerPopulated when the operation is destructive. A client can build an approval prompt from this field instead of maintaining its own hardcoded list of things to be careful about.
  • readOnlyWhether the call mutates anything. The cheapest signal a harness has for deciding what may run unattended and what waits for a person.

How does a customer-facing agent avoid seeing all 204 tools?

The audiences field. An admin key sees everything. A delegated end-user token — the one behind a support widget, talking to your customer — sees only the tools marked self-service: check my own order, look up my own booking, read my own contact record, search the public knowledge base, ask for a human. That is a dozen or so definitions, not 204, and the narrowing happens server-side before the catalogue is ever returned.

This matters more than it sounds. The usual advice for tool overload is to configure your client carefully, which puts a security-shaped decision in a config file maintained by whoever set the agent up. Audiences move it into the token. A self-service agent is not trusted-but-filtered; it cannot enumerate the admin tools, so it cannot be talked into calling one.

Why are 46 skills not 46 more tools?

Because workflows belong in documents, not in the tool catalogue. Munin ships 46 markdown skills — importing and scoring a lead list, launching a support desk, wiring a frontend to the widget and tracker, migrating a tenant between servers — and reaches all of them through exactly two tools, skills_list and skills_read. The agent lists the titles, reads the one it needs, and calls the primitives that skill names. Forty-six workflows, two definitions.

That is progressive disclosure implemented at the server, and it is the same shape Anthropic describes when it suggests adding a search_tools tool or laying tools out as files on a filesystem. The difference is only where the index lives. A skill is a document, so it can carry ordering, caveats, the gotcha that costs everyone an afternoon, and the reason a step exists — none of which fits in a tool description, and all of which is what an agent actually needs to get a six-call sequence right the first time.

It is also the answer to the obvious objection about the primitives. Yes, crm_import followed by crm_create_pipeline followed by crm_log_activity is more calls than one import_and_score_leads tool would be. The sequence is written down in skill://crm/import-and-score-leads, where it costs nothing until it is read.

The test

Count the definitions a model has to hold to answer one question — not the ones your server publishes. If those two numbers are equal, the problem is the client.

Which MCP clients handle a large catalogue well?

The ones that defer. Claude Code enables deferred loading by default and switches to on-demand discovery when MCP tool descriptions exceed a share of the context budget, so a large server costs a list of names rather than a wall of schemas — driving the whole platform from a terminal is a single claude mcp add. On the Claude API you get the same behaviour explicitly, with defer_loading on the MCP toolset entry and a regex or BM25 search variant. Any harness with a code-execution sandbox can go further and read definitions off a filesystem.

Eager clients are the constraint worth checking before you wire anything up. Cursor users have reported for over a year that the agent only receives roughly the first 40 tools across all configured servers, with the rest silently unavailable — issue #3369 is the long-running thread. It is a real limit and it has a boring fix: scope the connection. Munin in Cursor is worth wiring for the CRM and Conversations families and nothing else, because the reason to have Munin in an editor is reading the ticket that reported the bug, not running an outreach campaign from it.

The general rule I would give anyone building a server this size: publish the whole catalogue, namespace it ruthlessly, mark up every descriptor so a client can filter without a human's help, and let the client decide how much of it to hold at once. That is the division of labour the protocol is now designed around. It is also why the protocol mattering more than the interface was the right bet — clients got smarter about the catalogue without the catalogue changing at all.

Frequently asked questions

How many MCP tools is too many? It depends entirely on the client. With eager loading, Anthropic's documentation puts selection degradation at 30 to 50 tools. With deferred loading and tool search, the same documentation supports thousands and caps a single request at 10,000 deferred definitions. The number to watch is how many definitions reach the context window, not how many the server publishes.

How many tools does Munin have? 204 MCP tools at one endpoint, mcp.getmunin.com, covering CRM, Conversations, Knowledge Base, CMS, Outreach and Analytics, plus 218 REST endpoints over the same data and 46 bundled markdown skills. The live catalogue is public and uncredentialed at https://api.getmunin.com/v1/public/mcp-tools if you would rather count it than take my word for it.

Does a big MCP server slow down Claude or ChatGPT? Only if the client loads every definition up front. Claude Code defers MCP tools by default; the Claude API defers when you set defer_loading on the toolset; a code-execution harness reads definitions on demand. Clients without deferral pay for the whole catalogue on every request regardless of which server it came from.

Should I build one MCP tool per operation, or a few tools with an action parameter? One per operation, if you control the underlying system and can name the operations well. Per-operation tools give the model a schema instead of a free-text argument, and give the client a per-call signal for approval and scoping. Consolidated tools make more sense when you are wrapping a third-party API whose shape you did not choose.

How do you stop a customer-facing agent from reaching admin tools? With an audience on the token rather than a filter in the client. Every Munin tool descriptor carries an audiences array; a delegated end-user token is only ever shown the self-service subset, so the admin tools are not in the catalogue that agent receives and cannot be called by name.

Where should multi-step workflows live if not in the tool catalogue? In documents the agent can read on demand. Munin keeps 46 of them behind skills_list and skills_read, so a workflow costs two definitions no matter how many workflows there are. A document can also carry ordering, caveats and the reason a step exists, which a tool description cannot.

The argument, condensed

  • Tool count and context cost stopped being the same number in 2026. Deferred loading and tool search broke the link; most advice about tool overload has not caught up.
  • Anthropic puts eager-loading degradation at 30–50 tools and reports over 85 percent less definition overhead once loading is deferred, with selection accuracy holding across thousands.
  • Munin publishes 204 primitives rather than a dozen macro-tools, so each operation keeps its own schema, its own scopes, and its own approval prompt.
  • Every tool is prefixed by the module that owns it, so one regex against ^crm_ returns the whole family — the namespacing Anthropic's own tool-search guidance asks for.
  • Four fields on every descriptor — audiences, scopes, danger, readOnly — let a client narrow the catalogue without a human curating a list.
  • 46 bundled skills sit behind two tools, skills_list and skills_read, so workflows live in documents that cost nothing until they are read.

The catalogue is public and uncredentialed at api.getmunin.com/v1/public/mcp-tools, and the tool reference groups it by module.

Too many tools was never a counting problem. It's a discovery problem.