| name | native-mcp |
| description | MCP client: connect servers, register tools (stdio/HTTP). |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["linux","macos","windows"] |
| metadata | {"hermes":{"tags":["MCP","Tools","Integrations"],"related_skills":["mcporter"]}} |
Native MCP Client
Hermes Agent has a built-in MCP client that connects to MCP servers at startup, discovers their tools, and makes them available as first-class tools the agent can call directly. No bridge CLI needed -- tools from MCP servers appear alongside built-in tools like terminal, read_file, etc.
When to Use
Use this whenever you want to:
- Connect to MCP servers and use their tools from within Hermes Agent
- Add external capabilities (filesystem access, GitHub, databases, APIs) via MCP
- Run local stdio-based MCP servers (npx, uvx, or any command)
- Connect to remote HTTP/StreamableHTTP MCP servers
- Have MCP tools auto-discovered and available in every conversation
For ad-hoc, one-off MCP tool calls from the terminal without configuring anything, see the mcporter skill instead.
Prerequisites
- mcp Python package -- optional dependency; install with
pip install mcp. If not installed, MCP support is silently disabled.
- Node.js -- required for
npx-based MCP servers (most community servers)
- uv -- required for
uvx-based MCP servers (Python-based servers)
Install the MCP SDK:
pip install mcp
Quick Start
Add MCP servers to ~/.hermes/config.yaml under the mcp_servers key:
mcp_servers:
time:
command: "uvx"
args: ["mcp-server-time"]
Restart Hermes Agent. On startup it will:
- Connect to the server
- Discover available tools
- Register them with the prefix
mcp_time_*
- Inject them into all platform toolsets
Configuration Reference
Each entry under mcp_servers is a server name mapped to its config. There are two transport types: stdio (command-based) and HTTP (url-based).
Stdio Transport (command + args)
mcp_servers:
server_name:
command: "npx"
args: ["-y", "pkg-name"]
env:
SOME_API_KEY: "value"
timeout: 120
connect_timeout: 60
HTTP Transport (url)
mcp_servers:
server_name:
url: "https://my-server.example.com/mcp"
headers:
Authorization: "Bearer sk-..."
timeout: 180
connect_timeout: 60
All Config Options
| Option | Type | Default | Description |
|---|
command | string | -- | Executable to run (stdio transport, required) |
args | list | [] | Arguments passed to the command |
env | dict | {} | Extra environment variables for the subprocess |
url | string | -- | Server URL (HTTP transport, required) |
headers | dict | {} | HTTP headers sent with every request |
timeout | int | 120 | Per-tool-call timeout in seconds |
connect_timeout | int | 60 | Timeout for initial connection and discovery |
Note: A server config must have either command (stdio) or url (HTTP), not both.
⚠️ Critical: Only ONE mcp_servers Block
- YAML does NOT allow duplicate keys. If
mcp_servers: appears twice in config.yaml, only the FIRST block is parsed — the second is silently discarded.
- Diagnosis:
grep -n "mcp_servers" ~/.hermes/config.yaml — if the line number appears more than once, merge the blocks.
- Symptom of duplicates: Keepalive failures in
~/.hermes/logs/gateway.error.log: WARNING tools.mcp_tool: MCP server 'X' keepalive failed, triggering reconnect. Tools from the dropped server never appear in the runtime palette.
How It Works
Startup Discovery
When Hermes Agent starts, discover_mcp_tools() is called during tool initialization:
- Reads
mcp_servers from ~/.hermes/config.yaml
- For each server, spawns a connection in a dedicated background event loop
- Initializes the MCP session and calls
list_tools() to discover available tools
- Registers each tool in the Hermes tool registry
Tool Naming Convention
MCP tools are registered with the naming pattern:
mcp_{server_name}_{tool_name}
Hyphens and dots in names are replaced with underscores for LLM API compatibility.
Examples:
- Server
filesystem, tool read_file → mcp_filesystem_read_file
- Server
github, tool list-issues → mcp_github_list_issues
- Server
my-api, tool fetch.data → mcp_my_api_fetch_data
Auto-Injection
After discovery, MCP tools are automatically injected into all hermes-* platform toolsets (CLI, Discord, Telegram, etc.). This means MCP tools are available in every conversation without any additional configuration.
Connection Lifecycle
- Each server runs as a long-lived asyncio Task in a background daemon thread
- Connections persist for the lifetime of the agent process
- If a connection drops, automatic reconnection with exponential backoff kicks in (up to 5 retries, max 60s backoff)
- On agent shutdown, all connections are gracefully closed
Idempotency
discover_mcp_tools() is idempotent -- calling it multiple times only connects to servers that aren't already connected. Failed servers are retried on subsequent calls.
Transport Types
Stdio Transport
The most common transport. Hermes launches the MCP server as a subprocess and communicates over stdin/stdout.
mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
The subprocess inherits a filtered environment (see Security section below) plus any variables you specify in env.
HTTP / StreamableHTTP Transport
For remote or shared MCP servers. Requires the mcp package to include HTTP client support (mcp.client.streamable_http).
mcp_servers:
remote_api:
url: "https://mcp.example.com/mcp"
headers:
Authorization: "Bearer sk-..."
If HTTP support is not available in your installed mcp version, the server will fail with an ImportError and other servers will continue normally.
Security
Environment Variable Filtering
For stdio servers, Hermes does NOT pass your full shell environment to MCP subprocesses. Only safe baseline variables are inherited:
PATH, HOME, USER, LANG, LC_ALL, TERM, SHELL, TMPDIR
- Any
XDG_* variables
All other environment variables (API keys, tokens, secrets) are excluded unless you explicitly add them via the env config key.
mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_..."
Credential Stripping in Error Messages
If an MCP tool call fails, any credential-like patterns in the error message are automatically redacted before being shown to the LLM.
Troubleshooting
"MCP SDK not available -- skipping MCP tool discovery"
The mcp Python package is not installed. Install it:
pip install mcp
"No MCP servers configured"
No mcp_servers key in ~/.hermes/config.yaml, or it's empty. Add at least one server.
"Failed to connect to MCP server 'X'"
Common causes:
- Command not found: The
command binary isn't on PATH.
- Package not found: For npx servers, the npm package may not exist or may need
-y in args.
- Timeout: The server took too long to start. Increase
connect_timeout.
- Port conflict: For HTTP servers, the URL may be unreachable.
"MCP server 'X' requires HTTP transport but mcp.client.streamable_http is not available"
Your mcp package version doesn't include HTTP client support. Upgrade:
pip install --upgrade mcp
Tools not appearing
- Check that the server is listed under
mcp_servers (not mcp or servers)
- Ensure the YAML indentation is correct
- Check for duplicate
mcp_servers keys: grep -n "mcp_servers" ~/.hermes/config.yaml — must appear exactly once.
- Tool names are prefixed with
mcp_{server}_{tool} -- look for that pattern
- Adding or removing servers requires restarting the agent (no hot-reload)
- Tools exposed by the server but NOT in the runtime palette? The server is alive (HTTP 200 on
initialize, tools/list returns tools) but the agent's local tool registry doesn't have them. Fix: restart the Hermes gateway. The MCP handshake happens at startup; tools discovered after startup won't auto-register.
- When to restart vs. when to debug further: If
curl -X POST .../mcp with tools/list returns the tool schema AND the server shows enabled: true in config, but the agent can't see the tool — it's always a restart issue. Do NOT reinstall packages, do NOT modify config, do NOT reinstall the mcp pip package. Just restart.
Connection keeps dropping
The client retries up to 5 times with exponential backoff (1s, 2s, 4s, 8s, 16s, capped at 60s). If the server is fundamentally unreachable, it gives up after 5 attempts. Check the server process and network connectivity.
⚠️ Pitfall — Duplicate mcp_servers Keys in config.yaml
- Symptom: Keepalive failures:
WARNING tools.mcp_tool: MCP server 'X' keepalive failed, triggering reconnect in ~/.hermes/logs/gateway.error.log. Tools from the server never appear.
- Cause: YAML silently drops the second
mcp_servers: block. Only the first block is parsed.
- Diagnosis:
grep -n "mcp_servers" ~/.hermes/config.yaml — more than one line number = duplicates.
- Fix: Merge all server entries into a single
mcp_servers: block. Restart the gateway after fixing.
- Note: The agent cannot edit
config.yaml directly (security constraint). The user must fix duplicates manually or via hermes config.
⚠️ Pitfall — HTTP Transport MCP Servers
- JSON-RPC over HTTP: Remote MCP servers use JSON-RPC over HTTP POST. Test connectivity:
curl -s -X POST https://server.example.com/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'
- Workflow: Send
initialize first, then tools/list with a fresh id.
- 405 on GET ≠ server down. It means the server is alive but doesn't implement GET. This is expected.
- Server not registering? Check: (1) no duplicate
mcp_servers keys, (2) enabled: true, (3) URL is reachable via POST, (4) gateway has been restarted since config change.
Examples
Time Server (uvx)
mcp_servers:
time:
command: "uvx"
args: ["mcp-server-time"]
Filesystem Server (npx)
mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
Remote HTTP Server
mcp_servers:
company_api:
url: "https://mcp.mycompany.com/v1/mcp"
headers:
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
timeout: 180
Multiple Servers (single block!)
mcp_servers:
time:
command: "uvx"
args: ["mcp-server-time"]
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
company_api:
url: "https://mcp.internal.company.com/mcp"
headers:
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
All tools from all servers are registered simultaneously. Each server's tools are prefixed with its name to avoid collisions.
Sampling (Server-Initiated LLM Requests)
Hermes supports MCP's sampling/createMessage capability — MCP servers can request LLM completions through the agent during tool execution.
mcp_servers:
my_server:
command: "npx"
args: ["-y", "my-mcp-server"]
sampling:
enabled: true
max_tokens_cap: 4096
timeout: 30
max_rpm: 10
max_tool_rounds: 5
Disable sampling for untrusted servers with sampling: { enabled: false }.
Notes
- MCP tools are called synchronously from the agent's perspective but run asynchronously on a dedicated background event loop
- The native MCP client is independent of
mcporter -- you can use both simultaneously
- Server connections are persistent and shared across all conversations in the same agent process
- Adding or removing servers requires restarting the agent (no hot-reload currently)
- YAML duplicate key rule: Only ONE
mcp_servers: block per config file. Always merge, never duplicate.