### Receive Real-time Tool Progress Updates Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client This example shows how to receive real-time progress updates for a tool call using a callback function. The callback function receives the current progress and total, allowing for dynamic display of the operation's status. ```elixir callback = fn ^progress_token, progress, total -> percentage = if total, do: "#{progress}/#{total}", else: "#{progress}" IO.puts("Progress: #{percentage}") end MyApp.WeatherClient.call_tool("analyze_data", params, progress: [token: progress_token, callback: callback] ) ``` -------------------------------- ### Call Elixir MCP Tools with Error Handling Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Provides examples of invoking tools on an MCP server from Elixir, including handling successful responses, tool-specific errors, and connection errors. Accepts tool names and parameter maps, returning results or error tuples. Uses a case statement for comprehensive error management. ```elixir # Simple tool call {:ok, %{result: weather}} = MyApp.WeatherClient.call_tool("get_weather", %{ "location" => "San Francisco" }) # Complex parameters {:ok, %{result: forecast}} = MyApp.WeatherClient.call_tool("get_forecast", %{ "location" => "Tokyo", "days" => 5, "units" => "metric" }) # Comprehensive error handling case MyApp.WeatherClient.call_tool("get_weather", %{"location" => ""}) do {:ok, %{is_error: false, result: weather}} -> IO.puts("Success: #{inspect(weather)}") {:ok, %{is_error: true, result: error}} -> IO.puts("Tool error: #{error["message"]}") {:error, error} -> IO.puts("Connection error: #{inspect(error)}") end ``` -------------------------------- ### Configure Elixir Supervision Tree for MCP Client Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Configures a supervision tree to launch and manage the Elixir MCP client as a subprocess. This example shows how to specify the transport layer, in this case, using stdio to execute a 'weather-server' command. The client automatically handles launching, connection, and protocol management. ```elixir {MyApp.WeatherClient, transport: {:stdio, command: "weather-server", args: []}} ``` -------------------------------- ### Graceful Elixir Client Shutdown Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Provides examples of how to gracefully close Elixir client connections and release resources managed by MyApp.WeatherClient. This includes closing the default instance, closing a specifically named instance, and handling cleanup within a supervision tree's terminate callback. ```elixir # Close default client instance MyApp.WeatherClient.close() # Close named instance MyApp.WeatherClient.close(:weather_us) # In supervision tree cleanup def terminate(_reason, state) do MyApp.WeatherClient.close() :ok end ``` -------------------------------- ### Configure Timeouts for Elixir MCP Client Operations Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Shows how to set a timeout for potentially long-running operations performed by an Elixir MCP client. This example sets a 5-minute timeout for the `analyze_historical_data` tool call, preventing indefinite waiting. ```elixir # 5 minute timeout for slow operations opts = [timeout: 300_000] MyApp.WeatherClient.call_tool("analyze_historical_data", params, opts) ``` -------------------------------- ### Creating a Basic Client Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Define a client module to connect to an MCP server with specified capabilities and protocol version, and add it to your OTP supervision tree. ```APIDOC ## Creating a Basic Client Define a client module to connect to an MCP server with specified capabilities and protocol version. ```elixir defmodule MyApp.WeatherClient do use Hermes.Client, name: "MyApp", version: "1.0.0", protocol_version: "2024-11-05", capabilities: [:roots] end # Add to supervision tree children = [ {MyApp.WeatherClient, transport: {:stdio, command: "weather-server", args: []}} ] Supervisor.start_link(children, strategy: :one_for_one) # Client automatically: # - Launches weather-server as subprocess # - Negotiates capabilities # - Maintains connection # - Handles protocol details ``` ``` -------------------------------- ### Create Basic Elixir MCP Client Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Defines an Elixir client module for connecting to an MCP server, specifying name, version, protocol version, and capabilities. Includes integration into an OTP supervision tree for automatic management. Dependencies include the Hermes.Client module. ```elixir defmodule MyApp.WeatherClient do use Hermes.Client, name: "MyApp", version: "1.0.0", protocol_version: "2024-11-05", capabilities: [:roots] end # Add to supervision tree children = [ {MyApp.WeatherClient, transport: {:stdio, command: "weather-server", args: []}} ] Supervisor.start_link(children, strategy: :one_for_one) # Client automatically: # - Launches weather-server as subprocess # - Negotiates capabilities # - Maintains connection # - Handles protocol details ``` -------------------------------- ### Discover MCP Server Information and Capabilities in Elixir Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Demonstrates how to query an MCP server for its information and capabilities using an Elixir client. Functions like `get_server_info`, `get_server_capabilities`, and `list_tools` allow dynamic exploration of the server's interface and available tools. ```elixir # What's this server about? info = MyApp.WeatherClient.get_server_info() # => %{"name" => "Weather Server", "version" => "2.0.0", ...} # What capabilities does it offer? caps = MyApp.WeatherClient.get_server_capabilities() # => %{"tools" => %{"listChanged" => false}, ...} # What tools are available? {:ok, %{result: %{"tools" => tools}}} = MyApp.WeatherClient.list_tools() Enum.each(tools, fn tool -> IO.puts("#{tool["name"]}: #{tool["description"]}") end) # => get_weather: Get current weather for a location # => get_forecast: Get weather forecast ``` -------------------------------- ### Discovering Server Information Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Query server metadata and capabilities to understand what services are available. ```APIDOC ## Discovering Server Information Query server metadata and capabilities to understand what services are available. ```elixir # Get server identification info = MyApp.WeatherClient.get_server_info() # Returns: %{"name" => "Weather Server", "version" => "2.0.0", ...} # Get server capabilities caps = MyApp.WeatherClient.get_server_capabilities() # Returns: %{"tools" => %{"listChanged" => false}, ...} # List available tools {:ok, %{result: %{"tools" => tools}}} = MyApp.WeatherClient.list_tools() Enum.each(tools, fn tool -> IO.puts("#{tool["name"]}: #{tool["description"]}") end) # Output: # get_weather: Get current weather for a location # get_forecast: Get weather forecast ``` ``` -------------------------------- ### Discover Elixir MCP Server Information Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Demonstrates how to query an MCP server for its identification, capabilities, and available tools using the Elixir client. Returns Elixir maps containing server metadata and tool information. Requires a running MCP server and a configured client. ```elixir # Get server identification info = MyApp.WeatherClient.get_server_info() # Returns: %{"name" => "Weather Server", "version" => "2.0.0", ...} # Get server capabilities caps = MyApp.WeatherClient.get_server_capabilities() # Returns: %{"tools" => %{"listChanged" => false}, ...} # List available tools {:ok, %{result: %{"tools" => tools}}} = MyApp.WeatherClient.list_tools() Enum.each(tools, fn tool -> IO.puts("#{tool["name"]}: #{tool["description"]}") end) # Output: # get_weather: Get current weather for a location # get_forecast: Get weather forecast ``` -------------------------------- ### Manage Resources with Elixir MCP Client Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Illustrates how to interact with resources exposed by an MCP server, such as files or database content. This includes listing available resources, reading their contents, and handling different content types like text or binary blobs. ```elixir # What resources are available? {:ok, %{result: %{"resources" => resources}}} = MyApp.WeatherClient.list_resources() # Read a specific resource {:ok, %{result: %{"contents" => contents}}} = MyApp.WeatherClient.read_resource("weather://stations/KSFO") # Resources can have multiple content types for content <- contents do case content do %{"text" => text} -> IO.puts("Text content: #{text}") %{"blob" => blob} -> IO.puts("Binary data: #{byte_size(blob)} bytes") end end ``` -------------------------------- ### Working with Resources Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Access and read resources exposed by MCP servers such as files, databases, or other content. ```APIDOC ## Working with Resources Access and read resources exposed by MCP servers such as files, databases, or other content. ```elixir # List available resources {:ok, %{result: %{"resources" => resources}}} = MyApp.WeatherClient.list_resources() # Read specific resource {:ok, %{result: %{"contents" => contents}}} = MyApp.WeatherClient.read_resource("weather://stations/KSFO") # Handle multiple content types for content <- contents do case content do %{"text" => text} -> IO.puts("Text content: #{text}") %{"blob" => blob} -> IO.puts("Binary data: #{byte_size(blob)} bytes") end end ``` ``` -------------------------------- ### Access Elixir MCP Resources Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Illustrates how to list and read resources exposed by an MCP server using the Elixir client. It handles different content types, including text and binary data, returned from resource requests. Requires a server with resources available. ```elixir # List available resources {:ok, %{result: %{"resources" => resources}}} = MyApp.WeatherClient.list_resources() # Read specific resource {:ok, %{result: %{"contents" => contents}}} = MyApp.WeatherClient.read_resource("weather://stations/KSFO") # Handle multiple content types for content <- contents do case content do %{"text" => text} -> IO.puts("Text content: #{text}") %{"blob" => blob} -> IO.puts("Binary data: #{byte_size(blob)} bytes") end end ``` -------------------------------- ### Call MCP Tools with Elixir Client Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Shows how to execute tools exposed by an MCP server using the Elixir client. This includes calling tools with simple and complex parameters, and handling potential errors returned by the tool or the connection itself. ```elixir # Simple tool call {:ok, %{result: weather}} = MyApp.WeatherClient.call_tool("get_weather", %{ "location" => "San Francisco" }) # Tool with complex parameters {:ok, %{result: forecast}} = MyApp.WeatherClient.call_tool("get_forecast", %{ "location" => "Tokyo", "days" => 5, "units" => "metric" }) ``` ```elixir case MyApp.WeatherClient.call_tool("get_weather", %{"location" => ""}) do {:ok, %{is_error: false, result: weather}} -> # Success path {:ok, %{is_error: true, result: error}} -> # The tool itself reported an error IO.puts("Tool error: #{error["message"]}") {:error, error} -> # Protocol or connection error IO.puts("Connection error: #{inspect(error)}") end ``` -------------------------------- ### Configuring Transport Options Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Connect to MCP servers using different transport mechanisms based on deployment needs. ```APIDOC ## Configuring Transport Options Connect to MCP servers using different transport mechanisms based on deployment needs. ```elixir # Local subprocess via STDIO {MyApp.WeatherClient, transport: {:stdio, command: "python", args: ["-m", "my_server"]}} # HTTP endpoint {MyApp.WeatherClient, transport: {:streamable_http, base_url: "http://localhost:8000"}} # WebSocket for real-time bidirectional communication {MyApp.WeatherClient, transport: {:websocket, base_url: "ws://localhost:8000"}} # Server-Sent Events (deprecated) {MyApp.WeatherClient, transport: {:sse, base_url: "http://localhost:8000"}} # Transport selection guide: # - STDIO: Local tools, subprocess isolation, CLI utilities # - HTTP: Remote services, REST APIs, stateless operations # - WebSocket: Real-time bidirectional, persistent connections # - SSE: Server push updates (deprecated, use WebSocket) ``` ``` -------------------------------- ### Manage Multiple Elixir Client Instances Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Demonstrates how to run multiple instances of a client, such as MyApp.WeatherClient, to connect to different servers or regions simultaneously. This is achieved by defining distinct child specifications in a supervisor, each with a unique name and transport configuration. ```elixir children = [ Supervisor.child_spec( {MyApp.WeatherClient, name: :weather_us, transport: {:stdio, command: "weather-server", args: ["--region", "US"]}}, id: :weather_us ), Supervisor.child_spec( {MyApp.WeatherClient, name: :weather_eu, transport: {:stdio, command: "weather-server", args: ["--region", "EU"]}}, id: :weather_eu ) ] Supervisor.start_link(children, strategy: :one_for_one) # Use specific instances {:ok, us_weather} = MyApp.WeatherClient.call_tool(:weather_us, "get_weather", %{location: "NYC"}) {:ok, eu_weather} = MyApp.WeatherClient.call_tool(:weather_eu, "get_weather", %{location: "Paris"}) ``` -------------------------------- ### Calling Tools with Error Handling Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Invoke server tools with parameters and handle success, tool errors, and connection errors. ```APIDOC ## Calling Tools with Error Handling Invoke server tools with parameters and handle success, tool errors, and connection errors. ```elixir # Simple tool call {:ok, %{result: weather}} = MyApp.WeatherClient.call_tool("get_weather", %{ "location" => "San Francisco" }) # Complex parameters {:ok, %{result: forecast}} = MyApp.WeatherClient.call_tool("get_forecast", %{ "location" => "Tokyo", "days" => 5, "units" => "metric" }) # Comprehensive error handling case MyApp.WeatherClient.call_tool("get_weather", %{"location" => ""}) do {:ok, %{is_error: false, result: weather}} -> IO.puts("Success: #{inspect(weather)}") {:ok, %{is_error: true, result: error}} -> IO.puts("Tool error: #{error["message"]}") {:error, error} -> IO.puts("Connection error: #{inspect(error)}") end ``` ``` -------------------------------- ### Manage Multiple Elixir MCP Client Instances Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Demonstrates how to configure and use multiple instances of the same Elixir MCP client within a supervision tree, allowing connections to different servers or the same server with different configurations. Each instance can be given a unique name for targeted calls. ```elixir children = [ Supervisor.child_spec( {MyApp.WeatherClient, name: :weather_us, transport: {:stdio, command: "weather-server", args: ["--region", "US"]}}, id: :weather_us ), Supervisor.child_spec( {MyApp.WeatherClient, name: :weather_eu, transport: {:stdio, command: "weather-server", args: ["--region", "EU"]}}, id: :weather_eu ) ] # Use specific instances MyApp.WeatherClient.call_tool(:weather_us, "get_weather", %{location: "NYC"}) MyApp.WeatherClient.call_tool(:weather_eu, "get_weather", %{location: "Paris"}) ``` -------------------------------- ### Configure Elixir MCP Transport Options Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Details various transport configurations for the Elixir Hermes MCP client, including STDIO, HTTP, WebSocket, and SSE. Provides guidance on choosing the appropriate transport based on deployment needs. Each configuration specifies the transport type and relevant options. ```elixir # Local subprocess via STDIO {MyApp.WeatherClient, transport: {:stdio, command: "python", args: ["-m", "my_server"]}} # HTTP endpoint {MyApp.WeatherClient, transport: {:streamable_http, base_url: "http://localhost:8000"}} # WebSocket for real-time bidirectional communication {MyApp.WeatherClient, transport: {:websocket, base_url: "ws://localhost:8000"}} # Server-Sent Events (deprecated) {MyApp.WeatherClient, transport: {:sse, base_url: "http://localhost:8000"}} # Transport selection guide: # - STDIO: Local tools, subprocess isolation, CLI utilities # - HTTP: Remote services, REST APIs, stateless operations # - WebSocket: Real-time bidirectional, persistent connections # - SSE: Server push updates (deprecated, use WebSocket) ``` -------------------------------- ### Track Tool Progress with Token Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client This code snippet demonstrates how to track the progress of a tool call using a progress token. It's a simple way to monitor long-running operations without receiving intermediate updates. ```elixir MyApp.WeatherClient.call_tool("analyze_data", params, progress: [token: progress_token] ) ``` -------------------------------- ### Define Elixir MCP Client with Hermes Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Defines an Elixir client module using the Hermes.Client behavior. This includes setting client identification, version, protocol version, and supported capabilities. The client automatically handles server connection, capability negotiation, and protocol details when added to a supervision tree. ```elixir defmodule MyApp.WeatherClient do use Hermes.Client, name: "MyApp", # How you introduce yourself version: "1.0.0", # Your client's version protocol_version: "2024-11-05", # MCP protocol target version capabilities: [:roots] # What features you support end ``` -------------------------------- ### Graceful Client Shutdown Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client This snippet illustrates how to gracefully shut down the Hermes MCP client connection. It ensures that all associated resources are properly released, preventing potential issues with ongoing operations. ```elixir MyApp.WeatherClient.close() ``` -------------------------------- ### Configure Elixir Timeouts for Long Operations Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Illustrates how to handle operation timeouts in Elixir using MyApp.WeatherClient. This includes using the default timeout behavior, setting custom timeouts for slow operations, and implementing error handling for timeout scenarios. ```elixir # Default timeout behavior {:ok, result} = MyApp.WeatherClient.call_tool("quick_check", %{}) # Custom 5-minute timeout for slow operations opts = [timeout: 300_000] {:ok, result} = MyApp.WeatherClient.call_tool("analyze_historical_data", %{years: 10, granularity: "hourly"}, opts ) # Timeout error handling case MyApp.WeatherClient.call_tool("slow_operation", params, [timeout: 5000]) do {:ok, result} -> IO.puts("Completed: #{inspect(result)}") {:error, :timeout} -> IO.puts("Operation timed out") {:error, error} -> IO.puts("Error: #{inspect(error)}") end ``` -------------------------------- ### Configure Elixir MCP Client Transport Options Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Details various transport options for connecting an Elixir MCP client to a server. Supported transports include STDIO for local subprocesses, HTTP for remote services, WebSocket for real-time communication, and Server-Sent Events (SSE) for server-pushed updates. ```elixir # Local subprocess transport: {:stdio, command: "python", args: ["-m", "my_server"]} # HTTP endpoint transport: {:streamable_http, base_url: "http://localhost:8000"} # WebSocket for real-time transport: {:websocket, base_url: "ws://localhost:8000"} # Server-Sent Events transport: {:sse, base_url: "http://localhost:8000"} ``` -------------------------------- ### Generate Progress Token for Elixir MCP Operations Source: https://hexdocs.pm/hermes_mcp/0.14.1/hermes_mcp/building-a-client Illustrates the initial step for tracking progress on long-running operations within the hermes_mcp framework. It shows how to generate a unique progress token using `Hermes.MCP.ID.generate_progress_token()`, which would typically be passed to the operation. ```elixir # Generate a unique token for this operation progress_token = Hermes.MCP.ID.generate_progress_token() ``` -------------------------------- ### Track Progress for Elixir Long-Running Operations Source: https://context7.com/context7/hexdocs_pm_hermes_mcp_0_14_1/llms.txt Shows how to monitor the progress of long-running tool calls in Elixir using Hermes MCP. This involves generating a unique progress token and either tracking progress solely with the token or receiving real-time updates via a callback function. ```elixir # Generate unique progress token progress_token = Hermes.MCP.ID.generate_progress_token() # Option 1: Track with token only {:ok, result} = MyApp.WeatherClient.call_tool("analyze_data", %{dataset: "climate_2020"}, progress: [token: progress_token] ) # Option 2: Real-time progress updates via callback callback = fn ^progress_token, progress, total -> percentage = if total do Float.round(progress / total * 100, 2) else progress end IO.puts("Progress: #{percentage}%") end {:ok, result} = MyApp.WeatherClient.call_tool("analyze_data", %{dataset: "climate_2020", years: 50}, progress: [token: progress_token, callback: callback] ) # Output during execution: # Progress: 10.0% # Progress: 25.5% # Progress: 50.0% # Progress: 75.25% # Progress: 100.0% ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.