- Add MCP tool — lightweight connectivity check returning server identity, no DB hit (resolves agent connection-test friction) - Tighten 6 tool descriptions (get_relations, get_health_summary, query_metrics, get_trend, get_event_timeline, ping) to be searchable in the first 8-12 words - Document Hermes MCP client setup in ADR-0012 with token security caveat - Move completed plan to plans/done/
6.6 KiB
2026-08-04 — Hermes MCP client integration: native tool surface for oikos
Status: Plan.
Context: Hermes Agent (mac-mini workstation) now connects to oikos's MCP server
as a native MCP client (mcp_servers.oikos in ~/.hermes/config.yaml). All 37+ MCP
tools are available as mcp__oikos__* first-class Hermes tool calls — no more raw
curl with batch-initialize SSE parsing. The integration works; this plan tightens the
remaining seams.
Trigger: First-use retrospective identified three areas that make the integration harder to use than it should be.
1. Motivation
The oikos MCP server (internal/mcp/) speaks Streamable HTTP at
https://mcp.hubris.network/mcp. Hermes Agent's native MCP client connects to it on
startup, discovers tools, and registers them as callable functions. This replaces the
previous pattern where agents fired raw curl requests with batch initialize +
tools/call envelopes.
Three friction points observed:
- No lightweight connectivity check. The
/healthzHTTP endpoint exists but isn't exposed at the MCP protocol layer. An agent that wants to verify the MCP server is reachable must call a real tool (e.g.list_entitieswith a limit of 1) — every call carries the Streamable HTTP session-initialization overhead. - Bearer token in plaintext.
~/.hermes/config.yamlstores the token directly in themcp_servers.oikos.headers.Authorizationvalue. Hermes does not support env-var interpolation in MCP server configs, so the token can't live only in.env. - Zero-visibility streaming overhead. Streamable HTTP batches
initialize+tools/callper request. This adds ~2KB of transport per tool call that the agent never sees. For a singleget_health_summarycall this is negligible; for a 10-tool exploration pass it's 20KB of invisible overhead.
2. Changes
I — MCP health/ping tool (mcp__oikos__ping)
Why: Agents need a zero-cost connectivity check before calling production tools. Currently every check incurs the full Streamable HTTP initialize + tools/call round-trip.
What:
Add a ping tool that returns {"ok": true, "server": "oikos", "version": "dev"}.
No arguments. No DB hit. No auth check (already protected by the MCP transport's auth
layer — the request won't arrive if the bearer token is missing).
// internal/mcp/tools.go
{
Name: "ping",
Description: "Lightweight connectivity check. Returns immediately with server identity, no DB hit.",
InputSchema: jsonschema.Must(nil), // no params
Handler: func(ctx context.Context, args json.RawMessage, caller CallerInfo) (json.RawMessage, error) {
return json.RawMessage(`{"ok":true,"server":"oikos","version":"` + version.Version + `"}`), nil
},
}
Risk class: read-only. No auth, no DB, no state. Auto-approves.
Test: hermes mcp test oikos (from the Hermes CLI) verifies MCP server reachability
independently; the ping tool gives agent code the same signal programmatically.
II — Tool name documentation in server metadata
Why: Hermes prefixes MCP tools as mcp_{server}_{tool}, so get_health_summary
becomes mcp__oikos__get_health_summary. Agents discover tool names at runtime via
tools/list, but there's no short summary of what each tool group does that survives
into the MCP tool description.
What:
Audit and tighten every tool's Description field in internal/mcp/tools.go so the
first 8–12 words are a searchable one-liner an agent can pattern-match against.
Current descriptions that are vague or redundant get a prefix rewrite:
| Tool | Current description | Revised |
|---|---|---|
get_entity |
"Get entity metadata" | "Look up one entity by slug or UUID — type, state, attributes, health" |
list_entities |
"List entities" | "Browse entities by type, state, or name substring — paginated" |
upsert_knowledge |
"Record what you learned" | "Write a document/investigation/runbook to the knowledge graph — idempotent" |
run |
"Run ANY shell command" | "Execute a shell command on any host/LXC/VM — auto-classified by risk" |
Existing tools pass through unchanged if their description is already crisp. ~15 tools get description rewrites.
Risk class: read-only (config change). No runtime effect.
III — Env-var interpolation docs for Hermes config (oikos-side documentation)
Why: The bearer token lives in ~/.hermes/config.yaml in plaintext because Hermes
does not support ${VAR} interpolation in MCP server configs. This is a Hermes
upstream feature request, not an oikos change — but oikos should document the
workaround and track the upstream ask.
What:
Add a ### Hermes MCP client subsection to docs/infrastructure/mcp-server.md (or
create it if it doesn't exist) that covers:
- The config block to add to
~/.hermes/config.yaml(already done — record it for the next person). - The token exposure caveat: Hermes doesn't support env-var interpolation in
mcp_serversheadersyet (upstream issue nousresearch/hermes-agent#TODO — file once). - Workaround:
hermes config set security.redact_secrets true(already default) so the token value is stripped from tool output and logs even if it appears in diagnostic text. - How to verify the connection:
hermes mcp list→hermes mcp test oikos.
Risk class: docs-only.
3. Open questions
| Question | Decision |
|---|---|
Should ping bypass auth entirely or still require a valid bearer token? |
Still requires auth. The MCP transport layer validates the token before routing to ping — no special treatment needed. If the token is missing, the request never reaches the handler. |
Who files the Hermes upstream feature request for ${VAR} interpolation? |
Oikos operator (dtoro). The need is specific to this deployment. File at https://github.com/NousResearch/hermes-agent/issues. |
4. Not doing (yet)
- Persistent MCP sessions — Streamable HTTP stateless mode is fine for the current tool-call volume (~1–5 calls per agent turn). Persistent sessions would save ~2KB per call but add connection lifecycle complexity. Revisit if per-turn tool calls exceed 20.
tools/listcaching — Hermes already caches tool discovery at session start. The 37-tool list is ~4KB; caching adds complexity for negligible savings.
5. Verification
curl -X POST https://mcp.hubris.network/mcp ... -d '...ping...'returns{"ok":true,"server":"oikos","version":"dev"}hermes mcp listshowspingamong oikos toolshermes doctorpasses- Tool descriptions are crisp:
hermes mcp listoutput for oikos shows prefixed summaries