Boundra · Payment approval gateway for AI agents
[Boundra on mcprush — Grade A, Trust 95/100]
Boundra (boundra.io) — Boundaries for agent payments.
The boundary layer for agent payments: before any money moves, answer
"should this payment happen at all?"
Our thesis: the opportunity in agent payments is not "how to pay" (protocols
solved that) but "whether to pay."
One natural-language rule → compiled into a policy → every payment the agent
attempts is genuinely evaluated → allow / ask a human / veto, with a full
audit trail.
Two run modes:
- Offline simulation (
demo.py): stdlib only, self-contained mock merchant
and wallets, zero dependencies, zero network
- Real protocol (
demo/demo_real.py): standard MCP server + real x402 SDK +
Base Sepolia testnet
Data flow
[Boundra data flow]
Private keys stay with the user; the gateway is read-only; optional on-chain
commits contain hashes, never policy plaintext. Hosted MCP stores the signed
policy document you submit; self-hosted mode keeps it local. Revocation is free
— forever, no exceptions.
Integrating Boundra into your agent? See
docs/INTEGRATION.md — hosted API, fail-closed Python
and TypeScript x402 SDKs, two-phase budget settlement, and MCP paths.
See it run in 60 seconds
The complete flow, step by step
Zero to a signed, enforced policy in ~10 minutes. No accounts, no dashboards —
your wallet key is your identity.
0 · Try the hosted API (30 seconds, nothing to install)
1 · Bind your identity — the wallet is the account
Creates or imports a Base wallet. No signup, no email — the private key never
leaves your device, and your address is your identity everywhere in the
system.
2 · Set your policy
The wizard offers templates (personal assistant / travel / dev API /
procurement) or lets you write your own rule in plain English, then compiles
it and shows you exactly what will be enforced — before anything is signed.
3 · Sign & publish
You sign the policy document with your wallet key (EIP-191). It is published
as a versioned, hash-chained document. The default commitment is a local hash
log; Base Sepolia anchoring is optional. From this moment the gateway is
read-only for every agent — changing the policy without your key is impossible.
4 · Mount the MCP server into your agent
Hosted (zero install, multi-tenant, default-deny until you publish a signed
policy):
Or self-hosted:
5 · Every payment gets a verdict before signing
Your agent calls evaluate_payment; the 5-stage pipeline answers
ALLOW (sign & settle) / DENY (aborted pre-signature, zero on-chain
trace) / ASK (a challenge bound to this exact payment).
6 · When the agent asks, you decide
Paste the ASK challenge, sign it on your device — the agent retries with the
signed approval token. Forged, rebound, or replayed tokens are rejected.
7 · Watch, update, revoke
get_spend_report / get_audit_trail / get_policy_versions keep you in
control day to day. Every policy change is a new signed version
(set_policy); revoke_policy is instant default-deny and free forever.
Quick start (from source)
Architecture: where the gateway stands
Key finding: x402 SDK v2 natively provides the on_before_payment_creation
hook plus register_policy / set_spend_controls — the policy layer is not a
bolt-on; it is the slot the official protocol stack reserves. This validates
the wedge.
File map
Signed policies: the root of trust is the user's key, not the gateway's database (v2)
A policy is a document signed by the user's wallet, not a row in the
gateway's configuration:
- Read-only for agents: without the user's private key,
set_policy always
fails — impersonation, unsigned, and tampered submissions are all blocked
(seven scenarios in demo/demo_policy.py)
- Two stacked scopes: user-level (rules for all agents) × agent-level
(per-agent rules); the strictest verdict wins
- Every version bump is a signature: v2 must reference v1's hash; tampering
with any historical version → signature invalid + chain broken
- Privacy shape: optional on-chain commitments contain only hashes. Hosted
MCP stores the signed policy document submitted by the user; self-hosted mode
keeps policy plaintext on the user's device
Run: .venv/bin/python demo/demo_policy.py
Verdict credentials: every decision comes with a signed receipt (v4)
Every evaluate_payment response carries a credential — a
boundra.verdict/v1 receipt signed by the platform key (EIP-191). It answers
"who can prove this ALLOW / DENY / ASK actually happened, under this policy,
for this exact payment intent?"
- Binds the intent and expectations:
intent_hash covers the legacy
{amount, recipient, purpose} plus any supplied quote / expectation fields
(expected amount/payee, resource, method, network, asset). The credential also
carries explicit quote, expectation, and expectation_source fields
- Binds the policy:
policy_refs lists the policy version hashes used,
comparable against local or optional on-chain anchors
- Binds evaluation state:
audit_id, evaluation_id, and
reservation_status link the decision to its audit and budget lifecycle;
the secret reservation token is deliberately excluded
- Verifiable offline, by anyone: strip
proof, canonicalize the payload
(sorted keys, compact separators), recover the EIP-191 signer — it must
equal issuer and the platform address
0xF30955B6Be768370Da13fca237A5f252F6081d1C (the same address that receives
x402 revenue — one identity for signing and settlement). Published at
GET https://api.boundra.io/verdict-key.
Self-hosted gateways attach no credential unless BOUNDRA_VERDICT_KEY is set —
unsigned mode stays fully backward compatible.
Two-phase budget accounting
For hosted calls with an owner, ALLOW atomically reserves budget in SQLite and
returns evaluation_id plus a private reservation_token. After the real rail
settles, call POST /evaluations/{id}/settle with the transaction reference. If
payment fails or is abandoned, call /release to restore the allowance. Tokens
are SHA-256 hashed at rest and never enter audit logs or signed credentials.
Unconfirmed reservations expire after 15 minutes; duplicate settlement is
idempotent and cannot spend the same reservation twice.
MCP server tools
Mount into Claude Desktop
One line — uvx resolves dependencies and starts the server:
On first run, use the boundra-init wizard (same package): create/import a
wallet → pick a policy template → sign → publish via MCP, about 2 minutes.
When your agent hits ASK, run boundra-approve and paste the challenge to
produce a signed approval token.
⚠️ Known trust-boundary simplifications (must fix for production)
human_approved self-attested by the agent solved (v3): human
approval is now a signed approval token (approval.py) — ASK returns a
challenge bound to the exact payment intent; the user's device signs it;
the gateway verifies signature + field-by-field intent match + nonce
replay protection. The legacy self-attested path remains but is tagged
approve(legacy-deprecated).
- MCP-level interception is advisory — an agent framework can bypass the
gateway and talk to the wallet directly. Mitigation: pair with x402's
native hook (demonstrated in
demo/demo_real.py; the hook fires inside the SDK,
before signing). Endgame: compile the deterministic parts of policy into a
smart-contract wallet module, enforced at the settlement layer.
- Semantic detection is deterministic regex, not an LLM — the included
30-case corpus currently reports 15 TP / 15 TN / 0 FP / 0 FN (baseline before
rule tuning: 9 TP / 14 TN / 1 FP / 6 FN). This small, self-authored corpus is
a regression benchmark, not evidence of real-world detection rates. Run
.venv/bin/python tests/run_semantic_eval.py and inspect evaluations/.
- Anchoring defaults to a local log — the real contract
(
contracts/PolicyAnchor.sol) and web3 client (chain_anchor.BaseSepoliaAnchor)
are ready; set chain_config.json to switch to the real chain (deploy via
Remix with test ETH).
Economic model: the evaluation API is itself an x402 merchant
Tiered pricing:
Open core: the client, evaluation engine, and demos in this repo are
Apache-2.0. The hosted evaluation service (tiered pricing, free-quota
accounting, revenue ledger) runs from the private boundra-ops repo.
Verified / not yet verified
Verified (test_product.py 28 assertions + MCP protocol tests + 11 CC0
vectors + Python/TypeScript SDK tests): 4-layer policy stacking (platform red
lines × user × agent × Mandate) with strictest-wins; signed approval tokens
(valid passes, forged rejected, intent-rebinding rejected, replay rejected);
Mandate single-use; revocation defaults to deny and a signed v2 restores;
template render+compile; atomic reservation / release / idempotent settlement;
fail-closed SDK hooks; all MCP tools over the wire; gateway blocks an injection
attack inside the real x402 402 round-trip before the SDK signs; the full
tiered-pricing loop — first
proven on Base Sepolia (2026-10-16), then on Base mainnet (2026-10-21):
free tier passes, paid tier settles $0.003 USDC for real (buyer 1.010 → 1.007,
platform address credited 0.003), dogfood hook self-evaluates, semantic layer
blocks the injection, /revenue ledger entry.
The mainnet settlement tx is publicly verifiable: 0xf04d3497…4eac7e5
— the live API now settles on Base mainnet via Coinbase's CDP facilitator.
Earlier testnet proof: 0x5ad8ef4b…c474bbe
(the hosted service code is closed by design — the chain is the receipt).
Not yet verified: real on-chain anchoring (contract ready, needs test ETH
to deploy); real user demand; semantic layer false-positive rate under real
LLM behavior distributions.