Hermolaos (Hermolaos v0.3.0)
View SourceMCP (Model Context Protocol) client for Elixir.
Hermolaos provides a complete implementation of the Model Context Protocol, enabling Elixir applications to connect to MCP servers and access their tools, resources, and prompts.
Quick Start
# Connect to a local MCP server via stdio
{:ok, client} = Hermolaos.connect(:stdio,
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
)
# List available tools
{:ok, tools} = Hermolaos.list_tools(client)
# Call a tool
{:ok, result} = Hermolaos.call_tool(client, "read_file", %{"path" => "/tmp/test.txt"})
# Disconnect when done
:ok = Hermolaos.disconnect(client)Transports
Hermolaos supports two transport mechanisms:
Stdio Transport
Launches an MCP server as a subprocess and communicates via stdin/stdout.
{:ok, client} = Hermolaos.connect(:stdio,
command: "/path/to/server",
args: ["--arg1", "value"],
env: [{"DEBUG", "1"}]
)HTTP Transport
Connects to a remote MCP server via HTTP/SSE.
{:ok, client} = Hermolaos.connect(:http,
url: "http://localhost:3000/mcp",
headers: [{"authorization", "Bearer token"}]
)Error Handling
All operations return {:ok, result} or {:error, reason}. Errors
are typically Hermolaos.Protocol.Errors structs with error codes.
case Hermolaos.call_tool(client, "unknown_tool", %{}) do
{:ok, result} -> handle_result(result)
{:error, %Hermolaos.Protocol.Errors{code: -32601}} -> IO.puts("Tool not found")
{:error, reason} -> IO.puts("Error: #{inspect(reason)}")
endNotification Handling
To receive server notifications, configure a notification handler:
defmodule MyHandler do
@behaviour Hermolaos.Client.NotificationHandler
@impl true
def handle_notification({:notification, method, params}, state) do
IO.puts("Got notification: #{method}")
{:ok, state}
end
end
{:ok, client} = Hermolaos.connect(:stdio,
command: "my-server",
notification_handler: {MyHandler, %{}}
)
Summary
Functions
Calls a tool with the given arguments.
Sends a cancellation notification for a pending request.
Requests argument completion suggestions.
Connects to an MCP server.
Disconnects from the MCP server.
Extracts image data from a tool call result.
Extracts all images from a tool call result.
Gets a prompt by name, optionally with argument values.
Extracts text content from a tool call result.
Lists available prompts on the server.
Lists resource templates on the server.
Lists available resources on the server.
Lists available tools on the server.
Sends a ping to check server liveness.
Reads a resource by URI.
Gets server capabilities from the initialization response.
Gets server information from the initialization response.
Sets the server's logging level.
Gets the current connection status.
Subscribes to resource updates.
Unsubscribes from resource updates.
Types
@type client() :: Hermolaos.Client.Connection.t()
@type transport() :: :stdio | :http
Functions
Calls a tool with the given arguments.
Parameters
client- The MCP clientname- Tool namearguments- Tool arguments mapopts- Options::timeout- Request timeout override
Returns
{:ok, %{content: [...], isError: false}}- Success (atom keys){:ok, %{content: [...], isError: true}}- Tool error{:error, reason}- Protocol error
Examples
{:ok, result} = Hermolaos.call_tool(client, "read_file", %{"path" => "/tmp/test.txt"})
case result do
%{isError: false, content: content} ->
for item <- content do
case item do
%{type: "text", text: text} -> IO.puts(text)
%{type: "image", data: data} -> File.write!("image.png", Base.decode64!(data))
end
end
%{isError: true, content: content} ->
IO.puts("Tool error: #{inspect(content)}")
end
Sends a cancellation notification for a pending request.
Examples
:ok = Hermolaos.cancel(client, request_id)
Requests argument completion suggestions.
Parameters
client- The MCP clientref- Reference object (prompt or resource)argument- Argument to complete
Examples
ref = %{"type" => "ref/prompt", "name" => "code_review"}
argument = %{"name" => "language", "value" => "eli"}
{:ok, completions} = Hermolaos.complete(client, ref, argument)
Connects to an MCP server.
Parameters
transport- Either:stdioor:httpopts- Transport-specific options
Stdio Options
:command- Command to execute (required):args- Command arguments (default:[]):env- Environment variables as[{name, value}](default:[]):cd- Working directory (optional)
HTTP Options
:url- Server endpoint URL (required):headers- Additional HTTP headers (default:[]):req_options- Options passed to Req (default:[])
Common Options
:client_info- Client identification map (default: Hermolaos info):capabilities- Client capabilities (default: standard):notification_handler- Module or{module, state}for notifications:timeout- Default request timeout in ms (default: 30000):name- GenServer name (optional)
Examples
# Stdio with npx
{:ok, client} = Hermolaos.connect(:stdio,
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
)
# HTTP with authentication
{:ok, client} = Hermolaos.connect(:http,
url: "https://api.example.com/mcp",
headers: [{"authorization", "Bearer token123"}]
)
# Named connection
{:ok, _} = Hermolaos.connect(:stdio,
command: "my-server",
name: MyApp.MCPClient
)
# Later: Hermolaos.list_tools(MyApp.MCPClient)
@spec disconnect(client()) :: :ok
Disconnects from the MCP server.
This gracefully closes the connection, cleaning up resources.
Examples
:ok = Hermolaos.disconnect(client)
Extracts image data from a tool call result.
Returns the base64-decoded binary image data.
Examples
{:ok, result} = Hermolaos.call_tool(client, "browser_take_screenshot", %{})
case Hermolaos.get_image(result) do
{:ok, image_data} -> File.write!("screenshot.png", image_data)
:error -> IO.puts("No image in response")
end
Extracts all images from a tool call result.
Returns a list of base64-decoded binary image data.
Examples
{:ok, result} = Hermolaos.call_tool(client, "get_images", %{})
images = Hermolaos.get_images(result)
Enum.with_index(images, fn data, i ->
File.write!("image_#{i}.png", data)
end)
Gets a prompt by name, optionally with argument values.
Parameters
client- The MCP clientname- Prompt namearguments- Argument values map (default:%{})opts- Options
Examples
{:ok, prompt} = Hermolaos.get_prompt(client, "code_review")
{:ok, prompt} = Hermolaos.get_prompt(client, "summarize", %{"language" => "elixir"})
Extracts text content from a tool call result.
Tool results contain a list of content items. This helper extracts all text items and concatenates them.
Examples
{:ok, result} = Hermolaos.call_tool(client, "browser_snapshot", %{})
text = Hermolaos.get_text(result)
Lists available prompts on the server.
Options
:cursor- Pagination cursor:timeout- Request timeout override
Examples
{:ok, %{prompts: prompts}} = Hermolaos.list_prompts(client)
Lists resource templates on the server.
Options
:cursor- Pagination cursor:timeout- Request timeout override
Examples
{:ok, %{resourceTemplates: templates}} = Hermolaos.list_resource_templates(client)
Lists available resources on the server.
Options
:cursor- Pagination cursor:timeout- Request timeout override
Examples
{:ok, %{resources: resources}} = Hermolaos.list_resources(client)
Lists available tools on the server.
Options
:cursor- Pagination cursor for subsequent requests:timeout- Request timeout override
Returns
{:ok, %{tools: [...], nextCursor: ...}}- Success (atom keys){:error, reason}- Error
Examples
{:ok, %{tools: tools}} = Hermolaos.list_tools(client)
for tool <- tools do
IO.puts("Tool: #{tool.name} - #{tool.description}")
end
Sends a ping to check server liveness.
Examples
{:ok, %{}} = Hermolaos.ping(client)
Reads a resource by URI.
Parameters
client- The MCP clienturi- Resource URIopts- Options
Returns
{:ok, %{contents: [...]}}- Success (atom keys)
Examples
{:ok, %{contents: contents}} = Hermolaos.read_resource(client, "file:///project/README.md")
for content <- contents do
IO.puts(content.text)
end
Gets server capabilities from the initialization response.
Examples
{:ok, caps} = Hermolaos.server_capabilities(client)
if Hermolaos.Protocol.Capabilities.supports?(caps, :tools) do
# Server supports tools
end
Gets server information from the initialization response.
Examples
{:ok, %{"name" => "MyServer", "version" => "1.0.0"}} = Hermolaos.server_info(client)
Sets the server's logging level.
Parameters
client- The MCP clientlevel- Log level (debug, info, notice, warning, error, critical, alert, emergency)
Examples
{:ok, _} = Hermolaos.set_log_level(client, "debug")
@spec status(client()) :: Hermolaos.Client.Connection.status()
Gets the current connection status.
Returns
:disconnected- Not connected:connecting- Transport starting:initializing- MCP handshake in progress:ready- Ready for requests
Examples
:ready = Hermolaos.status(client)
Subscribes to resource updates.
Requires server to support resource subscriptions.
Examples
:ok = Hermolaos.subscribe_resource(client, "file:///project/src/main.rs")
Unsubscribes from resource updates.
Examples
:ok = Hermolaos.unsubscribe_resource(client, "file:///project/src/main.rs")