barrel_mcp_stdio (barrel_mcp v2.0.2)

View Source

stdio transport for MCP protocol.

This module implements the stdio transport for the Model Context Protocol, enabling communication with MCP clients like Claude Desktop that use stdin/stdout for message passing.

Usage Modes

  • Blocking mode - Call start/0 to run the server in the current process. The function blocks until stdin closes.
  • Supervised mode - Call start_link/0 to start as a gen_server that can be supervised.

Protocol

The stdio transport uses newline-delimited JSON-RPC 2.0 messages:

  • Each message is a single line of JSON
  • Messages are terminated by newline (\n)
  • Responses are written to stdout in the same format

Example: Blocking Mode

   %% In your escript or application main function:
   main(_Args) ->
       application:ensure_all_started(barrel_mcp),
       barrel_mcp_registry:wait_for_ready(),
  
       %% Register your tools
       barrel_mcp:reg_tool(<<"my_tool">>, my_module, my_function, #{
           description => <<"My tool description">>
       }),
  
       %% Start stdio server (blocks until stdin closes)
       barrel_mcp_stdio:start().

Example: Supervised Mode

   %% In your supervisor init/1:
   init(_Args) ->
       Children = [
           #{id => mcp_stdio,
             start => {barrel_mcp_stdio, start_link, []},
             restart => permanent,
             type => worker}
       ],
       {ok, {#{strategy => one_for_one}, Children}}.

Claude Desktop Integration

To use with Claude Desktop, configure claude_desktop_config.json:

   {
     "mcpServers": {
       "my-erlang-server": {
         "command": "/path/to/your/escript",
         "args": []
       }
     }
   }

The config file is located at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/claude/claude_desktop_config.json

See also: barrel_mcp, barrel_mcp_protocol.

Summary

Functions

Start the stdio server in blocking mode.

Start the stdio server as a supervised gen_server.

Functions

handle_call(Request, From, State)

handle_cast(Msg, State)

handle_info(Info, State)

init(_)

start()

-spec start() -> ok.

Start the stdio server in blocking mode.

This function starts the MCP stdio server in the current process. It reads JSON-RPC messages from stdin, processes them through the MCP protocol handler, and writes responses to stdout.

Important: This function blocks until stdin is closed (EOF). It is typically called as the last line of an escript main function or from a dedicated process.

Example

  -module(my_mcp_server).
  -export([main/1]).
 
  main(_Args) ->
      application:ensure_all_started(barrel_mcp),
      barrel_mcp_registry:wait_for_ready(),
 
      %% Register tools before starting
      barrel_mcp:reg_tool(<<"echo">>, ?MODULE, echo, #{
          description => <<"Echo back the input">>
      }),
 
      %% This blocks until stdin closes
      barrel_mcp_stdio:start().
 
  echo(Args) ->
      maps:get(<<"message">>, Args, <<>>).

start_link()

-spec start_link() -> {ok, pid()} | {error, term()}.

Start the stdio server as a supervised gen_server.

This function starts the MCP stdio server as a gen_server process that can be supervised. Unlike start/0, this 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, intensity => 5, period => 10},
      Children = [
          #{id => mcp_stdio,
            start => {barrel_mcp_stdio, start_link, []},
            restart => permanent,
            shutdown => 5000,
            type => worker,
            modules => [barrel_mcp_stdio]}
      ],
      {ok, {SupFlags, Children}}.

terminate(Reason, State)