MCP Tool Schemas: Helping Agents Call Them Correctly
An MCP tool schema is the contract an agent reads to decide when, what, and how to call. Put selection criteria in description, keep required to true minima, and return fixable failures in tool results with isError: true.
This post covers schema design only. If a server never appears in the client list or fails to connect, use a connection-failure guide instead. No pricing.
What belongs in description?
One-line answer: State what the tool does, when not to use it, and what each argument means—in concrete language. Avoid repeating the tool name with no substance.
Models pick tools from description more than from name. Official MCP tool guidance recommends clear names/descriptions, detailed JSON Schema, and examples inside the description when helpful.
Include:
- Behavior — “Fetch current weather for a city,” not “weather helper.”
- Limits / refusals — “US cities only,” “does not delete.”
- Disambiguation — one line separating near-duplicate tools.
- Side effects — write, delete, or send actions must be explicit.
Avoid:
- Empty labels (“utility,” “helper”)
- Promises that disagree with the schema
- Internal stack traces or repo paths that do not help selection
Describe every property (format, bounds, examples). "limit" alone is weak; "Maximum results to return, 1–20" is usable.
{
"name": "create_ticket",
"description": "Creates a tracker issue. Does not assign owners or delete. Only title and priority are required.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"required": ["title", "priority"],
"properties": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 120,
"description": "Issue title, 3–120 characters."
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "Priority: low | medium | high."
},
"labels": {
"type": "array",
"items": { "type": "string", "maxLength": 32 },
"maxItems": 8,
"description": "Optional. Up to 8 labels."
}
}
}
}
additionalProperties: false catches typos like include_archive early.
What goes in required?
One-line answer: Only fields without which the operation cannot run. Do not promote every key from a sample payload into required.
Copying a full example into required forces the model to invent values or loop on clarifying questions.
Practical rules:
- Required = impossible to execute without (IDs, paths, query text).
- Optional = sensible defaults (
limit,dry_run, sort order). - Keep fields required when silent defaults would change meaning (amount, destination path, privilege level).
- Encode ranges with
enum,minimum/maximum,minLength.
Re-validate in the handler with the same rules. Clients may interpret schemas loosely; runtime checks close the gap.
| Keep required | Keep optional |
|---|---|
| Target resource ID | Display-only UI fields |
| Write destination path | Default page size |
| Search query body | Debug flags |
Prefer many narrow tools over one “do everything” tool—schemas and required lists stay smaller.
How should failure messages look?
One-line answer: Separate protocol errors from tool execution errors; put fixable failures in the tool result with isError: true and an actionable sentence.
Per the MCP tools model:
- Protocol errors — unknown tool name, malformed request shape. Returned as JSON-RPC
error. Hard for the model to recover. - Tool execution errors — bad dates, out-of-range values, API/business failures. Put text in
contentand setisError: trueso the client can feed the model a retry.
Good:
Invalid departure date: must be in the future. Current date is 2026-09-24.
Bad:
Error: ECONNRESET at Object.<anonymous> (/app/src/handler.js:214:11)
Writing rules:
- Say what to change.
- Include allowed formats, ranges, or next actions.
- Omit stack traces, secrets, and raw absolute paths.
- Do not silently fill missing required fields—especially priority, money, or delete targets.
Timeouts, auth, and rate limits follow the same pattern: short cause text so the model can retry, shrink, or switch tools.
Wrap-up
For agent-friendly MCP tool schemas: put behavior and limits in description, keep required minimal, and return fixable failures via isError results. Connection/process failures are not schema bugs—check the client’s MCP logs first.