Blog / How to optimise your MCP tools by knowing how agents call them
Should your MCP server look different to Claude, GPT and a small model? We tested three tool surfaces
There's a growing idea that every model needs its own version of your tools: one set of descriptions for Claude, another for GPT, a third for the cheap model. Before building three surfaces, we wanted to know whether the models actually react differently to the same changes.
The three surfaces
We built one mock MCP server, a task tracker called “Acme Tasks” with synthetic data and 21 tools, and served it in three versions:
| Version | Descriptions | Behaviour | Tool list size |
|---|---|---|---|
| Before | Terse, like many real servers (“Stats.”) | Errors dump every tool's schema; lists return 50 full records by default; a date like “2026-10-14” is rejected | 1,369 tokens |
| Better descriptions | What each tool returns and when to use it, plus one line mapping the app's words to the API's (“waiting on someone” = blocked) | Same as before | 1,730 tokens |
| Fixed | Same as better descriptions | Short errors that say what to fix; plain dates accepted; 10 slim records by default with a summary; a small workspace overview | 1,730 tokens |
Three models ran five everyday questions (“how many tasks in Mobile app are waiting on someone?”, “who has the most open tasks?”…) twice on each version: Claude Code and Codex with their default frontier models, and OpenCode with a small free model, GLM-5.3 Flash.
Results by model
| Model (app) | Before | Better descriptions | Fixed |
|---|---|---|---|
| Claude Code, default model | 10/10 · 26,960 | 10/10 · 20,293 | 10/10 · 20,249 |
| Codex, default model | 10/10 · 89,129 | 10/10 · 89,101 | 10/10 · 78,126 |
| Small free model (OpenCode) | 10/10 · 21,344 | 10/10 · 20,756 | 10/10 · 17,168 |
Each 10/10 has a 95% range of 72–100%. Five answers were first marked wrong by our checker because they mentioned a task that should be excluded; reading them showed each named it only to explain why it was excluded, so we counted them as passes. These jobs are short lookups, one to four calls, so the ceiling is easy to hit; the differences are in how each model got there.
See how each model uses your tools before you fork them.
We run your users' jobs through Claude Code, Codex and other apps and models against your server, compare tool choice, errors and tokens per model, and tell you which changes are worth making.
What descriptions changed
Three of the questions are counts that one tool, get_stats, answers directly. With terse descriptions its whole description was “Stats.”, and models had to guess what it returned:
Without a clear description, Claude Code and the small model listed tasks and counted them: 12 and 17 list_items calls on those questions. With better descriptions that fell to 2 and 0, and Claude Code's median input dropped by a quarter. Codex picked the summary tool in 5 of 6 runs even with the terse version. The small model's other two runs used the workspace overview, which also has the counts.
So models do react differently to wording, but in one direction: clearer descriptions helped the models that needed help and didn't hurt the one that didn't. That's an argument for one better surface, not three different ones. How to write those descriptions is in how to optimise your MCP tools by knowing how agents call them.
What behaviour fixes changed
All 10 errors in the first two versions were the same: the agent asked for activity “since 2026-10-14” and the server wanted a full timestamp. Every model made that call, every run recovered, and the fixed version, which accepts a plain date, had 0 errors. On the versions with verbose errors, each failed call returned every tool's schema, so a single mistake added thousands of tokens.
| Model | Before | Fixed | Change |
|---|---|---|---|
| Claude Code | 84,740 chars | 10,068 chars | −88% |
| Codex | 32,929 chars | 4,440 chars | −87% |
| Small model | 68,521 chars | 4,911 chars | −93% |
These fixes are model-agnostic: they remove work the model shouldn't have to do. See error messages for AI agents for the error format.
Where models really differ
The per-model differences that have bitten us in real runs come from the agent app around the model, not from description wording:
- Server instructions: Claude Code cuts them at 4,096 characters, Grok Build at about 2,048, and Codex adds them to every tool description. See do agents read your MCP server instructions?
- Which half of a result is shown: Claude Code showed the model only
structuredContentand OpenCode only the text. See structuredContent or text? - Big results: Claude Code refused 40 results over its limit in 23 of 40 live runs on a production server, and read them back from files.
Those are worth designing for, because they change what the model sees. Rewriting descriptions per model is worth it only once your own runs show a model failing on wording that works for the others. For the cost side of the same experiment, see can cheaper models use your MCP server?
Go deeper: Why agents call the wrong tool, MCP server or CLI for AI agents?, Which MCP channels agents use.
How we measured
- Server: a local mock with synthetic data (4 projects, 6 people, 36 tasks, 76 events), 21 tools, three versions. Write tools existed and changed nothing; none were called.
- Apps and models: Claude Code 2.1.304 and Codex CLI 0.161.0 with their default models; OpenCode 1.18.34 with the free GLM-5.3 Flash model. Headless, isolated from other servers, 21 Oct 2026, about 21:10–21:35 (UTC+3).
- Runs: 5 jobs × 2 runs × 3 versions × 3 models = 90. Answers checked in code against the known answer, then failures read by hand (5 overridden to pass, reasons recorded).
- Tokens: from each app's own usage report, cached input included; tool list sizes in
o200k_base. Compare each model with itself: the apps' own prompts differ in size. - Limits: short lookup jobs only, 2 runs per job, one small model. 10/10 per cell can't show small differences in pass rate.
FAQ
Do different AI models need different MCP tool descriptions?
Not in our test. Claude Code, Codex and a small free model all passed 10 of 10 runs on each of three versions of the same server. Better descriptions changed which tools Claude Code and the small model picked, and barely changed Codex, but one good set of descriptions worked for all three.
What makes the biggest difference across models?
Behaviour, not wording. Accepting the input formats agents actually send, returning short errors that say what to fix, and keeping default results small cut errors to zero and result text by 87–93% for every model.
Should I build a proxy that rewrites tool descriptions per model?
Only if your own runs show a model failing on a description that works for others. Measure first: run the same jobs per model and compare pass rate, tool choice, errors and tokens. In our runs, a single surface was enough.
Why did Claude Code page through lists instead of using the summary tool?
With terse descriptions, the summary tool's description didn't say it returned counts per project and person. Claude Code listed items and counted them itself, in 5 of 6 runs. Once the description said what the tool returns, it used it in 6 of 6.
See how each model uses your tools before you fork them.
We run your users' jobs through Claude Code, Codex and other apps and models against your server, compare tool choice, errors and tokens per model, and tell you which changes are worth making.