Skip to main content
Glama
dinggi5

Kura

Kura (蔵 — a storehouse that guards your treasures)

A local EVM wallet for AI agents. On a Mac, when an AI like Claude makes an internet payment (x402), this is the wallet where a human approves it with a password.

  • Not a human wallet (like MetaMask) — it's for AI agents

  • Not a cloud SaaS — it runs locally only. Keys never leave this computer.

  • AI requests a payment → a human approves with a password → it executes

  • The chain is Base (Ethereum L2, near-zero fees). Default is the testnet (Base Sepolia)


At a glance

[ AI 앱 (Claude Code / 데스크톱) ]
        │  MCP로 "결제해줘" 요청
        ▼
[ Kura 데스크톱 앱 ]  ← 승인 팝업 → 사람이 비밀번호 입력
        │  서명 (키는 이 앱 안에서만)
        ▼
[ Base 체인 / x402 페이실리테이터 ]  ← 실제 결제

The password is only ever entered in the Kura app's input field. It never goes into chat windows, MCP, or config files.


Related MCP server: cardzero-mcp

Installation

Apple Silicon Mac (macOS 11 or later)

(A) Homebrew

brew install --cask dinggi5/tap/kura

(B) Download the DMG directly

Download Kura_<version>_aarch64.dmg from Releases, open it, and drag Kura into the Applications folder.

Since this is an app you're entrusting with your keys, I've written down the exact commands for verifying that the app you received is really the one I built in SECURITY.md.

(C) Build from source

Prerequisites: Rust, Node.js (20.19+ or 22.12+ — required by Vite 7), macOS.

git clone https://github.com/dinggi5/kura.git
cd kura
git checkout v0.1.1   # 배포본과 같은 소스. 빼면 개발 중인 최신 코드가 받아져요
npm ci                # package-lock.json 그대로 설치 (install 은 버전이 올라갈 수 있어요)

# 개발 모드로 바로 실행
npm run tauri dev

# 앱으로 빌드해 /Applications에 설치
npm run tauri build -- --bundles app --no-sign
ditto src-tauri/target/release/bundle/macos/Kura.app /Applications/Kura.app
open /Applications/Kura.app

Updates

The app updates itself.
Go to Settings → About to check the version and changelog, then click Install now and restart.

  • Only the check is automatic — installation always requires you to click it.

  • Downloaded files are installed only after their signature is verified (signature verification cannot be disabled). Details are in the "Updates" section of SECURITY.md.

  • If you don't want the automatic update-check traffic, turn off Settings → About → Check on startup.

Uninstalling

⚠️ Uninstalling the app does not delete your wallet. Keys, settings, and transaction history live in ~/.jigap outside the app, so removing just the app leaves them intact — I did this on purpose so you don't accidentally lose your assets (even brew uninstall --zap won't remove them).

# 앱만 제거 (지갑은 남음 — 나중에 다시 설치하면 그대로 이어서 써요)
brew uninstall --cask dinggi5/tap/kura   # 또는 /Applications/Kura.app 을 휴지통으로

To completely erase the wallet too on this Mac, follow this order:

  1. First make sure you have the 12-word recovery phrase in hand. You can view it again via the key button in the app's header.

  2. If there's a balance left, move it to another wallet.

  3. Quit Kura completely (right-click the menu bar icon → Quit). If it's running, it writes a state file to ~/.jigap every few seconds, so a deleted folder will reappear right away.

  4. Also quit any AI tools (like Claude Code) that have the Kura MCP attached.

  5. If you had auto-start enabled, turn it off or run rm ~/Library/LaunchAgents/Kura.plist (this file remains if you delete the app via Trash. If you uninstall with brew uninstall --cask, it goes away with it).

  6. Then run rm -rf ~/.jigap

Running that final rm -rf ~/.jigap without the 12 words means no one can ever recover that wallet's assets.


First run

Kura lives in the menu bar. When you launch it, a storehouse icon (◻︎) appears in the menu bar at the top of your screen, and the window only drops down when you click that icon. Clicking elsewhere closes it, and the app stays in the background waiting for AI payment requests. To quit completely, right-click the icon → Quit. (On first launch when no wallet exists yet, the window opens by itself.)

  1. Create a wallet — set a password (8+ characters) that you'll enter for every transfer. Your key is encrypted and stored with this password (~/.jigap/wallet.enc).

  2. Back up the seed — 12 words are shown. This is the real proof of ownership of your assets, so write them down on paper or in a password manager. Even if you forget your password, the 12 words alone can recover it: quit the app, first make sure you have the 12 words in hand, then delete ~/.jigap/wallet.enc and relaunch the app — you can restore it via Import on the first screen (you can also put them into any other standard BIP-39 wallet). However, deleting this file without the 12 words means losing your assets forever.

  3. Welcome tour — walks you through funding, AI connection, and safety features. You can revisit it anytime from the ⓘ Help in the header.


Funding (USDC)

To make payments, your wallet needs USDC (digital dollars).

  • Tap Receive in the app to see your address and QR code.

  • When sending from an exchange or another wallet, be sure to select the Base network. Sending on another network will lose your funds.

  • On the testnet (default), it's not real money. Use the Faucet button on the receive screen to get free test coins and practice.

  • ETH is optional — for x402 payments, the facilitator pays the fee, so you can have 0 ETH. You only need a little ETH for gas when sending directly via the app's Send (Base fees are around a cent). Funding with USDC alone is enough.


Connecting AI (Claude)

Register the Kura server in your AI app's MCP settings to connect. Once connected, a "Claude connected" badge appears on the main screen. Since 0.1.2, the MCP server is built into the app, so you can connect without cloning the source or installing Rust.

The easiest way — the "AI Connect" screen in the app

Click the "AI not connected" badge at the top of the main screen to open the connection screen.

  • Claude Desktop — click the "Connect" button and an extension install window appears in Claude. Just click 'Install' and you're done.

  • Claude Code — registered with one click (the app runs claude mcp add for you). From the next claude launch, it's connected from any folder.

Below is how to do the same thing by hand.

Claude Desktop — one extension file is all you need

Download kura-<version>.mcpb from the releases page and double-click it — Claude Desktop will ask to install it. (Or go to Claude Settings → Extensions → Choose file.)

The extension contains no executable — it only has a launcher that verifies the signature of the signed and notarized MCP server inside the installed Kura.app and then runs it. So you need to install the Kura app first.

Claude Code · other MCP apps

Register the in-app binary with its absolute path:

claude mcp add --scope user kura -- /Applications/Kura.app/Contents/MacOS/kura-mcp

(--scope user is the option that makes it available everywhere, not just "this folder". If you only want it in one project, you can omit it.)

For other MCP apps, write it in the settings like this:

{
  "mcpServers": {
    "kura": {
      "command": "/Applications/Kura.app/Contents/MacOS/kura-mcp"
    }
  }
}

If you're developing from source

The repo root already has .mcp.json. Running claude in this folder picks it up automatically (the first time it asks whether to use the server — approve it). This path is for development, rebuilding with cargo run every time — if you're using an installed build, registering the app path above is the right approach.

Tools the AI can use: get_wallet_status · get_balances · get_history (read-only) · request_payment (payment request → approval popup in the app) · x402_fetch (calls a URL that requires 402 payment).

If you change the MCP tools, restart the AI app for it to take effect (the server is loaded once at session start).


How a payment flows

  1. The AI requests a payment.

  2. The Kura window appears showing how much, to where (it pops up automatically even if the window was hidden).

  3. Enter the password and approve.

  4. The payment executes and the result goes back to the AI. If you don't approve within 5 minutes, it's automatically rejected.


Security model

  • Password approval — by default, every payment requires password approval (if autonomous payments are enabled, exceptions apply only under the conditions below). Keys are stored encrypted (Argon2id + AES-256-GCM) and are only decrypted at payment time, then wiped immediately (if an autonomous payment session is enabled, they're kept in memory only while unlocked).

  • Limits — set how much can be sent per transaction / per day in settings (default: 5 USDC single, 20 USDC daily). Anything over is blocked.

  • Emergency lock — turning on the shield button in the header immediately blocks all transfers.

  • Trusted addresses · autonomous payments — for automatic approval without a password, session unlock + small limits + trusted address must all be satisfied. Otherwise, a password is always required.

  • Transaction history — records all outgoing transfers, blocked attempts, and signatures.

  • Local-first — keys (~/.jigap/) live outside the repo and never get committed to git.

  • No analytics, no font CDN — the app connects to the internet on its own for only three things: ①the RPC server used for balance lookups and transfers ②x402 addresses requested by the AI ③update checks (GitHub). Usage data is never sent anywhere, and fonts are bundled in the app, so the UI renders fine offline too.

  • Update checks can be disabled — on launch it asks GitHub whether a new version exists (your IP and current version are logged there). Turning off Settings → About → Check on startup removes even this traffic. Whether the check is on or off, installation only proceeds when you click it — nothing ever changes silently.


For developers

You can also drive the same wallet from the CLI kura (it shares the MCP server and core logic). It's already inside the installed app, so one line on your PATH and you're set:

sudo mkdir -p /usr/local/bin
sudo ln -sf /Applications/Kura.app/Contents/MacOS/kura-cli /usr/local/bin/kura
kura status

To run from source:

cargo run --manifest-path ./kura-mcp/Cargo.toml --bin kura -- status
cargo run --manifest-path ./kura-mcp/Cargo.toml --bin kura -- balance
cargo run --manifest-path ./kura-mcp/Cargo.toml --bin kura -- history --limit 10
cargo run --manifest-path ./kura-mcp/Cargo.toml --bin kura -- pay <주소> <금액> --token usdc
cargo run --manifest-path ./kura-mcp/Cargo.toml --bin kura -- fetch <URL>

pay/fetch never take a password via the CLI — the Kura app must be running, and a human enters the password in the approval popup.

Tests:

(cd src-tauri && cargo test)        # 백엔드(지갑·암호화·한도·송금)
(cd kura-mcp && cargo test)         # MCP/CLI 어댑터
npx tsc --noEmit && npx vite build  # 프론트

The procedure for producing a release build (signed, notarized DMG) is in docs/RELEASE.md. It needs an Apple Developer account and a one-time setup, and after that it's one line:

./scripts/release.sh

Tech stack

Desktop

Tauri (Rust + web frontend)

Frontend

React + Tailwind CSS, Framer Motion, Lucide, Pretendard

Chain

Base / alloy-rs

Payments

x402 (EIP-3009 off-chain signatures)

AI connect

MCP server (rmcp)

Structure: [Rust core (src-tauri)] ← MCP / CLI adapters (kura-mcp). Only the GUI process has key access (signing) — that's the last line of defense.


License · status

MIT license — since this is code that handles keys and money, I believe it should be something you can read, verify, and modify yourself.

If you find a vulnerability, please report it through the private channel in SECURITY.md before filing an issue. The same document also lists what Kura cannot protect against.

The bundled Pretendard font is under the SIL Open Font License 1.1 (full text).

The number one user is myself — a wallet for Korean developers and creators on Apple Silicon Macs who pay with local LLMs/Claude. It's still an early 0.1.x version, so I recommend learning on the default testnet first and only putting what you can afford to lose on mainnet.

Available Tools

6 tools
get_balancesA

Reads the active account's USDC (for payments) and gas-token balances on the active network (Base mainnet, Arc mainnet, Base Sepolia, or Arc testnet, per the user's setting). The eth field is the gas balance and is ABSENT on chains where gas is paid in USDC itself (Arc) — there the USDC balance already covers gas, so never add the two together. Errors if there is no wallet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so admirably. It discloses that the `eth` field is absent on Arc, warns never to add USDC and eth balances together, and states the error condition if no wallet exists—critical behavior beyond a generic 'reads balances' line.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences: the first states the main purpose, the second explains the crucial Arc nuance, and the third covers failure mode. No filler, and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with no output schema, this is nearly complete. It explains the returned values (USDC and gas balances), names the `eth` field, clarifies the Arc exception, and states the error condition—enough for correct invocation and interpretation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero parameters, so schema coverage is trivially 100%. The description correctly provides no parameter-level detail since none is needed; the baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with 'Reads ... USDC ... and gas-token balances', a specific verb and resource, and immediately scopes to active account and network. It clearly differentiates itself from sibling tools like get_wallet_status or get_history by focusing on balance data, with concrete field semantics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It does not explicitly name alternatives, but it gives clear operational context: which networks apply, the Arc-specific gas behavior, and the no-wallet error condition. This makes the intended use obvious, although no exclusions or 'use X instead' guidance is stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historyA

Returns the active account's recent transaction attempts, newest first. status is one of sent, blocked, failed, signed (x402 signed, awaiting settlement), settled (x402 settled, settle_tx is the settlement tx), settle_failed, unknown (a signed transaction was submitted but the wallet couldn't confirm the chain received it — detail is its tx hash; it may have gone through, so never resend on the strength of this entry alone), or received (money that came in — to is the sender, detail the tx hash; both are empty for ETH a contract sent; found on-chain by the wallet app while it runs, back to 90 days). Use limit to cap how many come back (default 20).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoHow many recent entries to return (default 20, max 200).

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden and discharges much of it: newest-first ordering, the complete status taxonomy with meanings, the settlement semantics of signed/settled, and the important caveat that 'unknown' may have actually gone through. It omits auth/permission requirements and any cursor-based pagination behavior, keeping it out of 5 territory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, and nearly every clause is load-bearing — the status glossary genuinely helps an agent interpret output. It is a single dense run-on with nested parentheticals and repeats the schema's default 20, so it is efficient rather than exemplary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations, the description must explain the return payload, and it does: ordering, the status enum values, and what 'to' and 'detail' hold per status, including the 90-day on-chain backfill window. What remains unstated is the envelope/shape of the response and whether non-status fields exist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single 'limit' parameter is already documented with default 20 and max 200 in the schema. The description only restates 'Use limit to cap how many come back (default 20),' adding no new syntax or edge-case meaning. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Returns the active account's recent transaction attempts, newest first.' That is unambiguous and hard to confuse with get_balances, request_payment, or x402_fetch. It does not explicitly name a sibling to contrast against, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use / when-not-to-use routing against the sibling tools; the agent must infer that this is the history read. It does embed operational guidance ('never resend on the strength of this entry alone' for the unknown status), which is useful, but that is result interpretation rather than tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_wallet_statusA

Returns the wallet's state and address. state is encrypted (normal), legacy, or none. address is the ACTIVE account's address; accounts lists every account in the wallet (index, address, label) and account is the active index. Balances, history, and payment requests all use the active account, and only the user can switch accounts, in the wallet app. No password needed — read only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden of behavioral disclosure. It states 'No password needed — read only', discloses state value semantics, and clarifies that account switching can only be done by the user. These are valuable non-obvious behaviors for an agent. It falls short of 5 only by not mentioning error cases or what happens when no wallet is present, but for this simple read the disclosure is quite adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is about 85 words and front-loads the core action then clarifies the fields. Every sentence contributes: the state vs. address, the accounts list, the active-account context, and the read-only note. There is no filler. One minor phrasing in 'state is encrypted (normal), legacy, or none' could be clearer, but it does not materially hurt readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, this description is the complete contract for what the tool returns. It defines the 'state' enum, 'address', 'accounts' with index/address/label, and 'account' as active index. It also weaves in why this matters for sibling tools and that the user alone can switch accounts. For a parameter-less read-only status call, this is complete enough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

This tool takes 0 parameters and the schema is complete (empty). With no parameters, the description does not need to add parameter meaning. The parameter_semantics baseline for 0 params is thus a 4, and the description has no unnecessary parameter-related bloat.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the verb and resource: 'Returns the wallet's state and address.' It then enumerates exactly which fields are returned (state, address, accounts, account) and even gives possible state values. It differentiates itself from sibling tools by noting that balances, history, and payment requests all use the active account, making clear why this wallet-status read is distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: 'Balances, history, and payment requests all use the active account, and only the user can switch accounts, in the wallet app.' That tells an agent this tool supplies the account context needed before or alongside the sibling calls. It does not explicitly say 'call this before get_balances/get_history/request_payment', nor does it name the alternatives, so it stops short of a full when/when-not instruction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_agentA

Reads an agent's ERC-8004 record from the registry on the active Base network (read-only, on-chain only — the wallet never fetches the agent's website). Give it agent_id, the agent's number in the Identity Registry. Returns: registered, owner, wallet (the registered agentWallet), token_uri and the uri_domain read from it, declared_name (what the record calls itself), and feedback_clients (how many addresses left feedback). Pass pay_to and/or resource to also get a comparison: whether the address equals the registered wallet and whether the resource's domain equals the domain listed on-chain. IMPORTANT: registration is permissionless — anyone can register any name, domain, or wallet, and anyone can leave feedback. Being registered is NOT proof of safety. Only a mismatch is a strong signal, and only when the agent number came from a source you trust (the service's own docs), not from the payment response itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
pay_toNoOptional: an address to compare against the agent's registered wallet.
agent_idYesThe agent's ERC-8004 number (agentId — the Identity Registry NFT token id).
resourceNoOptional: a resource URL whose domain is compared with the domain listed on-chain.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses read-only behavior, that the wallet never fetches the agent's website, the exact return fields, the effect of optional params, and the critical caveat that registration is permissionless and not proof of safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but well-structured: purpose first, return fields, optional usage, then critical warning. Every sentence serves a purpose, including the trust caveat which is essential for correct interpretation. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description provides a full return-field list and explains the trust implications of results. It covers network, parameters, and interpretation, making it complete for correct invocation and result understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds functional meaning for optional parameters by explaining that pay_to and resource trigger comparisons and what those comparisons determine, going beyond the schema's simple type descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Reads') and resource ('agent's ERC-8004 record from the registry on the active Base network'), and clarifies it is read-only and on-chain only. This distinguishes it from sibling tools like x402_fetch, which likely involve off-chain fetching.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context for when to use the tool (verifying an agent's on-chain record) and what optional parameters trigger comparisons. It does not explicitly name alternatives or exclusions, but the read-only, on-chain-only scope and safety caveats give sufficient guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

request_paymentA

Asks the user to make a payment. The wallet app opens an approval window, and the payment is only sent once the user approves it with their password (it waits up to 5 minutes). The one exception is autopay, which the user turns on themselves — only then can a payment be approved automatically, and only within an unlocked session, a small limit, and a trusted address. Arguments: to (recipient address), amount (decimal string), token (USDC by default, or ETH), memo (what the payment is for — the user reads it to decide, so always fill it in), and optionally agent_id (the recipient's ERC-8004 number, if a service told you one — the wallet then shows the user whether the address matches that agent's registered wallet). Per-payment and daily limits and the emergency lock are enforced by the app. Never send a password as an argument — the user types it in the app. Returns: status, tx_hash, detail, and an explorer link. status is approved (the chain accepted the transfer), rejected or failed (nothing was sent — safe to ask again), or unknown: the user approved but the wallet couldn't confirm whether the transfer reached the chain (tx_hash is set when known). unknown means it MAY have been sent — never ask again on your own; tell the user and have them check the history or the tx.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesRecipient address (42 characters, starting with 0x).
memoNoWhat the payment is for — the user reads this in the approval window, so fill it in.
tokenNoToken: "USDC" (default) or "ETH".
amountYesAmount as a decimal string, for example "1.5".
agent_idNoOptional: the recipient's ERC-8004 agent number, if you know it from the service's own documentation or agent card. The wallet reads that agent's on-chain record and tells the user whether the address you are paying is the one registered for that agent. A mismatch is the useful part — a match is not proof of anything, since anyone can register. Leave it out if you don't know it; a wrong number just produces a "no such agent" note.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and does so: approval flow, 5-minute timeout, autopay exception, enforced per-payment/daily limits, emergency lock, and password handling. It also fully maps the status values (approved/rejected/failed/unknown) to their side effects, including the dangerous "unknown means it may have been sent" case.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded with the approval model and the critical status semantics before the parameter recap. It is long, and the argument enumeration duplicates the schema, but almost every sentence carries load-bearing operational or safety information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema and no annotations, the description fully documents the return shape (status, tx_hash, detail, explorer link) and the branching logic an agent must follow for each status. Nothing needed to invoke or react to this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description's "Arguments" list largely restates what the schema already documents verbatim (to, amount, token, memo, agent_id). It adds only marginal framing on memo and agent_id, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb+resource ("Asks the user to make a payment") and immediately describes the mechanism — the wallet's approval window and password confirmation. This human-in-the-loop framing distinguishes it from sibling operations like x402_fetch and get_history without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-not guidance: never re-ask on "unknown", while "rejected or failed" is safe to ask again. Also states the autopay precondition (user-enabled, unlocked session, small limit, trusted address) and the hard rule against passing passwords. No alternative tool is named, so it falls short of the top band.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_fetchA

Fetches an x402 paid resource (a URL). It GETs the URL first; if the server answers 402 Payment Required, it asks the user to approve the required payment (exact scheme, the active network, that chain's USDC) in the wallet app, then re-requests the same URL with the payment header to return the content. If no payment is required (no 402), it just returns the body. Settlement takes one of two shapes, chosen by the server's requirement: a facilitator settles the signed EIP-3009 authorization (no gas from this wallet), or — where gas is paid in USDC itself and the server asks for eip3009-client-broadcast — the wallet broadcasts the transfer itself, so the price AND its gas leave this balance. Approval works exactly as in request_payment (password by default; automatic only when the user has turned autopay on), and the app enforces per-payment and daily limits and the emergency lock. Never send a password as an argument. Arguments: url (required), memo (what the payment is for — the user reads it to decide). Returns: payment, paid, status, http_status, body, and amount/pay_to/settlement when paid; on a chain where the wallet broadcasts the payment itself, tx and explorer point at that transaction (both are empty on the facilitator-settled path). IMPORTANT — decide on payment, which says where the money is: "none" = nothing was paid, trying again is safe (declined, no 402, or "reverted": the chain rejected the transfer and only gas was spent); "confirmed" = the money left the wallet; "unknown" = it MAY have left (status pending/unknown, or settlement_failed on the facilitator path, where the server's refusal doesn't prove the facilitator didn't settle). For confirmed and unknown without content, asking again can pay a second time — stop and tell the user, showing the tx. paid is kept for older callers and is simply payment != "none". Read notice when present, and never retry on an HTTP status alone: after the money moved the server may answer with a fresh 402 challenge that reads as if the payment never happened.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesURL of the paid resource to fetch (http/https).
memoNoWhat the payment is for — the user reads this in the approval window, so fill it in.
agent_idNoOptional: the seller's ERC-8004 agent number, if you know it from the service's own documentation or agent card. The wallet then reads that agent's on-chain record and shows the user whether the payment address and the resource domain match what is registered. Leave it out if you don't know it — a wrong number just produces a "no such agent" note.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does it thoroughly: password-by-default vs autopay approval, per-payment/daily limits, emergency lock, the two settlement paths and which one spends gas from this wallet, and the 'never send a password as an argument' constraint. This is exactly the behavioral disclosure an unannotated tool needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded and almost every sentence carries load-bearing semantics (settlement paths, payment-field triage, retry hazards). However, it is delivered as one dense block mixing return values, gas behavior, and retry policy, which slightly hinders scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by enumerating the return fields (payment, paid, status, http_status, body, amount/pay_to/settlement, tx, explorer) and the triage semantics of `payment`. For a high-complexity payment tool, nothing an agent needs to call and interpret it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 and the schema already documents url, memo, and agent_id. The description reinforces memo's purpose ('the user reads it to decide') but adds no syntax or format details beyond the schema, so it does not exceed baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetches an x402 paid resource') and immediately distinguishes itself from the payment-request flow by contrasting with request_payment's approval behavior. An agent can tell exactly what this does versus the sibling read/status tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context on both execution paths (with/without a 402) and explicit retry guidance — 'decide on `payment`', 'never retry on an HTTP status alone', 'stop and tell the user'. It names request_payment as the reference for approval semantics. It stops short of an explicit when-not-to-use or a full alternative list, so not a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.4.1
    • Changedget_history2 fields changed
      • removedInput schema / properties / limit / default
        Removed value: -null
      • removedInput schema / properties / limit / nullable
        Removed value: -true
    • Changedlookup_agent4 fields changed
      • removedInput schema / properties / pay_to / default
        Removed value: -null
      • removedInput schema / properties / pay_to / nullable
        Removed value: -true
      • removedInput schema / properties / resource / default
        Removed value: -null
      • removedInput schema / properties / resource / nullable
        Removed value: -true
    • Changedrequest_payment6 fields changed
      • removedInput schema / properties / agent_id / default
        Removed value: -null
      • removedInput schema / properties / agent_id / nullable
        Removed value: -true
      • removedInput schema / properties / memo / default
        Removed value: -null
      • removedInput schema / properties / memo / nullable
        Removed value: -true
      • removedInput schema / properties / token / default
        Removed value: -null
      • removedInput schema / properties / token / nullable
        Removed value: -true
    • Changedx402_fetch4 fields changed
      • removedInput schema / properties / agent_id / default
        Removed value: -null
      • removedInput schema / properties / agent_id / nullable
        Removed value: -true
      • removedInput schema / properties / memo / default
        Removed value: -null
      • removedInput schema / properties / memo / nullable
        Removed value: -true
  2. 1 tool updatev0.4.0
    • Changedrequest_payment1 field changed
      • addedInput schema / properties / agent_id
        Added value: +{
        +  "default": null,
        +  "description": "Optional: the recipient's ERC-8004 agent number, if you know it from the service's own\ndocumentation or agent card. The wallet reads that agent's on-chain record and tells the\nuser whether the address you are paying is the one registered for that agent. A mismatch\nis the useful part — a match is not proof of anything, since anyone can register.\nLeave it out if you don't know it; a wrong number just produces a \"no such agent\" note.",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "nullable": true,
        +  "type": "integer"
        +}
  3. 2 tool updatesv0.3.0
    • Addedlookup_agent
    • Changedx402_fetch1 field changed
      • addedInput schema / properties / agent_id
        Added value: +{
        +  "default": null,
        +  "description": "Optional: the seller's ERC-8004 agent number, if you know it from the service's own\ndocumentation or agent card. The wallet then reads that agent's on-chain record and shows\nthe user whether the payment address and the resource domain match what is registered.\nLeave it out if you don't know it — a wrong number just produces a \"no such agent\" note.",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "nullable": true,
        +  "type": "integer"
        +}
  4. 5 tool updatesv0.2.0
    • First observedget_balances
    • First observedget_history
    • First observedget_wallet_status
    • First observedrequest_payment
    • First observedx402_fetch

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a clearly distinct capability: balance reading, wallet/account state, transaction history, initiating payments, x402 paid fetches, and ERC-8004 agent lookup. The only mild adjacency is get_balances vs get_wallet_status, but their descriptions clearly separate numeric balances from wallet/account state.

Naming Consistency4/5

Five of six tools follow a clean snake_case verb/noun pattern (get_balances, get_wallet_status, get_history, request_payment, lookup_agent). x402_fetch breaks the verb-first convention by leading with a protocol name, a minor deviation that is still readable.

Tool Count5/5

Six tools is well-scoped for a wallet/payment server, with each tool earning a distinct place (three read tools plus three action/lookup tools). Nothing feels redundant or padded.

Completeness4/5

The surface covers the core wallet lifecycle: check state, read balances, review history, request payments, pay for x402 resources, and verify agent identity. Gaps are deliberately out of scope (account switching and limits are user-only in the app), so no dead ends for an agent's expected workflow.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Gives AI agents a smart-contract wallet on Base (USDC) with 10 stdio tools: create wallets, send USDC payments, pay x402-protected HTTP resources, and run ERC-8183 escrow Jobs for A2A service delivery.
    10
    12 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    A budget-bound x402 payment wallet for AI agents: it autonomously pays HTTP 402 payment-gated URLs across every major chain (EVM, Solana, and many non-EVM families). Self-custodial and backendless, your key, your RPC, with spend caps enforced before any on-chain send.
    8
    9
    MIT