DEV Community

The Ops Log
The Ops Log

Posted on

Nearly half of MCP servers expose tools an agent could plausibly confuse

A reader made a point on my last post that I couldn't answer at the time, so I went and measured it.

The point: "tool added" is not automatically a safe change. I'd been filing additions under harmless because every old invocation still validates against its schema. But validation isn't selection. A new overlapping tool can capture calls that used to route somewhere else, and nothing errors — the agent just quietly starts doing something different.

I said name-overlap was the obvious first approximation and clearly incomplete. It is both of those things. Here's what it shows.

The measurement

377 registry-listed MCP servers that complete an anonymous handshake, 7,164 tools, every pair within each server compared — 170,345 pairs. A pair gets flagged when the names share most of their tokens, or the descriptions overlap heavily, or both moderately.

173 of 377 servers (45.8%) have at least one confusable tool pair.

Only 1.15% of all pairs are flagged, which is the same fact from the other end: confusion is concentrated in servers with big tool surfaces, not spread evenly.

Representative hits:

list_skills            <->  get_skills                     (identical tokens)
legislation            <->  list_legislation
tf_briefing            <->  tf_premium_briefing
ask_pipeworx           <->  ask_pipeworx_beta
ask_pipeworx           <->  ask_pipeworx_grounded
paid_crypto_call_pack  <->  paid_esports_call_pack         (near-identical descriptions)
Enter fullscreen mode Exit fullscreen mode

list_skills vs get_skills is the honest case. To a human that's a real distinction. To a model choosing from a flat list under token pressure, with descriptions it may or may not read carefully, it's a coin flip that nobody logs.

The subclass I expected to be big, and wasn't

My first cut looked for tools whose names differ only by a commercial tier word — free vs premium, pro, plus. If an agent picks wrong there, it isn't a correctness bug, it's a billing bug. That felt like it might be everywhere.

First pass said 147 pairs across 101 servers — 26.7%.

That number was wrong by about 33x, for two reasons I want to name because they're both easy to make:

  1. I'd included deep, full, advanced and extended as tier words. They aren't — they describe how much work a tool does, not what it costs. deep_research vs bet_research got flagged as a billing pair, which is nonsense.
  2. One gateway (gateway.pipeworx.io) publishes the same tool design across 13 separate endpoints. I counted it 13 times. It's one design decision, not 13 findings.

Tightened to unambiguous billing words and deduplicated by tool-pair signature: 47 distinct pairs across 3 servers. Under 1%.

So the vivid version is rare. It does exist, and it looks like this:

tf_briefing              <->  tf_premium_briefing
get_game_recommendation  <->  get_premium_game_recommendation
gpt55_summarize          <->  gpt55_summarize_plus / gpt55_summarize_pro
gpt55_translate          <->  gpt55_translate_plus / gpt55_translate_pro
Enter fullscreen mode Exit fullscreen mode

One server exposes free, _plus and _pro variants of four separate operations. An agent choosing between those by name similarity is making a purchasing decision with no signal that it's making one.

What I'd take from this

The general problem is real: ~46% of servers give an agent at least one genuinely ambiguous choice. Adding a tool to a server that already has 40 is not a no-op, and the reader who pushed back on me was right.

The billing case is rare but it's the one worth a guard rail, because it's the only class where the failure has a direct cost and no error surface. If you expose paid and free variants, put the price in the description and the tier in the annotations, not just in the tool name.

And the measurement is lexical, which is a real limitation. It cannot tell that two identically-named tools do different things, and it will flag pairs a competent model separates trivially. Treat 45.8% as an upper bound on ambiguity and a lower bound on the amount of thought this deserves.

Method

Same seeded random sample as my previous posts (random.seed(20260730)) drawn from the 5,346 registry endpoints that answer an anonymous handshake, so results are comparable across the series. initializenotifications/initializedtools/list, handling SSE frames and threading Mcp-Session-Id. Pairwise comparison uses Jaccard similarity on name tokens and on description terms with stopwords removed.

Raw tool inventories are cached, so the tier analysis was re-run against identical data after I tightened the definition — which is the only reason I caught that 33x error before publishing rather than after.


Previously: schema drift isn't a rate, it's a small set of servers that never stop moving.

Top comments (0)