agent-graph-mcp
agent-graph-mcp is an MCP server that compiles bounded declarative workflow specs to the real agent_graph::AgentGraph runtime. It keeps the original graph_create, graph_execute, and graph_status names and accepts the original V1 graph shape.
Status (2026-07-24): All 28 AG hostile-audit findings closed. 116 tests passing. Daemon + proxy transport verified over Unix socket. Ready for Hermes staging.
Quick Start (Hermes)
# Build and install
# Start daemon
&
# Configure Hermes (already done: hermes mcp add agent_graph --command ...)
# The proxy binary auto-connects to the daemon socket
Architecture
Hermes ──→ agent-graph-mcp (proxy) ──Unix socket──→ agent-graph-mcpd (daemon) ──→ SQLite
stdin/stdout framed Tokio async I/O
- Daemon (
agent-graph-mcpd): Single-process owner with file lock, Tokio async Unix socket listener, SQLite-backed persistence, startup mode enforcement, crash recovery - Proxy (
agent-graph-mcp): Stateless stdin/stdout ↔ framed socket bridge (or--directfor legacy in-process mode) - Socket: 0600 perms, 4-byte BE length prefix + JSON-RPC 2.0 framing
Capability boundary
- Runs are process-local and reported as
volatilewhile active. With--data-dir, terminal projections and explicitly requested deterministic pre-execution checkpoints are persisted to SQLite; uncheckpointed active rows still becomeinterrupted_non_resumableafter restart. - Normal execution is synchronous.
graph_execute {\"mode\":\"async\"}starts a background run that can be inspected and cancellation-requested by run ID. - Cancellation is observed while an LLM future is in flight by dropping the local provider future (best effort). The underlying provider request may still be in flight; terminal cancellation is recorded when the graph observes the interruption.
- With SQLite enabled, terminal write failures remain visible in the run record as
storage_class: \"volatile\"withpersistence_error; no failed write is reported as durable. - Durable integrity-sensitive records require
AGENT_GRAPH_INTEGRITY_KEY_PATHto name a readable external file containing at least 32 secret bytes. The key is never written to SQLite, receipts, or bundles. Without it, checkpoint/resume, durable approval, terminal receipt, and source-witness operations fail closed withINTEGRITY_KEY_REQUIRED. graph_run_start {\"checkpoint\":true}is an intentional pre-execution checkpoint.graph_run_checkpointreads it andgraph_run_resumereserves execution capacity before atomically consuming it once. Resume is available only for a linear chain of deterministicpassthroughand localstate_transformnodes, with SQLite-bound state, budget, graph-version, dependency, cursor, and HMAC-SHA256 checkpoint authentication. This is deterministic local resume, not generic replay.- Unordered parallel writes to the same state key are rejected unless
GraphSpec.reducersdeclares a reducer; sequential repeated writes remain allowed. evidence_requiredrequires durable SQLite-backed local witness IDs and bounded UTF-8 spans. Witness capture stores caller-supplied content only; locators are never fetched, and source authority is never independently verified.- Terminal receipts, checkpoints, approvals, and witnesses use HMAC-SHA256 authentication; their redacted bundles remain
integrity_only. They do not prove an external model call occurred and are not complete replay. graph_run_startaccepts optional positive-integermax_wall_clock_msandmax_nodesbudgets. Requested budgets and observed counters are included in terminal projections and receipts.max_llm_callsis rejected withINVALID_BUDGETSbecause this permitted runtime path has no real LLM invocation hook.- LLM, router, join, parallel, loop, subgraph, external/tool, provider, uncaptured source-witness, and generic replay behavior are excluded from resume. Durable approval is supported only as a SQLite-backed decision over an already-created deterministic-local checkpoint; it cannot execute HumanApproval nodes, arbitrary Hermes tools, shell, filesystem, provider actions, or secret/environment references.
- Crash recovery: Interrupted runs report
interruptedafter restart (neverrunningorcompleted). Checkpoint transactions are atomic — no partial rows after crash. Uncommittedgraph_createrolled back on restart.
Daemon controls
agent-graph-mcpd --data-dir PATH --socket PATH
Environment:
AGENT_GRAPH_INTEGRITY_KEY_PATH Path to 32+ byte integrity key file
- Startup mode (keyed vs keyless) is durable across restarts; flipping modes is rejected.
- Concurrent daemon instances on the same data directory are rejected via file lock.
- Legacy schema variants (missing
executionstable orowner_instance_idcolumn) are safely handled.
Tools (25 available)
graph_create, graph_execute, graph_run_start, graph_run_wait, graph_run_cancel, graph_run_get, graph_run_state, graph_run_events, graph_run_receipt, graph_run_checkpoint, graph_run_resume, graph_list, graph_inspect, graph_render, graph_status, graph_policy_check, graph_approval_list, graph_approval_get, graph_approval_request, graph_template_list, graph_template_candidates, graph_template_instantiate, graph_template_outcomes, graph_source_witness_capture, graph_source_witness_get
graph_approval_decide and graph_delete have been removed from the model-facing tool set (AG-002).
Audit closure
All 28 hostile-audit findings (AG-001 through AG-028) are closed. See agent-graph-mcp/docs/remediation/hostile-audit-closure-ledger.md for the full evidence matrix.
| Gate | Result |
|---|---|
cargo test (lib + daemon_recovery + integration) |
116 passed, 0 failed |
cargo fmt --all --check |
Clean |
cargo clippy -p agent-graph-mcp -- -D warnings |
Clean |
cargo audit adjudication |
8 advisories, all unreachable from binary |
| Daemon MCP lifecycle | initialize → tools/list (25 tools) over Unix socket |
| Crash recovery | Interrupted-run detection, checkpoint integrity, graph_create atomicity |
| Startup mode enforcement | Keyed/keyless flip rejection |
| Process multiplicity | File lock + watchdog reacquisition |
Verification
Evidence artifacts: .hermes/evidence/agent-graph-mcp-lifecycle-*.log, .hermes/evidence/advisory-adjudication.json