# `ExAthena.Tool.Spec`
[🔗](https://github.com/udin-io/ex_athena/blob/v0.7.1/lib/ex_athena/tool/spec.ex#L1)

Canonical, unified representation of a tool — whether backed by a
behaviour-implementing module or a dynamically-discovered MCP tool.

## Kinds

  * `:module` — wraps a module that implements `ExAthena.Tool`. All fields
    are populated from the module's callbacks at construction time.
  * `:mcp` — wraps a tool discovered from an MCP server. The tool name is
    namespaced as `"<server>_<tool>"`. MCP tools are never assumed
    parallel-safe.

## Construction

    spec = ExAthena.Tool.Spec.from_module(MyApp.ReadTool)
    spec = ExAthena.Tool.Spec.from_mcp(tool_map, "myserver")

## Dispatch

    ExAthena.Tool.Spec.execute(spec, args, ctx)

# `kind`

```elixir
@type kind() :: :module | :mcp
```

# `t`

```elixir
@type t() :: %ExAthena.Tool.Spec{
  description: String.t(),
  kind: kind(),
  mcp_server: String.t() | nil,
  mcp_tool_name: String.t() | nil,
  module: module() | nil,
  name: String.t(),
  parallel_safe?: boolean(),
  schema: map()
}
```

# `execute`

```elixir
@spec execute(t(), map(), ExAthena.ToolContext.t()) ::
  {:ok, term()} | {:error, term()} | {:halt, term()}
```

Execute the tool with `args` and `ctx`.

Dispatches to `module.execute/2` for `:module` specs, and to
`ExAthena.Mcp.Tool.execute/3` for `:mcp` specs.

# `from_mcp`

```elixir
@spec from_mcp(map(), String.t()) :: t()
```

Build a spec from an MCP tool map and server name.

`tool_map` is a map with string keys `"name"`, `"description"`, and
`"inputSchema"` as returned by `tools/list`. The resulting spec's `:name`
is `"<server>_<tool>"`.

# `from_module`

```elixir
@spec from_module(module()) :: t()
```

Build a spec from a module implementing `ExAthena.Tool`.

# `parallel_safe?`

```elixir
@spec parallel_safe?(t()) :: boolean()
```

Return the cached `parallel_safe?` flag.

---

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