### Complete Elixir Hermes Server Application Example Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This comprehensive Elixir script provides a full, runnable example of a Hermes server. It includes `Mix.install` for dependencies, the `MyApp.Greeter` tool definition, the `MyApp.Server` setup, and the supervision tree configuration to start the server. This file can be saved and executed directly for testing. ```Elixir Mix.install([{:hermes_mcp, "~> 0.11"}]) defmodule MyApp.Greeter do @moduledoc "Greet someone warmly" use Hermes.Server.Component, type: :tool schema do field :name, :string, required: true end def execute(%{name: name}, _frame) do {:ok, "Hello #{name}! Welcome to the MCP world!"} end end defmodule MyApp.Server do use Hermes.Server, name: "my-app", version: "1.0.0", capabilities: [:tools] # Register our greeter tool component MyApp.Greeter end children = [Hermes.Server.Registry, {MyApp.Server, transport: :stdio}] {:ok, _pid} = Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor) ``` -------------------------------- ### Local Development Setup for Elixir Phoenix Application Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/ascii/README.md These commands outline the steps to set up and start the Phoenix server for local development of the ASCII Art Studio application. This includes installing dependencies and launching the web server, making the application accessible via a local URL. ```Bash # Setup the application mix setup # Start the Phoenix server mix phx.server ``` -------------------------------- ### Complete Hermes MCP Client Implementation and Usage Example in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt Provides a full example of an Elixir client (`GitHubClient`) built with `Hermes.Client`. It defines high-level API methods for interacting with a GitHub MCP server (e.g., searching repositories, getting repository information, creating issues) and demonstrates how to start the client within a supervisor and use its functions. ```Elixir defmodule GitHubClient do use Hermes.Client, name: "github-client", version: "1.0.0", protocol_version: "2024-11-05" # High-level API methods def search_repos(query, opts \\ []) do params = %{ query: query, language: Keyword.get(opts, :language), sort: Keyword.get(opts, :sort, "stars") } call_tool("github/search_repos", params) end def get_repo_info(owner, repo) do read_resource("github://repos/#{owner}/#{repo}") end def create_issue(owner, repo, title, body) do call_tool("github/create_issue", %{ owner: owner, repo: repo, title: title, body: body }) end end # Usage children = [ {GitHubClient, transport: {:stdio, command: "uvx", args: ["mcp-server-github"]}} ] Supervisor.start_link(children, strategy: :one_for_one) # Search for Elixir repos {:ok, repos} = GitHubClient.search_repos("web framework", language: "elixir") # Get repo details {:ok, info} = GitHubClient.get_repo_info("phoenixframework", "phoenix") # Create an issue {:ok, issue} = GitHubClient.create_issue("myorg", "myrepo", "Bug: Something is broken", "Details about the bug..." ) ``` -------------------------------- ### Hermes MCP Setup Functions Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Composable setup functions used to establish various test contexts for MCP clients and servers. These functions streamline test environment initialization. ```APIDOC MCP Setup Functions: setup_client/2 - Sets up an MCP client for testing. initialize_client/2 - Initializes an MCP client. initialized_client/2 - Provides an already initialized MCP client. setup_server/2 - Sets up an MCP server for testing. initialize_server/2 - Initializes an MCP server. initialized_server/2 - Provides an already initialized MCP server. server_with_mock_transport/2 - Sets up an MCP server using MockTransport without full initialization. ``` -------------------------------- ### Run Phoenix Server with MCP Endpoint Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/echo-elixir/README.md These Bash commands outline the steps to set up and run the Echo MCP server. It includes installing dependencies and starting the Phoenix server, making the SSE endpoint accessible locally. This provides a quick guide for developers to get the server running for testing and development. ```Bash # Install dependencies mix setup # Start Phoenix server with MCP endpoint mix phx.server ``` -------------------------------- ### Install Hermes MCP Project Dependencies Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CONTRIBUTING.md Command to install all necessary Elixir and other project dependencies using `mix setup`, preparing the environment for development and testing. ```bash mix setup ``` -------------------------------- ### Hermes Server Architecture Patterns Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Explains the foundation for all MCP servers using `Hermes.Server.Base`, detailing required and optional callbacks for server modules and how transport layers are configured for server communication. It emphasizes implementing `Hermes.Server.Behaviour`. ```APIDOC Hermes.Server.Base: - Serves as the foundation for all MCP servers. - Server modules must implement `Hermes.Server.Behaviour` callbacks: - Required: - init/1 - handle_request/2 - handle_notification/2 - server_info/0 - Optional: - server_capabilities/0 ``` -------------------------------- ### Build and Test Hermes MCP Project Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Provides a set of common `mix` commands for managing the Hermes MCP project lifecycle, including dependency fetching, code compilation, running tests, code formatting, linting, type checking, and documentation generation. ```bash # Setup dependencies mix deps.get # Compile code mix compile --force --warnings-as-errors # Run all tests mix test --trace # Run a single test mix test test/path/to/test_file.exs:line_number --trace # Format code mix format # Run linting mix credo --strict # Type checking mix dialyzer # Generate documentation mix docs ``` -------------------------------- ### Run Hermes MCP Test Suite Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CONTRIBUTING.md Command to execute the full test suite for the Hermes MCP project. This is used both for initial setup verification and as part of the development workflow to ensure code correctness. ```bash mix test ``` -------------------------------- ### Run Hermes MCP Development Servers Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CONTRIBUTING.md Commands to start the Echo server (Python) and Calculator server (Go) for local development and testing. The Echo server supports stdio transport, while the Calculator server supports both stdio and HTTP/SSE transport. ```bash # Start the Echo server (Python) # For now only support stdio transport just echo-server # Start the Calculator server (Go) # Supports both stdio and http/sse transport just calculator-server sse ``` -------------------------------- ### Attach Telemetry Handlers for Hermes MCP Client Events in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt Shows how to subscribe to Hermes MCP client events using Elixir's `:telemetry` library. It includes examples for handling request start and stop events to log method calls and durations, providing insights into client interactions and performance. ```Elixir :telemetry.attach_many("mcp-client-handler", [ [:hermes, :client, :request, :start], [:hermes, :client, :request, :stop], [:hermes, :client, :request, :exception] ], &handle_event/4, nil ) def handle_event([:hermes, :client, :request, :start], measurements, metadata, _) do Logger.info("MCP request started: #{metadata.method}") end def handle_event([:hermes, :client, :request, :stop], measurements, metadata, _) do duration_ms = System.convert_time_unit(measurements.duration, :native, :millisecond) Logger.info("MCP request completed: #{metadata.method} in #{duration_ms}ms") end ``` -------------------------------- ### Build and Run MCP Server in Production Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/session-manager/README.md Compiles the TypeScript source code into a production-ready build and then starts the compiled server for deployment. ```bash npm run build npm start ``` -------------------------------- ### Invoke MCP Server Tools in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-client.md This Elixir example demonstrates how to call tools exposed by an MCP server using `call_tool`. It shows both simple tool invocation with basic parameters and more complex calls with multiple parameters, illustrating how to interact with the server's functionality. ```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" }) ``` -------------------------------- ### Run Hermes Standard I/O SSE Server Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md Command to start the Hermes Standard I/O Server-Sent Events (SSE) client. This client connects to a specified base URL and enables verbose logging for debugging purposes. ```bash mix hermes.stdio.sse --base-url=http//:localhost:4000 -vvv ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/session-manager/README.md Installs the necessary Node.js packages and dependencies for the MCP server project using npm. ```bash npm install ``` -------------------------------- ### Define and Configure Hermes MCP Server in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/README.md This comprehensive example demonstrates how to define an MCP server module using `Hermes.Server`, including capabilities like tool registration. It also shows how to add the server to your application's supervision tree and integrate it into a Plug or Phoenix router for HTTP transport. The `init` callback registers an 'echo' tool with input schema and description, while `handle_tool` implements its logic. ```elixir # Define a server with tools capabilities defmodule MyApp.MCPServer do use Hermes.Server, name: "My Server", version: "1.0.0", capabilities: [:tools] @impl true # this callback will be called when the # MCP initialize lifecycle completes def init(_client_info, frame) do {:ok,frame |> assign(counter: 0) |> register_tool("echo", input_schema: %{ text: {:required, :string, max: 150, description: "the text to be echoed"} }, annotations: %{read_only: true}, description: "echoes everything the user says to the LLM") } end @impl true def handle_tool("echo", %{text: text}, frame) do Logger.info("This tool was called #{frame.assigns.counter + 1}") {:reply, text, assign(frame, counter: frame.assigns.counter + 1)} end end # Add to your application supervisor children = [ Hermes.Server.Registry, {MyApp.MCPServer, transport: :streamable_http} ] # Add to your Plug/Phoenix router (if using HTTP) forward "/mcp", Hermes.Server.Transport.StreamableHTTP.Plug, server: MyApp.MCPServer ``` -------------------------------- ### Interact with MCP Server API using cURL Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/session-manager/README.md Examples demonstrating how to initialize a session, list available tools, and call a specific tool using cURL commands, including handling the session ID header for subsequent requests. ```bash # Initialize connection (will return a session ID in the response headers) curl -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}},"id":1}' # Use the returned session ID for subsequent requests SESSION_ID="" # List available tools curl -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "mcp-session-id: $SESSION_ID" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}' # Call a tool curl -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "mcp-session-id: $SESSION_ID" \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"session_info","arguments":{}},"id":3}' ``` -------------------------------- ### Hermes Server Module Definition and Initialization Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/reference.md Explains how to define and start a `Hermes.Server` module, including required configuration options and various transport mechanisms. This covers setting the server name, version, capabilities, and configuring transports like stdio, streamable HTTP, or no transport for embedding. ```Elixir use Hermes.Server, options ``` ```APIDOC Required Options: - name: Your server name (string) - version: Your server version (string) - capabilities: List of capabilities to expose Starting a Server: {MyApp.Server, transport: transport_config} Transport Options: - :stdio: Standard input/output - {:streamable_http, port: 8080}: HTTP server - :none: No transport (for embedding) ``` -------------------------------- ### Hermes MCP Client API: Basic and Advanced Operations Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt This API documentation covers the core functionalities of the Hermes MCP client, including initializing connections, listing capabilities (tools, resources, prompts), calling tools, reading resources, and getting prompts. It also details advanced options such as setting timeouts, tracking progress with callbacks, and performing batch operations for multiple requests. ```APIDOC MyApp.MCPClient.initialize() - Initializes the connection to the MCP server. - Returns: `{:ok, _}` on success. MyApp.MCPClient.list_tools() - Lists available tools from the MCP server. - Returns: `{:ok, tools}` where `tools` is a list of tool definitions. MyApp.MCPClient.list_resources() - Lists available resources from the MCP server. - Returns: `{:ok, resources}` where `resources` is a list of resource definitions. MyApp.MCPClient.list_prompts() - Lists available prompts from the MCP server. - Returns: `{:ok, prompts}` where `prompts` is a list of prompt definitions. MyApp.MCPClient.call_tool(tool_name: string, params: map, options: map) - Calls a specific tool on the MCP server. - Parameters: - `tool_name`: The name of the tool to call (string). - `params`: A map of parameters to pass to the tool. - `options`: Optional map for advanced control. - `timeout`: (integer) Maximum time in milliseconds to wait for a response. - `progress`: (function) A callback function `fn progress, message -> ... end` for tracking operation progress. - Returns: `{:ok, result}` where `result` is the tool's output. MyApp.MCPClient.read_resource(resource_uri: string, options: map) - Reads content from a specified resource URI. - Parameters: - `resource_uri`: The URI of the resource to read (string). - `options`: Optional map, e.g., `headers` for authentication. - Returns: `{:ok, data}` where `data` is the content of the resource. MyApp.MCPClient.get_prompt(prompt_name: string, params: map) - Retrieves messages for a specific prompt. - Parameters: - `prompt_name`: The name of the prompt to retrieve (string). - `params`: A map of parameters to pass to the prompt. - Returns: `{:ok, messages}` where `messages` is a list of prompt messages. MyApp.MCPClient.batch(operations: list) - Performs multiple operations in a single request (protocol 2025-03-26+). - Parameters: - `operations`: A list of tuples, each representing an operation: - `{:call_tool, tool_name, params}` - `{:read_resource, resource_uri}` - Returns: `{:ok, results}` where `results` is a list of results for each operation. ``` -------------------------------- ### Interact with Hermes MCP Client in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/home.md This snippet provides examples of how to interact with a configured Hermes client. It shows how to ping the server to check connectivity, list available tools, and call a specific tool with parameters, demonstrating basic communication with an MCP server. ```elixir # Is anyone there? MyApp.ClaudeClient.ping() # => :pong # What tools are available? {:ok, response} = MyApp.ClaudeClient.list_tools() # => Discover web search, news, and more... # Let's search for something {:ok, result} = MyApp.ClaudeClient.call_tool("search", %{query: "elixir lang"}) ``` -------------------------------- ### Run Hermes MCP Server in Development Mode (Bash) Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/upcase/README.md This Bash script provides the commands to set up and run the Hermes MCP server in development mode. It navigates to the project directory, fetches dependencies, and starts the server without halting, making it suitable for local development and testing. ```Bash cd priv/dev/upcase mix deps.get mix run --no-halt ``` -------------------------------- ### Define Hermes MCP Server in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/server.txt This Elixir code defines a basic Hermes Model Context Protocol (MCP) server, specifying its name, version, and initial capabilities such as tools, resources, and prompts. It uses the `use Hermes.Server` macro for setup. ```Elixir defmodule MyApp.MCPServer do use Hermes.Server, name: "my-app", version: "1.0.0", capabilities: [:tools, :resources, :prompts] end ``` -------------------------------- ### Interactive CLI Testing for Hermes Servers Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md These Bash commands illustrate how to perform interactive testing of Hermes servers using `mix` tasks. They provide examples for testing both STDIO and HTTP transports, allowing developers to quickly verify server functionality from the command line. ```Bash # Test STDIO server mix hermes.stdio.interactive --command elixir --args=--no-halt,my_app.exs ``` ```Bash # Test HTTP server mix hermes.streamable_http.interactive --base-url=http://localhost:8080 --header 'authorization: Bearer 123' ``` -------------------------------- ### Hermes Telemetry and Observability Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Describes the framework for emitting consistent telemetry events and structured logging within Hermes. It covers specific client and server events, as well as general message logging for enhanced observability. ```APIDOC Hermes.Telemetry: - Used for emitting consistent telemetry events. - Client events: - event_client_init/0 - event_client_request/0 - event_client_response/0 - Server events: - event_server_init/0 - event_server_request/0 - event_server_response/0 Hermes.Logging: - Used for structured logging. - client_event/2: Logs client-specific events. - server_event/2: Logs server-specific events. - message/4: Logs protocol messages. ``` -------------------------------- ### Elixir ExUnit Testing for Hermes Components Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/recipes.md Provides examples of testing Hermes MCP components using ExUnit. It covers testing schema validation with `validate_params` and verifying component execution with valid parameters and a mock frame. ```Elixir defmodule MyApp.ComponentTest do use ExUnit.Case, async: true describe "complex tool validation" do test "validates required fields" do tool = MyApp.ComplexTool # Test schema validation assert {:error, errors} = Hermes.Server.Component.validate_params(tool, %{}) assert errors[:required_field] == ["is required"] end test "executes with valid params" do params = %{required_field: "value", optional_field: 42} frame = %Hermes.Server.Frame{assigns: %{user: %{id: 1}}} assert {:ok, result} = MyApp.ComplexTool.execute(params, frame) assert result.processed == true end end end ``` -------------------------------- ### Hermes OTP Compliance and GenServer Patterns Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Describes the adherence to OTP principles and common GenServer patterns within Hermes. It covers process structure, naming conventions, state immutability, hibernation for memory optimization, and graceful shutdown procedures. ```APIDOC OTP Compliance: - All core components are GenServers with proper OTP supervision. - GenServer Naming: Use `Hermes.genserver_name/1` validator with Peri schemas. - State Immutability: Always return updated state from `handle_*` callbacks. - Hibernation: Use `:hibernate` for reduced memory footprint in `init`. - Graceful Shutdown: Implement proper `terminate/2` callbacks with cleanup logic. ``` -------------------------------- ### Elixir Unit Test for Hermes Tool Execution Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md An Elixir unit test example using ExUnit to verify the correct execution of a Hermes tool. It demonstrates how to simulate a tool call, decode the JSON response, and assert on the content of the result. ```elixir defmodule MyApp.ServerTest do use ExUnit.Case alias Hermes.Server.Frame test "greeter tool works correctly" do frame = %Frame{} assert {:reply, resp, ^frame} = Greeter.execute(%{name: "joe"}, frame) assert {:ok, %{"result" => %{"content" => content}}} = JSON.decode(resp) assert [%{"text" => "Hello joe! Welcome to the MCP world!"}] = content end end ``` -------------------------------- ### Hermes ID Generation and Request Tracking Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Explains the mechanisms for generating unique IDs for requests and responses using `Hermes.MCP.ID`, along with strategies for timer management and tracking the lifecycle of requests from initiation to completion or timeout. ```APIDOC Hermes.MCP.ID: - Used for generating unique request/response IDs. - generate_request_id/0: Generates a new request ID. - generate_error_id/0: Generates a new error ID. Timer Management: - Use `Process.send_after/3` for implementing request timeouts. Request Lifecycle: - Track requests with timers. - Ensure cleanup on completion or timeout. ``` -------------------------------- ### Create and Use an MCP Client in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms.txt This example illustrates how to define and use an MCP client with the Hermes.Client module in Elixir. It shows how to configure the client with a name, version, and protocol version, and how to integrate it into a supervision tree with a specified transport. The snippet also demonstrates basic client operations like listing tools and calling a tool. ```elixir defmodule MyApp.AnthropicClient do use Hermes.Client, name: "MyApp", version: "1.0.0", protocol_version: "2025-06-18" end # Start in supervision tree children = [ {MyApp.AnthropicClient, transport: {:stdio, command: "uvx", args: ["mcp-server-anthropic"]}} ] # Use the client {:ok, tools} = MyApp.AnthropicClient.list_tools() {:ok, result} = MyApp.AnthropicClient.call_tool("search", %{query: "elixir"}) ``` -------------------------------- ### Integrate Hermes Server into Elixir Supervision Tree Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This Elixir code shows how to add the `MyApp.Server` to an application's supervision tree. By including `{MyApp.Server, transport: :stdio}` in the children list, the server is started as part of the application, configured to use standard I/O for communication, which is useful for local testing. ```Elixir children = [ # Start with STDIO for easy testing {MyApp.Server, transport: :stdio} ] ``` -------------------------------- ### Handle Hermes MCP Client Roots Requests in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt This example demonstrates how to implement the `handle_roots_list_request` callback for a Hermes MCP client that declares the `:roots` capability. This function is responsible for providing a list of file system roots to the MCP server. ```elixir defmodule MyApp.MCPClient do use Hermes.Client, name: "MyApp", version: "1.0.0", capabilities: [:roots] # Provide file system roots def handle_roots_list_request(_params, session) do roots = [ %{uri: "file:///home/user/project", name: "Project Root"} ] {:ok, roots, session} end end ``` -------------------------------- ### Hermes Client Architecture Patterns Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Outlines the design patterns for Hermes client-side operations, focusing on state management, request configuration, and lifecycle tracking. This includes functions for managing client state, tracking requests, and handling progress callbacks and capabilities. ```APIDOC Hermes.Client.State: - Manages all client state operations. - new/1: Creates a new client state. - add_request_from_operation/3: Adds a request based on an operation. - remove_request/2: Removes a tracked request. - register_progress_callback/3: Registers a callback for progress updates. - get_progress_callback/2: Retrieves a registered progress callback. - validate_capability/2: Validates a client capability. - merge_capabilities/2: Merges client capabilities. Hermes.Client.Operation: - Used for configuring individual requests. - Encapsulates progress tracking, timeouts, method, and parameters. Hermes.Client.Request: - Manages the lifecycle of client requests. - Handles ID generation, timing, and caller reference management. ``` -------------------------------- ### Add Hermes MCP Server to Elixir Supervision Tree Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/server.txt This Elixir code demonstrates how to integrate the Hermes MCP server and its registry into a supervision tree. It ensures the server starts and is managed by the OTP supervision system, using `:stdio` as the transport mechanism. ```Elixir children = [ Hermes.Server.Registry, {MyApp.MCPServer, transport: :stdio} ] Supervisor.start_link(children, strategy: :one_for_one) ``` -------------------------------- ### Hermes Transport Layer Architecture Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Describes the `Hermes.Transport.Behaviour` for implementing various communication transports, including required callbacks and available modules. It also covers how transports are integrated into client and server configurations for sending messages. ```APIDOC Hermes.Transport.Behaviour: - All transports must implement this behaviour. - Required callbacks: - start_link/1 - send_message/2 - shutdown/1 - Transport modules: - Hermes.Transport.STDIO - Hermes.Transport.SSE - Hermes.Transport.WebSocket - Hermes.Transport.StreamableHTTP Client Transport Integration (Hermes.Client): - Transport is stored in state configuration as `%{layer: TransportModule, name: process_name}`. - Messages are sent via `transport.layer.send_message(transport.name, data)`. Server Transport Integration (Hermes.Server): - Transport is configured in server options as `transport: [layer: TransportModule, name: process_name]`. - Available server transport modules: - Hermes.Server.Transport.STDIO - Hermes.Server.Transport.StreamableHTTP ``` -------------------------------- ### Add Hermes MCP Client to Elixir Supervision Tree Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt This example shows how to integrate the defined Hermes MCP client into an Elixir application's supervision tree. It configures the client with a `stdio` transport, specifying the command and arguments for the MCP server subprocess. ```elixir children = [ {MyApp.MCPClient, transport: {:stdio, command: "uvx", args: ["mcp-server-name"]}} ] Supervisor.start_link(children, strategy: :one_for_one) ``` -------------------------------- ### Define and Use Hermes MCP Client in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/README.md This example illustrates how to define an MCP client module using `Hermes.Client` and integrate it into your application's supervision tree. It then demonstrates how to use the client to make a remote tool call, specifically invoking the 'echo' tool with a text parameter and handling the result. ```elixir # Define a client module defmodule MyApp.MCPClient do use Hermes.Client, name: "MyApp", version: "1.0.0", protocol_version: "2025-03-26" end # Add to your application supervisor children = [ {MyApp.MCPClient, transport: {:streamable_http, base_url: "http://localhost:4000"}} ] # Use the client {:ok, result} = MyApp.MCPClient.call_tool("echo", %{text: "this will be echoed!"}) ``` -------------------------------- ### Configure MCP Client Transport Options in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-client.md This snippet outlines various transport options for connecting an Elixir MCP client to a server. It provides examples for local subprocess (STDIO), HTTP endpoint, WebSocket for real-time communication, and Server-Sent Events (SSE), along with a brief description of when to use each. ```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"} ``` -------------------------------- ### Create an Elixir Hermes Server Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This Elixir snippet demonstrates how to define a Hermes server (`MyApp.Server`) using `Hermes.Server`. It assigns a name and version to the server, declares its capabilities (e.g., `:tools`), and registers the previously defined `MyApp.Greeter` component, making it available through this server. ```Elixir defmodule MyApp.Server do use Hermes.Server, name: "my-app", version: "1.0.0", capabilities: [:tools] # Register our greeter tool component MyApp.Greeter end ``` -------------------------------- ### Discover MCP Server Information, Capabilities, and Tools in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-client.md This Elixir code shows how to dynamically query an MCP server for its general information, supported capabilities, and available tools. It demonstrates calling `get_server_info()`, `get_server_capabilities()`, and `list_tools()` methods, then iterating through the discovered tools to print their names and descriptions. ```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) ``` -------------------------------- ### Run MCP Server in Development Mode Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/session-manager/README.md Starts the MCP server in development mode, enabling hot reloading for efficient code changes and rapid iteration. ```bash npm run dev ``` -------------------------------- ### Hermes MCP Assertion Functions Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Domain-specific assertion functions designed for testing MCP messages. These provide clear error messages and simplify validation of MCP responses, errors, and notifications. ```APIDOC MCP Assertion Functions: assert_mcp_response/2 - Asserts that an MCP message is a valid response. assert_mcp_error/3 - Asserts that an MCP message is an error with specific details. assert_mcp_notification/2 - Asserts that an MCP message is a valid notification. assert_success/2 - Asserts a successful outcome from an MCP operation. assert_resources/2 - Asserts the presence or correctness of resources in an MCP message. assert_tools/2 - Asserts the presence or correctness of tools in an MCP message. ``` -------------------------------- ### Define an AI Tool for Product Search in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This Elixir code defines a more complex AI tool, `MyApp.ProductSearch`, for searching products. It uses `Hermes.Server.Component` and specifies a `schema` with `query`, `limit`, and `category` fields. The `execute` function integrates with existing business logic (`MyApp.Catalog.search`) to filter and format product data, returning a JSON response to the AI assistant. ```Elixir defmodule MyApp.ProductSearch do @moduledoc "Search for products in our catalog" use Hermes.Server.Component, type: :tool alias Hermes.Server.Response schema do field :query, :string, required: true field :limit, :integer, default: 10 field :category, :string end @impl true def execute(%{query: query} = params, frame) do limit = params[:limit] || 10 category = params[:category] products = MyApp.Catalog.search(query) |> maybe_filter_by_category(category) |> Enum.take(limit) |> Enum.map(&format_product/1) {:reply, Response.json(Response.tool(), products), frame} end defp maybe_filter_by_category(products, nil), do: products defp maybe_filter_by_category(products, category) do Enum.filter(products, &(&1.category == category)) end defp format_product(product) do %{ id: product.id, name: product.name, price: product.price, description: product.description } end end ``` -------------------------------- ### Hermes MCP Message Builders Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Functions within `Hermes.MCP.Builders` for constructing various MCP messages like requests, responses, and notifications. These builders ensure consistent message formats and reduce boilerplate. ```APIDOC Hermes.MCP.Builders: init_request/1 - Creates an initialization request message. ping_request/0 - Creates a ping request message. tools_list_request/1 - Creates a tools list request message. build_request/2 - Builds a custom request message from a given type and payload. build_response/2 - Builds a custom response message from a given type and payload. build_notification/2 - Builds a custom notification message from a given type and payload. ``` -------------------------------- ### Add Incomer Elixir Package Dependency Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/dev/client/README.md This snippet demonstrates how to add the 'incomer' package as a dependency in an Elixir project's `mix.exs` file, specifying the version constraint. This is a standard step for installing Hex packages. ```elixir def deps do [ {:incomer, "~> 0.1.0"} ] end ``` -------------------------------- ### Test Hermes MCP Client Interactions in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt Illustrates how to write tests for Hermes MCP client interactions using `Hermes.MCP.Case`. It covers setting up a mock server, connecting a client, initializing it, and asserting responses for tool listing requests to ensure correct client behavior. ```Elixir defmodule MyApp.MCPClientTest do use Hermes.MCP.Case test "client connects and lists tools" do # Mock server {:ok, server} = setup_server(MyMockServer) # Connect client {:ok, client} = setup_client(MyApp.MCPClient, transport: {:mock, server: server} ) {:ok, client} = initialize_client(client) # Test tool listing request = tools_list_request() assert_mcp_response(client, request) do assert length(response.result.tools) > 0 end end end ``` -------------------------------- ### Calling a Tool with Progress Tracking in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-client.md This snippet demonstrates how to use `MyApp.WeatherClient.call_tool` to execute an external tool. It shows two methods for handling progress: a simple token-based approach for basic tracking and a more advanced callback mechanism for real-time, detailed progress updates, including total and current progress. ```Elixir MyApp.WeatherClient.call_tool("analyze_data", params, progress: [token: progress_token] ) ``` ```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] ) ``` -------------------------------- ### Hermes Validation and Schema Patterns Source: https://github.com/cloudwalk/hermes-mcp/blob/main/CLAUDE.md Details the use of Peri for validation within Hermes, including schema definition, option parsing, and custom validators. It emphasizes defining validation schemas as module attributes for consistency. ```APIDOC Peri Integration: - Use `import Peri` and `defschema` for all validation. - Option Parsing: Employ `parse_options!/1` pattern for GenServer initialization. - Schema Definitions: Define validation schemas as module attributes. - Custom Validators: Use `{:custom, &validator_function/1}` for complex validation logic. ``` -------------------------------- ### Define an AI Tool for Greeting in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This Elixir code defines a simple AI tool named `MyApp.Greeter` using `Hermes.Server.Component`. It specifies a `schema` for input parameters (a required `name` string) and an `execute` function that processes the input to return a greeting message. This structure allows AI assistants to discover, understand, and call the tool. ```Elixir defmodule MyApp.Greeter do @moduledoc "Greet someone warmly" use Hermes.Server.Component, type: :tool schema do field :name, :string, required: true end def execute(%{name: name}, _frame) do {:ok, "Hello #{name}! Welcome to the MCP world!"} end end ``` -------------------------------- ### Perform Basic Operations with Hermes MCP Client in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/priv/static/llms/client.txt This snippet illustrates fundamental interactions with a Hermes MCP client, including listing available tools, calling a specific tool with parameters, and reading content from a resource URI. ```elixir # List available tools {:ok, tools} = MyApp.MCPClient.list_tools() # Call a tool {:ok, result} = MyApp.MCPClient.call_tool("calculator", %{a: 5, b: 3}) # Read a resource {:ok, content} = MyApp.MCPClient.read_resource("file:///config.json") ``` -------------------------------- ### Hermes Server Client-Server Interaction for Resources Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This API documentation illustrates the interaction flow between an AI client and a Hermes server when dealing with resources. It shows how a client can `list_resources()` to discover available data, and then `read_resource("config://app/settings")` to fetch the content of a specific resource, receiving a JSON response. ```APIDOC Client: list_resources() Server: [{uri: "config://app/settings", name: "Application Config", ...}] Client: read_resource("config://app/settings") Server: {contents: [{text: "{\n \"environment\": \"production\",\n ..."}]} ``` -------------------------------- ### Test Elixir Hermes Server Interactively via STDIO Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md This Bash command allows interactive testing of the Elixir Hermes server. It uses `mix hermes.stdio.interactive` to launch an interactive session, passing the Elixir script (`my_app.exs`) as an argument. This enables direct communication with the server over standard I/O for debugging and verification. ```Bash mix hermes.stdio.interactive -c elixir --args=--no-halt,my_app.exs ``` -------------------------------- ### Manage MCP Server Resources in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-client.md This Elixir code demonstrates how to interact with resources exposed by an MCP server. It shows how to list available resources using `list_resources()` and then read the contents of a specific resource using `read_resource()`, handling different content types like text and binary data. ```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 ``` -------------------------------- ### Define and Register Hermes Server and Component in Elixir Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/home.md This comprehensive snippet demonstrates how to build your own Hermes MCP server and expose custom functionality as a tool. It defines a server module, registers a component (`MyApp.Greeter`) as a tool with a schema, and shows how to include these in the application's supervision tree to make them discoverable by AI assistants. ```elixir defmodule MyApp.Server do use Hermes.Server, name: "my-app", version: "1.0.0", capabilities: [:tools] component MyApp.Greeter end defmodule MyApp.Greeter do @moduledoc "Greet someone warmly" use Hermes.Server.Component, type: :tool schema do field :name, :string, required: true end def execute(%{name: name}, _frame) do {:ok, "Hello #{name}! Welcome to the MCP world!"} end end # on your application.ex children = [ Hermes.Server.Registry, {MyApp.Greeter, transport: :stdio} ] ``` -------------------------------- ### Hermes MCP Interactive Session Commands Source: https://github.com/cloudwalk/hermes-mcp/blob/main/pages/building-a-server.md Documentation for commands available within the Hermes MCP interactive session. These commands allow users to check server status, list available tools, call specific tools with arguments, and inspect the current client state. ```APIDOC mcp> ping - Description: Checks the server's responsiveness. - Returns: "pong" mcp> list_tools - Description: Lists all available tools registered with the MCP. - Returns: A list of tool names and their descriptions. - Example Output: Available tools: - greeter: Greet someone warmly - product_search: Search for products in our catalog mcp> call_tool - Description: Invokes a specific tool with provided arguments. - Parameters: - Tool name: The name of the tool to call (e.g., "greeter"). - Tool arguments (JSON): JSON object containing arguments for the tool (e.g., {"name": "Alice"}). - Returns: The result of the tool execution. - Example Usage: Tool name: greeter Tool arguments (JSON): {"name": "Alice"} Result: Hello Alice! Welcome to the MCP world! mcp> show_state - Description: Displays the current client state and protocol information. - Returns: Details about the client's protocol version and initialization status. - Example Output: Client State: Protocol: 2024-11-05 Initialized: true ... ```