The tools the MCP server offers, and the one place a name becomes a function.
A tool answers {:ok, %{text: text, structured: map}, state} or
{:error, message, state}. The text is what a model reads; the structured
part is the same answer for a program that would rather not parse prose. The
protocol layer turns the second form into isError, which is how the
specification says "this call failed, the message says how" rather than "the
server is broken".
Every tool is read-only except one that writes a file the caller named:
quiddity_export_mjcf, a scene in metres.
Where the parts come from
A call names a path. The server keeps the parsed part from the first call, so asking three questions about one file reads it once — and a tool never takes a handle from a caller, because a handle is not something a model should have to hold.
Summary
Functions
Calls a tool by name.
The tool catalogue, as tools/list answers it.
The names of the tools, for a test to hold the catalogue to.
Functions
@spec call(String.t(), map(), Quiddity.Mcp.state()) :: {:ok, %{text: String.t(), structured: map()}, Quiddity.Mcp.state()} | {:error, String.t(), Quiddity.Mcp.state()}
Calls a tool by name.
An unknown name, or a missing required argument, is an error a model can read and retry — not a crash.
@spec catalogue() :: [map()]
The tool catalogue, as tools/list answers it.
@spec names() :: [String.t()]
The names of the tools, for a test to hold the catalogue to.