#AI#AI Agent#MCP

MCP Tool Schema Design: Helping Models Call Tools Reliably Instead of Guessing Parameters

An MCP tool's input and output schemas form a long-lived contract among the model, client, and business service. This article covers parameter design, error models, pagination, compatibility, and testability so a growing tool catalog remains usable.

Key Points

  • Topic Focus: AI、AI Agent、MCP
  • Suitable for: indie hackers, full-stack engineers, AI application developers
  • Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Author @admin·Published July 26, 2026·Updated July 26, 2026

Whether a model can call a tool correctly often depends less on how polished the description is and more on whether the schema clearly defines the business boundaries. Ambiguous parameter names, too many optional fields, and outputs consisting only of natural-language text all force the model to keep guessing during multi-turn tasks. Production-grade MCP tools should be designed as public APIs.

Start with a Task, Not a Backend Endpoint

Backend interfaces commonly expose every field, as in update_ticket(id, body). When a model sees this interface, it does not know which fields in body it can change or which changes require confirmation. A better design divides tools around user tasks: get_ticket, add_ticket_comment, and change_ticket_priority. Each tool performs exactly one auditable action.

Use verb-object tool names, and avoid generic names such as doAction and run. Clearly state prerequisites, scope of impact, and whether the tool writes data in its description. Models cannot reliably infer risk from names, so semantics such as "creates an external resource" or "returns aggregate data only" must be explicit.

Keep Input Parameters Few and Strictly Constrained

Prefer enums, explicit string formats, and shallow object hierarchies. For example, priority should not accept arbitrary strings:

json
{
  "ticketId": "INC-1042",
  "priority": "high",
  "reason": "Customer-facing checkout is unavailable"
}

Here, priority should be restricted to low, medium, high, and critical instead of accepting natural-language values such as "urgent," "P0," or "high-priority." Users can still provide natural-language input, but the client or a parsing layer in front of the tool should normalize it. The tool contract should not be responsible for ambiguous interpretation.

Keep only the fields that are essential to completing the task as required fields. Remove information that can be derived from the session, authorization context, or current project. For example, the model should not be asked to provide the user ID or tenantId. The more parameters there are, the more likely the model is to omit them, fill them incorrectly, or guess values across tenants.

Design Outputs for Both Models and People

Do not make a tool return only "success." At minimum, include stable machine-readable fields, a user-readable summary, and information about available next steps:

json
{
  "ticket": { "id": "INC-1042", "priority": "high", "status": "open" },
  "changed": ["priority"],
  "summary": "Updated the priority of INC-1042 to high.",
  "nextActions": ["add_ticket_comment", "get_ticket"]
}

Machine-readable fields allow the next tool call to reference an exact ID, the summary lets the user confirm the actual result, and nextActions reduces the model's need to guess which tools are available. Query tools should return structured results, pagination cursors, and a total-count range instead of combining thousands of table rows into a Markdown paragraph.

Errors Are Part of the Contract

Divide errors into at least four categories: invalid input, insufficient permissions, missing resources, and retryable dependency failures. Each category should give the model a stable code and actionable guidance:

json
{
  "code": "SCOPE_REQUIRED",
  "message": "The current session cannot export analytics data.",
  "retryable": false,
  "requiredScope": "analytics.export"
}

Do not return database errors, stack traces, or downstream HTML verbatim. They do not help the model recover and may expose internal implementation details. For rate limits and transient failures, tell the caller when to retry instead of allowing the model to repeatedly replay the same write operation.

Maintain Compatibility as Tools Evolve

Fields in published tools must not be renamed or given different meanings arbitrarily. New fields can initially be optional and provide default behavior. Deprecated fields should remain available for one migration cycle, with their replacements identified in the description and response. Use a new tool name or an explicit version for breaking changes instead of silently modifying the old contract.

Every tool needs at least three types of tests: schema-validation tests, authorization-boundary tests, and end-to-end example tests. Add successful examples and representative failure cases to the regression suite, then rerun it after model upgrades, description rewrites, or backend changes. A stable schema is not decorative documentation; it is the infrastructure that allows the MCP ecosystem to keep expanding.

Further Reading

Related

Related Content