# `Raxol.MCP.TreeWalker`
[🔗](https://github.com/DROOdotFOO/raxol/blob/v2.7.0/lib/raxol/mcp/tree_walker.ex#L1)

Traverses a view element tree and derives namespaced MCP tools from widgets.

The view tree is the output of a TEA app's `view/1` function -- nested maps
with `:type`, `:id`, `:attrs`, `:children` keys. TreeWalker walks this tree,
finds widgets that implement `Raxol.MCP.ToolProvider`, calls `mcp_tools/1`
to get tool specs, namespaces them by widget ID, and wraps callbacks that
dispatch TEA messages through the session's Dispatcher.

## Usage

    context = %{dispatcher_pid: dispatcher_pid}
    tools = TreeWalker.derive_tools(view_tree, context)
    Raxol.MCP.Registry.register_tools(tools)

Tool names are namespaced as `"widget_id.action"`, e.g., `"search_input.type_into"`.
Nodes without an `:id` key are skipped (layout containers like `:column`, `:row`).

## Excluding Widgets

Set `mcp_exclude: true` in a widget's attrs to suppress tool derivation:

    %{type: :text_input, id: "internal", attrs: %{mcp_exclude: true}}

The widget and its children still render normally -- only MCP tool
exposure is suppressed. Useful for decorative or internal widgets.

## Explicit provider marker (`attrs.component_module`)

Components whose root emits a plain layout type (`:column`, `:row`) can
declare their providing module explicitly instead of growing this
package's type map (the harness block Components do this):

    %{type: :column, id: "blk", attrs: %{component_module: MyBlock}}

An explicit marker wins over the built-in type map; the same
`ToolProvider` guard applies, so a module that does not implement the
behaviour still derives nothing, and a non-atom marker is ignored.

# `context`

```elixir
@type context() :: %{
  dispatcher_pid: pid() | nil,
  type_map: %{required(atom()) =&gt; module()}
}
```

# `default_type_map`

```elixir
@spec default_type_map() :: %{required(atom()) =&gt; module()}
```

The built-in declaration-type -> Component-module map used when `context`
carries no `:type_map`.

Exposed so the main app can assert it against `Raxol.UI.Registry`; this
package cannot derive the map from that registry (main raxol is not a
dependency), so conformance is a test, not a compile-time guarantee.

# `derive_tools`

```elixir
@spec derive_tools(map() | [map()], context()) :: [Raxol.MCP.Registry.tool_def()]
```

Derives MCP tool definitions from a view element tree.

Returns a list of `Registry.tool_def()` maps with namespaced names and
wrapped callbacks that dispatch TEA messages.

## Options in context

  * `:dispatcher_pid` - pid of the session's Dispatcher (for message dispatch)
  * `:type_map` - optional override for widget type -> module mapping

---

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