Anubis.Client (anubis_mcp v0.16.0)
High-level DSL for defining MCP (Model Context Protocol) clients.
This module provides an Ecto-like interface for creating MCP clients with minimal boilerplate. By using this module, you get a fully functional MCP client with automatic supervision, transport management, and all standard MCP operations.
Usage
Define a client module:
defmodule MyApp.AnthropicClient do
use Anubis.Client,
name: "MyApp",
version: "1.0.0",
protocol_version: "2024-11-05",
capabilities: [:roots, {:sampling, list_changed?: true}]
endAdd it to your supervision tree:
children = [
{MyApp.AnthropicClient,
transport: {:stdio, command: "uvx", args: ["mcp-server-anthropic"]}}
]Use the client:
{:ok, tools} = MyApp.AnthropicClient.list_tools()
{:ok, result} = MyApp.AnthropicClient.call_tool("search", %{query: "elixir"})Options
The use macro accepts the following required options:
:name- The client name to advertise to the server (string):version- The client version (string):protocol_version- The MCP protocol version (string):capabilities- List of client capabilities (see below)
Capabilities
Capabilities can be specified as:
- Atoms:
:roots,:sampling - Tuples with options:
{:roots, list_changed?: true} - Maps for custom capabilities:
%{"custom" => %{"feature" => true}}
Transport Configuration
When starting the client, you must provide transport configuration:
{:stdio, command: "cmd", args: ["arg1", "arg2"]}{:sse, base_url: "http://localhost:8000"}{:websocket, url: "ws://localhost:8000/ws"}{:streamable_http, url: "http://localhost:8000/mcp"}
Process Naming
By default, the client process is registered with the module name.
You can override this with the :name option in child_spec or start_link:
# Custom atom name
{MyApp.AnthropicClient, name: :my_custom_client, transport: ...}
# For distributed systems with registries (e.g., Horde)
{MyApp.AnthropicClient,
name: {:via, Horde.Registry, {MyCluster, "client_1"}},
transport_name: {:via, Horde.Registry, {MyCluster, "transport_1"}},
transport: ...}When using via tuples or other non-atom names, you must explicitly provide
the :transport_name option. For atom names, the transport is automatically
named as Module.concat(ClientName, "Transport").
Summary
Functions
Generates an MCP client module with all necessary functions.
Guard to check if an atom is a valid client capability.
Guard to check if a capability is supported by checking map keys.
Types
@type capabilities() :: [capability() | {capability(), capability_opts()} | map()]
@type capability() :: :roots | :sampling
@type capability_opts() :: [{:list_changed?, boolean()}]
Functions
Generates an MCP client module with all necessary functions.
This macro is used via the use directive and accepts the following options:
:name- Client name (required, string):version- Client version (required, string):protocol_version- MCP protocol version (required, string):capabilities- List of capabilities (optional, defaults to empty list)
The macro generates:
child_spec/1- For supervision tree integrationstart_link/1- To start the client- All MCP operation functions (ping, list_tools, call_tool, etc.)
Guard to check if an atom is a valid client capability.
Guard to check if a capability is supported by checking map keys.