Progressive discovery¶
The usual way to put a command-line tool behind MCP is to turn every command into a tool. It is direct and it is what the first generation of Cobra bridges did. It also scales badly in the one dimension that matters to a model: a client fetches the whole catalogue, schemas included, and carries it in the context of every conversation. A tool with eighty commands ships eighty schemas before the user has typed a word, and most of them are never used.
This module's default is to publish three tools instead, whatever the size of
the catalogue: search_tools, get_tool_details and call_tool. The model
searches (or browses an empty query), inspects the one operation it needs, and
calls it. A schema enters the conversation when it is about to be used, and
only that schema. The catalogue can be as large as the tool, and the context
cost stays flat.
Why it is an application pattern, not a protocol feature¶
Nothing in MCP knows about this. To a client, call_tool is an ordinary tool
that happens to take a name and an arguments object; discovery is a
convention the server and the model agree on through the tool descriptions.
That is why compact mode works with every client that speaks MCP, and also why
it carries a trade.
The trade: approval¶
A client that asks before running a destructive tool asks about the tool it
can see. In compact mode that is call_tool, so its annotations have to be
conservative (destructive, open-world), and every operation behind it inherits
that prompt. The per-operation hints an application declares still exist and
reach the model through get_tool_details, and reach a host through the
registry, but they do not reach the client's own approval UI.
Direct mode gives that UI back. Each operation is its own native tool with its
own annotations, at the cost of the catalogue being pushed up front. It is an
explicit choice at server construction (WithMode(Direct)), never inferred
from the client, and the same registry and policy serve both. Choosing a
mode is the practical guide.
What discovery is not¶
Search is not a gate. A known operation may be invoked without a prior search, and inspecting an operation grants no permission to run it. Discovery, inspection and execution each consult the host's policy; execution consults it again with the validated arguments even when inspection just succeeded. A denied name and an unknown name produce the same answer, so the catalogue cannot be probed. Registry membership is not authorisation.
Search is bounded: five summaries by default, twenty at most, a 256-byte query, a 16 KiB page, and cursors that are encrypted, scoped to the caller and expire after ten minutes. These are starting policies from spec 0001 (OQ6), tuned against a synthetic thousand-operation catalogue rather than a real workload, and the reference pages state the exact numbers.