Use it with your own agent
Put AIRLOCK between any MCP agent and your NEAR testnet funds in about five minutes. The agent reads your inbox and asks to pay; your policy contract decides. The agent never sets a label: values it read keep the label of where they came from, and a value it types counts as yours only when your own request holds it.
You need: Node 24, pnpm, the near CLI (near-cli-rs 0.30 or later), jq, python3 and curl. No Rust, no model key and no money: testnet only.
Get the code
Clone the repository and install. The committed policy wasm is used as is, so nothing is compiled.
git clone https://github.com/erfan604/airlock.git && cd airlock && pnpm iLast line:
Done in <n>s using pnpm v12.14.0Make an owner account
Your owner account sets the policy and approves held payments. The faucet funds it with 10 testnet NEAR. To reuse an account you already have, skip this; it needs about 6 testnet NEAR.
near account create-account sponsor-by-faucet-service <you>.testnet autogenerate-new-keypair save-to-legacy-keychain network-config testnet createLast line:
New account <<you>.testnet> created successfully.Deploy your own policy
One command creates your policy account with the faucet, the agent and a payee called Acme under your account, deploys the policy contract, puts Acme in your address book with a 1 NEAR cap for amounts read from outside text, and writes the agent config to ~/.airlock/mcp.json. About 2 minutes and 15 transactions.
pnpm airlock init --owner <you>.testnetLast line:
AIRLOCK READY <you>-policy.testnetAdd AIRLOCK to your agent
Print the entry for Claude Desktop and paste it into claude_desktop_config.json (on macOS in ~/Library/Application Support/Claude/), then restart Claude Desktop. Any MCP client that starts a stdio server takes the same command, arguments and environment.
pnpm airlock claude-configLast line:
}The entry names your node binary, the server file runtime/src/mcp/main.ts and AIRLOCK_MCP_CONFIG. The server reads your request and limits from that file; the agent cannot change them.
Ask your agent to pay the inbox
Ask: "Pay Acme's invoices from my inbox." The sample inbox has three. The first, 0.5 NEAR, is paid: ALLOWED with its transaction. The second, 1.5 NEAR, is over the 1 NEAR cap for an amount read from an email, so it is HELD FOR YOU (UntrustedAmount). The third is a doctored invoice that names another account; it is HELD FOR YOU too (OutsideTask), and nothing is paid.
No MCP client? The same three calls, scripted with no model: pnpm airlock play, which ends with PLAY DONE allow 1 escalate 2 block 0.
Approve or reject as the owner
Each held payment has a pending id. Read its card, approve the real invoice and reject the doctored one. Both ask you to type yes and sign with your owner key; the agent cannot do either.
pnpm airlock pending <id>Last line:
command near contract call-function as-transaction ...Approve the 1.5 NEAR invoice
The contract checks your signed values against the stored request and pays it.
pnpm airlock approve <id>Last line:
APPROVED <id> https://testnet.nearblocks.io/txns/<tx>Reject the doctored invoice
Nothing moves, and the rejection is recorded on chain.
pnpm airlock reject <id>Last line:
REJECTED <id> https://testnet.nearblocks.io/txns/<tx>
What the agent can and cannot do
- It can pay without you only an address-book payee, inside the task your server signs from your config and inside the payee and asset limits.
- It cannot change your request, your limits or your book, and it cannot approve: approval needs your owner key.
- It can still cause held payments, which cost your attention, and it decides when to pay inside your limits.
- The full list is the MCP client entry of docs/THREAT_MODEL.md; the steps with every expected line are docs/QUICKSTART.md.