mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-04 17:57:28 +08:00
Broad drift audit against origin/main (b52b63396).
Reference pages (most user-visible drift):
- slash-commands: add /busy, /curator, /footer, /indicator, /redraw, /steer
that were missing; drop non-existent /terminal-setup; fix /q footnote
(resolves to /queue, not /quit); extend CLI-only list with all 24
CLI-only commands in the registry
- cli-commands: add dedicated sections for hermes curator / fallback /
hooks (new subcommands not previously documented); remove stale
hermes honcho standalone section (the plugin registers dynamically
via hermes memory); list curator/fallback/hooks in top-level table;
fix completion to include fish
- toolsets-reference: document the real 52-toolset count; split browser
vs browser-cdp; add discord / discord_admin / spotify / yuanbao;
correct hermes-cli tool count from 36 to 38; fix misleading claim
that hermes-homeassistant adds tools (it's identical to hermes-cli)
- tools-reference: bump tool count 55 -> 68; add 7 Spotify, 5 Yuanbao,
2 Discord toolsets; move browser_cdp/browser_dialog to their own
browser-cdp toolset section
- environment-variables: add 40+ user-facing HERMES_* vars that were
undocumented (--yolo, --accept-hooks, --ignore-*, inference model
override, agent/stream/checkpoint timeouts, OAuth trace, per-platform
batch tuning for Telegram/Discord/Matrix/Feishu/WeCom, cron knobs,
gateway restart/connect timeouts); dedupe the Cron Scheduler section;
replace stale QQ_SANDBOX with QQ_PORTAL_HOST
User-guide (top level):
- cli.md: compression preserves last 20 turns, not 4 (protect_last_n: 20)
- configuration.md: display.platforms is the canonical per-platform
override key; tool_progress_overrides is deprecated and auto-migrated
- profiles.md: model.default is the config key, not model.model
- sessions.md: CLI/TUI session IDs use 6-char hex, gateway uses 8
- checkpoints-and-rollback.md: destructive-command list now matches
_DESTRUCTIVE_PATTERNS (adds rmdir, cp, install, dd)
- docker.md: the container runs as non-root hermes (UID 10000) via
gosu; fix install command (uv pip); add missing --insecure on the
dashboard compose example (required for non-loopback bind)
- security.md: systemctl danger pattern also matches 'restart'
- index.md: built-in tool count 47 -> 68
- integrations/index.md: 6 STT providers, 8 memory providers
- integrations/providers.md: drop fictional dashscope/qwen aliases
Features:
- overview.md: 9 image models (not 8), 9 TTS providers (not 5),
8 memory providers (Supermemory was missing)
- tool-gateway.md: 9 image models
- tools.md: extend common-toolsets list with search / messaging /
spotify / discord / debugging / safe
- fallback-providers.md: add 6 real providers from PROVIDER_REGISTRY
(lmstudio, kimi-coding-cn, stepfun, alibaba-coding-plan,
tencent-tokenhub, azure-foundry)
- plugins.md: Available Hooks table now includes on_session_finalize,
on_session_reset, subagent_stop
- built-in-plugins.md: add the 7 bundled plugins the page didn't
mention (spotify, google_meet, three image_gen providers, two
dashboard examples)
- web-dashboard.md: add --insecure and --tui flags
- cron.md: hermes cron create takes positional schedule/prompt, not
flags
Messaging:
- telegram.md: TELEGRAM_WEBHOOK_SECRET is now REQUIRED when
TELEGRAM_WEBHOOK_URL is set (gateway refuses to start without it
per GHSA-3vpc-7q5r-276h). Biggest user-visible drift in the batch.
- discord.md: HERMES_DISCORD_TEXT_BATCH_SPLIT_DELAY_SECONDS default
is 2.0, not 0.1
- dingtalk.md: document DINGTALK_REQUIRE_MENTION /
FREE_RESPONSE_CHATS / MENTION_PATTERNS / HOME_CHANNEL /
ALLOW_ALL_USERS that the adapter supports
- bluebubbles.md: drop fictional BLUEBUBBLES_SEND_READ_RECEIPTS env
var; the setting lives in platforms.bluebubbles.extra only
- qqbot.md: drop dead QQ_SANDBOX; add real QQ_PORTAL_HOST and
QQ_GROUP_ALLOWED_USERS
- wecom-callback.md: replace 'hermes gateway start' (service-only)
with 'hermes gateway' for first-time setup
Developer-guide:
- architecture.md: refresh tool/toolset counts (61/52), terminal
backend count (7), line counts for run_agent.py (~13.7k), cli.py
(~11.5k), main.py (~10.4k), setup.py (~3.5k), gateway/run.py
(~12.2k), mcp_tool.py (~3.1k); add yuanbao adapter, bump platform
adapter count 18 -> 20
- agent-loop.md: run_agent.py line count 10.7k -> 13.7k
- tools-runtime.md: add vercel_sandbox backend
- adding-tools.md: remove stale 'Discovery import added to
model_tools.py' checklist item (registry auto-discovery)
- adding-platform-adapters.md: mark send_typing / get_chat_info as
concrete base methods; only connect/disconnect/send are abstract
- acp-internals.md: ACP sessions now persist to SessionDB
(~/.hermes/state.db); acp.run_agent call uses
use_unstable_protocol=True
- cron-internals.md: gateway runs scheduler in a dedicated background
thread via _start_cron_ticker, not on a maintenance cycle; locking
is cross-process via fcntl.flock (Unix) / msvcrt.locking (Windows)
- gateway-internals.md: gateway/run.py ~12k lines
- provider-runtime.md: cron DOES support fallback (run_job reads
fallback_providers from config)
- session-storage.md: SCHEMA_VERSION = 11 (not 9); add migrations
10 and 11 (trigram FTS, inline-mode FTS5 re-index); add
api_call_count column to Sessions DDL; document messages_fts_trigram
and state_meta in the architecture tree
- context-compression-and-caching.md: remove the obsolete 'context
pressure warnings' section (warnings were removed for causing
models to give up early)
- context-engine-plugin.md: compress() signature now includes
focus_topic param
- extending-the-cli.md: _build_tui_layout_children signature now
includes model_picker_widget; add to default layout
Also fixed three pre-existing broken links/anchors the build warned
about (docker.md -> api-server.md, yuanbao.md -> cron-jobs.md and
tips#background-tasks, nix-setup.md -> #container-aware-cli).
Regenerated per-skill pages via website/scripts/generate-skill-docs.py
so catalog tables and sidebar are consistent with current SKILL.md
frontmatter.
docusaurus build: clean, no broken links or anchors.
375 lines
13 KiB
Markdown
375 lines
13 KiB
Markdown
---
|
|
title: "Native Mcp — MCP client: connect servers, register tools (stdio/HTTP)"
|
|
sidebar_label: "Native Mcp"
|
|
description: "MCP client: connect servers, register tools (stdio/HTTP)"
|
|
---
|
|
|
|
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
|
|
|
# Native Mcp
|
|
|
|
MCP client: connect servers, register tools (stdio/HTTP).
|
|
|
|
## Skill metadata
|
|
|
|
| | |
|
|
|---|---|
|
|
| Source | Bundled (installed by default) |
|
|
| Path | `skills/mcp/native-mcp` |
|
|
| Version | `1.0.0` |
|
|
| Author | Hermes Agent |
|
|
| License | MIT |
|
|
| Tags | `MCP`, `Tools`, `Integrations` |
|
|
| Related skills | [`mcporter`](/docs/user-guide/skills/optional/mcp/mcp-mcporter) |
|
|
|
|
## Reference: full SKILL.md
|
|
|
|
:::info
|
|
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
|
:::
|
|
|
|
# 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:
|
|
|
|
```bash
|
|
pip install mcp
|
|
# or, if using uv:
|
|
uv pip install mcp
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
Add MCP servers to `~/.hermes/config.yaml` under the `mcp_servers` key:
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
time:
|
|
command: "uvx"
|
|
args: ["mcp-server-time"]
|
|
```
|
|
|
|
Restart Hermes Agent. On startup it will:
|
|
1. Connect to the server
|
|
2. Discover available tools
|
|
3. Register them with the prefix `mcp_time_*`
|
|
4. Inject them into all platform toolsets
|
|
|
|
You can then use the tools naturally -- just ask the agent to get the current time.
|
|
|
|
## 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)
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
server_name:
|
|
command: "npx" # (required) executable to run
|
|
args: ["-y", "pkg-name"] # (optional) command arguments, default: []
|
|
env: # (optional) environment variables for the subprocess
|
|
SOME_API_KEY: "value"
|
|
timeout: 120 # (optional) per-tool-call timeout in seconds, default: 120
|
|
connect_timeout: 60 # (optional) initial connection timeout in seconds, default: 60
|
|
```
|
|
|
|
### HTTP Transport (url)
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
server_name:
|
|
url: "https://my-server.example.com/mcp" # (required) server URL
|
|
headers: # (optional) HTTP headers
|
|
Authorization: "Bearer sk-..."
|
|
timeout: 180 # (optional) per-tool-call timeout in seconds, default: 120
|
|
connect_timeout: 60 # (optional) initial connection timeout in seconds, default: 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.
|
|
|
|
## How It Works
|
|
|
|
### Startup Discovery
|
|
|
|
When Hermes Agent starts, `discover_mcp_tools()` is called during tool initialization:
|
|
|
|
1. Reads `mcp_servers` from `~/.hermes/config.yaml`
|
|
2. For each server, spawns a connection in a dedicated background event loop
|
|
3. Initializes the MCP session and calls `list_tools()` to discover available tools
|
|
4. 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.
|
|
|
|
```yaml
|
|
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`).
|
|
|
|
```yaml
|
|
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. This prevents accidental credential leakage to untrusted MCP servers.
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
github:
|
|
command: "npx"
|
|
args: ["-y", "@modelcontextprotocol/server-github"]
|
|
env:
|
|
# Only this token is passed to the subprocess
|
|
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. This covers:
|
|
|
|
- GitHub PATs (`ghp_...`)
|
|
- OpenAI-style keys (`sk-...`)
|
|
- Bearer tokens
|
|
- Generic `token=`, `key=`, `API_KEY=`, `password=`, `secret=` patterns
|
|
|
|
## Troubleshooting
|
|
|
|
### "MCP SDK not available -- skipping MCP tool discovery"
|
|
|
|
The `mcp` Python package is not installed. Install it:
|
|
|
|
```bash
|
|
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. Ensure `npx`, `uvx`, or the relevant command is installed.
|
|
- **Package not found**: For npx servers, the npm package may not exist or may need `-y` in args to auto-install.
|
|
- **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:
|
|
|
|
```bash
|
|
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
|
|
- Look at Hermes Agent startup logs for connection messages
|
|
- Tool names are prefixed with `mcp_{server}_{tool}` -- look for that pattern
|
|
|
|
### 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.
|
|
|
|
## Examples
|
|
|
|
### Time Server (uvx)
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
time:
|
|
command: "uvx"
|
|
args: ["mcp-server-time"]
|
|
```
|
|
|
|
Registers tools like `mcp_time_get_current_time`.
|
|
|
|
### Filesystem Server (npx)
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
filesystem:
|
|
command: "npx"
|
|
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
|
|
timeout: 30
|
|
```
|
|
|
|
Registers tools like `mcp_filesystem_read_file`, `mcp_filesystem_write_file`, `mcp_filesystem_list_directory`.
|
|
|
|
### GitHub Server with Authentication
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
github:
|
|
command: "npx"
|
|
args: ["-y", "@modelcontextprotocol/server-github"]
|
|
env:
|
|
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
timeout: 60
|
|
```
|
|
|
|
Registers tools like `mcp_github_list_issues`, `mcp_github_create_pull_request`, etc.
|
|
|
|
### Remote HTTP Server
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
company_api:
|
|
url: "https://mcp.mycompany.com/v1/mcp"
|
|
headers:
|
|
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
|
|
X-Team-Id: "engineering"
|
|
timeout: 180
|
|
connect_timeout: 30
|
|
```
|
|
|
|
### Multiple Servers
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
time:
|
|
command: "uvx"
|
|
args: ["mcp-server-time"]
|
|
|
|
filesystem:
|
|
command: "npx"
|
|
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
|
|
|
github:
|
|
command: "npx"
|
|
args: ["-y", "@modelcontextprotocol/server-github"]
|
|
env:
|
|
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
|
|
company_api:
|
|
url: "https://mcp.internal.company.com/mcp"
|
|
headers:
|
|
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
|
|
timeout: 300
|
|
```
|
|
|
|
All tools from all servers are registered and available 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. This enables agent-in-the-loop workflows (data analysis, content generation, decision-making).
|
|
|
|
Sampling is **enabled by default**. Configure per server:
|
|
|
|
```yaml
|
|
mcp_servers:
|
|
my_server:
|
|
command: "npx"
|
|
args: ["-y", "my-mcp-server"]
|
|
sampling:
|
|
enabled: true # default: true
|
|
model: "gemini-3-flash" # model override (optional)
|
|
max_tokens_cap: 4096 # max tokens per request
|
|
timeout: 30 # LLM call timeout (seconds)
|
|
max_rpm: 10 # max requests per minute
|
|
allowed_models: [] # model whitelist (empty = all)
|
|
max_tool_rounds: 5 # tool loop limit (0 = disable)
|
|
log_level: "info" # audit verbosity
|
|
```
|
|
|
|
Servers can also include `tools` in sampling requests for multi-turn tool-augmented workflows. The `max_tool_rounds` config prevents infinite tool loops. Per-server audit metrics (requests, errors, tokens, tool use count) are tracked via `get_mcp_status()`.
|
|
|
|
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
|
|
- Tool results are returned as JSON with either `{"result": "..."}` or `{"error": "..."}`
|
|
- 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)
|