mcp server
unitares-host-adapter
Thin client bindings that mount UNITARES governance into agent hosts: Hermes Agent, and OpenAI-compatible clients through a governance proxy
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
{
"mcpServers": {
"unitares-host-adapter": {
"command": "uvx",
"args": [
"unitares-host-adapter"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 21, 2026UNITARES for Hermes
Host integrations for UNITARES, self-hosted accountability infrastructure for long-running AI agents.
UNITARES connects process identities, claims, evidence, reviews, and outcomes in an operator-owned record that survives restarts, context loss, and handoffs. This package connects Hermes Agent and OpenAI-compatible clients to that server through lifecycle hooks or a request proxy.
The default Hermes plugin creates an identity for each active session and reports completed turns. Selected findings, evidence, reviews, and outcomes require explicit agent calls or additional integration. The server provides those capabilities; installing the adapter does not automatically capture them or reconstruct earlier work.
Start with the Hermes setup below. For the broader product and evidence behind its claims, see the UNITARES README and evidence and limits.
Hermes Agent
Coming from the Hermes plugin catalog? Start here. The catalog installs a reviewed commit; a direct repository install can contain newer, unreleased behavior.
| Installation source | Version and behavior |
|---|---|
| Catalog entry, checked 2026-10-14 | 0.3.3, pinned to bf534cf: session identity and fixed turn reports. |
This repository's master | 0.4.0a1, an unpublished continuity candidate: adds lineage links, numeric turn observations, and best-effort presence release. See candidate behavior. |
The catalog page renders the README from its pinned commit. Editing this repository's README does not update that page or change what existing catalog installs run.
Install and enable
You need Hermes Agent 0.21.0 or later and a reachable UNITARES Streamable HTTP MCP server. The plugin does not start a server for you. If you need one, follow the UNITARES Docker install; its default local endpoint is http://127.0.0.1:8767/mcp/.
Install the reviewed version from the catalog UI or CLI:
hermes plugins install unitares
When prompted, set UNITARES_MCP_URL to your server's endpoint, including /mcp/ and its trailing slash. Accept the package dependency installation when Hermes asks; it builds this library and installs mcp and httpx into the Hermes environment. A separate pip install is unnecessary for the directory plugin.
If you skipped configuration, set these values in your active Hermes profile's .env file (normally ~/.hermes/.env):
UNITARES_MCP_URL=http://127.0.0.1:8767/mcp/
# Only needed when your server requires a token:
# UNITARES_BEARER=your-server-token
There is no default server. Hermes checks the required URL before loading the plugin; the library also refuses to send anything while it is unset. The default loopback Docker server needs no bearer token. For a protected server, use a token accepted by its UNITARES_MCP_BEARER_TOKENS setting.
Enable the plugin if you did not enable it during installation, then check its status:
hermes plugins enable unitares
hermes plugins list
The plugin name is unitares, even though the repository and Python package are named unitares-host-adapter. Restart your Hermes CLI process after enabling it. If you use the gateway, run hermes gateway restart.
For deliberate testing of the unpublished candidate, hermes plugins install cirwel/unitares-host-adapter installs directly from the repository. This is a different source from the reviewed catalog pin; check the installed version with hermes plugins list before comparing behavior.
For a server on another machine or in another container, 127.0.0.1 refers to the machine/container running Hermes. Use an address Hermes can reach and configure the server's allowed hosts and authentication as described in the MCP client guide.
Verify it is working
Start a Hermes conversation and complete one assistant turn. On your UNITARES dashboard, look for an identity labelled Hermes Agent and check-in activity after the completed turn. In catalog version 0.3.3, onboarding can happen on session start or lazily at the first turn. In 0.4.0a1, it waits for the first turn so Hermes can supply lineage; merely opening a session creates no server identity. Both versions reuse the binding for later turns while that session remains active in the same process.
Installing this plugin does not add agent-callable tools or a chat command. It reports automatically; a successful install alone does not prove the server is reachable.
What the catalog plugin sends (0.3.3)
| Event | Sent to your configured UNITARES server |
|---|---|
| New active session | A fresh identity request with label Hermes Agent, model type hermes-agent, and a client hint containing the Hermes platform and model name. |
| Completed assistant turn | The fixed marker Hermes assistant turn completed, fixed complexity 0.2, and metadata identifying the report as a host observation (substrate_interpretation). The server-issued session binding accompanies the check-in. |
| Session finalize or reset | Local adapter state is cleared; this version sends no server-side close or presence-release call. |
Default hooks send no user, assistant, or tool text, tool names, arguments, or results. Version 0.3.3 sends no tool counts or duration measurements. Per-tool outcomes remain opt-in. These automatic markers describe host activity; they are not agent-authored reflections or independent evidence that a task succeeded.
Version 0.3.3 has no persisted session-to-identity mapping or lineage declaration. A new process onboards a fresh identity even if it resumes an earlier Hermes conversation.
Continuity candidate (0.4.0a1)
The code on master adds the following behavior. It is not included in the current catalog pin:
- Deferred onboarding:
on_session_startdoes not mint an identity. The first turn binds the session after Hermes has supplied its parent information. - Lineage: when a parent UUID is known, new identities declare
subagent,compaction, orexplicitlineage. A mapped session resumed in a new process becomes an explicit successor. In-place compaction keeps the current binding; unknown parents do not produce invented lineage. - Local continuity hints: up to 200 Hermes session IDs, their UNITARES UUIDs, and timestamps are retained in
<HERMES_HOME>/plugin-data/unitares/sessions.json. Noclient_session_idor proof tokens are persisted. This records ancestry; it does not let a new process act as the predecessor. - Numeric observations: received tool callbacks are counted locally. Turn reports include tool-call and error counts, accumulated tool duration, and elapsed time since the turn-start hook, in milliseconds when available. Counting makes no network call and sends no tool text.
- Presence release: finalize/reset attempts to release server presence when supported, then drops the in-memory binding. The lineage map remains for a later successor.
If the lineage map is missing, unreadable, or its parent entry has been dropped from the bounded history, work continues with a fresh identity. Candidate coverage is exercised in continuity tests; those tests do not establish a successful live rollout.
The candidate remains alpha and unpublished. Before a catalog update, validate one exact revision through clean installation, delegation, resume after finalization, in-place compaction, finalization, and server outage. Earlier soak results from another revision do not establish this candidate's readiness.
Failures and policy actions
In both versions, verdicts are recorded on the server, but the default plugin does not show them to the agent or enforce them. Hook failures are fail-open: Hermes continues after a governance error. The hooks are synchronous, so a slow or unreachable server can still delay a turn. Transport defaults are 10 seconds for connection and 30 seconds for each tool operation; discovery and onboarding may require multiple operations, so these are not a single deadline for the whole hook. After three consecutive failed guarded operations, the adapter stops retrying for that session until finalize/reset clears its failure state.
Troubleshooting
Check hermes plugins list and warnings in your active profile's logs/ directory (normally ~/.hermes/logs/errors.log).
| Symptom | What to check |
|---|---|
| Plugin installed but inactive | Enable unitares, accept dependency installation, and restart the CLI or gateway. |
Missing UNITARES_MCP_URL | Set it in the active profile's .env; restart Hermes so the process sees the change. There is no fallback endpoint. |
| No identity or check-ins | Complete a turn, check the URL and server availability, and inspect hook warnings. Confirm the dashboard is connected to the same server. |
| HTTP 421 / refused Host | Add the hostname and port used in the client URL to the server's UNITARES_MCP_ALLOWED_HOSTS, then restart the server. Version 0.3.2 names this setting in its warning; older catalog pins may only log an exception type. |
| Authentication failure | Set UNITARES_BEARER to a token accepted by your server and restart Hermes. |
| Hook warnings followed by silence | Three consecutive failures open the session's circuit breaker. Fix the cause, then reset the session or restart Hermes. |
| Public tool contract incompatibility | The server must advertise sync_state and either onboard or start_session. Check the server version and advertised tool configuration. |
| No lineage or numeric turn observations | Check the installed version. The reviewed 0.3.3 plugin does not implement the 0.4.0a1 candidate features. |
Let the agent call UNITARES tools
Automatic lifecycle reporting and direct MCP access are independent. If you want the agent to inspect state, write findings, or request reviews itself, also add your server to Hermes's MCP configuration:
# ~/.hermes/config.yaml (use your active profile's config)
mcp_servers:
unitares:
url: http://127.0.0.1:8767/mcp/
tools:
resources: false
prompts: false
This example is for the default local server without authentication. For bearer headers and remote servers, use the MCP client guide. Restart Hermes after changing the configuration. Direct MCP access makes tools available; the agent decides when to call them.
Advanced: manual binding and per-tool modes
The example below targets this checkout's 0.4.0a1 candidate. For a custom Hermes plugin, install this checkout into the Python environment Hermes uses:
python3 -m pip install .
Create a plugin that delegates to the binding. Use this as an alternative to the repository plugin so you do not register duplicate lifecycle hooks:
# ~/.hermes/plugins/unitares/plugin.yaml
manifest_version: 1
name: unitares
kind: standalone
version: 0.4.0a1
description: UNITARES governance lifecycle adapter for Hermes
provides_hooks:
- pre_llm_call
- post_llm_call
- post_tool_call
- on_session_start
- on_session_finalize
- on_session_reset
# ~/.hermes/plugins/unitares/__init__.py
from unitares_host_adapter.bindings.hermes import register as register_unitares
def register(ctx):
register_unitares(ctx)
Set UNITARES_MCP_URL and optional UNITARES_BEARER as above, enable unitares, and restart Hermes.
Per-tool modes require explicit registration and matching hook declarations in the custom plugin manifest:
| Registration option | Add to provides_hooks | Behavior |
|---|---|---|
enable_gate=True | pre_tool_call | Ask governance before a tool call; block on a blocking verdict. Errors remain fail-open. |
enable_ambient=True | transform_tool_result | Append governance annotations to tool results the agent sees. |
enable_outcomes=True | post_tool_call | Send tool success/failure observations. |
For example, after ensuring all three hooks are declared in the manifest (post_tool_call is already present in the candidate example):
register_unitares(ctx, enable_gate=True, enable_ambient=True, enable_outcomes=True)
The default privacy disclosure above applies to light mode. Per-tool modes send additional context: gate and ambient check-ins include tool names and argument previews; outcomes include tool names and status/error metadata. Review these modes before enabling them for your workload.
Other hosts
Claude Code and Codex
Use UNITARES for Claude Code and Codex
for those hosts' installation steps, hooks, and skills. This Hermes adapter
does not install their integrations. Its uhaa helper only exposes
--version and spec.
Any MCP-capable host (explicit-only fallback)
Add your UNITARES server's MCP endpoint (for example http://127.0.0.1:8767/mcp/) to your host's MCP config. No adapter needed for explicit mode; install this package only if you want ambient or gated delivery.
Direct MCP access lets the agent publish selected findings and evidence, inspect its working state, request reviews, and record outcomes. The agent decides when to call these tools. Automatic lifecycle reporting requires a host binding or the proxy below.
OpenAI-compatible clients — Ollama, Open WebUI, Cursor (governance proxy)
For clients that speak the OpenAI-compatible chat-completions protocol but expose no lifecycle hooks, run the governance proxy in front of the model server and point the client's base URL at it. This example pins the same 0.3.3 source revision as the reviewed Hermes catalog entry:
python3 -m pip install "unitares-host-adapter[proxy] @ git+https://github.com/cirwel/unitares-host-adapter@bf534cf031593f785b6022f0edf0fc594c2aa912"
UNITARES_MCP_URL=http://127.0.0.1:8767/mcp/ \
UNITARES_PROXY_UPSTREAM=http://localhost:11434 \
uhaa-proxy # listens on http://127.0.0.1:11435 -> point your client at /v1
The proxy uses one UNITARES identity for the proxy process. It reports requests to /v1/chat/completions; other routes pass through without check-ins. Reports contain the requested model name and message count, rather than conversation text. Multiple clients sharing a proxy also share that identity, so this does not identify each client or agent process separately.
The default UNITARES_PROXY_MODE=observe submits a check-in after the response without blocking the model request. In enforce mode, the proxy checks policy before forwarding and returns a refusal when the server reports a blocking action. Both modes are fail-open on governance errors. The proxy can gate model requests; it cannot intercept tools that the client later executes. Use a host's pre-tool hook for tool-call gating.
Set UNITARES_BEARER if the governance server requires authentication. The model request, including conversation text, is forwarded to UNITARES_PROXY_UPSTREAM; the smaller model-name/message-count summary is what goes to UNITARES. If the proxy cannot onboard at startup, it forwards requests without governance for that process lifetime; restart it after restoring server access.
These reports make runtime activity visible to the operator. They do not establish task correctness, preserve selected evidence, or record reviews and outcomes automatically.
Library delivery modes
| Mode | Who initiates | When it fires | Default depth |
|---|---|---|---|
| Explicit | Agent (via MCP tool call) | When the agent asks | auto |
| Ambient | Host (tool-result hook) | Every tool call | lite |
| Gated | Host (pre-tool-call hook) | Before any tool call | N/A (block or pass) |
These are library capabilities. The default Hermes plugin uses automatic turn reporting, with ambient, gated, and outcome hooks disabled. See SPEC.md for the delivery-surface contract.
Repository map
| Path | Purpose |
|---|---|
plugin.yaml, __init__.py | Installable Hermes directory plugin and runtime entrypoint. |
src/unitares_host_adapter/bindings/hermes.py | Hermes lifecycle hooks and opt-in tool modes. |
src/unitares_host_adapter/bindings/openai_proxy.py | OpenAI-compatible governance proxy. |
SPEC.md | Host-agnostic delivery-surface specification. |
tests/ | Core, transport, binding, and plugin contract tests. |
The UNITARES server owns the durable record of identities, claims, evidence, governed reviews, and outcomes, and returns runtime policy actions at checkpoints. The separate governance plugin packages Claude/Codex hooks, skills, and guidance. This repository supplies host bindings and requires a server for governance operations.
Status
v0.4.0a1 — unpublished alpha candidate. Signatures may change before 1.0.
Version 0.3.3 reads current UNITARES sync_state decision envelopes (action_summary and state_summary) as well as older canonical verdict responses. Opt-in gates respect the final policy action and typed AGENT_PAUSED refusals on later calls; an advisory cold-start pause deferred by policy does not block a tool. Guided decisions remain visible in ambient annotations. Contract fixtures were generated by UNITARES's actual envelope builder at commit f5cb44268, covering minimal, compact, standard, mirror, and full responses. This validates response compatibility; it is not an end-to-end Hermes deployment test.
Supported integrations:
| Integration | Available behavior |
|---|---|
| Hermes directory plugin | Session identity and automatic turn reporting. |
| Custom Hermes binding | Opt-in tool gating, annotations, and outcome observations. |
| OpenAI-compatible proxy | Chat-completion request reporting and optional request gating under one proxy identity. |
| Direct MCP configuration | Agent-initiated access to server tools, independent of the adapter. |
Claude Code and Codex lifecycle hooks are provided by the separate governance plugin. The Python package is installed from GitHub; it is not published on PyPI.