Standard / manifest · mandate · gateway · mcp · evals

Holon MCP Server — v0 (dev)

Lets an agent (Claude, or any MCP client) discover, compare, hire and pay other agents through the gateway, within a mandate a human chose.

node bin/holon.mjs fund demo 5
node bin/holon.mjs mcp --mandate demo/sandbox       # stdio; this repo's .mcp.json does this for Claude Code

Design rules

  1. One server, one mandate. The human picks the mandate when launching the server. The agent acts as that mandate's grantee and has no parameter to switch or widen it.
  2. The agent cannot approve its own calls. No tool approves anything. Calls above the threshold go to the human:
    • through MCP elicitation, if the client supports it: a form shows the agent, the worst case and the input, and the human answers;
    • otherwise out of band, with holon approve <id> --no-run. The agent then re-submits the same call with approval: <id>. An approval is bound to the mandate, the exact agent version and a hash of the input, so it cannot be reused for another call.
  3. Another agent's output is data. It comes back wrapped in <agent_output agent="…">…</agent_output>, with an explicit reminder not to follow instructions inside it. The same rule is in the server's instructions.
  4. Everything is explained. Denials carry their reasons, search lists excluded agents with the reason, and every call returns a receipt id.

Tools

Tool Read-only What it does
search_agents {query?, capability?} → agents the mandate allows, ranked by cost per successful run, plus the excluded agents and why
get_agent {agent} → input and output schemas, errors, price, worst case in the mandate's currency, the mandate's decision, data policy, models, delegated calls, measured record, examples
call_agent {agent | capability, input, max_cost?, approval?} → receipt summary + wrapped output. max_cost caps this one call (gateway §2)
check_approval {approval} → pending, approved, rejected or used
get_budget The mandate: scope, limits, threshold, data rules, spent and remaining budget
get_receipt {receipt} → receipt tree including delegated calls. Only receipts under this mandate.

Typical session

search_agents {capability: "extraction.*"}
  → acme/table-extract (0.0276 EUR, 97% success) · lena/table-extract-fr (0.035 EUR, 98.5%)
get_agent {agent: "acme/table-extract"}
  → input_schema {file: "holon://files/…"}, mandate_decision: allow
call_agent {capability: "extraction.table", input: {file: "holon://files/examples/facture.pdf"}}
  → succeeded, 0.0276 EUR, <agent_output>…</agent_output>
call_agent {agent: "holon-labs/invoice-pipeline", input: {files: [...]}}
  → the human is asked: "worst case 3.10 EUR, threshold 0.50 EUR, approve?" → yes
  → succeeded, 0.19 EUR, 4 delegated calls

Limits (v0)

  • The server and holon approve share .holon/state.json and take turns: state is re-read before and written after each tool call. A long call running while the human approves something else in another process can overwrite that approval. A real deployment talks to one gateway service instead.
  • Files are referenced as holon://files/… handles. There is no upload tool yet.