Raxol.MCP.Registry (Raxol MCP v2.6.0)

Copy Markdown View Source

ETS-backed registry for MCP tools and resources.

Any module can register tools and resources. The registry stores definitions alongside callback functions that are invoked when tools are called or resources are read.

Reads (list_tools, call_tool, list_resources, read_resource) go directly to ETS with read_concurrency: true -- no GenServer bottleneck. Writes (register_*, unregister_*) serialize through the GenServer.

Tool Registration

tools = [
  %{
    name: "raxol_screenshot",
    description: "Capture a screenshot",
    inputSchema: %{type: "object", properties: %{id: %{type: "string"}}},
    callback: fn args -> {:ok, [%{type: "text", text: "screenshot data"}]} end
  }
]
Registry.register_tools(registry, tools)

Resource Registration

resources = [
  %{
    uri: "raxol://session/demo/model",
    name: "Session Model",
    description: "Current TEA model state",
    callback: fn -> {:ok, %{counter: 5}} end
  }
]
Registry.register_resources(registry, resources)

Summary

Functions

Call a registered tool by name with arguments.

Returns a specification to start this module under a supervisor.

Get circuit breaker status for a tool, resource, or prompt key.

Get a prompt by name, rendering it with the given arguments.

List all registered prompts (definitions without callbacks).

List all registered resources (definitions without callbacks).

List all registered tools (definitions without callbacks).

Read a registered resource by URI.

Registers tools and/or resources in one call after validating each tool shape via Raxol.MCP.ToolDef.validate/1.

Register one or more tools.

Manually reset a circuit breaker.

Start the registry, linked to the calling process.

Types

prompt_def()

@type prompt_def() :: %{
  name: String.t(),
  description: String.t(),
  arguments: [map()],
  callback: (map() -> {:ok, [map()]} | {:error, term()})
}

resource_def()

@type resource_def() :: %{
  uri: String.t(),
  name: String.t(),
  description: String.t(),
  callback: (-> {:ok, term()} | {:error, term()})
}

tool_def()

@type tool_def() :: %{
  name: String.t(),
  description: String.t(),
  inputSchema: map(),
  callback: (map() -> {:ok, term()} | {:error, term()})
}

Functions

call_tool(registry \\ __MODULE__, name, arguments)

@spec call_tool(GenServer.server(), String.t(), map()) ::
  {:ok, term()} | {:error, term()}

Call a registered tool by name with arguments.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

circuit_status(registry \\ __MODULE__, key)

@spec circuit_status(GenServer.server(), Raxol.MCP.CircuitBreaker.key()) :: map()

Get circuit breaker status for a tool, resource, or prompt key.

get_prompt(registry \\ __MODULE__, name, arguments)

@spec get_prompt(GenServer.server(), String.t(), map()) ::
  {:ok, [map()]} | {:error, term()}

Get a prompt by name, rendering it with the given arguments.

handle_manager_cast(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_cast/2.

handle_manager_info(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_info/2.

list_prompts(registry \\ __MODULE__)

@spec list_prompts(GenServer.server()) :: [map()]

List all registered prompts (definitions without callbacks).

list_resources(registry \\ __MODULE__)

@spec list_resources(GenServer.server()) :: [map()]

List all registered resources (definitions without callbacks).

list_tools(registry \\ __MODULE__)

@spec list_tools(GenServer.server()) :: [map()]

List all registered tools (definitions without callbacks).

read_resource(registry \\ __MODULE__, uri)

@spec read_resource(GenServer.server(), String.t()) ::
  {:ok, term()} | {:error, term()}

Read a registered resource by URI.

register_all(registry \\ __MODULE__, opts)

@spec register_all(
  GenServer.server(),
  keyword()
) :: :ok | {:error, {:invalid_tool, non_neg_integer(), [atom()]}}

Registers tools and/or resources in one call after validating each tool shape via Raxol.MCP.ToolDef.validate/1.

Reduces the common consumer boilerplate:

:ok = Registry.register_tools(registry, tools)
:ok = Registry.register_resources(registry, resources)

to a single call:

:ok = Registry.register_all(registry, tools: tools, resources: resources)

Returns {:error, {:invalid_tool, index, reasons}} (no tools or resources registered) when validation fails.

Note: this helper requires the Raxol.MCP.Registry module to be loaded at runtime. Consumers with raxol_mcp as an optional dep should still gate the call with Code.ensure_loaded?(Raxol.MCP.Registry). Optional deps are an Elixir-level concern; no helper can paper over a missing module.

register_prompts(registry \\ __MODULE__, prompts)

@spec register_prompts(GenServer.server(), [prompt_def()]) :: :ok

Register one or more prompts.

register_resources(registry \\ __MODULE__, resources)

@spec register_resources(GenServer.server(), [resource_def()]) :: :ok

Register one or more resources.

register_tools(registry \\ __MODULE__, tools)

@spec register_tools(GenServer.server(), [tool_def()]) :: :ok

Register one or more tools.

reset_circuit(registry \\ __MODULE__, key)

@spec reset_circuit(GenServer.server(), Raxol.MCP.CircuitBreaker.key()) :: :ok

Manually reset a circuit breaker.

start_link(init_opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Start the registry, linked to the calling process.

unregister_prompts(registry \\ __MODULE__, names)

@spec unregister_prompts(GenServer.server(), [String.t()]) :: :ok

Unregister prompts by name.

unregister_resources(registry \\ __MODULE__, uris)

@spec unregister_resources(GenServer.server(), [String.t()]) :: :ok

Unregister resources by URI.

unregister_tools(registry \\ __MODULE__, names)

@spec unregister_tools(GenServer.server(), [String.t()]) :: :ok

Unregister tools by name.