barrel_mcp (barrel_mcp v2.0.2)
View SourceMain API module for barrel_mcp.
This module provides the primary public interface for the barrel_mcp library, implementing the Model Context Protocol (MCP) specification.
Overview
barrel_mcp allows you to expose tools, resources, and prompts that AI assistants (like Claude) can interact with. The library supports both server mode (exposing your functionality) and client mode (consuming external MCP servers).
Quick Start
%% Start the application
application:ensure_all_started(barrel_mcp).
%% Register a simple tool
barrel_mcp:reg_tool(<<"greet">>, my_module, greet_handler, #{
description => <<"Greet someone by name">>
}).
%% Start HTTP server
{ok, _} = barrel_mcp:start_http(#{port => 9090}).Handler Functions
All handlers (tools, resources, prompts) must be exported functions with arity 1, receiving a map of arguments:
-module(my_module).
-export([greet_handler/1]).
greet_handler(Args) ->
Name = maps:get(<<"name">>, Args, <<"World">>),
<<"Hello, ", Name/binary, "!">>.
Summary
Functions
List all tools (alias for list_tools/0).
Call a tool locally.
Send elicitation/create to the client behind a session to request structured user input. Requires the client to have declared elicitation capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
Find a tool by name.
Get a prompt with arguments filled in.
List all currently connected clients as [{ServerId, Pid}].
List all registered prompts.
List all registered resource templates.
List all registered resources.
Return the ids of currently connected sessions whose client declared elicitation capability.
Return the ids of currently connected sessions whose client declared roots capability.
Return the ids of currently connected sessions whose client declared sampling capability.
List all registered tools.
Push a notifications/<kind>/list_changed envelope to every currently-connected SSE session. Hosts call this when they mutate the catalogue out-of-band (the registry already calls it for reg/4,5 and unreg/2).
Emit notifications/message (the MCP server log stream) to a session. The notification is dropped silently when Level is below the session's configured level (logging/setLevel). Logger is an optional component name; pass undefined to omit it. Data is the structured payload — typically a string or a map.
Emit notifications/progress to a session. Total may be omitted (defaults to undefined = absent in the wire payload).
Notify all subscribers of a resource that it has changed. The notification body is a JSON-RPC notification with no params; the client is expected to issue a resources/read to fetch the new state.
Read a resource locally.
Register a tool (alias for reg_tool/4).
Register a completion handler for a prompt argument or a resource-template argument. Handlers receive (PartialValue, Ctx) and return {ok, [Suggestion]} or {ok, [Suggestion], #{has_more => true}}.
Register a prompt with the MCP server.
Register a resource with the MCP server.
Register a resource template (RFC 6570 URI template).
Register a tool with the MCP server.
Send roots/list to the client behind a session to enumerate the host's available roots (typically filesystem or workspace roots the host has authorised the server to operate on). Requires the client to have declared roots capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
Call a tool (alias for call_tool/2).
Send sampling/createMessage to the client behind a session. Requires the client to have declared sampling capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
Start a supervised MCP client connecting to a remote server.
Start the HTTP server for MCP.
Start the Streamable HTTP server for MCP (Protocol 2025-03-26).
Start the stdio server for MCP.
Start the stdio server as a supervised gen_server.
Stop a previously-started client.
Stop the HTTP server.
Stop the Streamable HTTP server.
Unregister a tool (alias for unreg_tool/1).
Unregister a prompt.
Unregister a resource.
Unregister a resource template.
Unregister a tool.
Look up the pid of a connected client by ServerId.
Functions
List all tools (alias for list_tools/0).
Call a tool locally.
Executes a registered tool handler with the given arguments. Useful for testing tools without going through the MCP protocol.
Example
{ok, Result} = barrel_mcp:call_tool(<<"search">>, #{
<<"query">> => <<"erlang">>
}).
-spec elicit_create(binary(), map(), map()) -> {ok, Result :: map()} | {error, timeout | not_supported | no_sse | not_found | term()}.
Send elicitation/create to the client behind a session to request structured user input. Requires the client to have declared elicitation capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
Find a tool by name.
Looks up a tool by name and returns its metadata if found.
Get a prompt with arguments filled in.
Executes the prompt handler with the provided arguments and returns the generated messages.
List all currently connected clients as [{ServerId, Pid}].
List all registered prompts.
List all registered resource templates.
List all registered resources.
-spec list_sessions_with_elicitation() -> [binary()].
Return the ids of currently connected sessions whose client declared elicitation capability.
-spec list_sessions_with_roots() -> [binary()].
Return the ids of currently connected sessions whose client declared roots capability.
-spec list_sessions_with_sampling() -> [binary()].
Return the ids of currently connected sessions whose client declared sampling capability.
List all registered tools.
Returns a list of tuples containing tool names and their metadata.
Example
Tools = barrel_mcp:list_tools(),
%% Returns: [{<<"search">>, #{description => ...}}, ...]
-spec notify_list_changed(tool | resource | prompt) -> ok.
Push a notifications/<kind>/list_changed envelope to every currently-connected SSE session. Hosts call this when they mutate the catalogue out-of-band (the registry already calls it for reg/4,5 and unreg/2).
Emit notifications/message (the MCP server log stream) to a session. The notification is dropped silently when Level is below the session's configured level (logging/setLevel). Logger is an optional component name; pass undefined to omit it. Data is the structured payload — typically a string or a map.
Emit notifications/progress to a session. Total may be omitted (defaults to undefined = absent in the wire payload).
-spec notify_resource_updated(binary()) -> ok.
Notify all subscribers of a resource that it has changed. The notification body is a JSON-RPC notification with no params; the client is expected to issue a resources/read to fetch the new state.
Read a resource locally.
Executes the resource handler and returns its content.
Register a tool (alias for reg_tool/4).
-spec reg_completion(Ref, Module, Function, Opts) -> ok | {error, term()} when Ref :: {prompt, binary(), binary()} | {resource_template, binary(), binary()}, Module :: module(), Function :: atom(), Opts :: map().
Register a completion handler for a prompt argument or a resource-template argument. Handlers receive (PartialValue, Ctx) and return {ok, [Suggestion]} or {ok, [Suggestion], #{has_more => true}}.
-spec reg_prompt(Name, Module, Function, Opts) -> ok | {error, term()} when Name :: binary(), Module :: module(), Function :: atom(), Opts :: #{description => binary(), arguments => [#{name := binary(), description => binary(), required => boolean()}]}.
Register a prompt with the MCP server.
Prompts are pre-defined conversation templates that AI assistants can use. They support arguments for dynamic content generation.
Options
description- Prompt descriptionarguments- List of argument definitions
Each argument definition is a map with:
name- Argument name (binary)description- Argument descriptionrequired- Whether the argument is required (boolean)
Handler Return Value
The handler must return a map with:
description- Prompt descriptionmessages- List of message maps withroleandcontent
Example
barrel_mcp:reg_prompt(<<"summarize">>, my_mod, summarize, #{
description => <<"Summarize content">>,
arguments => [
#{name => <<"content">>, description => <<"Text to summarize">>, required => true},
#{name => <<"style">>, description => <<"Summary style">>, required => false}
]
}).
-spec reg_resource(Name, Module, Function, Opts) -> ok | {error, term()} when Name :: binary(), Module :: module(), Function :: atom(), Opts :: #{name => binary(), uri => binary(), description => binary(), mime_type => binary()}.
Register a resource with the MCP server.
Resources expose data that AI assistants can read, such as configuration files, database records, or dynamic content.
Options
name- Human-readable resource nameuri- Unique resource URI (e.g.,<<"file:///config">>)description- Resource descriptionmime_type- MIME type (default:<<"text/plain">>)
Handler Return Values
binary()- Text contentmap()- JSON content (auto-encoded)#{blob => binary(), mimeType => binary()}- Binary content
Example
barrel_mcp:reg_resource(<<"config">>, my_mod, get_config, #{
name => <<"App Configuration">>,
uri => <<"config://app/settings">>,
description => <<"Current application settings">>,
mime_type => <<"application/json">>
}).
-spec reg_resource_template(Name, Module, Function, Opts) -> ok | {error, term()} when Name :: binary(), Module :: module(), Function :: atom(), Opts :: #{name => binary(), uri_template => binary(), description => binary(), mime_type => binary()}.
Register a resource template (RFC 6570 URI template).
Resource templates surface as resources/templates/list on the wire and let clients discover URI patterns the server can serve via resources/read.
Options:
name— display name.uri_template— RFC 6570 URI template (e.g.<<"file:///{path}">>).description— human-readable description.mime_type— content type (default<<"text/plain">>).
-spec reg_tool(Name, Module, Function, Opts) -> ok | {error, term()} when Name :: binary(), Module :: module(), Function :: atom(), Opts :: #{description => binary(), input_schema => map(), annotations => map(), _ => _}.
Register a tool with the MCP server.
Tools are functions that AI assistants can call to perform actions or retrieve information. Each tool has a unique name and a handler function that processes requests.
Options
description- Human-readable description of the toolinput_schema- JSON Schema defining expected input formatannotations- Map of MCP behavioural hints surfaced underannotationsontools/list. Spec keys arereadOnlyHint,destructiveHint,idempotentHint,openWorldHint(all booleans). Values pass through verbatim.
Handler Return Values
The handler function can return:
binary()- Returned as text contentmap()- Automatically JSON encoded[map()]- List of content blocks
Example
barrel_mcp:reg_tool(<<"search">>, my_mod, search, #{
description => <<"Search the database">>,
input_schema => #{
<<"type">> => <<"object">>,
<<"properties">> => #{
<<"query">> => #{<<"type">> => <<"string">>}
},
<<"required">> => [<<"query">>]
}
}).
-spec roots_list(binary()) -> {ok, [map()]} | {error, timeout | not_supported | no_sse | not_found | term()}.
Send roots/list to the client behind a session to enumerate the host's available roots (typically filesystem or workspace roots the host has authorised the server to operate on). Requires the client to have declared roots capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
Call a tool (alias for call_tool/2).
-spec sampling_create_message(binary(), map(), map()) -> {ok, Result :: map(), Usage :: map()} | {error, timeout | not_supported | no_sse | not_found | term()}.
Send sampling/createMessage to the client behind a session. Requires the client to have declared sampling capability in its initialize request and an active SSE stream. Blocks until the client responds or timeout_ms (default 30s) elapses.
-spec start_client(term(), barrel_mcp_client:connect_spec()) -> {ok, pid()} | {error, term()}.
Start a supervised MCP client connecting to a remote server.
ServerId is any term the host uses to identify the connection (typically a binary). Spec is a barrel_mcp_client:connect_spec():
barrel_mcp:start_client(<<"github">>, #{
transport => {http, <<"https://mcp.github.com/">>},
handler => {my_handler_mod, []},
auth => {bearer, <<"ghp_xxx">>},
capabilities => #{sampling => true}
}).
-spec start_http(Opts) -> {ok, pid()} | {error, term()} when Opts :: #{port => pos_integer(), ip => inet:ip_address(), auth => map()}.
Start the HTTP server for MCP.
Starts a Cowboy HTTP server that handles MCP JSON-RPC requests. The server listens for POST requests at /mcp and /.
Options
port- Port number (default: 9090)ip- IP address to bind (default:{0, 0, 0, 0})auth- Authentication configuration (seebarrel_mcp_auth)
Authentication Example
barrel_mcp:start_http(#{
port => 9090,
auth => #{
provider => barrel_mcp_auth_bearer,
provider_opts => #{
secret => <<"your-jwt-secret">>
}
}
}).See also: barrel_mcp_auth, barrel_mcp_http.
-spec start_http_stream(Opts) -> {ok, pid()} | {error, term()} when Opts :: #{port => pos_integer(), ip => inet:ip_address(), auth => map(), session_enabled => boolean(), ssl => #{certfile := string(), keyfile := string(), cacertfile => string()}}.
Start the Streamable HTTP server for MCP (Protocol 2025-03-26).
Starts a Cowboy HTTP server implementing the MCP Streamable HTTP transport. This transport supports: - POST for client requests with JSON or SSE streaming responses - GET for server-to-client notification streams (SSE) - DELETE for session termination - Session management via Mcp-Session-Id header
This is the transport expected by Claude Code's --transport http` option. == Options == <dl> <dt>port</dt><dd>Port number (default: 9090)</dd> <dt>ip</dt><dd>IP address to bind (default: {0, 0, 0, 0})</dd> <dt>auth</dt><dd>Authentication configuration (see <a docgen-rel="seeerl" docgen-href="barrel_mcp_auth" href="barrel_mcp_auth.html"><code>barrel_mcp_auth</code></a>)</dd> <dt>session_enabled</dt><dd>Enable session management (default: true)</dd> <dt>ssl</dt><dd>SSL/TLS configuration for HTTPS: certfile, keyfile, cacertfile (optional)</dd> </dl> == Example == ``` %% Start with API key authentication barrel_mcp:start_http_stream(#{ port => 9090, auth => #{ provider => barrel_mcp_auth_apikey, provider_opts => #{keys => [<<"my-api-key">>]} } }). %% Start with HTTPS barrel_mcp:start_http_stream(#{ port => 9443, ssl => #{ certfile => "/path/to/cert.pem", keyfile => "/path/to/key.pem" } }).''
Claude Code Integration
After starting the server, add it to Claude Code:
claude mcp add my-server --transport http http://localhost:9090/mcp \
--header "X-API-Key: my-api-key"See also: barrel_mcp_auth, barrel_mcp_http_stream.
-spec start_stdio() -> ok.
Start the stdio server for MCP.
Starts an MCP server that communicates over stdin/stdout. This is the transport used for Claude Desktop integration.
Warning: This function blocks and runs the read-handle-respond loop until the input stream closes.
Claude Desktop Configuration
Configure your claude_desktop_config.json:
{
"mcpServers": {
"my-server": {
"command": "/path/to/my_app",
"args": ["mcp"]
}
}
}See also: barrel_mcp_stdio, start_stdio_link/0.
Start the stdio server as a supervised gen_server.
Starts an MCP stdio server that can be supervised. Unlike start_stdio/0, this function returns immediately after spawning the server process.
The server registers locally as barrel_mcp_stdio.
Example
%% In your supervisor:
init([]) ->
SupFlags = #{strategy => one_for_one},
Children = [
#{id => mcp_stdio,
start => {barrel_mcp, start_stdio_link, []},
restart => permanent,
type => worker}
],
{ok, {SupFlags, Children}}.See also: barrel_mcp_stdio, start_stdio/0.
-spec stop_client(term()) -> ok | {error, not_found}.
Stop a previously-started client.
-spec stop_http() -> ok | {error, not_found}.
Stop the HTTP server.
Stops the MCP HTTP server if running.
-spec stop_http_stream() -> ok | {error, not_found}.
Stop the Streamable HTTP server.
Stops the MCP Streamable HTTP server if running.
-spec unreg(binary()) -> ok.
Unregister a tool (alias for unreg_tool/1).
-spec unreg_completion(term()) -> ok.
-spec unreg_prompt(Name :: binary()) -> ok.
Unregister a prompt.
-spec unreg_resource(Name :: binary()) -> ok.
Unregister a resource.
-spec unreg_resource_template(Name :: binary()) -> ok.
Unregister a resource template.
-spec unreg_tool(Name :: binary()) -> ok.
Unregister a tool.
Removes a previously registered tool from the MCP server. After unregistration, the tool will no longer appear in tools/list responses.
Look up the pid of a connected client by ServerId.