# Why the model won't call your tool

> Source: <https://dev.to/getmcpulse/why-the-model-wont-call-your-tool-4k43>
> Published: 2026-09-16 08:26:29+00:00

Your tool is registered. It appears in `tools/list`. The model never calls it, or calls a different one instead.

There are six reasons this happens. They are not equally likely, and the instinct — assume the description needs to be better — is right about a third of the time.

Here they are in order of how often they turn up across 4,749 public MCP servers.

**Most likely.** 17.7% of public tools have a description containing no word that distinguishes them from a sibling. On servers with more than sixty tools it is 32.4%.

The tell is that a *neighbouring* tool gets called instead of yours, consistently. Not randomly — the same substitution every time.

**How to check.** Print your whole tool list and read your tool's description next to the one that keeps getting called. If you can swap the two descriptions and both still read correctly, the model has nothing to choose on.

**The fix.** Lead with the difference, not the category. "Search orders" describes four of your tools. "Search orders by customer, including cancelled ones" describes one. Naming the return shape is the single most distinguishing sentence available and almost nobody writes it.

**Second most likely**, and the one people check last. 21.5% of parameters across the corpus have no description at all.

A model that cannot work out what to put in a required field will avoid the tool rather than guess. This looks identical to a description problem from outside, and it is not.

The clearest version:

```
fetch    id, document_id      (neither described)
```

A model has to pick one and nothing tells it which, or whether they differ. So it picks a different tool.

**How to check.** Cover the parameter *names* and look only at types and descriptions. If you could not supply a value, neither can the model.

**Watch for the internal identifier specifically.** A tool requiring a `warehouse_id` is unreachable from a conversation where nobody has ever seen a warehouse ID. That is not a description problem — it is a tool that needs a lookup step before it, or a name-based alternative.

When descriptions collide, the name is what decides — in 89.6% of collision cases. So a colliding description plus a generic name is the case where nothing is choosing at all.

`get` leads **15.6%** of all public tool names. If your tool is `get_thing` and a sibling is `fetch_thing`, those are synonyms in English and the model is guessing.

**The fix.** One verb per operation, across the whole server. Never ship two words from the same row:

`get` / `fetch` / `read` / `retrieve`
`list` / `getAll`
`search` / `query` / `find`
`delete` / `remove`
Schema goes into the context window on every connection. The median server spends about 1,251 tokens; the 90th percentile spends 7,992. The largest in the corpus spends around 216,000 — which does not fit a 200K window at all.

The failure here is not that your tool is badly described. It is that it is the fortieth candidate in a list the model is skimming, and attention is finite.

**How to check.** Count your tools. Under fifteen, this is not your problem. Past thirty, it is probably your main one.

The model sends `"Direct"` where you accept `"direct"`, your server rejects it, and from the model's side that reads as a broken tool rather than a fixable mistake — so it stops trying.

857 parameters in the corpus name their valid values in the description and leave the schema as an open string. Moving them into an `enum` is one line.

**The tell for this one is distinctive:** the tool *does* get called, once, and then never again in that session.

Two rarer causes worth ruling out.

**A duplicate tool name.** Only 0.19% of servers — nine in the whole corpus — but when it happens, one of the two tools cannot be called at all, and the symptom points somewhere else entirely. Almost always a generated tool list. One assertion in CI catches it forever.

**The tool is not in the response you think it is.** Servers that build their list conditionally can emit something different from what the code appears to register. Read the real `tools/list` output rather than the registration code.

`valid values` / `options:` — catches cause 5.
That is fifteen minutes and it covers all six.

Every cause above is a property of your schema, and this is the honest limit: we have never observed a model choosing a tool on any of these servers. The rates say how often each pattern *exists*, not how often it costs you a call.

It is entirely possible your tool is skipped for a reason no schema shows — the client truncates long lists, the model was mid-task, the user phrased something unusually. Distinguishing those from the six above needs data from inside your server: which tools get called, which get retried, which return empty. A schema check is what you can do before you have any of that.

The [schema checker](https://getmcpulse.com/check) tests causes 1, 2, 3, 5 and 6 on a paste of your `tools/list`, scored against servers your own size. It names the sibling each colliding tool is hardest to tell apart from — which for cause 1 is usually the whole answer. Runs in your browser, nothing uploaded.

*Originally published at [getmcpulse.com](https://getmcpulse.com/blog/why-the-model-wont-call-your-tool).*
