How to Design Good MCP Tools

The hardest part of an MCP server is often not protocol code. It is deciding what capabilities to expose and how to shape them for reliable model use.

Use task-level names

Prefer names that describe intent. find_customer_by_email is clearer than query_db. Descriptions should explain when to use a tool, what it returns, and important limits.

Keep parameter sets small

Large schemas increase tool-selection and argument-generation errors. Separate genuinely different operations instead of creating a single “do_everything” tool with dozens of optional fields.

Design safe defaults

Read-only behavior should be easier to invoke than destructive behavior. For mutations, include explicit identifiers, avoid surprising cascades, and support dry-run or approval patterns when practical.

Idempotency

If network retries are possible, mutation tools should use idempotency keys or deterministic request identifiers where the downstream system supports them. Otherwise a retry can create duplicate tickets, payments, or deployments.

Return model-friendly results

Return enough structured information for the model to continue, but avoid dumping huge raw payloads. Include stable IDs that later tools can consume.

Anti-pattern: automatically converting every internal API endpoint into an MCP tool. Curate the surface around agent tasks and authorization boundaries.