Hermes MCP Gateway
Provides integration with the Hermes agent platform, exposing a curated allowlist of Hermes tools such as web search/extract, browser automation, vision analysis, and skill lookup, along with Hermes/Honcho memory operations, while excluding shell, filesystem, and task-management tools.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Hermes MCP Gateway
Single localhost-only MCP endpoint that aggregates native Hermes execution, a strict Hermes tool allowlist, Samchon Graph, guarded capabilities and Honcho memory through progressive tool disclosure without patching upstream source.
Endpoint
MCP:
http://127.0.0.1:3060/mcpProcess health:
http://127.0.0.1:3060/healthzFinal-cutover readiness:
http://127.0.0.1:3060/readyz
healthz is a local liveness check that never calls providers. readyz requires the curated native tools, web provider, Samchon Graph, LSP adapter, guarded capabilities, Honcho and startup files. The catalog is frozen until restart. Modern MCP 2026-07-28 HTTP is sessionless: execute_code uses an independent server-generated owner per request. Browser, direct terminal and process_manage require a validated legacy SDK session or a gateway-issued session_token; raw client headers and caller-provided owner IDs never grant ownership. Modern clients should discover session_open, call it once, and pass its returned token as the top-level tool_call.session_token on calls that need browser/terminal/process continuity. Tokens are random, revocable, expire after 15 minutes, and are capped at 256 active capabilities. session_close revokes the capability, kills only its owner's native processes, and drops only its local browser binding. Independent shell pipelines can use execute_code with hermes_tools.terminal without a separate Gateway confirmation parameter.
Related MCP server: OpenAI-Compatible MCP Gateway
Tool policy
Native direct tools bind Hermes' existing session ContextVars inside the request worker, so terminal cwd/environment and process ownership remain client-scoped. Per-call hook IDs are independently generated; they distinguish concurrent executions without granting resource ownership or weakening approval hooks.
HTTP disconnects/timeouts kill and reap native execution worker trees, including tracked descendants in separate process groups. The Gateway never retries execution. Other thread-backed native tools retain best-effort cancellation: cancellation is not rollback. Arbitrary Python has the service user's privileges; this is not an OS sandbox.
tools/list exposes only six tools: tool_search, tool_describe, tool_call, startup_context, memory_context, and skills_list. Deferred tools are available only through the validated one-call discovery bridge. Search uses Hermes native BM25 over the frozen catalog; descriptions expose authoritative input schemas.
Hermes is default-deny and may expose only:
web_search,web_extractvision_analyzeskills_list,skill_viewnative filesystem:
read_file,write_file,patch,search_filesnative code:
execute_codethrough isolated per-request worker processesnative terminal/process:
terminal,process_managemedia:
image_generate,video_analyzeCamofox-compatible native browser tools:
browser_navigate,browser_click,browser_type,browser_press,browser_snapshot,browser_scroll,browser_back,browser_get_images,browser_console,browser_vision
The gateway does not expose browser_exec, browser_cdp, computer_use, raw Hermes memory/todo state, TTS, or Kanban tools. session_search, delegate_task, and cronjob are exposed only through gateway-owned guarded adapters, not through the stateless Hermes allowlist.
Hermes Agent also uses the existing read-only LSP adapter directly through a separate stdio MCP entrypoint: python -m hermes_mcp_gateway.lsp_stdio. It exposes only lsp_diagnostics, lsp_hover, lsp_definition, lsp_references, lsp_document_symbols, and lsp_status. The same project-root allowlist, manual-only language-server installation policy, and LSP workspace trust rules apply. This is a native Hermes MCP connection, not a loopback call into the ChatGPT Gateway.
Samchon Graph is exposed as one inspect_code_graph tool. The caller supplies an absolute cwd; the gateway resolves it inside the allowlisted work/source roots and reuses a bounded resident MCP session per project root. The upstream MCP surface must contain exactly that one graph tool.
Guarded Hermes capabilities are:
session_search— read-only search over the local Hermes session database. Cross-profile override is intentionally unavailable; results are historical conversation context, not proof of current external state.delegate_task— the long synchronous Gateway path is rejected before model inference. Use supported native Hermes automation through a prepared background job instead of holding an MCP response open. Hermes' own native delegation remains unchanged.cronjob— read-onlylist, plus guardedcreate,update,pause,resume,remove, andrun. Mutations use host-side permission controls. Model/provider/base-URL overrides and script/no-agent/monitor execution fields are not exposed; delivery defaults tolocal.
The catalog exposes exactly six public tools. Native Git worktrees replace the retired coordinator; no optional coordinator service is needed. No tools are dynamically added to the catalog during a session; a Gateway restart refreshes discovery. A new ChatGPT MCP connection may be required to refresh the public schemas.
Gateway-owned startup tool:
startup_context— reads only the four fixed Hermes startup files (.hermes.md,SOUL.md,MEMORY.md, andUSER.md). It accepts no path and is not a generic filesystem surface.
Startup readiness performs the same bounded, no-follow read as the tool, including UTF-8 and serialized-output validation. Both content and the JSON envelope must fit their configured budgets; an oversized envelope fails explicitly rather than returning a successful but cut JSON document. The read-only LSP stdio entrypoint also redacts sensitive text and bounds output; oversized results carry a valid JSON truncation receipt.
Memory tools are:
memory_profile(read-only)memory_searchmemory_contextmemory_reasoningmemory_conclude
Memory identity is resolved through Hermes Honcho configuration. The existing workspace=hermes and user peer are preserved; only this adapter's assistant peer is chatgpt. Conclusion writes require a durable kind (preference, decision, architecture, project_state) and reject secret-like or explicitly temporary content. List/delete operations retain Honcho semantics.
Execution Guard
Direct MCP terminal is restricted to short foreground commands: at most
30 seconds, with timeout=30 explicitly supplied to Hermes if omitted.
Any direct background request, PTY mode, foreground request above the cap,
or background-only notification/persistence option fails before execution
with LONG_RUNNING_OPERATION_REQUIRES_JOB. Use job_start for build,
test, deploy or other potentially lengthy work. Native terminal enforces
its subprocess deadline; cancelling only a Python thread would not safely
stop its child processes, so the gateway deliberately does not use
asyncio.wait_for(to_thread(...)) as a hard-kill mechanism.
execute_code retains its isolated worker/process-tree cleanup and now
has a 30-second total deadline, including queue wait. Neither tool's
timeout rolls back effects already performed. Tool selection remains the
agent's choice, but an incorrect long/background choice is rejected rather
than silently started unrecoverably. The dedicated job adapter is exempt
from these direct terminal restrictions.
Backend budgets and request diagnostics
Host resource enforcement
Production sets HERMES_MCP_RESOURCE_POLICY to the bootstrap-managed, non-secret
root-owned /etc/hermes-mcp-gateway-resources.json policy. Missing or invalid
configured policies fail closed; leaving the setting unset retains the legacy
development/test mode, not a production protection.
The existing native terminal remains the job executor. A Gateway-owned systemd
user scope applies limits before executing each job, under hermesjobs.slice;
short execute_code workers use the separately capped hermesshort.slice.
Neither critical service belongs to these workload slices. This is cooperative
resource management, not a security sandbox for arbitrary same-UID code.
job_prepare accepts optional resource_profile="light"|"heavy" (default
heavy). The host fixes profile limits; active memory reservations, one-heavy
admission and host headroom may reduce the existing four-job quota. A rejection
does not execute the command. Unknown work keeps its reservation and workspace
quarantine; it is never replayed automatically.
Under enforcement, direct foreground terminal fails before execution with
RESOURCE_ISOLATION_REQUIRES_JOB. Wrapping that stateful native path would
silently break cwd/environment continuity. Use execute_code with
hermes_tools.terminal for short independent commands, or prepared jobs for
longer work. Native session semantics are unchanged in legacy development mode.
readyz.job_admission reports resource capability separately from control-plane
readiness. A resource outage must reject new work without provoking a Tunnel
reconnect loop. HTTP/session disconnects do not cancel accepted jobs; controlled
Gateway shutdown drains then stops owned scopes. Restart survival with complete
output/exit recovery is not promised. Scope inactivity and exit code 137 alone
are not proof of command success or OOM respectively.
The 30-second worker limit is not a universal tool deadline. Hermes MCP reads
and LSP RPCs use their configured 30-second budgets; Graph has a separate
120-second call budget. Camofox owns its browser.command_timeout HTTP budget
(default 30 seconds); auxiliary vision uses native download/provider budgets
and bounded retries. Several backend steps may run sequentially, so these are
not promises that the entire browser/media call ends within 30 seconds.
Gateway cancellation does not forcibly kill thread-backed native handlers.
Those handlers remain counted until actual completion, including after an HTTP
disconnect. Long synchronous Gateway delegation is rejected before inference.
Honcho workers share the same completion tracking, including after a memory
timeout. A timed-out memory mutation reports state=unknown: an early readback
that finds no record does not prove the original worker stopped, so never replay
it before completion and reconciliation. Session-owned native work retains its
owner lease until actual completion; revocation cleanup follows that completion.
Request telemetry records generated request IDs, tool, elapsed time and result category. A validated inbound request ID is correlated by a truncated SHA256, not logged verbatim or used for authorization. Arguments, commands, recovery credentials and raw headers are excluded. Compare these events with Tunnel metrics; an empty-poll timeout is not itself proof of a failed tool request.
Resumable background jobs
For builds, tests and other long commands use the two-phase deferred protocol:
Open an interactive capability with
session_open.job_prepare(command, workdir, max_runtime?, idempotency_key?, resource_profile?)durably freezes the request and returnsjob_idplus a one-timerecovery_token. No command executes during preparation.Save both values outside Git in a private, owner-only recovery file before continuing. Do not put recovery tokens in logs, durable memory or chat prose.
job_start(job_id, recovery_token)with a valid interactive session starts only that frozen request. It no longer accepts a command or workdir.After any missing start response, use the same credential with
job_statusfrom a new HTTP connection. Repeating an authorized start cannot relaunch it.
Preparation accepts an allowlisted workdir, an optional random idempotency key
(16–128 characters) and max_runtime of 1–7200 seconds (default: 1800).
Unused preparation is bounded and expires; it does not reserve active capacity
or lock a workspace. Active admission happens atomically at start. Work still
uses Hermes terminal(background=true, persist_on_release=true); the Gateway is
not a second executor. The background deadline is enforced by bounded
maintenance/termination, not an exact wall-clock kill guarantee.
Parallel agents: Four jobs globally, at most two per verified MCP session. Admission is atomic in SQLite even when two Gateway instances race. Active jobs cannot use the same or nested working directories: create a separate Git worktree for each agent, even when working on the same repository. Status/cancel synchronize per job, so a slow native poll cannot block an unrelated job. A full quota or busy workspace returns an explicit error, not an unbounded queue. The per-session allowance is not a durable per-person quota: a new session gets a fresh identity. Enforcing limits across all sessions for one person would require a trusted stable principal from the authenticated ingress. Interactive terminal, browser, Git remotes, databases, and manual filesystem changes are not workspace-locked by this job admission mechanism; coordinate shared operations separately.
job_status and job_cancel authorize using the job credential alone; an
unrelated expired interactive session token cannot block recovery. This does
not relax session validation for prepare/start, browser, terminal or process
tools. A session's fixed 15-minute expiry does not kill an accepted job.
The ID alone grants no access. SQLite stores only the recovery token's hash,
the temporarily needed prepared command, and bounded redacted output in a
0600 database. The command payload is discarded when start is admitted.
States include prepared, starting, running, succeeded, failed,
cancelled, timed_out, expired and unknown. Completed receipts are retained
for seven days; recovery before finalization also depends on Hermes' native
process/result retention.
Never blindly retry push, deploy, migrations or other mutations. A duplicate preparation returns the earlier ID/state, not its token. If the preparation response is lost, no start has yet been authorized by this client: inspect the duplicate's state before preparing again with a new key. Once start was issued, use the previously saved credential; never substitute a new request/key merely because the response is missing. Existing legacy receipts remain recoverable. Idempotent launch admission does not promise exactly-once external effects.
Gateway restarts may terminate live processes with their systemd cgroup.
A newly started Gateway can recover durable receipts and query Hermes'
native process registry if the underlying process still exists, but it
must report unknown when actual completion cannot be established.
An unverifiable unknown remains a capacity/workspace quarantine even after its
deadline. Reconcile it against the job-owned native process and external target;
do not label it succeeded or free its workspace without evidence. Deployment
must abort rather than force-cancel these jobs. This mechanism cannot force a
paused ChatGPT client to resume, or guarantee live work survives a VPS outage.
Original terminal calls are not resumable jobs.
Operator admission and deployment
The local-only scripts/job_admission.py supports status, drain, resume
and consistent SQLite snapshot. It is not exposed over MCP. Run it as the
database owner, with --database /home/hermes/.hermes/gateway-jobs.sqlite3.
drain and resume also require the same private --owner-token (32–128 safe
characters). The gate claim is atomic, stores only the token's hash, and refuses
to release another operator's pause; status never returns ownership tokens.
Keep database and snapshot paths under trusted-owner directories without
group/world write access. Unsafe parents and symlinks are rejected before
SQLite opens either path.
Draining pauses fresh starts atomically while recovery and authorized duplicate
starts remain available. It waits for starting/running/unknown jobs; on timeout
it fails closed and leaves admission paused for the deploy owner to restore.
Prepared but unstarted requests do not block drain. Never restore an old job
snapshot over live receipts as an ordinary rollback step.
The bootstrap repository owns the scoped deployment and host lock. It stops
Tunnel ingress, takes a consistent backup, drains jobs, then checks the cheap
/healthz.inflight_requests and inflight_native_calls counters before restarting
Gateway. Native threads remain counted after an HTTP waiter is cancelled; a zero
handler count alone does not prove the native work stopped. Legacy Gateways
without that counter require explicit operator acknowledgment rather than a
false claim that foreground work was measured idle. Health/readiness success
alone does not prove the actual ChatGPT control-plane route.
Native execution limits
Discover and describe execute_code, then call it through tool_call with code. The Gateway does not require a redundant client-supplied confirmation flag: user consent is handled by the ChatGPT host. This is not authorization proof at the MCP transport; access remains restricted to loopback and the authenticated Tunnel Client. The Gateway's allowlists, owner isolation, and resource limits remain in force.
Every call invokes unmodified upstream Hermes execute_code inside a new Linux worker. A child subreaper keeps double-forked descendants owned until cleanup. Interpreter state does not persist between Gateway requests; reset is accepted for native schema compatibility but each worker already starts fresh. The native whole-script approval guard runs in a request-bound context; the callback grants only the dispatched script once, and denies further approval requests. No session/always/YOLO grant is installed. Existing operator approval configuration still applies.
Limits: 64 KiB UTF-8 code, two concurrent workers, 30-second total deadline including queue wait, 1 MiB per worker stdout/stderr transport stream, and 65,536-character redacted Gateway output. Native defaults additionally cap tool calls at 50 and stdout at 50 KiB; configured native limits can be stricter. Child environment scrubbing and the explicit native RPC allowlist remain active. Only read_file, write_file, search_files, patch, foreground terminal, web_search, and web_extract are granted over RPC. Direct Python imports/subprocesses are not restricted by that allowlist and can access user files; execution is not a security jail. Context Mode indexing/search is intentionally not emulated.
Browser
The unified ChatGPT gateway exposes the 10 Hermes native browser tools that are available in the pinned Camofox mode. The gateway subprocess uses the same HERMES_HOME=/home/hermes/.hermes and inherits CAMOFOX_URL=http://127.0.0.1:9377, so ChatGPT and Hermes Agent share the same Hermes-managed persistent Camofox userId/profile. Tool calls still use Hermes/Camofox task-session semantics rather than a second browser profile. browser_exec and browser_cdp remain absent because the pinned Camofox backend does not provide those Hermes backends.
Web prerequisite
Hermes natively supports web_search and web_extract through its managed Nous Tool Gateway using the Firecrawl provider. The gateway does not fabricate these schemas and does not implement a second web stack.
The narrow upstream-supported activation path is:
Authenticate the existing Hermes profile with
hermes auth add nous --type oauth --no-browser. This adds Nous OAuth state without requiring the default inference provider to switch to Nous.Select the managed web backend in Hermes config:
web: backend: firecrawl use_gateway: true
Hermes may advertise the web_search/web_extract schemas as soon as the managed backend is selected, even before Nous authentication is usable. The gateway therefore performs one real web_search and one real web_extract smoke call at startup and treats nested provider errors as not-ready. /readyz becomes 200 only when those calls succeed; otherwise the process stays degraded and tunnel cutover is forbidden. Provider/auth changes require a gateway restart so readiness and the MCP schema remain stable for the process lifetime.
Tests
Startup tests use temporary job-state directories and close their background
maintenance tasks. Never point test fixtures or staging listeners at the live
job database; test_startup_state_isolation.py guards this boundary.
PYTHONPATH=src:/srv/agents/src/hermes-agent \
/home/hermes/.hermes/venvs/hermes/bin/python -m unittest discover -s tests -vLocal integration gates before tunnel cutover:
Modern sessionless HTTP
execute_codesmoke: no confirmation field required, native file/search/terminal RPC succeeds, requests do not share state, cancellation kills native descendants.vision_analyze,skills_list, native file/terminal/process_managetools,image_generate,video_analyze, and the exact 10 Camofox-compatiblebrowser_*tools; explicit absence ofcomputer_use,browser_exec, andbrowser_cdp.Guarded capability checks: real
session_search, read-onlycronjob list, and fail-fast synchronous Gateway delegation without model inference.Honcho profile/context/search and controlled
memory_concludecreate/readback/delete.Gateway MCP initialize + exact six-tool
tools/list, lexical search + describe, denied direct hidden calls, and representativetool_callcalls covering LSP, Camofox browser navigation/snapshot, and cwd-scoped Samchon Graph.healthzandreadyzreadback, including Samchon Graph readiness.systemd restart and enabled-state readback.
Keep Tunnel Client
mainpointed only at3060/mcp; its historical profile name is an identity label, not a dependency. Retire old components only after readiness and native execution gates pass.
systemd
The repository ships systemd/hermes-mcp-gateway.service. It uses Wants/After rather than hard Requires, binds the application itself to loopback, imports the same Hermes runtime environment files, and keeps upstream failures from cascading through systemd dependency teardown.
Native Git worktrees
Coding agents use Git's built-in worktree commands directly in their own terminal sessions. No task coordinator, workspace MCP tools, or separate database is required. Each agent works in a unique branch/worktree and must preserve uncommitted or unpushed changes. Worktrees isolate Git state, not OS-level filesystem access.
This server cannot be deployed
Related MCP Connectors
Cross-tool persistent memory and context for AI assistants over MCP.
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA single MCP server that gives Claude, ChatGPT, Codex, and any MCP-compatible AI access to the same personal context via two tools: context_get and context_log.1MIT
- FlicenseNot gradedqualityDmaintenanceLocal MCP server that exposes fixed tools for GPT, Claude, and Gemini while routing to any OpenAI-compatible chat completions backend with independent configuration per target.1-
- FlicenseNot gradedqualityDmaintenanceAggregates multiple MCP servers and custom Python tools behind a single endpoint, with intelligent context and tool discovery for AI agents.-
- AlicenseNot gradedqualityCmaintenanceProvides a local context-memory layer for AI assistants, enabling retrieval-augmented queries, explanations, feedback, and status checks via MCP tools.1Apache 2.0