# `Quiddity.Mcp.Tools`
[🔗](https://github.com/d-led/ex.quiddity/blob/main/lib/quiddity/mcp/tools.ex#L1)

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.

# `call`

```elixir
@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.

# `catalogue`

```elixir
@spec catalogue() :: [map()]
```

The tool catalogue, as `tools/list` answers it.

# `names`

```elixir
@spec names() :: [String.t()]
```

The names of the tools, for a test to hold the catalogue to.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
