@keyban/cli
v0.2.2
Published
Keyban command line: agent wallet commands and their MCP server
Readme
@keyban/cli
Give an AI agent its own blockchain wallet: balances, USDC transfers and x402 payments, under a spending policy the agent cannot change.
The keyban command serves the wallet's tools two ways: keyban mcp as an MCP
server, and keyban wallet <tool> as one subcommand per tool, for scripts and
humans.
Registry name: io.keyban.mcp/agent-wallet.
keyban mcp runs locally over stdio, next to your MCP client. It holds one share
of a FROST threshold key in its wallet file; Keyban holds the other. No single
side can move funds alone, and the model never sees either share or your API
key.
You need a Keyban wallet first
This server drives a wallet Keyban provisions. It does not create one, and it
has nothing to drive without one — installing the package on its own gets you
a server offering only setup_instructions and the guide tool get_instructions,
which point back here. The
threshold key is the reason: one share lives here, the other lives with us, so
there is a Keyban side to every wallet by construction and no configuration can
replace it.
So the order is:
- Get a Keyban account at https://keyban.io.
- Create an agent wallet in the admin app, or from your assistant with the
Keyban admin MCP (
https://mcp.keyban.io/mcp). It provisions the wallet, its API key, and a one-shot invite key that authorises this client as a signer. - Take the configuration the wallet's page in the admin app hands you —
either the environment block for the table below, or a ready-to-install
.mcpbbundle with the values already in it. - Then install, with those values in the environment.
An agent skill walks an AI agent through the same steps, then through operating the wallet.
Install
Once you have the credentials from step 3:
npx -y @keyban/cli@latest mcpKeep the @latest: without a version, npx reuses the copy it cached on first
run, and a restart never picks up a new release.
Or install the command once and call the tools directly:
npm install -g @keyban/cli
keyban wallet balance
keyban wallet x402-pay --url https://example.com/paid --max-amount 0.01
keyban wallet --helpWith Claude Code:
claude mcp add agent-wallet \
-e KEYBAN_API_KEY=… \
-e KEYBAN_APP_ID=… \
-e KEYBAN_INVITE_KEY=0x… \
-e KEYBAN_WALLET_ADDRESS=0x… \
-e KEYBAN_NETWORK=… \
-- npx -y @keyban/cli@latest mcpOn first boot the server runs a key generation, keeps its share in the wallet
file (KEYBAN_WALLET_PATH, else $XDG_CONFIG_HOME/keyban/wallet.json), and registers itself on chain as a signer of that wallet using the
invite key. That happens once per machine; the invite key is spent by it.
Configuration
The five required values all come from step 2 — none of them is something you can pick yourself.
| Variable | Required | What it is |
|---|---|---|
| KEYBAN_API_KEY | yes | API key of the application the wallet belongs to. Never exposed to the model. |
| KEYBAN_APP_ID | yes | Identifier of the Keyban application. |
| KEYBAN_INVITE_KEY | yes | One-shot ECDSA private key authorizing this client's first-boot registration as a signer. |
| KEYBAN_WALLET_ADDRESS | yes | Address of the account this server drives. |
| KEYBAN_NETWORK | yes | Network the wallet operates on: BaseMainnet, BaseSepolia, XdcMainnet or XdcApothem. |
| KEYBAN_BASE_URL | no | Backend base URL, or one of dev, testing, staging, prod, sandbox. Defaults to https://api.prod.keyban.io. |
| KEYBAN_DKG_BLOB | no | Pre-generated signer share, base64 JSON. For runtimes whose disk does not last; it does not replace the invite key. |
| KEYBAN_WALLET_PATH | no | The wallet file, holding these variables and the share. Defaults to $XDG_CONFIG_HOME/keyban/wallet.json. |
| KEYBAN_CONFIG | no | All the variables above as one base64 JSON object, for runtimes like AgentCore where each variable is a chore to add. A variable set on its own wins. |
| MCP_LOG_FILE | no | Path the server writes its log to. |
| MCP_LOG_LEVEL | no | debug, info, warn or error. Defaults to info for keyban mcp, warn for keyban wallet. |
keyban mcp --http serves stateless streamable-HTTP on 0.0.0.0:8000,
POST /mcp, for Amazon Bedrock AgentCore. It has no authentication of its own:
AgentCore authenticates callers before they reach it. Anywhere else it is an
open wallet endpoint, so use it on AgentCore only.
Tools
Each tool is also a keyban wallet subcommand, its name in kebab-case
(x402_pay → keyban wallet x402-pay) and its arguments as options.
Read-only:
| Tool | What it does |
|---|---|
| get_instructions | Read the agent wallet guide (the keyban-agent-wallet skill) |
| api_status | Check Keyban API status |
| get_account_info | Get wallet account info |
| balance | Check wallet balance |
| list_expense_transactions | List wallet transactions |
| expense_stats | Get spending statistics |
| wait_for_intent | Wait for approval decisions |
| x402_info | Inspect the x402 price of a URL |
| discover_x402_services | Search the x402 service directory |
| list_missions, get_mission | Read the missions and their statistics |
| list_mission_runs, get_mission_run | Read this wallet's mission runs |
| list_runs_of_mission | List this wallet's runs of one mission, paginated, filterable by status |
| list_mission_run_payments | List every payment of a run, paginated (get_mission_run only carries the 50 most recent) |
| publish_mission | Check a draft can be published and show the page to publish it |
Writing:
| Tool | What it does |
|---|---|
| sign_message | Sign a message |
| cancel_intent | Cancel a pending payment intent |
| transfer_usdc | Transfer USDC — moves funds |
| x402_pay | Pay for an x402 resource — moves funds |
| create_mission, update_mission, discard_mission_draft | Draft a mission on this wallet |
| request_mission_trial | Ask a trial of the draft, validated by a human |
| start_mission_run, log_mission_progress, complete_mission_run, abandon_mission_run | Run a mission |
Every tool carries a title and the applicable readOnlyHint or
destructiveHint, so a client can tell the two groups apart before calling
anything.
Spending policy
Transfers and x402 payments are checked against the wallet's policy on the
Keyban side. A call the policy will not clear on its own does not fail
silently: it comes back naming a payment intent that needs a human decision.
The answer carries the link to approve it and the next steps;
wait_for_intent blocks until a wallet operator approves or declines, and the agent
retries once it is approved. The policy lives with the wallet, not with this
process, so editing this server's configuration cannot widen it.
In clients that render MCP apps (Claude, Claude Desktop, ChatGPT…),
x402_pay and transfer_usdc show a card and wait for the decision in the
same call: the amount, who it pays, a countdown to the deadline, a button that
opens the payment in the Keyban dashboard and one that withdraws the request.
Once approved, the call signs and settles, and the card turns into a receipt.
The card follows the payment through await_payment_approval and
watch_payment_approval, tools only it can call. It approves nothing:
approval needs the user's own Keyban session.
The mission tools come from the Keyban API description (/openapi.json, kept
in the user's cache), called with the wallet's key on its own wallet.
request_mission_trial, an on-demand start_mission_run and
publish_mission show a mission card: what is asked, a button that opens the
trial, the run or the mission page in the dashboard, and its status until a
human decides, through watch_mission_approval. Validating and publishing
stay the user's, in the dashboard.
In clients that declare URL elicitation but render no MCP apps (Claude Code), the held payment asks the client to open the approval page instead: the client shows the user the URL, opens it in the browser once they agree, and the call waits for the decision just as with the card. A client that does neither gets the link and the steps in the answer.
Trust boundary
The share and the API key are protected by your user account, nothing finer:
the wallet file is readable by you alone (mode 600), so any program running as
you can read them, and can run keyban too. What bounds such a program is the same thing that bounds
the agent: Keyban co-signs every signature and applies the wallet's policy
first. Treat the machine account that holds the share like one that holds an
SSH key.
If you suspect the share or the API key leaked, rotate them: add a new signer to the wallet, set it up, then delete the old signer. Deleting it removes its key from the wallet on chain and revokes its API key, so the leaked pair can no longer sign nor reach the API. The wallet address does not change.
Documentation
License
Apache-2.0. See LICENSE.
