Tool design, the art of description
Why 80% of MCP servers get ignored. Tool design decides whether the model finds you.
The underestimated problem
You've written your MCP server, all tools work, everything's running. But Claude never calls them.
Why? Because the model doesn't know your tools exist, or doesn't understand what they do.
The tool description is more important than the tool code. The code gets called 10 times. The description gets read by the model every single time it's deciding which tool to use.
The three rules for tool names
1. Verb + object. get_customer is better than customer. send_email is better than email. The model needs the verb to understand the action.
2. Specific, not generic. get_stripe_customer is better than get_customer if your server is multi-source. fetch_latest_blog_post is better than fetch_data.
3. Consistent across tools. If you use get_X, list_X, create_X, stick with it. Don't have get_customer in one tool, fetch_user in the next, then retrieve_account. Unify.
The tool description
This is the most important text in the whole server. 1-3 sentences explaining:
- What the tool does.
- When to use it (most people forget).
- When NOT to use it (even more forget).
Example, bad:
Returns a list of customers.
Example, good:
Lists customers from the CRM database. Use this when the user asks for multiple customers or wants an overview. For a single specific customer use
get_customerinstead. Returns max 100 entries, paginate viaoffsetparameter.
The second text helps the model decide. The first is pure documentation.
Input schemas are part of the description
Each parameter should:
- Have a clear name (
customer_id, notid). - Have a description (use Zod schemas with
.describe(...)). - Have a sensible default if optional.
The model reads the schema together with the tool description. Unclear parameters lead to wrong calls.
Output design
The model also reads the output. Two rules:
1. Short text when possible, JSON when needed. Simple tools return a single text block:
"Customer Max Mustermann found. Email: max@example.com, Last order: 2025-11-15 (Product X, 250 EUR)."
Tools that deliver structured data return JSON:
{"customers": [{"id":"123","name":"Max","email":"max@example.com","lastOrder":"2025-11-15"}]}
2. Explain errors clearly.
On errors, not {"error":"failed"}. Instead:
"Couldn't find the customer. Possible reasons: invalid ID, DB connection down. Try `list_customers` to find the right ID."
The model decides better when it knows WHY something didn't work.
The MCP discovery hint
For stdio servers Claude reads the tool list at startup. For HTTP servers you can also set a global system prompt explaining WHAT your server can do. That's the "instructions" in the server setup:
const server = new Server(
{
name: "my-crm-server",
version: "0.1.0",
description: "CRM integration. Provides access to customers, deals, interactions. Use for sales workflows, not for support tickets."
},
{ capabilities: { tools: {} } }
);
The description text is shown to the model when it's deciding which tool is relevant. Use that.
The final rule
Read your tool descriptions out loud. If they sound like docs, they're bad. If they sound like instructions for a colleague, they're good.
Next lesson
Deployment. From local server to npm package, Cloud Run, or MCPize. How to go from "works on my machine" to "installable for others".