@clementvial

Developer from Canada 🇨🇦
Product, infrastructure, AI, and web3.
Mostly on AWS and Cloudflare.

All notes

MCP Tool Descriptions Are the Prompt

I built an MCP server around an existing REST API and named the tools after the endpoints. The model called the wrong one constantly, or called the right one with an argument it had invented.

Nothing was broken. The model only sees three things per tool: the name, the description, and the JSON schema. That’s the entire interface, and I had written all three for a machine that already knew what I meant.

Name for the intent, not the route

get_v2_issues_query describes your URL structure. search_issues describes what somebody wants. The second one gets picked correctly, because the model is matching intent against a name, not reading your API docs.

Descriptions do more work than they look like they should. Say when to use the tool, and say when not to, because that second sentence is what stops it firing on every vaguely related turn.

tools.ts
server.tool(
'search_issues',
'Search issues by text, label, or assignee. Use for questions about ' +
'existing issues. Do not use to create or edit an issue.',
{ query: z.string().describe('Free text, matched against title and body') },
handler,
);

Parameter descriptions get read too. So do enums, and an enum is worth more than a sentence explaining which strings are legal.

Errors are instructions

Returning a stack trace teaches the model nothing and it retries the same call. Return the correction:

No project named “backend”. Available: web, api, infra.

It fixes the argument and moves on, usually in the same turn. This one change removed most of my retry loops.

Fewer tools

Every description sits in the context window on every single turn, so a forty-tool server is both expensive and harder to choose from. Two tools that overlap will get confused with each other forever.

Merging related endpoints into one tool with a parameter beats exposing them separately. So does collapsing anything that always requires three calls in a row into a single tool that does the sequence.

Write the descriptions first, before the handlers. If you can’t say in one sentence when to use a tool and when not to, the model won’t work it out from the code.