barrel_mcp_client (barrel_mcp v2.0.2)
View SourceMCP client for connecting to external MCP servers.
A gen_statem that owns one connection to one MCP server. Two transports are supported: stdio (subprocess) and Streamable HTTP (POST + SSE GET).
States:
connecting— transport is opening.initializing—initializerequest in flight.ready— handshake complete; calls accepted.closing— owner asked to close.
Inbound JSON-RPC envelopes from the transport are routed by decode_envelope/1:
- response/error with
id— match against the pending-request table, post the result to the waiting caller. - request with
id— dispatch to the configuredbarrel_mcp_client_handlermodule; reply (sync or async) goes back over the same transport. - notification (no
id) — dispatch to handler; resource update notifications are also routed to subscribers.
Server-side host application code never sees the transport layer; it talks to this module via the API below. Whether to bind an LLM provider (Anthropic, OpenAI, Hermes-style local model) into this loop is the host's job — barrel_mcp itself stays a pure MCP library.
Summary
Functions
Invoke a tool by name. Args is forwarded verbatim as the JSON-RPC arguments field. Returns the server's result map, which has a <<"content">> list of content blocks.
Invoke a tool with options.
Cancel a previously-issued request by id. Sends notifications/cancelled to the server and unblocks the caller with {error, cancelled}.
Close the connection.
Send completion/complete to ask the server to suggest values for a prompt or resource template argument. Ref is the JSON-RPC ref map (e.g. #{<<"type">> => <<"ref/prompt">>, <<"name">> => N}) and Argument is #{<<"name">> => Key, <<"value">> => Partial}.
Render a prompt with the given arguments.
List prompts advertised by the server. Single page.
List prompts with pagination control. Same Opts shape as list_tools/2.
Walk every prompts/list page.
List resource templates advertised by the server. Single page.
List resource templates with pagination control. Same Opts shape as list_tools/2.
Walk every resources/templates/list page.
List resources advertised by the server. Single page.
List resources with pagination control. Same Opts shape as list_tools/2.
Walk every resources/list page and return the union.
List tools advertised by the server. Returns a single page. Use list_tools/2 with #{want_cursor => true} or list_tools_all/1 to walk pagination.
List tools with pagination control.
Walk all tools/list pages and return the full list.
Inform the connected server that the host's roots list has changed. The server may follow up with roots/list to fetch the new set. Hosts that mutate their roots after initialize (e.g. user opened a new workspace) call this so the server picks up the change without polling.
Send a ping request and wait for the response.
Return the negotiated protocol version (e.g. <<"2025-11-25">> or <<"2025-03-26">> if the server downgraded).
Read a resource by URI.
Deliver a deferred reply for a server-initiated request that the handler answered with {async, Tag, _}. Result is either a plain term (sent as the JSON-RPC result) or {error, Code, Message}.
Return the server capabilities map negotiated during initialize. Useful to gate work on optional features.
Return the serverInfo map the server reported during initialize (with keys like <<"name">> and <<"version">>).
Send logging/setLevel. Level is one of debug, info, notice, warning, error, critical, alert, emergency as a binary.
Start an unsupervised client.
Start a supervised client. Linked to the calling process.
Subscribe the calling process to updates for Uri. The calling process receives {mcp_resource_updated, Uri, Params} on every inbound notifications/resources/updated for that URI until it calls unsubscribe/2 or the client closes.
Cancel a long-running task by id. Returns {ok, _} on acceptance; the task transitions to cancelled status, which the server then broadcasts via notifications/tasks/status.
Fetch a single task by id.
List long-running tasks owned by the connected session. Single page; use tasks_list/2 with #{want_cursor => true} or tasks_list_all/1 to walk pagination.
Walk every tasks/list page.
Fetch the final result of a completed task. Returns the task's stored result map; for failed tasks returns {error, {Code, Message}}; for tasks still working returns {error, {_, <<"Task not yet complete">>}}.
Stop receiving updates for Uri on the calling process.
Types
-type connect_spec() :: #{transport := {http, binary() | string()} | {stdio, #{command := string(), args => [string()]}}, client_info => #{name => binary(), version => binary()}, capabilities => map(), handler => {module(), term()}, auth => none | {bearer, binary()} | {oauth, map()} | {oauth_client_credentials, map()} | {oauth_enterprise, map()}, protocol_version => binary(), request_timeout => pos_integer(), init_timeout => pos_integer(), ping_interval => pos_integer() | infinity, ping_failure_threshold => pos_integer()}.
Functions
Invoke a tool by name. Args is forwarded verbatim as the JSON-RPC arguments field. Returns the server's result map, which has a <<"content">> list of content blocks.
Invoke a tool with options.
Opts may contain:
{progress_token, Token}— register the calling process to receive{mcp_progress, Token, Params}messages until the request settles.{timeout, Ms}— override the per-request timeout (request_timeoutfrom the connect spec, default 30000).
Cancel a previously-issued request by id. Sends notifications/cancelled to the server and unblocks the caller with {error, cancelled}.
-spec close(pid()) -> ok.
Close the connection.
Send completion/complete to ask the server to suggest values for a prompt or resource template argument. Ref is the JSON-RPC ref map (e.g. #{<<"type">> => <<"ref/prompt">>, <<"name">> => N}) and Argument is #{<<"name">> => Key, <<"value">> => Partial}.
Render a prompt with the given arguments.
List prompts advertised by the server. Single page.
-spec list_prompts(pid(), map()) -> {ok, [map()], binary() | undefined} | {ok, [map()]} | {error, term()}.
List prompts with pagination control. Same Opts shape as list_tools/2.
Walk every prompts/list page.
List resource templates advertised by the server. Single page.
-spec list_resource_templates(pid(), map()) -> {ok, [map()], binary() | undefined} | {ok, [map()]} | {error, term()}.
List resource templates with pagination control. Same Opts shape as list_tools/2.
Walk every resources/templates/list page.
List resources advertised by the server. Single page.
-spec list_resources(pid(), map()) -> {ok, [map()], binary() | undefined} | {ok, [map()]} | {error, term()}.
List resources with pagination control. Same Opts shape as list_tools/2.
Walk every resources/list page and return the union.
List tools advertised by the server. Returns a single page. Use list_tools/2 with #{want_cursor => true} or list_tools_all/1 to walk pagination.
-spec list_tools(pid(), map()) -> {ok, [map()], NextCursor :: binary() | undefined} | {ok, [map()]} | {error, term()}.
List tools with pagination control.
Opts may contain:
{cursor, Cursor}— start from a previously-returnednextCursor.{want_cursor, true}— return{ok, Items, NextCursor}even on the last page (withundefinedforNextCursor).{timeout, Ms}— override the per-request timeout.
Walk all tools/list pages and return the full list.
-spec notify_roots_list_changed(pid()) -> ok.
Inform the connected server that the host's roots list has changed. The server may follow up with roots/list to fetch the new set. Hosts that mutate their roots after initialize (e.g. user opened a new workspace) call this so the server picks up the change without polling.
Send a ping request and wait for the response.
Return the negotiated protocol version (e.g. <<"2025-11-25">> or <<"2025-03-26">> if the server downgraded).
Read a resource by URI.
Deliver a deferred reply for a server-initiated request that the handler answered with {async, Tag, _}. Result is either a plain term (sent as the JSON-RPC result) or {error, Code, Message}.
Return the server capabilities map negotiated during initialize. Useful to gate work on optional features.
Return the serverInfo map the server reported during initialize (with keys like <<"name">> and <<"version">>).
Send logging/setLevel. Level is one of debug, info, notice, warning, error, critical, alert, emergency as a binary.
-spec start(connect_spec()) -> {ok, pid()} | {error, term()}.
Start an unsupervised client.
-spec start_link(connect_spec()) -> {ok, pid()} | {error, term()}.
Start a supervised client. Linked to the calling process.
Subscribe the calling process to updates for Uri. The calling process receives {mcp_resource_updated, Uri, Params} on every inbound notifications/resources/updated for that URI until it calls unsubscribe/2 or the client closes.
Cancel a long-running task by id. Returns {ok, _} on acceptance; the task transitions to cancelled status, which the server then broadcasts via notifications/tasks/status.
Fetch a single task by id.
List long-running tasks owned by the connected session. Single page; use tasks_list/2 with #{want_cursor => true} or tasks_list_all/1 to walk pagination.
Walk every tasks/list page.
Fetch the final result of a completed task. Returns the task's stored result map; for failed tasks returns {error, {Code, Message}}; for tasks still working returns {error, {_, <<"Task not yet complete">>}}.
Stop receiving updates for Uri on the calling process.