Wallet infrastructure for Ai agents. EVM + Solana. x402 payments. No KYC.
Runs on your machine from its package; the steps are below.
At most: moves money, runs code or commands, deletes data, or sends messages for you.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
npx -y agentwallet-mcp
MCP client config
{
"mcpServers": {
"agentwallet": {
"command": "npx",
"args": [
"-y",
"agentwallet-mcp"
]
}
}
}Permissionless wallet infrastructure for AI agents. Create wallets, sign transactions, and broadcast on-chain, on any EVM chain and Solana. Built-in guards. No KYC. The only AI agent wallet that accepts crypto for its own API fees.
Your keys can stay on your machine. Set one environment variable and every signature happens in your own process. No server sees the key, no company can freeze the wallet, and you can verify that claim by reading src/local-wallet.ts or by running the server with the API pointed at a closed port.
No KYC. No KYT. No approval process. No transaction monitoring. No one can block your wallet. Pay with USDC on-chain, no credit card required.
| Local (self-custody) | Hosted (custodial) | |
|---|---|---|
| Who holds the key | You, in your own process | Encrypted on AgentWallet servers |
| Set up | One env var, no account needed | API key |
| Chains | EVM + Solana | EVM + Solana |
| Can anyone freeze it | No | Yes, that is what pause is for |
| Spend guards | AGENTWALLET_MAX_TX_NATIVE, AGENTWALLET_MAX_TX_TOKEN, AGENTWALLET_MAX_TX_SOL, AGENTWALLET_MAX_AUTOPAY | Server-side limits, pause, rate limits |
| Paywalls, usage, billing | Needs an API key too | Included |
Run wallet_mode at any time and the server will tell you which one you are in, and which address it controls.
{
"mcpServers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_PRIVATE_KEY": "0xyour_key",
"AGENTWALLET_RPC_8453": "https://your-own-rpc",
"AGENTWALLET_MAX_TX_NATIVE": "0.05"
}
}
}
}
Use AGENTWALLET_KEYFILE=/path/to/key instead if you would rather keep the key out of your shell config (one or the other: the server refuses to start when both are set). The key is read once, never written to disk, never logged, and never included in an error message.
AGENTWALLET_RPC_<chainId> (or AGENTWALLET_RPC_URL for all chains) points at an endpoint you trust (https; plain http only on localhost). Without it a public RPC is used, and a public RPC can see which addresses you ask about. Decimals for a token outside the registry come from that RPC and are accepted only up to 18; pin anything else with AGENTWALLET_TOKEN_DECIMALS.
AGENTWALLET_MAX_TX_NATIVE is a per-transaction ceiling in native units (ETH, MATIC and so on). In hosted mode the server enforces limits; in local mode there is no server, so these guards are the only ones there are. Set them.
AGENTWALLET_MAX_TX_TOKEN is the equivalent ceiling for ERC-20 movement, in human units of the token. Set this one too if you hold stablecoins. The native cap cannot see a token transfer: an ERC-20 send carries value = 0 with the amount in the calldata, so AGENTWALLET_MAX_TX_NATIVE alone leaves a USDC balance uncapped. AGENTWALLET_MAX_TX_TOKEN covers transfer, transferFrom, approve, increaseAllowance, Permit2 approve, and deposit() / withdraw(uint256) on the chain's own wrapped-native contract (so wrap_eth and unwrap_eth keep working under the cap), the approvals because an unbounded allowance is a drain waiting to happen. Any other calldata sent to a token contract or to Permit2 is refused while the cap is set, because the guard cannot price it; set AGENTWALLET_ALLOW_UNKNOWN_TOKEN_CALLS=1 to allow such calls deliberately. increaseAllowance is judged on the resulting total: the current allowance is read first and the call refuses if it cannot be, so two compliant increments cannot stack a standing allowance above the cap. Calls to other contracts (routers, bridges) pass, since they can only pull what an approval already allowed; a contract counts as "other" only when it demonstrably declines decimals(), so an absurd or malformed answer, or an RPC that cannot be reached, refuses rather than allows. Decimals are resolved locally from the trusted registry, then the token's own decimals(); a token that resolves neither way is evaluated at 0 decimals, the only value that cannot fail open. For a token outside the registry the RPC is the only source of decimals, and an RPC you do not control could scale the amount and the cap together; pin such tokens with AGENTWALLET_TOKEN_DECIMALS (for example 8453:0x<token>=6) and the pin is used everywhere the RPC's answer would have been.
"env": {
"AGENTWALLET_SOLANA_KEY": "[12,34...]",
"AGENTWALLET_SOLANA_RPC": "https://your-own-rpc",
"AGENTWALLET_MAX_TX_SOL": "1",
"AGENTWALLET_MAX_TX_TOKEN": "25"
}
Accepts whichever format you already have: a solana-keygen id.json array, a base58 secret key as exported by Phantom, or base64. Use AGENTWALLET_SOLANA_KEYFILE to point at a file instead. Native SOL and SPL token transfers are both signed locally, and a missing associated token account is created for the recipient automatically.
Set either key, or both. They are independent: run EVM locally and Solana hosted, or the reverse.
An operation with no matching local key is refused, never silently routed to the hosted signer. If you have an EVM key configured and ask for a Solana transfer with no Solana key, the server stops and tells you which variable is missing. Quietly moving funds onto a key you do not hold, while you believe you are in self-custody, is the worst thing this server could do.
Local signing uses viem for EVM and @solana/web3.js for Solana, plus bs58 for key parsing. SPL instructions are built by hand rather than with @solana/spl-token, because that package pulls in bigint-buffer, which carries a high severity buffer overflow advisory. A wallet has no business shipping that to save a dozen lines of instruction encoding.
npm audit reports no advisories as of 1.13.5; the overrides in package.json keep two advisories under @solana/web3.js's jayson closed. Earlier releases carried advisories inside @modelcontextprotocol/sdk's HTTP transport dependencies. This server speaks stdio, so that code never loads, and the SDK is not something this package can patch. Run the audit yourself. Publishing a tree you can inspect is the point.
AGENTWALLET_MAX_TX_NATIVE, AGENTWALLET_MAX_TX_TOKEN, AGENTWALLET_MAX_TX_SOL, AGENTWALLET_MAX_AUTOPAY). x402 replay protection and on-chain verification apply either wayCompetitor comparisons are kept at hifriendbot.com/wallet/#pricing with the date they were last verified. They live there rather than here because a published npm README cannot be corrected when someone else changes their prices.
Get your free API key at hifriendbot.com/wallet, no credit card required, no KYC, no approval wait.
Add to your config:
{
"mcpServers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_USER": "your_username",
"AGENTWALLET_PASS": "your_api_key",
"AGENTWALLET_WALLET_ID": "1"
}
}
}
}
AGENTWALLET_WALLET_IDis optional. Set it to enable x402 auto-pay: when you exceed the free tier without a credit card, the MCP server automatically pays for operations with USDC from this wallet. Only the metered routes (creating a wallet, signing, sending) are paid this way, at mostAGENTWALLET_MAX_AUTOPAY_PER_HOURtimes an hour (default 20), and every automatic payment is reported in the tool result underautopay_payment. A 402 on any other route is reported, never paid.Auto-pay safety cap.
AGENTWALLET_MAX_AUTOPAY(optional, default1) is the most one x402 payment may authorize, in stablecoin units:1means one dollar. It prices registry stablecoins only (USDC, USDT, USDbC, DAI on the supported chains, USDC and USDT on Solana). A requirement in the chain's native asset or in any other token is refused, because "1" measured in ETH is a few thousand dollars; list such assets inAGENTWALLET_AUTOPAY_ASSETS(comma-separated addresses or mints, or the wordnative) to allow them, and the cap then applies in that asset's own units. Any requirement above the cap is rejected instead of paid, so a malformed or tampered payment requirement cannot drain the wallet. This automatic path settlesexactrequirements only; anuptooffer from the API is refused before any wallet call, because paying a usage maximum upfront is not what the offer means (usepay_x402, which signs a Permit2 authorization for it). The cap is the operator's ceiling: amax_paymentargument can lower it for one call but never raise it. Raise the variable itself if you genuinely need larger automatic payments (for example"5"for up to 5 USDC per call).
claude mcp add agentwallet \
-e AGENTWALLET_USER=your_username \
-e AGENTWALLET_PASS=your_api_key \
-e AGENTWALLET_WALLET_ID=1 \
-- npx -y agentwallet-mcp
Add to your settings:
{
"mcp": {
"servers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_USER": "your_username",
"AGENTWALLET_PASS": "your_api_key",
"AGENTWALLET_WALLET_ID": "1"
}
}
}
}
}
| Tool | Description |
|---|---|
create_wallet | Create a new EVM or Solana wallet |
list_wallets | List all your wallets |
get_wallet | Get wallet details by ID |
get_balance | Check native token balance on any chain |
get_token_balance | Check ERC-20 or SPL token balance |
get_token_info | Get ERC-20 token name, symbol, and decimals |
transfer | Send native tokens (ETH, SOL, POL, BNB, etc.) |
transfer_token | Send ERC-20 or SPL tokens (USDC, USDT, etc.) |
send_transaction | Sign and broadcast a raw transaction |
sign_transaction | Sign a transaction without broadcasting |
call_contract | Read-only contract call (eth_call) |
approve_token | Approve ERC-20 token spending for DeFi |
get_allowance | Check ERC-20 token allowance |
wrap_eth | Wrap native tokens to WETH/WAVAX/etc. |
unwrap_eth | Unwrap WETH back to native tokens |
pay_x402 | Pay x402 invoices (exact via EIP-3009, upto via Permit2), with approvals above the cap |
check_approval | Status of a human approval created by an over-cap pay_x402 |
approve_permit2 | One-time token approval to Permit2 for upto endpoints |
check_token_risk | Honeypot, tax, owner-power and holder-concentration flags for a token |
create_paywall | Create an x402 paywall to charge for a resource |
list_paywalls | List all your x402 paywalls |
get_paywall | Get paywall details by ID |
update_paywall | Update paywall pricing, resource, or status |
delete_paywall | Delete a paywall |
get_paywall_payments | View payment history for a paywall |
get_x402_revenue | Aggregate revenue stats across all paywalls |
wallet_mode | Report whether signing is local (self-custody) or hosted, and which address is in use |
export_wallet_key | How to export a hosted wallet key and move to self-custody |
buy_verification_credits | Buy x402 verification credits with USDC on-chain |
get_usage | Check your monthly usage and billing |
get_chains | List all supported chains |
pause_wallet | Emergency pause a wallet |
unpause_wallet | Resume a paused wallet |
delete_wallet | Delete a wallet |
| Chain | ID | Native Token | Stablecoin |
|---|---|---|---|
| Ethereum | 1 | ETH | USDC |
| Base | 8453 | ETH | USDC |
| Polygon | 137 | POL | USDC |
| BSC | 56 | BNB | USDT |
| Arbitrum | 42161 | ETH | USDC |
| Optimism | 10 | ETH | USDC |
| Avalanche | 43114 | AVAX | USDC |
| Zora | 7777777 | ETH | USDC |
| PulseChain | 369 | PLS | USDC |
| Solana | 900 | SOL | USDC |
| Solana Devnet | 901 | SOL | USDC |
Pair with guessmarket-mcp to let your AI agent trade prediction markets:
All on-chain. All through MCP. No frontend needed.
AgentWallet speaks the x402 open payment standard the way the spec defines it. When your Ai agent hits an API that answers HTTP 402, pay_x402 does the whole flow:
PAYMENT-REQUIRED header or the v1 JSON body.exact option (you can steer it with prefer_chain).TransferWithAuthorization for exactly that amount. Nothing is broadcast and no gas is paid by the payer; the endpoint's facilitator settles it on-chain.PAYMENT-SIGNATURE for v2, X-PAYMENT for v1).PAYMENT-RESPONSE / X-PAYMENT-RESPONSE) and, if the endpoint declined, its stated reason in retry_error.Verified against Coinbase's public facilitator (isValid: true for v1 and v2 payloads) and live x402 servers on Base. Works in both custody modes: the local key signs in-process; hosted wallets sign through POST /wallets/{id}/x402/authorize, a narrow endpoint that only ever signs this one struct and runs the same pause and token-cap checks as a transfer.
pay_x402(
url="https://api.example.com/premium-data",
wallet_id=1,
max_payment="1.00"
)
max_payment lowers the cap for one call. It cannot raise it: AGENTWALLET_MAX_AUTOPAY (default 1) is the operator's ceiling, and a max_payment above it is ignored and reported back as max_payment_ignored, so neither a malicious 402 endpoint nor a prompt-injected agent can authorize more than the operator allowed. Hosted wallets can go above the ceiling only through an emailed owner approval (below); local mode raises the variable. In local mode AGENTWALLET_MAX_TX_TOKEN applies to authorizations too, because an authorization is a transfer somebody else executes. Authorizations are valid for at most AGENTWALLET_X402_MAX_TIMEOUT seconds (default 3600) however long the endpoint asks for, and a repeat pay_x402 call for the same endpoint, amount and recipient inside that window re-sends the earlier signature instead of signing a second one (its nonce is single-use, so a server that withheld the resource after settling cannot be paid twice; pass fresh_authorization=true to force a new one). The label shown for the asset comes from the registry or the chain, never from the 402 body.
Schemes. exact (EIP-3009, gasless for the payer) is preferred and works on every EVM chain AgentWallet knows. upto (a Permit2 maximum the seller settles at actual usage) is signed as a PermitWitnessTransferFrom bound to the endpoint's facilitator; it needs a one-time approve_permit2 per token (or AGENTWALLET_PERMIT2_AUTO_APPROVE=1). An upto option without extra.facilitatorAddress is refused, never approximated with an upfront transfer. Native-asset and Solana requests, and AgentWallet's own paywalls, are paid by an on-chain transfer proved by transaction hash, which is what those servers verify.
Approvals above the cap. On a hosted wallet, a payment above the cap does not have to fail. With request_approval (default on; AGENTWALLET_APPROVALS=0 turns it off) the wallet owner gets an email with approve and deny links, pay_x402 returns an approval_id, and the agent retries with it once check_approval says approved. An approval is bound to one wallet, chain, asset, recipient and maximum, expires in 24 hours, and is consumed by one signature. Local mode has no approval channel: the caps in your environment are the policy, and an approval_id passed there is refused.
Asset risk. check_token_risk (and every approve_token result) reports honeypot, tax, owner-power, verified-source, holder-concentration and liquidity flags from GoPlus Security, with an on-chain fallback. A warning for the caller to weigh, never a block.
Proof. Real settlements are listed in PAYMENTS.md; the first is a 0.02 USDC exact payment on Base with the facilitator paying the gas.
AGENTWALLET_PRIVATE_KEY to a key that holds USDC on Base. Hosted: AGENTWALLET_USER and AGENTWALLET_PASS from hifriendbot.com/wallet.payment_made: true, the amount, payment_method, and settlement.transaction, the on-chain hash. No ETH needed for exact: the endpoint's facilitator pays the gas.Token domains. The EIP-712 domain comes from the endpoint's extra.name / extra.version, then a short registry of USDC deployments, then the token contract's own name() / version(). If none of those answer, the payment is refused rather than signed with a guessed domain.
Delegated payers. If the paying address is an EIP-7702 delegated account, pay_x402 reports it in payer_delegation (the delegate and whether it answers ERC-1271). A delegate without ERC-1271 is declined by facilitators that check account code before recovering the signer, and the reason they return reads like a signature fault; the warning names the real cause. Pay from a plain EOA for reliable settlement.
AgentWallet also lets you accept x402 payments. Create a paywall, point it at any resource, and get a public URL that charges agents automatically:
create_paywall(
wallet_id=1,
name="Premium API",
amount="0.01",
token_name="USDC",
token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
chain_id=8453,
resource_url="https://your-api.com/data"
)
When an agent hits the paywall URL:
pay_x402 (or any x402-compatible client)On-chain verification ensures every payment is real. Replay protection prevents double-spending. Revenue tracking shows you who paid, how much, and when. 1,000 free verifications/month, then $0.0005 each. See the pricing comparison for how that stacks up.
| Feature | Coinbase CDP | AgentWallet |
|---|---|---|
| Setup Time | Install SDK + configure | 3 lines of config |
| Approval Process | Identity verification required | None, instant access |
| KYC Required | Yes | No |
| KYT / Transaction Monitoring | Yes | No |
| Can Block Your Wallet | Yes | No |
| Built-in Guards | Yes (requires setup) | Yes (hosted: active by default; local: env caps you set) |
| Free Operations / Month | 5,000 | 6,000 |
| Cost Per Operation | $0.005 | $0.00345 |
| x402 Verification Cost | $0.001 | $0.0005 |
| Free x402 Verifications / Month | 1,000 | 1,000 |
| x402 Acceptance (Paywalls) | No | Yes |
| Pay for API Fees with Crypto | No (credit card only) | Yes (USDC via x402) |
| Supported Chains | 8 EVM + Solana | Any EVM + Solana |
| Token Tools | Yes | ERC-20 + SPL (34 tools) |
| MCP Server | Yes | Yes |
AgentWallet is the only AI agent wallet infrastructure that accepts crypto for its own API fees. Every competitor, Coinbase CDP, Circle, MoonPay, Crossmint, Turnkey, requires a credit card or monthly invoice. With AgentWallet, your agent can pay for operations with USDC on-chain via the x402 protocol. No credit card, no invoice, no billing portal. Just on-chain payments.
When your agent exceeds the free tier (6,000 ops/month) without a credit card configured, the API returns HTTP 402 with USDC payment instructions. Your agent pays on-chain, retries with proof of payment, and the operation executes. Fully automated via the MCP server.
You can also pre-purchase x402 verification credits with USDC using the buy_verification_credits tool, keeping your paywalls running beyond the free 1,000 verifications/month without needing a credit card.
Which guards apply depends on who holds the key.
Hosted mode (the server holds the key): every guard below is active by default, no configuration required.
Local mode (you hold the key): there is no server in the signing path, so the server-side limits and pause above cannot see or stop a locally signed transaction, and nobody (including us) can freeze a local wallet. Your protection is the per-transaction caps enforced inside your own process before anything is signed. Set them before you fund the wallet; an unset cap means no limit.
AGENTWALLET_MAX_TX_NATIVE: ceiling per transaction in native units (ETH, MATIC, and so on)AGENTWALLET_MAX_FEE_NATIVE: the most one transaction may burn in fees, gas x max fee per gas, in native units (default 0.01). The value cap alone did not bound fees: a node answering an absurd tip or gas estimate could take the whole balance as priority fee on a cap-compliant transfer. Caller-supplied gas_limit / max_fee / priority_fee are honoured and then bounded by this capAGENTWALLET_MAX_TX_TOKEN: ceiling per ERC-20 transfer or approval, in human units of the tokenAGENTWALLET_ALLOW_UNKNOWN_TOKEN_CALLS: set to 1 to let calldata the token cap cannot price reach a token contract or Permit2 (refused by default while the cap is set)AGENTWALLET_TOKEN_DECIMALS: pin decimals for tokens outside the registry (8453:0x<token>=6,<mint>=9); a pin is used for amounts and caps instead of asking the RPCAGENTWALLET_MAX_TX_SOL: ceiling per native SOL transfer (also charged for the rent of a recipient token account an SPL send has to create). It does not cover SPL token amounts: AGENTWALLET_MAX_TX_TOKEN does, on Solana as on EVMAGENTWALLET_MAX_AUTOPAY: ceiling per x402 auto-payment in stablecoin units (default 1); AGENTWALLET_AUTOPAY_ASSETS opts native or non-stable assets in; AGENTWALLET_X402_MAX_TIMEOUT bounds how long a signed authorization stays valid (default 3600 seconds)AGENTWALLET_SOLANA_RPC_<chainId> (or AGENTWALLET_SOLANA_RPC for all clusters): the RPC's genesis hash is checked against the chain id before anything is sent, and an EVM RPC's eth_chainId likewise, so one URL cannot silently serve a different network than the one requestedAGENTWALLET_TOKEN_RISK=0: skip the GoPlus lookup approve_token performs (a third-party call that reveals which token you are about to approve)AGENTWALLET_CHAIN_ID: the EVM chain used when a call names none (default 8453)AGENTWALLET_LEGACY_PAYWALL_ORIGINS: comma-separated https origins whose legacy-shaped 402 may be settled by an on-chain transfer proved by hash; every other host gets a signed authorizationEvery AGENTWALLET_* variable is validated at startup: a malformed cap stops the server rather than reading as "no limit", and an unrecognised name (a misspelled cap) stops it too. wallet_mode reports every guard with its parsed value. Tool arguments are strict: an unknown argument name (a typo in max_payment) is an error, never silently ignored. pay_x402 signs one live authorization per resource; a second, different requirement for the same resource is refused until the first expires unless fresh_authorization is passed. Node.js 22.19 or newer is required.
Either mode, for x402 paywalls you run through the hosted API:
Bug bounty program: $50 to $500 for responsible disclosure (details).
pay_x402 validates the target URL before every outbound request and again on
each redirect hop. IP literals are canonicalized (including IPv4-mapped IPv6
such as [::ffff:127.0.0.1]) and hostnames are resolved, with loopback,
private, link-local, carrier-grade NAT, multicast and cloud-metadata
destinations refused.
Validation and connection use the same DNS answer. Each hop resolves once, and
the socket is pinned to an address from that answer, so a hostname cannot
resolve public for the check and private for the connection. The hostname is
still used for the Host header and for TLS SNI and certificate validation, so
pinning is invisible to legitimate endpoints.
Credentials stay with the origin they were given to. If an endpoint redirects
pay_x402 to a different origin, the caller-supplied Authorization, Cookie
and X-PAYMENT headers, and every other custom header, are dropped before the
next hop; only content-negotiation headers (Accept, Accept-Language,
Accept-Encoding, User-Agent, Content-Type) are carried. A redirect that
turns a POST into a GET also sheds the body headers. Same-origin redirects keep
everything, as a browser would.
Report security issues privately to security@hifriendbot.com.
MIT