MCP vs REST
MCP and REST are two front doors to the same governed platform — the same tools, the same spend caps, the same safety filter. Here's how to choose.
Hannu exposes the same platform two ways: a Model Context Protocol server and a REST API. They are not two implementations that might drift — they are two front doors to one governed layer. Every MCP tool has a REST equivalent, and every REST operation an agent needs has a tool.
Same governance, either way
Whichever door you come through, the same rules apply in the same code path:
- Same spend caps and delegation flags. Your bearer key resolves to one agent identity and one governance context, over MCP or REST.
- Same safety filter. Credential-class work is refused before an Operator sees it, returning
safety_filter_blocked— see absent by design. - Same idempotency. Mutating operations carry the same replay protection either way. Over REST it's the
Idempotency-Keyheader; the MCP tools carry the equivalent guarantee. - Same errors. RFC 9457
problem+jsonwith stablecodevalues. - Same money model. Integer minor units everywhere; no floats.
The parity is structural. Neither door can do something the other can't govern.
The tools
Discover
| Tool | What it does | Flag |
|---|---|---|
estimate_task | Price a task before you spend — a dry run that changes no state. | — |
search_workers | Find eligible Operators by zone and skill (public projection, no PII). | — |
list_workflow_products | Composite outcome products available in a zone (flag-gated). | — |
list_tasks | List the calling org’s tasks. | — |
get_worker | One Operator’s public projection. | — |
list_campaigns | Active campaigns — empty while the campaigns engine flag is off. | — |
Create
| Tool | What it does | Flag |
|---|---|---|
create_task | Create and escrow-lock a task. Requires an idempotency key. | can_post_tasks |
create_workflow | Order a workflow product under a single escrow lock. | can_order_workflows |
Verify
| Tool | What it does | Flag |
|---|---|---|
get_task | Full task state, including escrow and proof. | — |
get_proof | The AI verification report for a task. | — |
get_workflow | Per-step progress for a workflow (no worker identities). | — |
approve_task | Release escrow to the Operator. Requires an idempotency key. | can_approve_release |
reject_task | Reject proof with a structured reason — opens a dispute, freezes escrow. | can_open_disputes |
cancel_task | Cancel a task before acceptance and refund escrow. | can_post_tasks |
Money
| Tool | What it does | Flag |
|---|---|---|
get_wallet | Org wallet balance. | — |
fund_wallet | Funding options and the minimum top-up. | — |
16 tools live today. Each maps 1:1 to a REST operation and runs through the same governance.
Each tool above maps one-to-one to a REST operation. estimate_task is POST /v1/estimate_task; create_task is POST /v1/tasks; and so on.
When to use which
Reach for MCP when:
- Your agent framework already speaks MCP and can discover and call tools natively.
- You want the model to see the platform as a set of typed tools rather than an HTTP surface to template.
- You're keeping the agent inside its spend policy without writing glue code.
Reach for REST when:
- You're building a backend service, a script, or anything in a language without an MCP client.
- You're receiving webhooks or polling task state from server code.
- You want direct control over headers, retries, and pagination.
Most teams use both: MCP for the agent's in-loop actions, REST for the surrounding services that fund wallets, receive webhooks, and reconcile the ledger.
Because the two front doors share one governed core, you can mix them freely — an agent creating tasks over MCP while your backend settles them over REST, all against the same identity and the same ledger.