mcp-interface-design
mcp-interface-design — make MCP tools an agent can use without a human
A good MCP server is a contract written for a model reader, not an API written for a programmer. The agent never reads your source; it reads tool names, descriptions, and schemas, then guesses. Every ambiguity becomes a wrong call. This skill is the discipline for removing that ambiguity.
⚠️ Critical Constraints
-
The description IS the selection mechanism. The model picks a tool from its name + description alone. A vague description silently routes to the wrong tool. Why: there is no embedding fallback — pure reasoning over text.
- WRONG:
get_data— "Gets data from the system." - CORRECT:
search_invoices— "Find invoices by customer, date range, or status. Returns up to 50 matches with id, amount, and status. Useget_invoicefor full line items."
- WRONG:
-
Schemas must be strict and self-describing. Loose schemas (
type: objectwith no properties, free-form strings for enums) let the model send garbage that only fails at runtime. Why: validation at the boundary is cheaper than a failed tool call mid-reasoning.- WRONG:
{"status": {"type": "string"}} - CORRECT:
{"status": {"type": "string", "enum": ["open","paid","void"], "description": "Invoice lifecycle state"}}
- WRONG:
-
Errors must teach the next action. A bare
500orinvalid argumentstrands the agent. Why: the agent's only recovery signal is the error text — make it actionable.- WRONG:
{"error": "bad request"} - CORRECT:
{"error": "date_from (2026-13-01) is not a valid ISO date. Expected YYYY-MM-DD."}
- WRONG:
-
Least-privilege, read-by-default. Never expose a destructive tool (delete/send/pay) without an explicit, narrowly-scoped definition and an auth scope to match. Why: an agent will eventually call every tool you expose; surface area is liability.