clermes-mcp
Exposes a Clermes worker fleet as typed tools over HTTP and stdio, enabling a coordinator to drive the fleet with structured tool calls.
README
clermes-mcp
An MCP server that exposes a Clermes worker fleet as typed tools over HTTP and stdio.
Clermes is a file-based coordination harness for a fleet of long-lived coding-agent workers. The bash dispatcher at canopy-workshop/clermes is the source of truth for tmux and session state. clermes-mcp is a thin Python shell over that dispatcher, so a coordinator that speaks MCP (Hermes, Claude, an editor MCP client, anything) can drive the fleet with structured tool calls instead of scraping panes and writing poll loops.
clermes-mcp is an enhancement, not a requirement. The clermes CLI is fully usable on its own. This server is the integration layer that makes a Clermes fleet a first-class citizen in multiagent workflows.
The reference worker is Claude Code. The reference coordinator is Hermes. Any other coding agent (Codex, Aider, antigravity, opencode) and any other MCP-speaking coordinator fit the same harness. Nothing about the protocol or this server is agent-specific.
What you get
- Typed read tools for fleet inventory, pane capture, lock and dispute inspection.
- Typed action tools (operator role only) for dispatch, respawn, reply, halt, spawn, kill, fleet-wide heal.
- Blocking or async per call. The client picks. Blocking returns the done file inline. Async returns a job id and the caller polls.
- Auto-heal before send. If a worker pane is in bash, dead, or some other state, dispatch kills and respawns it before sending.
- Anti-compact resend. After dispatch, the server watches for the conversation-compacted-then-idle pane state and re-sends the brief once if it sees the swallow signature.
- Role gating.
operatorexposes the full surface.workerexposes read tools only. A worker-role MCP client cannot see dispatch or kill at all. The gate is structural: the action tools are never registered in that role. - No outbound to humans. The server never exposes a tool that contacts humans. I treat that as a fixed invariant of the project. Don't fork it back in.
Install
pip install clermes-mcp
You also need:
- The
clermesbash dispatcher on your PATH (or at$CLERMES_HOME/clermes). tmuxandjqon the host running the worker fleet.- A worker fleet (Claude Code, or any equivalent CLI agent with an interactive TUI).
Configure
Everything resolves from environment variables. Defaults work for a typical install at ~/.clermes.
| Setting | Env var | Default |
|---|---|---|
| Clermes home | CLERMES_HOME |
~/.clermes |
| Dispatcher bin | CLERMES_BIN |
$CLERMES_HOME/clermes, then $(which clermes) |
| Bind host | CLERMES_MCP_HOST |
127.0.0.1 |
| Bind port | CLERMES_MCP_PORT |
9675 |
| Bearer token | CLERMES_MCP_TOKEN |
unset (server warns on HTTP transport) |
| Role | CLERMES_MCP_ROLE |
operator |
| Default mode | CLERMES_MCP_MODE |
blocking |
If $CLERMES_HOME/voice-preamble.txt exists, its contents prepend to dispatches with public_artifact=true. Otherwise a neutral default applies. The preamble is the right place to put your repo's voice rules. Don't bake them into the server.
config.yaml under $CLERMES_HOME is read if present, for the paths.home override only. Every other field is informational.
Run the diagnostic check:
clermes-mcp doctor
It verifies paths, the dispatcher, the registry, and protocol directories.
Run
HTTP (recommended for multiagent integration):
clermes-mcp serve --transport http --host 127.0.0.1 --port 9675
stdio (for local subprocess clients):
clermes-mcp serve --transport stdio
To inspect the schema for every tool:
clermes-mcp tools
Run as a service
Drop the unit file at examples/clermes-mcp.service into ~/.config/systemd/user/ and enable it:
systemctl --user daemon-reload
systemctl --user enable --now clermes-mcp
journalctl --user -u clermes-mcp -f
On systems where user-systemd lingering is unreliable (WSL across wsl --shutdown, some headless setups), use whatever your platform's session-supervisor of choice is. A simple cron @reboot line works too. tmux is a last resort because the MCP server has no TTY needs.
Wire into a coordinator
The reference is Hermes:
mcp_servers:
clermes:
url: "http://127.0.0.1:9675/mcp"
headers:
Authorization: "Bearer ${CLERMES_MCP_TOKEN}"
timeout: 1800
connect_timeout: 30
A 30-minute timeout lines up with the blocking ceiling on long dispatches. For async use, the request returns immediately with a job id and the timeout can drop to anything.
Other MCP-speaking coordinators wire in the same way.
Tool surface
Read tools (every role):
list_workers(): flat list of{name, state, alive, locked, task_id?, workdir}.fleet_snapshot(): full per-worker pane text and classification.capture(worker, lines=80): pane tail with classification.worker_health(worker):claude | bash | dead | other:<proc>.list_open_tasks(): lock files joined with the assigned-task map.read_dispute(task_id): raw markdown of a dispute file, or null.read_result(task_id): parsed JSON of a done file, or null.list_done(limit=50): recent completed task ids.list_jobs() / job_status(job_id) / job_result(job_id): async job plumbing.
Action tools (operator role only):
dispatch(worker, brief, slug?, wait=true, mode=blocking, timeout=1800, public_artifact=false, auto_heal=true, anti_compact_resend=true): the headline tool.respawn(worker): kill then spawn (the dispatcher'shealis fleet-wide; this is the single-worker equivalent).spawn(worker) / kill(worker) / heal_fleet(): direct dispatcher wrappers.reply(worker, message, wait_for_task_id?, mode=blocking, timeout=1800): send without a newTASK_IDfooter. Use to answer a dispute or select an injection-dialog option.halt(task_id): touch the halt file so an announced action does not proceed past its grace window.
Security model
- Bind localhost by default.
127.0.0.1:9675. Don't bind0.0.0.0without a reverse proxy and a token in front of it. - Bearer token auth on HTTP. Set
CLERMES_MCP_TOKENand require it on every HTTP request. Without it the server logs a warning at startup and accepts anything. - Role gating.
CLERMES_MCP_ROLE=workerstrips every action tool from the registered surface. A worker-role MCP client cannot see, let alone call, dispatch or kill. - No outbound to humans. Nothing in the tool surface contacts email, SMS, agencies, webhooks, or chat. Adding one breaks the threat model of this project; don't do it.
- No
shell=Trueanywhere. All subprocess calls pass argv as a list. Briefs are arbitrary text and cannot escape the process boundary. - Token redaction in error strings surfaced to the client.
Layout
clermes-mcp/
├── README.md
├── LICENSE
├── pyproject.toml
├── .env.example
├── src/clermes_mcp/
│ ├── __init__.py
│ ├── __main__.py CLI entry point
│ ├── server.py FastMCP app, tool registration, transport wiring
│ ├── dispatcher.py async subprocess wrapper around the bash CLI
│ ├── protocol.py file I/O for done/dispute/announce/halt/locks/assigned
│ ├── pane.py pane-text classification heuristics
│ ├── jobs.py in-process async job registry
│ ├── config.py env + optional config.yaml loader
│ ├── doctor.py diagnose paths, dispatcher, deps
│ └── models.py pydantic schemas
├── tests/ pytest suite, all hermetic against the stub
├── examples/
│ ├── stub-clermes fake dispatcher for CI and demo
│ ├── clermes-mcp.service systemd --user unit
│ └── hermes-config.snippet.yaml
└── docs/PROTOCOL.md generic coordination contract
Testing
pip install -e ".[dev]"
pytest
ruff check src tests
Every test runs against examples/stub-clermes. No live fleet, no tmux. CI on its own can validate the full server surface.
Status
Pre-1.0. The tool surface is stable enough to ship, but expect minor breakage in tool names and arg shapes until the integration with at least two coordinators settles.
License
MIT.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.