📑 Table of contents

Hermes Agent #15: MCP Servers — Extending Hermes with External Tools

Hermes Agent 🔴 Advanced ⏱️ 10 min read 📅 2026-05-05

MCP Servers: Extending Hermes with External Tools

Hermes Agent is already a powerful agent with its 68 built-in tools. But imagine instantly connecting it to GitHub, Notion, PostgreSQL, Stripe, or any internal API — without writing a single line of Python code in Hermes's core. That's exactly what MCP (Model Context Protocol) enables: an open standard created by Anthropic that establishes a universal bridge between AI agents and external tool servers.

In this advanced article, we explore everything MCP brings to Hermes Agent: configuration in config.yaml, the two supported transports (stdio and HTTP), concrete examples with popular servers, secure token management, automatic tool discovery, permissions, and even how to build your own MCP server.

What is MCP and Why Does It Matter?

Model Context Protocol (MCP) is an open protocol that standardizes how language models interact with external tools. Instead of integrating each service individually, MCP defines a common interface: an MCP server exposes tools via JSON-RPC, and any MCP client (like Hermes) can discover and call them automatically.

Why use MCP with Hermes?

  • Massive ecosystem: hundreds of MCP servers already exist on npm and PyPI — GitHub, filesystem, databases, cloud APIs, productivity tools
  • Declarative configuration: add a server in config.yaml, restart, and tools appear immediately
  • Isolation: each MCP server runs in its own process with its own environment variables
  • Dynamic updates: MCP servers can signal changes to their tool list in real-time via the notifications/tools/list_changed notification

Hermes integrates MCP natively through the tools/mcp_tool.py module, which manages the full lifecycle: connection, discovery, tool invocation, and cleanup.

Configuration in config.yaml

All MCP configuration lives in the mcp_servers section of ~/.hermes/config.yaml. Each entry represents a named MCP server. Here's the full structure:

mcp_servers:
  server_name:
    # For stdio servers (local process):
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"]
    env:
      VARIABLE: "value"
    timeout: 120          # per-tool-call timeout in seconds (default: 120)
    connect_timeout: 60   # initial connection timeout (default: 60)

  http_server:
    # For remote servers (HTTP):
    url: "https://mcp.example.com/mcp"
    headers:
      Authorization: "Bearer sk-..."
    timeout: 180

Environment variables use the ${VAR} syntax and are automatically resolved from ~/.hermes/.env and os.environ. This means your API tokens should never be written in plain text in config.yaml:

mcp_servers:
  github:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"

Resolution follows this priority order: ~/.hermes/.env → system variables → defaults.

The Two Transports: stdio and HTTP

Hermes supports two MCP transport modes, each suited to different use cases.

stdio Transport

The stdio transport launches the MCP server as a subprocess. Hermes communicates with it through standard input and output (stdin/stdout). This is the most common and simplest mode:

mcp_servers:
  time:
    command: uvx
    args: ["mcp-server-time"]

  filesystem:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]

stdio advantages:
- No network server to manage
- Maximum security (no network exposure)
- Natural isolation (separate process)
- Ideal for local tools like filesystem or Git

HTTP Transport (StreamableHTTP)

The HTTP transport connects Hermes to a remote MCP server via URL. This is ideal for cloud APIs and managed services:

mcp_servers:
  notion:
    url: https://mcp.notion.com/mcp

  custom_api:
    url: https://my-mcp-server.example.com/mcp
    headers:
      Authorization: "Bearer ${MY_API_KEY}"
      X-Custom-Header: "value"
    timeout: 180

HTTP advantages:
- Access to cloud services (Notion, Stripe, etc.)
- Share one server across multiple agents
- Natural scalability
- Supports authentication headers

GitHub — Repository Operations

The official GitHub MCP server gives Hermes the ability to create issues, manage pull requests, read source code, and much more:

mcp_servers:
  github:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"

Once configured, GitHub tools appear in Hermes's registry under the mcp-github toolset. You can then ask Hermes: "Create an issue on my repo for bug X" or "List open PRs on project Y".

Filesystem — Secure System Access

The filesystem server allows Hermes to read and write in directories you explicitly authorize:

mcp_servers:
  filesystem:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]

Important security note: the path passed as an argument strictly defines the access boundary. Hermes cannot read or write outside this directory. This is a built-in sandbox.

Web Search — Real-time Web Access

Several MCP web search servers exist. Here's an example:

mcp_servers:
  web_search:
    command: uvx
    args: ["mcp-server-web-search"]
    env:
      SEARCH_API_KEY: "${SEARCH_API_KEY}"

Notion — Knowledge Base

Notion provides a native MCP server accessible via HTTP:

mcp_servers:
  notion:
    url: https://mcp.notion.com/mcp

Time Server — Minimal Example

The time server is the simplest example to verify your MCP configuration works:

mcp_servers:
  time:
    command: uvx
    args: ["mcp-server-time"]

Automatic Tool Discovery

This is one of the most powerful aspects of MCP integration in Hermes. On startup, Hermes automatically performs for each configured server:

  1. Connection to the server (via stdio or HTTP)
  2. tools/list call to discover all available tools
  3. Registration in the tool registry under the mcp-<server_name> toolset
  4. Exposure to the model with descriptions and JSON Schema parameter definitions

Hermes assigns each MCP tool a prefixed name like mcp__github__create_issue or mcp__filesystem__read_file. The model sees these tools exactly like native tools — there's no difference from the agent's perspective.

Dynamic Refresh

MCP servers can send the notifications/tools/list_changed notification to signal that their tool list has changed. Hermes responds with a complete "deregister then rediscover" cycle: it removes all tools from the affected toolset, then rediscovers them.

To manually force reloading all MCP servers without restarting Hermes, use the /reload-mcp command in the CLI.

Security and Permissions

Security is a central aspect of MCP integration in Hermes. Multiple protection layers are in place.

Environment Variable Isolation

Environment variables defined in the env section of an MCP server are only passed to that subprocess. They don't pollute Hermes's global environment or other servers. If an MCP server is compromised, it only has access to its own tokens.

Selective Disabling

You can disable entire MCP servers while keeping them in the configuration:

mcp_servers:
  github:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"
    disabled: true  # Server disabled but preserved in config

Per-tool Permissions

Hermes supports per-tool filtering to restrict which MCP tools are available. You can list allowed or blocked tools per server, offering granular control over what the agent can do with each external service.

Security Best Practices

  • Never put tokens in plain text in config.yaml — always use ${VAR} and the .env file
  • Limit filesystem MCP paths to the strict minimum needed
  • Disable MCP servers you're not actively using
  • Audit active MCP servers regularly with /tools in the CLI
  • Prefer stdio transport when possible (no network exposure)

Creating a Simple MCP Server

Building your own MCP server is surprisingly easy thanks to the Python mcp SDK. Here's a minimal server exposing calculation tools:

#!/usr/bin/env python3
"""My first MCP server - math tools."""

from mcp.server.fastmcp import FastMCP

mcp = FastMCP(
    "my_server",
    instructions="Advanced math tools.",
)

@mcp.tool()
def calculate(expression: str) -> str:
    'Safely evaluates a mathematical expression.'
    allowed = set("0123456789+-*/().% ")
    if not all(c in allowed for c in expression):
        return f"Error: unauthorized characters in {expression}"
    try:
        result = eval(expression)
        return str(result)
    except Exception as e:
        return f"Evaluation error: {e}"

@mcp.tool()
def unit_conversion(value: float, from_unit: str, to_unit: str) -> str:
    'Converts a value between units (km/mi, kg/lb, C/F).'
    conversions = {
        ("km", "mi"): value * 0.621371,
        ("mi", "km"): value * 1.60934,
        ("kg", "lb"): value * 2.20462,
        ("lb", "kg"): value * 0.453592,
        ("C", "F"): value * 9/5 + 32,
        ("F", "C"): (value - 32) * 5/9,
    }
    key = (from_unit.lower(), to_unit.lower())
    if key not in conversions:
        return f"Conversion {from_unit} -> {to_unit} not supported"
    return f"{value} {from_unit} = {conversions[key]:.4f} {to_unit}"

if __name__ == "__main__":
    mcp.run()

To connect this server to Hermes, add it in config.yaml:

mcp_servers:
  maths:
    command: python3
    args: ["/path/to/my_mcp_server.py"]

After restart, Hermes will have access to the calculate and unit_conversion tools automatically.

Hermes as an MCP Server

Hermes Agent can also function as an MCP server! The hermes mcp serve command exposes Hermes conversations as MCP tools, allowing other MCP clients (Claude Code, Cursor, Codex) to list conversations, read messages, send messages, and manage permissions.

{
  "mcpServers": {
    "hermes": {
      "command": "hermes",
      "args": ["mcp", "serve"]
    }
  }
}

This feature is implemented in mcp_serve.py and exposes 10 tools including conversations_list, messages_read, messages_send, events_poll, and channels_list.

Troubleshooting

MCP Server Won't Connect

Symptom: MCP tools don't appear in the tool list.

Solutions:
1. Verify the mcp package is installed: pip install mcp
2. Check the command path (use absolute path if necessary)
3. Test the server manually: run the command with the same arguments in a terminal
4. Increase connect_timeout if the server is slow to start (some Node.js servers via npx download dependencies on first launch)

"command not found" Error

If npx or uvx aren't found, it's a PATH issue. Solutions:
- Use the absolute path: /usr/bin/npx or /home/user/.local/bin/uvx
- Ensure your PATH is correctly configured in ~/.hermes/.env

Environment Variables Not Resolved

If ${GITHUB_TOKEN} appears literally in logs instead of the resolved value:
- Verify the variable is defined in ~/.hermes/.env
- Verify the name matches exactly (case-sensitive)
- Don't forget quotes around the value: "${GITHUB_TOKEN}"

Timeout on Tool Calls

If MCP tool calls regularly fail with timeout:
- Increase timeout in the server configuration (default: 120 seconds)
- Increase connect_timeout for slow initial connections (default: 60 seconds)

Diagnostic Commands

# List all active MCP tools
hermes chat --list-tools | grep mcp__

# Reload all MCP servers (in the CLI)
/reload-mcp

# Check configuration
hermes config | grep -A 20 mcp_servers

Conclusion

MCP servers transform Hermes Agent from a powerful tool into a modular and extensible platform. With a simple declaration in config.yaml, you instantly add capabilities that would otherwise be impossible or require significant development effort.

What we covered:
- Simple configuration in the mcp_servers section of config.yaml
- Two transports: stdio for local tools, HTTP for cloud services
- Concrete examples: GitHub, filesystem, web search, Notion
- Secure environment variables with ${VAR} syntax and per-server isolation
- Automatic discovery: MCP tools appear as native tools in the registry
- Dynamic refresh via notifications/tools/list_changed and /reload-mcp
- Multi-layer security: process isolation, filesystem sandbox, granular permissions
- Custom server creation with the Python mcp SDK
- Hermes as an MCP server for integration with other MCP clients

Each new MCP server you configure extends Hermes's capabilities without any code changes. That's the promise of a truly composable AI agent.

Related articles:
- /article/hermes-agent-outils-disponibles — The 68 native tools of Hermes Agent
- /article/hermes-agent-configurer-modeles-providers — Configuring models and providers
- /article/hermes-agent-connecter-telegram — Connecting Telegram to Hermes
- /article/hermes-agent-delegation-sous-agents — Task delegation with subagents
- /article/hermes-agent-cron-jobs-automatisation — Automating with cron jobs