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
- 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.
- 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 withapproval: <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.
- 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'sinstructions. - 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 approveshare.holon/state.jsonand 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.