A few days ago I posted Schema descriptions are load-bearing: why missing parameter descriptions break MCP clients. The argument: every parameter without a description is a load-bearing element silently absent from the schema, and agents fail in ways that look like model problems but are actually contract problems.
The post got a comment from @mickyarun that's worth its own essay:
The "load-bearing" framing is the right shape — the same observation applies one level up at the tool level. Most MCP catalogues we've audited had perfectly described parameters but no description of when not to call this tool, which is the bit that actually decides whether an agent reaches for the right surface. The half-hour we spent adding "anti-purpose" descriptions to about a dozen of our internal tools cut the wrong-tool-selected rate roughly in half. Arguably the parameter case in this post is just the most visible instance of a broader rule: every field of every schema an agent reads is doing structural work whether you specified it or not.
He's right, and the pattern deserves a name. Call it the anti-purpose pattern: every tool description should specify not just what the tool is for, but what it is not for.
HOW vs WHETHER
Parameter descriptions answer HOW to call a tool — what types, what shape, what valid values.
Tool descriptions answer WHETHER to call a tool — does this surface match the user's intent at all.
Both are schema. Both are load-bearing. The first is usually under-specified. The second is almost always under-specified.
Why "Searches the web" fails
Most MCP tool descriptions read like marketing copy:
"Searches the web for information""Retrieves data from the database""Sends an email"
This is fine in isolation. It collapses the moment an agent has three search tools, two database tools, and four messaging tools loaded at once — which is the actual production scenario.
The agent has to disambiguate. The schema gave it nothing to disambiguate with. So it picks the first plausible match, or the one with the cleanest parameter list, or the one whose name lexically matches the user's phrasing. None of these correlate with correctness.
The anti-purpose pattern
The fix is mechanical:
Before: "Searches the web for information"
After: "Searches the public web for current events,
news, and recently published content.
Do not use for: code lookup (use code_search),
internal documentation (use docs_search),
or queries answerable from training data."
Three changes:
- Specific scope — "public web" not "the web", "current events" not "information"
- Disambiguation pointers — names the sibling tools the agent might confuse this with
- Explicit exclusions — the "do not use for" clause
@mickyarunreports roughly 50% fewer wrong-tool-selection errors after adding clauses like this to about a dozen internal tools. That's a half-hour edit producing a measurable behavior shift, with no model change and no prompt-engineering tax on the consumer side.
Why tool authors skip this
Two reasons, both fixable:
- The author knows what the tool is for, so the description is implicit. Authors write descriptions that document the tool's positive purpose because that's what they were thinking about while writing it. The negative purpose — what they consciously decided this tool would not do — never makes it onto the page.
- MCP examples don't model it. Look at any MCP server template or quickstart and tool descriptions are one-line declaratives. There's no canonical example that says "here's what a production tool description looks like with anti-purpose."
The first is fixed by a checklist. The second is fixed by people writing posts like this one.
Concrete checklist
When writing or auditing a tool description, the description should answer:
- Scope: What specifically does this operate on? ("public web", "this user's calendar", "Postgres tables in the analytics schema")
- Trigger: What user intent should select this tool?
- Anti-trigger: What user intent looks similar but should select a different tool?
- Sibling pointer: Which neighboring tools are the most likely confusion sources, and what should send the agent there instead?
If you have more than one tool in your MCP server, all four are load-bearing. Skipping any of them outsources the disambiguation to whatever the model happens to guess.
Coming to mcp-probe
This is the next axis I'm adding to mcp-probe. Parameter-description coverage is already scored. Tool-description quality — including a heuristic for anti-purpose clauses — belongs in the same scorecard.
Thanks to @mickyarun for the comment that pulled the framing one level up. Schema descriptions are load-bearing. So is every other field of the contract an agent is asked to read.
Top comments (0)