Quickstart
Generate a local signing key, wire Herkos into an MCP config, and run the in-path broker. Allow only the tools you name. Everything else is denied.
You need the herkos binary on your path. If you have not installed it yet, see Install.
1. Generate your signing key
Herkos signs every receipt with a local ed25519 key. keygen writes it 0600 and it stays on your machine. There is no upload step and no account.
$ herkos keygen
2. Wire Herkos in front of a server
register --server rewrites an existing MCP server in your config in place, so the agent launches it through Herkos instead of directly - no un-brokered path is left behind. Name the tools to allow with --allow-tool; the server's command and any env are preserved.
$ herkos register --config .mcp.json --server github --allow-tool get_issue --allow-tool list_issues
Point --config at your agent's MCP config. They all use a top-level mcpServers map, which is what register edits:
| Agent | Config file |
|---|---|
| Claude Code (project) | <repo>/.mcp.json |
| Cursor | <repo>/.cursor/mcp.json or ~/.cursor/mcp.json |
| Cline | ...globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json |
Claude Code prompts you to approve a project-scoped server on first run. Its user/local scope lives in a nested ~/.claude.json that register does not edit yet - for that, use a project .mcp.json or claude mcp add-json. The Cline path is from a community guide; confirm it on your machine before relying on it.
To undo it and restore the original launch line (command, args, and env are put back exactly):
$ herkos unregister --config .mcp.json
3. Run the broker
If your agent launches MCP servers directly, you can also run the broker yourself. serve speaks the MCP stdio wire format and sits in-path in front of the upstream server, so it brokers a real MCP server unchanged. A tools/call to any tool you did not allow is blocked in-path and answered with a JSON-RPC error; an allowed call is forwarded untouched. The agent's session keeps running.
$ herkos serve --allow-tool read_file --allow-tool list_dir -- npx -y @some/mcp-server
4. Keep a signed audit log
Add --receipts <dir> and every brokered tool call is appended to a signed, hash-chained log in a fresh per-session file: an offline-verifiable record of the calls that went through the broker. Editing, reordering, or dropping a record breaks verification. On shutdown the log is sealed and its tip hash is printed, so you can record it and later detect a truncated log. Check it any time with herkos verify --pubkey, no network or service needed.
$ herkos serve --allow-tool read_file --receipts ~/.herkos/audit -- npx -y @some/mcp-server
Verify a sealed log against the public key serve printed on startup. A cleanly closed log reports VERIFIED; one with its tail chopped reports INCOMPLETE and exits non-zero.
$ herkos verify --file ~/.herkos/audit/<session>.jsonl --pubkey <hex>
On Linux, add --isolate to run the upstream in a network namespace with no route out. It can still speak MCP to Herkos over stdio, but it cannot open its own socket to any host - so the broker is the only way out. Use it for servers that do not need their own outbound network. Unprivileged; see the security model.
5. Audit and read receipts
Scan an MCP config for over-scoped tools, poisoned descriptions, and servers with unrestricted egress. Compare against a baseline to catch drift.
$ herkos scan --config mcp.json --baseline baseline.json
The scan prints a one-line summary like this:
herkos scan: 0 over-scoped tools, 0 poisoned tool-descriptions, 1 servers with unrestricted egress - your code never left this machine
The scan summary is a status line, not a signed file. The Merkle span receipt is a different artifact, the JSON written on the select path that records which spans touched the model. herkos receipt summarizes one of those, printing its root, enforcement mode, and span count:
$ herkos receipt --file receipt.json
To check a receipt or an audit log cryptographically against a public key, use herkos verify --pubkey (shown above). It is the only command that verifies a signature.
By default the broker gates the tool name of outbound tools/call only: it does not inspect arguments or gate other methods. With a served set pinned (--served-span plus --index) it also blocks arguments carrying verbatim repo lines from outside that set. It normalizes case and whitespace first, so a reflow or recase of a served line still trips it; encoding, paraphrase, or splitting a line across calls still defeats it. Treat it as a userspace tripwire, not a wall. --isolate cuts a server's own outbound network at the kernel. Read the security model before relying on any of it for something sensitive.
Next
Read Concepts to understand SpanGate and receipts, or jump to the full CLI reference.