# `Mead.MCP.Policy`
[🔗](https://github.com/albertosca/mead/blob/main/lib/mead/mcp/policy.ex#L1)

Decides which tools the model sees and whether a named call may run. Pure: it reads no process
and asks no server.

The inputs are the catalog entries (what the connected servers offer), the normalized servers
of `Mead.MCP.Configuration` (what the operator allowed, with a class per tool), and the options
of the turn. A tool is visible only if the server offers it, the configuration lists it, and its
class is allowed for this turn: `:read` always, `:effect` only with `tools: :effect`. Any other
value of `tools:` is the default, because an unclear request must not widen access.

What a server says about itself, such as an annotation that a tool is read-only, is never
consulted. The model sees `server__tool`; the first `__` splits it, which is unambiguous because
a configured server name has no underscore.

# `class`

```elixir
@type class() :: :read | :effect
```

# `authorize`

```elixir
@spec authorize(term(), [map()], [map()], keyword()) ::
  {:ok, %{server: atom(), tool: String.t(), class: class()}}
  | {:error, :unknown_tool | :not_allowed}
```

# `model_name_valid?`

```elixir
@spec model_name_valid?(atom(), String.t()) :: boolean()
```

Whether `server__tool` is a name the model can be shown. A tool whose name fails this is never
visible, so the configuration refuses it at boot instead of hiding it without a word.

# `visible_tools`

```elixir
@spec visible_tools([map()], [map()], keyword()) :: [map()]
```

---

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