barrel_mcp_client_handler behaviour (barrel_mcp v2.0.2)
View SourceBehaviour for handling server-initiated MCP messages.
A host application implements this module to react to requests the server sends *to* the client (per the declared client capabilities) and to notifications the server emits.
Capabilities and the matching callbacks:
sampling— server may callsampling/createMessageto ask the host to run an LLM completion.roots— server may callroots/listto enumerate the filesystem boundaries the host exposes.elicitation— server may callelicitation/createto prompt the user for a value.
Notifications cover the rest of the spec: notifications/cancelled, notifications/progress, notifications/resources/updated, notifications/resources/list_changed, notifications/tools/list_changed, notifications/prompts/list_changed, notifications/message.
A default implementation in barrel_mcp_client_handler_default returns method_not_found for every request and ignores every notification, so a host only writes callbacks for capabilities it actually declares.
Async replies: when answering a request requires a long-running operation (e.g. an HTTP call to an LLM provider), return {async, Tag, State} from handle_request/3 and later send barrel_mcp_client:reply_async(ClientPid, Tag, Result) from any process. The client's state machine will not block while the handler is computing.
Example
A handler that answers sampling/createMessage synchronously:
-module(my_sampler).
-behaviour(barrel_mcp_client_handler).
-export([init/1, handle_request/3, handle_notification/3,
terminate/2]).
init(Args) -> {ok, Args}.
handle_request(<<"sampling/createMessage">>, Params, S) ->
Reply = call_my_llm(Params), %% your provider integration
Result = #{<<"content">> => #{<<"type">> => <<"text">>,
<<"text">> => Reply},
<<"model">> => <<"my-model">>,
<<"role">> => <<"assistant">>},
{reply, Result, S};
handle_request(Method, _Params, S) ->
{error, -32601, <<"Method not found: ", Method/binary>>, S}.
handle_notification(_Method, _Params, S) -> {ok, S}.
terminate(_Reason, _State) -> ok.Wire the handler in via the connect spec: #{handler => {my_sampler, []}}.
See examples/sampling_host/ for a runnable end-to-end version.