# MCP Integration Pattern in Hermes Agent: A Complete Guide to Connecting External MCP Servers

> Understand the MCP integration pattern in Hermes Agent. This guide details connecting external MCP servers as native tools using a discovery and registration system.

- Repository: [Nous Research/hermes-agent](https://github.com/NousResearch/hermes-agent)
- Tags: how-to-guide
- Published: 2026-03-09

---

**Hermes Agent implements the Model Context Protocol (MCP) integration pattern by treating external MCP servers as long-running background services that expose their tools as native Hermes tools through a dedicated asyncio-based discovery and registration system.**

The MCP integration pattern in Hermes Agent enables seamless extension of agent capabilities by connecting to external MCP servers. According to the NousResearch/hermes-agent source code, this architecture allows developers to integrate both local stdio-based servers and remote HTTP endpoints without modifying the core agent logic.

## Understanding the MCP Integration Architecture

Hermes Agent follows a persistent connection pattern where each configured MCP server runs as a background task. The architecture separates transport handling from tool execution, ensuring that network interruptions or server restarts do not crash the main agent process.

The integration relies on three core components: the configuration layer in [`hermes_cli/config.py`](https://github.com/NousResearch/hermes-agent/blob/main/hermes_cli/config.py), the server management logic in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py), and the tool registration system in [`tools/registry.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/registry.py). Together, these components enable automatic discovery, schema conversion, and runtime execution of MCP-exposed functionality.

## Configuring MCP Servers in Hermes Agent

### Configuration File Structure

MCP servers are defined in the user's `~/.hermes/config.yaml` under the `mcp_servers` key. Each server entry specifies transport parameters, timeouts, and environment variables.

```yaml
mcp_servers:
  filesystem:
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    env: {}
    timeout: 120
    connect_timeout: 60

  remote_api:
    url: "https://my-mcp.example.com/mcp"
    headers:
      Authorization: "Bearer sk-..."
    timeout: 180

```

### Stdio vs HTTP Transport

Hermes Agent supports two transport mechanisms for MCP integration. **Stdio transport** launches the server as a local subprocess, suitable for command-line tools like the filesystem server. **HTTP transport** connects to existing remote services via SSE (Server-Sent Events) endpoints, enabling integration with cloud-hosted MCP providers.

The `MCPServerTask` class in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py) handles transport abstraction, automatically selecting the appropriate client implementation based on the presence of either `command` (stdio) or `url` (HTTP) in the configuration.

## How Hermes Agent Discovers and Registers MCP Tools

### The Discovery Process

Tool discovery initiates when the agent starts or when the user issues the `/reload-mcp` command. The `discover_mcp_tools()` function in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py) loads the YAML configuration and launches an `MCPServerTask` for each configured server.

```python

# From tools/mcp_tool.py - conceptual flow

def discover_mcp_tools():
    config = load_mcp_config()
    for server_name, server_config in config.items():
        task = MCPServerTask(server_name, server_config)
        task.start()

```

### MCPServerTask and Connection Management

Each `MCPServerTask` runs in a dedicated asyncio task within a background daemon thread. The task opens the transport, creates an `mcp.ClientSession`, runs `session.initialize()`, and calls `session.list_tools()` to retrieve available capabilities.

The task implements automatic reconnection with exponential back-off. If the connection drops, the task enters a retry loop, ensuring that temporary network failures do not permanently disable external tools.

### Tool Registration and Schema Conversion

For each discovered MCP tool, Hermes Agent converts the MCP schema to the internal Hermes format using `_convert_mcp_schema()`. The function maps MCP's JSON Schema definitions to Hermes tool parameters and registers the tool with the central registry via `registry.register()`.

Additionally, the system generates four utility tools for every MCP server: `list_resources`, `read_resource`, `list_prompts`, and `get_prompt` (implemented in `_build_utility_schemas`). These expose MCP's resource and prompt capabilities as callable Hermes functions.

All MCP tools are grouped into a custom toolset named `mcp-<server>` and injected into every platform toolset (e.g., `hermes-cli`, `hermes-telegram`), making them immediately available in conversations.

## Runtime Operations and Tool Execution

### Synchronous Wrappers for Async Operations

While MCP operations are asynchronous, Hermes Agent exposes them through synchronous tool handlers to maintain compatibility with the agent's execution loop. The `_make_tool_handler()` function creates a closure that bridges sync and async contexts.

When a user invokes an MCP tool, the handler calls `_run_on_mcp_loop()`, which schedules the actual async execution on the background MCP event loop and blocks until completion or timeout.

### Timeout Handling and Error Sanitization

Each MCP tool call respects the timeout specified in the configuration (defaulting to 120 seconds). If the server fails to respond, the wrapper raises a timeout exception that the agent can handle gracefully.

Error messages undergo sanitization to prevent credential leakage. The `_run_on_mcp_loop()` function strips sensitive information from stack traces before returning them to the user interface, ensuring that API keys or tokens defined in headers remain confidential.

## Managing MCP Server Lifecycle

### Checking Server Status

The `get_mcp_status()` function in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py) provides real-time visibility into MCP server health. It returns a list of status objects containing the server name, transport type, number of discovered tools, and connection state.

```python
from tools.mcp_tool import get_mcp_status

for srv in get_mcp_status():
    print(f"{srv['name']} ({srv['transport']}): "
          f"{srv['tools']} tools – "
          f"{'connected' if srv['connected'] else 'offline'}")

```

This information powers the agent's startup banner, displaying which external services are available for the current session.

### Reloading Servers with /reload-mcp

Hermes Agent supports hot-reloading of MCP configurations without restarting the entire agent. The `/reload-mcp` slash command, implemented in [`gateway/run.py`](https://github.com/NousResearch/hermes-agent/blob/main/gateway/run.py), triggers a graceful shutdown of existing MCP connections followed by a fresh discovery cycle.

When executed, the command calls `shutdown_mcp_servers()` to terminate current tasks, then invokes `discover_mcp_tools()` to re-read the configuration and establish new connections. This enables dynamic addition or modification of MCP servers during long-running agent sessions.

### Graceful Shutdown

When the agent terminates or when reloading configurations, `shutdown_mcp_servers()` ensures clean disconnection from all MCP services. The function signals each `MCPServerTask` to exit, closes active client sessions, and stops the background event loop, preventing resource leaks and hanging subprocesses.

## Summary

- **Hermes Agent** implements the MCP integration pattern by running external servers as persistent background tasks managed by `MCPServerTask` in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py).
- **Configuration** occurs in `~/.hermes/config.yaml` under the `mcp_servers` key, supporting both stdio subprocesses and HTTP/SSE endpoints.
- **Discovery** happens via `discover_mcp_tools()`, which initializes connections, converts MCP schemas using `_convert_mcp_schema()`, and registers tools with the central registry.
- **Runtime execution** uses synchronous wrappers (`_make_tool_handler()`) that schedule async calls on a dedicated background loop with configurable timeouts and error sanitization.
- **Lifecycle management** includes status checking via `get_mcp_status()`, hot-reloading via the `/reload-mcp` command in [`gateway/run.py`](https://github.com/NousResearch/hermes-agent/blob/main/gateway/run.py), and graceful shutdown via `shutdown_mcp_servers()`.

## Frequently Asked Questions

### What is the MCP integration pattern in Hermes Agent?

The MCP integration pattern in Hermes Agent treats external Model Context Protocol servers as long-running background services that expose their capabilities as native Hermes tools. According to the source code in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py), the pattern involves persistent asyncio tasks (`MCPServerTask`) that maintain connections, automatically reconnect on failure, and bridge asynchronous MCP operations with the agent's synchronous tool execution loop.

### How do I configure an external MCP server in Hermes Agent?

To connect an external MCP server, add an entry to the `mcp_servers` section of your `~/.hermes/config.yaml` file. For local servers, specify the `command` and `args` keys to launch a stdio subprocess. For remote services, provide a `url` key pointing to the HTTP/SSE endpoint. You can also set `timeout`, `connect_timeout`, and `headers` (for HTTP) to control connection behavior and authentication.

### What transport protocols does Hermes Agent support for MCP?

Hermes Agent supports two transport mechanisms for MCP integration: **stdio** and **HTTP/SSE**. The stdio transport launches the MCP server as a local subprocess, ideal for command-line tools like the filesystem server. The HTTP transport connects to remote servers via Server-Sent Events, suitable for cloud-hosted MCP providers. The `MCPServerTask` class in [`tools/mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/main/tools/mcp_tool.py) automatically selects the appropriate client based on whether the configuration contains a `command` (stdio) or `url` (HTTP) key.

### How can I reload MCP servers without restarting Hermes Agent?

Hermes Agent supports hot-reloading of MCP configurations through the `/reload-mcp` slash command. When invoked from the chat interface or CLI, the command handler in [`gateway/run.py`](https://github.com/NousResearch/hermes-agent/blob/main/gateway/run.py) calls `shutdown_mcp_servers()` to gracefully terminate existing connections, then triggers `discover_mcp_tools()` to re-read the configuration and establish fresh connections. This allows you to add, remove, or modify MCP servers dynamically during long-running agent sessions without losing conversation context.