Client Usage
Using the Hermes MCP client.
Basic Setup
Once configured in your supervision tree, the client automatically:
- Connects to the server
- Negotiates protocol version
- Exchanges capabilities
- Completes handshake
Connection Status
case Hermes.Client.ping(client) do
:pong ->
IO.puts("Server is responsive")
{:error, reason} ->
IO.puts("Connection error: #{inspect(reason)}")
end
Server Information
# Get capabilities
capabilities = Hermes.Client.get_server_capabilities(client)
# Get server info
info = Hermes.Client.get_server_info(client)
Working with Tools
List Tools
case Hermes.Client.list_tools(client) do
{:ok, %{result: %{"tools" => tools}}} ->
for tool <- tools do
IO.puts("#{tool["name"]}: #{tool["description"]}")
end
{:error, error} ->
IO.puts("Error: #{inspect(error)}")
end
Call Tool
case Hermes.Client.call_tool(client, "calculator", %{expr: "2+2"}) do
{:ok, %{is_error: false, result: result}} ->
IO.puts("Result: #{inspect(result)}")
{:ok, %{is_error: true, result: error}} ->
IO.puts("Tool error: #{error["message"]}")
{:error, error} ->
IO.puts("Protocol error: #{inspect(error)}")
end
Working with Resources
List Resources
{:ok, %{result: %{"resources" => resources}}} =
Hermes.Client.list_resources(client)
for resource <- resources do
IO.puts("#{resource["name"]} (#{resource["uri"]})")
end
Read Resource
case Hermes.Client.read_resource(client, "file:///data.txt") do
{:ok, %{result: %{"contents" => contents}}} ->
for content <- contents do
case content do
%{"text" => text} -> IO.puts(text)
%{"blob" => blob} -> IO.puts("Binary: #{byte_size(blob)} bytes")
end
end
{:error, error} ->
IO.puts("Error: #{inspect(error)}")
end
Pagination
# First page
{:ok, %{result: result}} = Hermes.Client.list_resources(client)
resources = result["resources"]
cursor = result["nextCursor"]
# Next page
if cursor do
{:ok, %{result: more}} =
Hermes.Client.list_resources(client, cursor: cursor)
end
Working with Prompts
List Prompts
{:ok, %{result: %{"prompts" => prompts}}} =
Hermes.Client.list_prompts(client)
for prompt <- prompts do
IO.puts("#{prompt["name"]}: #{prompt["description"]}")
end
Get Prompt
args = %{"language" => "elixir", "task" => "refactor"}
case Hermes.Client.get_prompt(client, "code_review", args) do
{:ok, %{result: %{"messages" => messages}}} ->
for msg <- messages do
IO.puts("#{msg["role"]}: #{msg["content"]}")
end
{:error, error} ->
IO.puts("Error: #{inspect(error)}")
end
Timeouts
Set custom timeouts per operation:
# 60 second timeout
opts = [timeout: 60_000]
Hermes.Client.call_tool(client, "slow_tool", %{}, opts)
Default timeout is 30 seconds.
Autocompletion
Get completion suggestions:
# For prompt arguments
ref = %{"type" => "ref/prompt", "name" => "code_review"}
arg = %{"name" => "language", "value" => "py"}
{:ok, response} = Hermes.Client.complete(client, ref, arg)
# => ["python", "pytorch", "pydantic"]
# For resource URIs
ref = %{"type" => "ref/resource", "uri" => "file:///"}
arg = %{"name" => "path", "value" => "doc"}
{:ok, response} = Hermes.Client.complete(client, ref, arg)
# => ["docs/", "docker-compose.yml", "documentation.md"]
Error Handling
See Error Handling for patterns.
Graceful Shutdown
Hermes.Client.close(client)
This also shuts down the transport.