Most MCP servers that disappoint are not broken. Their tools are just hard for a model to use: vague names, generic descriptions, too many options. These are the rules we follow on every connector.
1. Design for questions, not endpoints
Start from the questions people actually ask. "Which deals have not moved in two weeks?" deserves its own tool, even if the API needs three calls to answer it.
2. Keep the list short
Five to fifteen tools is the sweet spot. Every extra tool is another option the model can pick by mistake.
3. Name tools as verbs in your team's language
find_customer, list_stale_deals, log_call_note. Avoid internal names like crm_obj_q_v2.
4. Write descriptions as instructions
The description is a prompt. Say what the tool returns, when to use it and when not to.
Bad: "Gets deals."
Good: "List open deals that had no activity for N days, with owner,
stage and amount. Use for questions about stuck or stale deals.
Do not use for closed deals."
5. Make arguments hard to get wrong
- Use enums for fixed choices like stage names.
- Give sensible defaults and limits.
- Accept human inputs (names, emails) and resolve ids on the server.
6. Return less, but better
Return the fields people need with readable names, not raw API payloads with hundreds of keys. Summarize long histories.
7. Separate reading from writing
Keep read tools and write tools apart, and make writes narrow: update_deal_stage, not update_record with any field.
8. Make errors useful
"No customer found for that email. Try searching by company name." lets the model recover. A stack trace does not.
9. Test with real questions
Collect 20 real questions from the team and run them after every change. That test set is worth more than any framework.
We apply these rules on every connector we build.