Skip to main content
Glama
hermes-mcp-gateway

hermes-mcp-gateway

by rmax-ai

hermes-mcp-gateway

A governed MCP gateway that exposes Hermes Agent one-shot task execution to remote MCP clients over MCP Streamable HTTP. Clients authenticate with OAuth 2.1 client credentials, receive per-client RBAC (toolset/model/workdir allowlists, concurrency and duration caps), and terminal-capable clients run behind task-level human-in-the-loop approval. Every task, approval, and issued token is written to a SQLite audit store.

Architecture

MCP client ── HTTP (Bearer JWT) ──> gateway (policy / audit)
                                        │
                                        ▼
              hermes -p mcp-worker chat -q <prompt>  (subprocess)
                                        │
                                        ▼
                              per-task status.json + session store

The gateway is a single Starlette app: /token and /.well-known/* handle OAuth discovery and issuance, /healthz reports liveness, and /mcp is the Bearer-authed MCP Streamable HTTP endpoint. Tasks run as governed hermes -p mcp-worker chat -q subprocesses with capped duration, captured stdout/stderr, and the Hermes session id attributed back to the task row.

Related MCP server: ChatGPT Gateway MCP Nyan

Quickstart

uv sync

mkdir -p ~/.hermes/mcp-gateway
cp deploy/config.yaml.example ~/.hermes/mcp-gateway/config.yaml
# edit the config: point hermes.bin at hermes and set workdirs to a real path

openssl rand -hex 32   # this is your signing key
export HERMES_MCP_GATEWAY_SIGNING_KEY="<the hex value>"

# hash a client secret and put its sha256 into config for the client
uv run hermes-mcp-gateway clients hash spec-client-secret
# edit config: replace the placeholder secret_hash for your client

uv run hermes-mcp-gateway --check   # validate config, no server started
uv run hermes-mcp-gateway serve     # or just: hermes-mcp-gateway
curl -sf http://127.0.0.1:8778/healthz

Getting a token

The token endpoint speaks client credentials with either client_secret_basic or client_secret_post:

# client_secret_basic: HTTP Basic (client_id:client_secret)
curl -s -u research:spec-client-secret \
  -d grant_type=client_credentials \
  http://127.0.0.1:8778/token

# client_secret_post: credentials in the form body
curl -s \
  -d grant_type=client_credentials \
  -d client_id=research \
  -d client_secret=spec-client-secret \
  http://127.0.0.1:8778/token

The response is {"access_token": "...", "token_type": "Bearer", "expires_in": 600, "scope": "..."}. Pass access_token as the bearer token on /mcp.

MCP client configuration

OAuth bearer handling is client-specific, so configure your client to send the bearer token directly on the /mcp URL.

Claude Code (.mcp.json):

{
  "mcpServers": {
    "hermes-mcp-gateway": {
      "type": "http",
      "url": "http://127.0.0.1:8778/mcp",
      "headers": {
        "Authorization": "Bearer <access_token>"
      }
    }
  }
}

Generic mcpServers JSON (many clients accept this shape):

{
  "mcpServers": {
    "hermes-mcp-gateway": {
      "url": "http://127.0.0.1:8778/mcp",
      "headers": {
        "Authorization": "Bearer <access_token>"
      }
    }
  }
}

Security model

  • Deny-by-default toolset scopes: a client can only request toolsets granted by a toolset:* scope, and any disallowed toolset rejects the whole request.

  • Empty resolved toolsets are forced to the locked-down safe toolset (never the profile's own defaults, which would include terminal).

  • Workdir jail: tasks run only inside a real directory that resolves under a configured workdir root, symlink escapes rejected.

  • Model allowlist: configured models restrict which models a client may pick.

  • Per-client concurrency and duration caps (max_concurrency, max_duration_s) plus a turn budget (max_turns).

  • Task-level human-in-the-loop: requires_approval clients with terminal park the task as pending_approval until an operator approves or denies.

  • Per-task session_id attribution: the Hermes session id is parsed from task stderr and stored.

  • SQLite audit store records a row for every task, approval decision, and issued token.

  • --yolo is never passed to hermes; approval timeouts and non-TTY dangerous command approvals stay at hermes defaults and auto-deny inside hermes.

Operator CLI

The hermes-mcp-gateway entry point serves the gateway by default and exposes operator verbs. Every verb reads --config like serve does.

Command

Effect

serve (default)

Run the gateway server

clients list

Table of clients: id, scopes, approval flag, caps, workdirs, models

clients hash <secret|->

Print sha256:<hex> of a client secret (- reads stdin)

approvals pending

Rows of task_id, client_id, created_at, prompt

approvals approve <task_id>

Approve and spawn a pending task (no-op if already decided)

approvals deny <task_id> [reason]

Deny a pending task with an optional reason

tasks list [--client ID] [--limit N]

List tasks, newest first

tasks show <task_id>

Full task row plus approval state and output path

tasks cancel <task_id>

Cancel a running task (no-op if already finished)

token issue <client_id> [scopes...]

Dev-only token issuance (requires HERMES_MCP_GATEWAY_ALLOW_DEV_TOKEN=1)

All verbs exit nonzero on an unknown task or client.

Deployment (systemd user unit)

mkdir -p ~/.config/systemd/user
cp deploy/hermes-mcp-gateway.service ~/.config/systemd/user/
chmod 600 ~/.hermes/mcp-gateway/env   # file holds HERMES_MCP_GATEWAY_SIGNING_KEY
systemctl --user daemon-reload
systemctl --user enable --now hermes-mcp-gateway
journalctl --user -u hermes-mcp-gateway -f

The unit template lives at deploy/hermes-mcp-gateway.service; it runs the gateway from the project venv, reads the signing key from ~/.hermes/mcp-gateway/env, and restarts on failure.

Roadmap

  • Command-level HITL via the hermes approval queue (finer than task-level).

  • RS256 / JWKS token verification for stateless, header-only clients.

  • Notification push (webhook/queue) when a task needs approval or finishes.

  • Per-task cost and token evidence sourced from the session store.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Enables policy-governed MCP interactions with deterministic authorization, tenant isolation, minimized PII exposure, and human approval gates for sensitive mutations, while producing structured audit events.
      3
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables agent clients to safely connect to tools and execution resources through MCP with authorization, approvals, audit, chat-context isolation, SSH/Docker access, and long-running command session tracking.
      MIT
    • F
      license
      C
      quality
      C
      maintenance
      Enables stdio-capable MCP clients to run governed enterprise operations tasks, including policy/runbook retrieval and ticket and user lookups or writes. High-risk actions are held for human approval and role-based access is enforced server-side, so clients cannot bypass governance.
      4
      1
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables controlling a Hermes Agent instance from any MCP client, exposing a broad set of Hermes CLI operations over MCP Streamable HTTP with bearer auth.
      MIT