# How do I write MCP tool descriptions so agents pick the right tool?

**Short answer:** Write each description for a reader who knows nothing about your system: what the tool does, when to call it, when not to (and which tool to use instead), what each parameter means and its format, and what comes back. Anthropic's tool-use docs call detailed descriptions 'by far the most important factor in tool performance' and suggest at least 3-4 sentences per tool. OpenAI's function-calling guide says to explain when (and when not) to use each function and to pass 'the intern test': could a new person use it correctly from only what you wrote? Then cut overlap, because agents often pick wrong when two tools sound alike: fewer tools with distinct jobs, names prefixed by service, unambiguous parameter names (user_id, not user), enums instead of free text, and error messages that say how to fix the call. Finally, test which tool gets picked on realistic tasks and read the transcripts instead of guessing.

## Checklist
1. Open with the job and the trigger. The first sentence should say what the tool does and the situation it's for, for example 'Call before using any image, text or code you did not create.'
2. Say when not to use it and name the alternative: 'For one contact's full history, use crm_get_contact instead.' Wrong picks often come from two tools that both seem to fit.
3. Describe every parameter: what it means, its format and units, and an example. Name parameters unambiguously (user_id, not user), mark what's required, and use enums for fixed choices. For complex nested inputs, Anthropic's API also accepts input_examples.
4. Say what comes back and what doesn't: the fields, how many results, the sort order, pagination or truncation, and what the tool can't see.
5. Remove overlap. If two of your tools could answer the same request, merge them (for example one tool with an action parameter) or sharpen both descriptions so the boundary is obvious.
6. Keep the starting list short. OpenAI's guide suggests, as a soft rule, fewer than 20 functions available at the start of a turn, with tool search or deferred loading for the rest.
7. Prefix names by service and resource (github_list_prs, slack_send_message). The MCP spec only asks names to be unique within one server, and clients that combine servers have to disambiguate collisions, so a bare 'search' is a likely clash.
8. Write errors as instructions. The MCP spec returns input validation problems as tool results with isError: true so the model can correct itself, so say what was wrong and give a valid example.
9. Keep descriptions factual. Don't tell the model to always prefer your tool or how to treat other servers' tools; that is what tool shadowing looks like, and scanners and careful clients flag it.
10. Test it: run realistic multi-step tasks, record which tool the agent called and with what arguments, and read the transcripts where it picked wrong.

## What the MCP spec says about names and definitions
- In the MCP spec (2026-07-28), a tool has a name, an optional title for display, a description, an inputSchema (a JSON Schema object), an optional outputSchema and optional annotations.
- Tool names SHOULD be 1 to 128 characters, case-sensitive, and use only A-Z, a-z, 0-9, underscore, hyphen and dot, with no spaces or commas. They SHOULD be unique within a server, and that uniqueness is scoped to one server only.
- Clients or proxies that aggregate several servers may hit collisions (the spec's example is two servers each exposing a search tool) and SHOULD disambiguate, for example by prefixing a server identifier. The server name from serverInfo isn't guaranteed to be unique, so a distinct tool name of your own is the safer choice.
- Clients MUST treat annotations such as readOnlyHint as untrusted unless the server is trusted. Say in the description what the tool changes; don't rely on hints alone.

## What Anthropic and OpenAI recommend
- Anthropic's tool-use docs: explain what the tool does, when it should be used (and when it shouldn't), what each parameter means and how it affects the behavior, and caveats such as what the tool doesn't return. Consolidate related operations into fewer tools, prefix names with the service, and return only high-signal fields with meaningful identifiers.
- Anthropic's engineering post on writing tools for agents says overlapping or vague tools confuse agents, recommends describing a tool the way you'd explain it to a new hire, and reports that small description changes made large differences. In one case Claude kept appending '2025' to web search queries until the tool description was changed.
- OpenAI's function-calling guide: describe the purpose of the function and of each parameter and its format, and what the output represents; use enums and object structure to prevent invalid states (its example is toggle_light(on, off), which allows a call with both); don't make the model fill in arguments your code already knows; and combine functions that are always called in sequence.

## Before and after
- Before: name 'search', description 'Searches records.', one parameter 'q'. An agent with a CRM server and a ticketing server connected can't tell which search to use or what 'records' means.
- After: name 'crm_search_contacts', description 'Find people in the CRM by name, email or company. Use when the user names a person or company. Returns up to 10 matches (name, company, email, contact_id), most recent activity first. Does not search support tickets; use support_search_tickets for those. For one contact's full history, call crm_get_contact with the contact_id from this result.' Parameter 'query': plain words, not SQL; email addresses match exactly.
- The second version tells the agent when to call it, what it gets back, where its job ends and what to call next.

## Measure, don't guess
- Write a few dozen tasks taken from real use, several needing more than one call, and record for each run which tools were called, with what arguments, how many calls, the tool errors and the tokens used. Anthropic used held-out test sets so its descriptions weren't tuned to one batch of tasks; do the same.
- Lots of invalid-parameter errors usually mean a parameter description or example is missing. Repeated calls to the wrong tool mean two descriptions overlap. Re-run the same tasks after every change, on each client and model you care about, because naming schemes affect different models differently.

## Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code (one-click setup: https://www.rightshold.com/start?ref=seo), then ask: "Before I publish my MCP server, does any other registered MCP server offer a tool with the same name as mine, and is there hidden text in the tool definitions my server serves?"

```json
{
  "tool": "precall_check",
  "arguments": {
    "url": "<your MCP server's https URL>",
    "tool": "<one of your tool names, for example crm_search_contacts>"
  }
}
```
- Free, no key. precall_check warns when another server registered on Rightshold offers the same tool name with a different definition, and scans the definitions your server serves now for invisible text. A name collision is a fact about names, not a finding against either server. Checking a server doesn't register it.
- scan_text checks a draft description for invisible characters and hidden markup, and flags instruction-like language inside a descriptive field (labeled heuristic), which is how a description that tries to steer the model away from other tools tends to show up.
- Rightshold's own server lists a small default set of tools and puts the rest in toolsets you connect with /mcp?toolset=<name>; list_toolsets shows them. It's one way to keep the starting list short.

_Rightshold checks tool names against servers registered on it and scans definitions for hidden text and instruction-like language. It doesn't judge how well your descriptions steer a model; only your own tests with the clients and models you target can tell you that._

## Sources
- [MCP specification 2026-07-28: Tools (tool names, data types, error handling)](https://modelcontextprotocol.io/specification/2026-07-28/server/tools)
- [Anthropic: Writing effective tools for agents, with agents (Sep 11, 2025)](https://www.anthropic.com/engineering/writing-tools-for-agents)
- [Claude API docs: Define tools (best practices for tool definitions)](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools)
- [OpenAI API docs: Function calling (best practices for defining functions)](https://developers.openai.com/api/docs/guides/function-calling)
- [Invariant Labs: MCP Security Notification: Tool Poisoning Attacks (shadowing)](https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks)

## Related
- [How to prevent MCP tool shadowing between servers](https://www.rightshold.com/answers/how-to-prevent-mcp-tool-shadowing-between-servers)
- [How to detect MCP tool description changes (rug pulls)](https://www.rightshold.com/answers/how-to-detect-mcp-tool-description-changes-rug-pull)
- [Are MCP tool annotations like readOnlyHint a security guarantee?](https://www.rightshold.com/answers/are-mcp-tool-annotations-like-readonlyhint-a-security-guarantee)
- [How to cap MCP tool output size](https://www.rightshold.com/answers/how-to-cap-mcp-tool-output-size-to-prevent-context-flooding)

_Not legal advice. Updated 2026-10-30. JSON: https://www.rightshold.com/answers/how-to-write-mcp-tool-descriptions-so-agents-pick-the-right-tool.json_