Raxol.MCP.TreeWalker (Raxol MCP v2.7.0)

Copy Markdown View Source

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.

Summary

Functions

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

Derives MCP tool definitions from a view element tree.

Types

context()

@type context() :: %{
  dispatcher_pid: pid() | nil,
  type_map: %{required(atom()) => module()}
}

Functions

default_type_map()

@spec default_type_map() :: %{required(atom()) => 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(tree, context)

@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