# `BB.MCP.Tools`
[🔗](https://github.com/beam-bots/bb_mcp/blob/main/lib/bb/mcp/tools.ex#L5)

Shared logic used by the per-tool component modules under
`BB.MCP.Tools.*`.

Tools take a `robot` argument that selects which configured robot module
they operate on. The list of configured robots is read from
`Application.get_env(:bb_mcp, :robots, [])`.

# `available_names`

```elixir
@spec available_names() :: String.t()
```

Comma-separated list of configured robot names, for error messages.

# `fetch_robot`

```elixir
@spec fetch_robot(map()) :: {:ok, module()} | {:error, struct()}
```

Resolve a `robot` argument from tool params to a robot module.

Returns `{:ok, module}` or `{:error, Anubis.MCP.Error.t()}`.

# `get_arg`

```elixir
@spec get_arg(map(), atom()) :: term()
```

Fetch a tool argument from string-keyed or atom-keyed params.

# `parse_path`

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

Parse a parameter path string (`"motion.max_speed"`) into atoms.

# `robot_arg_schema`

```elixir
@spec robot_arg_schema() :: map()
```

Schema fragment for the `robot` argument, shared by every tool.

# `robots`

```elixir
@spec robots() :: BB.MCP.Robots.config()
```

Read the configured robots map.

# `to_anubis_error`

```elixir
@spec to_anubis_error(term()) :: Anubis.MCP.Error.t()
```

Convert any failure value into an `Anubis.MCP.Error` for the JSON-RPC reply.

`BB.Error` (Splode) exceptions are rendered via `Exception.message/1` with
their user-declared fields exposed under `data`, so MCP clients see the
actual reason (e.g. "Robot is in state `:armed`, requires one of: `:disarmed`")
instead of a generic "Internal error". Anubis errors pass through unchanged.

---

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