Skip to main content
The x402 Agent is a TypeScript client for the x402 payment protocol (v2) that gives any autonomous agent the ability to pay for HTTP 402-protected resources using a Fireblocks vault. It handles the full payment loop: detecting the 402 Payment Required response, constructing and signing the EIP-712 payment payload via Fireblocks, and retrying the original request with proof of payment. Gasless signing happens off-chain — the agent never submits an on-chain transaction itself. Source: github.com/fireblocks/x402-agent Ships in two forms: an MCP server for Claude Desktop, Cursor, and other MCP clients, and a CLI for scripting and testing payment flows from the terminal. Before production use, combine the four security layers in Secure deployment so the agent can only spend what you explicitly allow.

Requirements

  • Node.js 18+
  • Fireblocks API account with a vault configured
  • Sufficient token balance on the target network (for example, USDC on Base)

How it works

Payment sequence

The agent never calls the facilitator directly. It sends signed payment headers to the merchant server; the merchant’s x402 middleware calls the facilitator to verify and settle on-chain.
  1. Initial request — Agent sends GET to the resource server.
  2. 402 Payment Required — Resource server returns a PaymentRequired JSON body with accepts[] payment options.
  3. (Optional) Integrity check — Agent verifies the envelope against the facilitator’s did:web key (see Payment Instruction Integrity).
  4. Select mechanism — Agent picks the first supported accepts[] entry (preference: eip3009permit2; overridable via MECHANISM).
  5. Build and sign EIP-712 — Agent constructs typed data locally and signs via Fireblocks.
  6. Retry with signature — Agent resends the GET with a PAYMENT-SIGNATURE header. Resource server settles the payment and returns the resource with a PAYMENT-RESPONSE receipt header.
Two round-trips total: the initial 402, then the retry with signature.

Transfer mechanisms

ERC-7710 delegation is not supported — Fireblocks cannot sign delegation payloads. Permit2 supports two schemes, chosen by the server in the 402 accepts[].scheme field:
  • exact — authorizes the merchant to pull exactly the amount in the 402 body. Recommended default.
  • upto — authorizes the merchant to pull up to the amount in the 402 body (the actual debit is decided by the facilitator at settlement time). Useful for variable-cost endpoints, but gives the merchant discretion within the cap. Pair with tighter Policy Engine rules if you use it.

Payment Instruction Integrity

The agent can verify that the PaymentRequired body wasn’t tampered with between the facilitator and the client.
  • The facilitator emits a base64url-encoded envelope on PaymentRequired.integrity (also mirrored on the X-402-Integrity response header).
  • The envelope is signed ES256 (P-256) and the key is resolved via did:web.
  • Canonical bytes: SHA-256( JCS({x402Version, accepts}) || "\n" || iat || "\n" || exp ).
  • resource.url, error, and extensions are intentionally excluded from the signed slice.
Set VERIFY_INTEGRITY=true for best-effort verification (warns if missing or invalid), or REQUIRE_INTEGRITY=true to abort when the envelope is absent or invalid. The require_integrity parameter on x402_get_and_pay enforces integrity for a single call and cannot relax env settings.

Get started

Place your Fireblocks private key at the path referenced by FIREBLOCKS_PRIVATE_KEY_PATH.

Usage

MCP server

The MCP server exposes four tools: Start the server (stdio):

Connect to Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) — use absolute paths. Windows config lives at %APPDATA%\Claude\claude_desktop_config.json; Linux at ~/.config/Claude/claude_desktop_config.json.
Restart Claude Desktop to pick up the server.

Test with MCP Inspector

Example prompts

x402_get_and_pay options

Auto selection picks the best-funded option in preference order: eip-3009permit2. Set MECHANISM=permit2 to force a specific mechanism. Manual selection returns the full list of funded options when more than one is available. Re-call with option_index=<N> to complete the payment.

CLI

Run a one-shot payment from the terminal:
Or invoke directly with npx (no global install):
For a production build:

Secure deployment

The agent never custodies keys — it asks Fireblocks to sign. Combine four controls so the agent can only spend what you’ve explicitly allowed, even if the host running it is compromised or an LLM driving it goes off-rails.

Provision a scoped Fireblocks API user

Grant only the minimum permissions the agent actually needs. Create a dedicated API user in the Fireblocks Console — don’t reuse a workspace-admin key. See the official Fireblocks guides on creating a new API user and best practices for choosing user roles.
  • Role: Signer (or any role limited to Create Transaction / signing operations). No policy edit, no user management, no workspace admin.
  • Vault scope: Restrict to a single dedicated vault used only for x402 spend. Keep its balance small — top it up as needed rather than parking your treasury there.
  • IP allowlist: Add the machine(s) that will run the agent.
  • CSR / API key fingerprint: Record both so you can rotate confidently.

Store the API credentials securely

The Fireblocks API key and its private signing key file are highly sensitive credentials.
API credentials must never be shared publicly — not in commits, not in chat transcripts, not in screenshots.
Store the private key file with restricted access (chmod 600), preferably outside the repo, and never bake it into a container image. The agent reads FIREBLOCKS_API_KEY (the API user ID, a UUID) and FIREBLOCKS_PRIVATE_KEY_PATH (path to the API user’s private signing key). Treat both like production secrets. Never commit .env, .secrets/, the API user PEM, or the rendered .mcp.json (the project’s .gitignore already excludes these — keep it that way).

Enforce human-in-the-loop signing via the Policy Engine

This is the strongest control and the one most worth setting up. The Fireblocks Policy Engine (TAP) gates every signing request at the Fireblocks side — not in agent code — so it survives a compromise of the agent host or its API key. See the Fireblocks rule parameters guide for the full schema. Recommended rules for an x402 agent vault:
  • Whitelist destinations. Allow only the asset types and recipient addresses you expect (for example, USDC on Base to specific facilitator settlement contracts). Deny everything else.
  • Per-tx amount cap matched to a single x402 micropayment (for example, ≤ 1 USDC).
  • Per-period velocity cap (hourly / daily) matched to the agent’s autonomous budget.
  • Designate a manual signer / approver above a threshold. Configure the policy to require a designated approver for any transaction above your auto-sign threshold; approvals are pushed to the Fireblocks mobile app and enforced cryptographically by the policy, not by trust in the agent code. This is the canonical Fireblocks human-in-the-loop pattern (same approach recommended by the fireblocks-mcp server).
  • 2-eyes for any change to the policy itself so a compromised admin can’t widen the rules silently.

Constrain the agent at the application layer

These are defense-in-depth — the Policy Engine is still the source of truth. Useful for autonomous-agent flows where the URL or LLM context can’t be trusted:
  • Fireblocks base-URL allowlist (on by default). FIREBLOCKS_BASE_URL must be HTTPS under *.fireblocks.io. The Fireblocks SDK does not validate this URL itself, and its signed JWT only binds the request path — not the host — so an attacker who tampers with FIREBLOCKS_BASE_URL (via a poisoned .env, shell compromise, or CI env injection) could MITM the API channel and replay signed requests against the real Fireblocks within the 55s JWT validity window. For private / alternative endpoints, set FIREBLOCKS_BASE_URL_ALLOWED_HOSTS=host1,host2 with the exact additional hostnames you trust.
  • SSRF guard (on by default). Every outbound URL is validated before any request is made: non-http/https schemes are rejected, and IP literals or DNS results in private / loopback / link-local / metadata-range space (including 169.254.169.254, GCP metadata.google.internal, Alibaba 100.100.100.200, IPv6 fc00::/7 / fe80::/10 / ::1) are blocked. HTTP redirects (maxRedirects: 0) are disabled so a 3xx can’t bypass the upfront check. Set ALLOW_LOCAL_TARGETS=true only for local development.
  • ALLOWED_MERCHANT_HOSTS — agent refuses any request whose host isn’t in the comma-separated list. Recommended whenever the URL can come from an LLM or external feed.
  • REQUIRE_CONFIRM=true (MCP only) — x402_get_and_pay returns a payment preview and refuses to sign until called again with confirmed=true.
  • REQUIRE_INTEGRITY=true — refuse to sign 402 responses that fail Payment Instruction Integrity verification.
  • Prefer Permit2 exact over upto unless you specifically need variable-cost semantics.

Troubleshooting

References