# Z-ZERO MCP β€” Payment Infrastructure for Agentic Commerce (USDC on Base, gasless) [![MCP Badge](https://lobehub.com/badge/mcp/dempty-glitch-z-zero-mcp)](https://lobehub.com/mcp/dempty-glitch-z-zero-mcp) [![npm](https://img.shields.io/npm/v/z-zero-mcp-server)](https://www.npmjs.com/package/z-zero-mcp-server) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) **AI Agents today can plan, reason, and code β€” but they are financially blind.** They cannot hold money, make payments, or prove their trustworthiness. Every purchase still requires a human to copy-paste a credit card number. Z-ZERO fixes that. One MCP server gives your agent (Claude, Cursor, any MCP-compatible client) two payment rails β€” **gasless USDC on Base** for crypto-native checkouts, and **JIT single-use virtual cards** for the 99% of the web that only takes cards β€” while the model **never sees a real card number**. ```bash npx z-zero-mcp-server ``` **What makes it different:** - πŸ” **Zero-trust by design** β€” the AI never sees PAN, CVV, or expiry. Card data exists only in RAM, injected via Playwright at the last step, then wiped. - β›½ **Gasless USDC on Base** β€” auto-detects crypto checkout (EIP-681) and settles as a gasless USDC transfer sponsored by Coinbase Paymaster. The agent holds only USDC β€” no ETH, no gas UX. - πŸ’³ **JIT single-use virtual cards** β€” amount-locked, 1-hour TTL, burned after a single use. Fiat fallback for the rest of the web. - 🧠 **Smart Routing + checkout intelligence** β€” `get_merchant_hints` serves platform-specific checkout playbooks (Shopify, Etsy, WooCommerce…). - ✍️ **Linked purpose + outcome** β€” the server signs the criteria the agent records at issuance. Before checkout, `execute_payment` hands those criteria back and requires a second call with `go` or `pause`; a confirmed purchase seals the answer into the signed receipt. The record is inspectable without pretending the platform judged whether the agent told the truth. - πŸ”„ **Structured failure labels** β€” failed checkouts are labeled with a fixed 14-class `failure_class` (automatically, not only when an agent remembers to report) and stored as evidence for the merchant knowledge base. Facts are promoted into shared hints only after a later outcome or review verifies them. --- ## Live on Base Mainnet - βœ… Proof β€” real gasless USDC transfer on Base mainnet: [`0xdfd1f2f8…5d7a`](https://basescan.org/tx/0xdfd1f2f824e1232c3e03c52485332570ff01fbb0340c5571f699ed1218735d7a) - Onboarding is just "deposit USDC" β€” no seed phrases in the agent, no native gas token, no exchange account. --- ## How It Works ``` User AI Agent MCP Tools Z-ZERO API β”‚ β”‚ β”‚ β”‚ β”‚ "Buy me this β”‚ β”‚ β”‚ β”‚ Shopify item" β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ β”‚ β”‚ read mcp://resources/sop (MANDATORY) β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ │◀── platform rules ──── β”‚ β”‚ β”‚ + payment SOP β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ get_merchant_hints("_platform_shopify") β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ GET /checkout-hints β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ │◀── pre_steps+notes ───◀──── hints data ────── β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ (fills shipping form, reaches payment page) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ request_payment_token(amount, cart, criteria)β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ │◀── temp_auth token ─── (1-hour TTL) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ execute_payment(token, checkout_url) β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ │◀── purpose_check ───── (nothing charged) β”‚ β”‚ β”‚ compare locked criteria with final page β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ execute_payment(..., recheck: go | pause) β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ β”‚ pause β†’ no card is filled β”‚ β”‚ β”‚ go β†’ Playwright fills + submits, β”‚ β”‚ β”‚ then burns token if confirmed πŸ”₯ β”‚ β”‚ │◀──── βœ… success ────── β”‚ β”‚ "Done! Your item β”‚ β”‚ β”‚ β”‚ is ordered." β”‚ β”‚ β”‚ │◀────────────────── β”‚ β”‚ ``` *The AI agent never touches card data β€” it only handles single-use tokens. Real card details are injected by Playwright at the last step and wiped from RAM.* > **Crypto checkout branch:** when `auto_pay_checkout` detects a crypto-native checkout (EIP-681), it skips the card flow entirely and settles as a **gasless USDC transfer on Base** β€” see above. --- ## Why Z-ZERO Z-ZERO is not a checkout bot β€” it's payment infrastructure for the agentic-commerce era (agentic transactions are projected to reach **$1.5T by 2030** β€” Juniper Research). **Today**, the web is built for humans: agents must fill forms and click buttons, and every purchase still needs a human's card. Z-ZERO solves that now β€” JIT single-use virtual cards + gasless USDC on Base, with card data isolated from the model. **Tomorrow**, agent payments become a standardized protocol β€” and what we build along the way is the long-term value: - **Shared checkout intelligence** β€” every transaction (and every failure) makes the network smarter. - **An open standard for agent payments** β€” any agent platform plugs in via MCP; any rail (cards, USDC, x402) can be added. - **KYA β€” Know Your Agent** β€” verifiable agent reputation. The question isn't "can this agent pay?" but "should you trust it to?" πŸ“– Full vision & architecture: [The Z-Zero Whitebook](https://z-zero.xyz/whitebook) --- ## Quick Install (Recommended) ```bash npx z-zero-mcp-server ``` Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "z-zero": { "command": "npx", "args": ["-y", "z-zero-mcp-server@latest"], "env": { "Z_ZERO_API_KEY": "zk_live_your_passport_key_here" } } } } ``` Get your Passport Key at: **[z-zero.xyz/dashboard/agents](https://z-zero.xyz/dashboard/agents)** --- ## Security: rotate-on-connect (v1.5.0+) The key you copy from the dashboard (or paste into a chat) is only a **one-time bootstrap ticket**. The moment your agent connects with it, the MCP server silently swaps it for a fresh key: - The fresh key travels **server β†’ MCP process β†’ disk** and is stored in `~/.z-zero/credentials` (mode `0600`). It never appears in any LLM conversation, tool result, or config file. - The pasted key is **dead within seconds** β€” a copy living in a chat transcript, clipboard, or screenshot can no longer be used by anyone. - On startup the MCP loads the key from `~/.z-zero/credentials` first; the `Z_ZERO_API_KEY` env var is only a bootstrap fallback. **One key = one machine.** All agents on the same machine (Claude Desktop, Claude Code, Cursor, …) share the same MCP install and the same credentials file β€” install once, every agent can pay. Connecting a *different* machine with a copied key rotates it, which instantly disconnects the original machine. That is deliberate: it blocks key sharing **and** doubles as an intrusion alarm β€” if your agent suddenly fails auth, someone else used your key; go to the dashboard and revoke. Older self-hosted backends without the rotate endpoint keep working β€” the pasted key simply stays active as before. --- ## Requirements - **Node.js v18+** β€” [nodejs.org](https://nodejs.org) - **Passport Key** β€” starts with `zk_live_`, get it from the dashboard above --- ## Available MCP Tools ### Group 1 β€” Wallet Config (Passive) | Tool | Description | |------|-------------| | `list_cards` | List all virtual card aliases and balances | | `check_balance` | Check spendable USD balance for a card alias | | `get_deposit_addresses` | Get your Base deposit address to top up with USDC (stablecoin on Base) | | `set_api_key` | Activate a new Passport Key instantly, no restart needed | | `show_api_key_status` | Check if a Passport Key is currently loaded (prefix only) | ### Group 2 β€” Manual Card Payment (Active) | Tool | Description | |------|-------------| | `request_payment_token` | Issue a JIT single-use virtual-card token for a specific amount (1hr TTL). Pass `cart`, `criteria`, and `ship_to` to create the signed issuance record | | `execute_payment` | **Two calls required:** first without `recheck` returns the locked criteria and charges nothing; second supplies `recheck: { page_shows, decision: go\|pause }`. `pause` does not fill the card; confirmed `go` returns a signed receipt | | `cancel_payment_token` | Cancel an unused token and refund to wallet | | `request_human_approval` | Pause and request human confirmation before proceeding | ### Group 3 β€” Smart Autopilot | Tool | Description | |------|-------------| | `auto_pay_checkout` | Fully autonomous checkout β€” auto-detects Web3 or Fiat and completes payment | | `get_merchant_hints` | Fetch platform-specific checkout playbook (pre-steps + selectors) from Knowledge Base | | `report_checkout_fail` | Report a failed checkout with a **structured `failure_class`** (14-class enum) β€” feeds the self-healing loop | | `verify_receipt` | Verify a signed receipt by id β€” prove a purchase happened instead of claiming it | > πŸ“– **Note:** Version checking is handled automatically in each API call. No separate tool needed. --- ## Agent primitives (v1.9.0) Four linked records and controls an agent can use here that it cannot get from a normal virtual card alone. ### 1. Signed intent β€” the card knows what it is for Pass the cart when you request a token: ```jsonc request_payment_token({ card_alias: "Card_01", amount: 44.00, merchant: "etsy.com", cart: [{ title: "Ceramic mug β€” matte white", qty: 2, unit_price: 18.50 }], ship_to: "12 Nguyen Hue, District 1, Ho Chi Minh City, VN", criteria: { source: "user_described", items: [ { key: "item", stated: "two matte-white ceramic mugs" }, { key: "max_total", stated: "no more than $44 delivered" } ] } }) ``` Z-ZERO signs that statement (EIP-191) during issuance. It is a tamper-evident record of the criteria the agent supplied as the owner's instruction β€” not an independent proof that the human personally approved every line. The shipping address is stored as a hash, never raw. **Before you request a token, compare the checkout page with what the user actually asked for** β€” same items, same quantity, same variant, same destination. A mismatch you catch there costs nothing. After the token, it costs a card. ### 2. Purpose check β€” read first, then declare `go` or `pause` `execute_payment` is deliberately a two-call tool: ```jsonc // Call 1 β€” omit recheck. No browser, PAN, or charge. execute_payment({ token, checkout_url, actual_amount: 44.00 }) // β†’ { status: "purpose_check", nothing_charged: true, owner_asked_for: ... } // Call 2 β€” describe the final page and make an explicit decision. execute_payment({ token, checkout_url, actual_amount: 44.00, recheck: { page_shows: "2 matte-white mugs, delivered total $44.00", decision: "go" } }) ``` Use `decision: "pause"` when anything differs. The card is not filled and the token remains active and refundable. On `go`, the checkout runs; if the merchant confirms the order, the declaration is sealed into the signed receipt with the outcome. The platform records what the agent declared; it does not independently inspect the page or certify that the declaration was true. ### 3. Signed receipt β€” prove the purchase, don't claim it On a confirmed payment you get back: ```jsonc "signed_receipt": { "receipt_id": "8ea36791-…", "receipt_hash": "0x…", "match": { "total": "over", "domain": "ok" }, "diff": [{ "field": "total", "expected": 44.00, "observed": 46.75 }], "verify_url": "https://z-zero.xyz/receipt/8ea36791-…" } ``` `diff` is the part that matters: it is what the merchant actually did versus what was authorized. Share `verify_url` with the user β€” the page is public and anyone can check it. Verification is three checks: the signature is valid, the signer is Z-ZERO, and the fields shown still hash to what was signed (so editing the record afterwards is detectable, including by us). **What a valid receipt does and does not prove.** It proves the record is signed by Z-ZERO and unaltered. It does not by itself prove the merchant charged what the receipt says β€” most fields start life as the agent's reading of a web page. Every receipt therefore carries `provenance` per field: `zzero_issued` (the limit we set), `issuer_captured` (confirmed by the card issuer's capture webhook β€” settlement evidence), `agent_reported` (unverified), `human_verified`. Until the capture webhook lands, this is a **signed execution receipt**, not settlement proof, and it says so. ### 4. Structured failure classes β€” every failure teaches the network `report_checkout_fail` takes a fixed enum, not free text: `card_declined_issuer` Β· `card_declined_bin_block` Β· `avs_mismatch` Β· `3ds_required` Β· `bot_detected` Β· `form_changed` Β· `price_changed` Β· `out_of_stock` Β· `shipping_unsupported` Β· `login_required` Β· `timeout` Β· `outcome_unconfirmed` Β· `intent_mismatch` Β· `unknown` Failed runs are also labeled automatically from the browser outcome, so the network learns even when nobody remembers to report. Card numbers are redacted at capture β€” they never reach a log, screenshot or DOM dump. --- ## REST API Reference The Z-ZERO backend is hosted at `https://z-zero.xyz`. All endpoints require a `Bearer` token using your Passport Key. > ⚠️ **Use the MCP tools above instead of calling REST directly.** If you must call REST, use the exact paths below. ### `GET /api/tokens/cards` Returns your card list, balance, and deposit addresses. ```bash curl -X GET "https://z-zero.xyz/api/tokens/cards" \ -H "Authorization: Bearer zk_live_your_key" ``` **Aliases (also work):** - `GET /api/v1/cards` ← for agents that guess REST-style paths ### `POST /api/tokens/issue` Issue a JIT payment token. ### `POST /api/tokens/resolve` Resolve a token to card data (server-side only). ### `POST /api/tokens/burn` Burn a used token. ### `POST /api/tokens/cancel` Cancel an unused token (refunds balance). --- ## Troubleshooting ### "Z_ZERO_API_KEY is missing" 1. Go to [z-zero.xyz/dashboard/agents](https://z-zero.xyz/dashboard/agents) 2. Copy your Passport Key (starts with `zk_live_`) 3. Add it to your config as `Z_ZERO_API_KEY` 4. **Restart** Claude Desktop / Cursor ### "Invalid API Key" (401) - Double-check you copied the full key (e.g. `zk_live_c0g3l`) - Make sure there are no extra spaces or line breaks ### "404 Not Found" on `/api/v1/cards` - This is a legacy path alias β€” it should now work. If not, use `/api/tokens/cards` directly. --- *Security: the key you paste is never kept β€” it rotates the moment your agent first connects, and the fresh key lives only in a local owner-only file (`~/.z-zero/credentials`, mode 0600), never in any LLM conversation. Card data exists only in volatile RAM during execution.*