Most teams debug a tool integration from the inside out. The agent sends a call, the call fails, and someone improves the error message. That work is worth doing, but it is the wrong default. An agent that fails on a call has already spent a round trip, a slice of its step budget, and whatever context it burned deciding to call that tool. An agent that never makes the malformed call spends nothing.
The separation matters because the two artifacts have different audiences and different lifetimes. The tool definition is assembled into the model's context on every call, alongside the system message and the user message, and it is re-sent each turn (the Prompt Engineering Guide). The schema is the static part of that prefix. The error message is returned after generation and consumed only in the recovery path. If the only place a constraint exists is the error, the model learns it by failing, one budget unit at a time.
The Model Context Protocol formalizes where the contract lives. Each tool is identified by a name and includes metadata describing its schema, and clients discover that metadata through a tools/list request before any tools/call happens (the MCP tools specification). The server controls exactly what the model sees, which means the six fields below belong in that listing, not in a wiki page a human reads.
There is a trust caveat worth stating plainly. The MCP specification's security section requires that descriptions of tool behavior, such as annotations, "should be considered untrusted, unless obtained from a trusted server," because tools represent arbitrary code execution (the MCP specification). So the contract you write is a contract the model and the host both have reason to scrutinize. Write it as checkable fact, not as marketing copy.



