# `Raxol.MCP.FocusLens`
[🔗](https://github.com/DROOdotFOO/raxol/blob/v2.8.0/lib/raxol/mcp/focus_lens.ex#L1)

Attention-aware tool filtering for MCP surfaces.

Complex UIs can expose 100+ tools, but LLM tool selection degrades
past ~20. FocusLens filters the full tool set to a manageable subset
based on which widget has focus.

## Modes

  * `:all` -- the first `:max_tools` tools (default 15), unfiltered
  * `:focused` -- return the session's tools for the focused widget + globals
  * `:hover` -- return the session's tools for the focused widget + the
    hovered widget + globals

Derived tool names are `"session_id.widget_id.action"`. In `:focused` and
`:hover` modes a tool belongs to the session when the first `.` segment of
its name is exactly `:session_id`, and to a widget when the second is
exactly the widget ID, so another session's tools for a widget with the
same ID never leak in. A session or widget ID never holds a `.`
(`Raxol.MCP.TreeWalker.id?/1`). A global tool is one with no `.` in its
name (a server-level tool such as `raxol_list`). With `:registry` given,
the session's `"session_id.discover_tools"` meta-tool follows the widget
tools, so agents can search the session's full set by keyword; without
it, the meta-tool is not added. Every mode cuts its result to
`:max_tools`.

## Usage

    all_tools = TreeWalker.derive_tools(view_tree, context)

    # Headless: show everything
    FocusLens.filter(all_tools, mode: :all)

    # Interactive: show focused + globals
    FocusLens.filter(all_tools,
      mode: :focused,
      session_id: "demo",
      focused_id: "search_input"
    )

    # Mouse tracking: anticipatory tool exposure
    FocusLens.filter(all_tools,
      mode: :hover,
      session_id: "demo",
      focused_id: "search_input",
      hover_id: "submit_btn"
    )

# `tool_def`

```elixir
@type tool_def() :: Raxol.MCP.Registry.tool_def()
```

# `discover_tools_name`

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

The name of the session's `discover_tools` meta-tool.

# `discover_tools_spec`

```elixir
@spec discover_tools_spec(GenServer.server(), String.t()) :: tool_def()
```

Returns the session's `"session_id.discover_tools"` meta-tool spec.

This tool lets agents search the session's full tool set by keyword when
FocusLens is hiding tools. Pass a registry reference so the tool can query
the registered tools; it matches only the tools named under `session_id`.

# `filter`

```elixir
@spec filter([tool_def()], keyword()) :: [tool_def()]
```

Filters a list of tools based on focus state.

## Options

  * `:mode` - `:all` (default), `:focused`, or `:hover`
  * `:session_id` - the session whose tools `:focused` and `:hover` select
    (required in those modes)
  * `:focused_id` - widget ID that currently has focus
  * `:hover_id` - widget ID under the mouse cursor (for `:hover` mode)
  * `:max_tools` - maximum number of tools to return (default: 15)
  * `:registry` - Registry reference for `discover_tools` (optional)

---

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