@quackai/q402-mcp 0.7.6 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +9 -9
  2. package/dist/index.js +42 -25
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # @quackai/q402-mcp
2
2
 
3
- > MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 9 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.
3
+ > MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 10 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@quackai/q402-mcp.svg)](https://www.npmjs.com/package/@quackai/q402-mcp)
6
6
  [![license](https://img.shields.io/npm/l/@quackai/q402-mcp.svg)](./LICENSE)
7
7
 
8
8
  > **🎟️ Free trial available (2026-05-19 → 2026-06-30)** — 2,000 gasless transactions on BNB Chain (USDC + USDT), 30-day window, no card. One wallet signature: <https://q402.quackai.ai>.
9
9
  >
10
- > **Trial-scope policy:** API keys minted under the free-trial program (`plan: "trial"`) are restricted to BNB Chain with USDC/USDT — server-side enforcement, returns `403 TRIAL_BNB_ONLY` otherwise. **Paid API keys see the full 9-chain matrix at all times.**
10
+ > **Trial-scope policy:** API keys minted under the free-trial program (`plan: "trial"`) are restricted to BNB Chain with USDC/USDT — server-side enforcement, returns `403 TRIAL_BNB_ONLY` otherwise. **Paid API keys see the full 10-chain matrix at all times.**
11
11
 
12
- Quote → route → (optional) settle stablecoin payments across 9 EVM chains, from any MCP client. Recipient gets the full amount; sender pays $0 gas via [Q402](https://q402.quackai.ai)'s EIP-7702 relayer.
12
+ Quote → route → (optional) settle stablecoin payments across 10 EVM chains, from any MCP client. Recipient gets the full amount; sender pays $0 gas via [Q402](https://q402.quackai.ai)'s EIP-7702 relayer.
13
13
 
14
14
  ---
15
15
 
@@ -77,7 +77,7 @@ Create `~/.q402/mcp.env` yourself with the template below. Live mode only flips
77
77
 
78
78
  # ── API key (pick one or both for auto-routing) ──
79
79
  Q402_TRIAL_API_KEY= # Free Trial, BNB only (from /event)
80
- Q402_MULTICHAIN_API_KEY= # Paid Multichain, all 9 chains (from /payment)
80
+ Q402_MULTICHAIN_API_KEY= # Paid Multichain, all 10 chains (from /payment)
81
81
 
82
82
  # ── Signing path — pick ONE of Mode A / B / C ──
83
83
  # Mode A: your MetaMask EOA's hex private key.
@@ -143,7 +143,7 @@ Then export the values in `~/.zshrc` / `~/.bashrc`. See the [Codex config refere
143
143
 
144
144
  `q402_quote` works with zero configuration — no API key, no private key, no env file. Ask:
145
145
 
146
- > *"Compare gas costs to send 50 USDC to vitalik.eth across all 9 Q402 chains."*
146
+ > *"Compare gas costs to send 50 USDC to vitalik.eth across all 10 Q402 chains."*
147
147
 
148
148
  ---
149
149
 
@@ -193,12 +193,12 @@ Template `q402_doctor` writes to `~/.q402/mcp.env`:
193
193
  # ── API key — fill ONE (or both for auto-routing) ──
194
194
  # Auto-routing (same for q402_pay AND q402_batch_pay):
195
195
  # chain="bnb" + Q402_TRIAL_API_KEY set → Trial (free sponsored)
196
- # anything else → Multichain (paid 9-chain)
196
+ # anything else → Multichain (paid 10-chain)
197
197
  # Batch ambiguity: 6+ recipient BNB batch with Trial set returns
198
198
  # status="ambiguous" instead of executing — agent asks user to pick.
199
199
  # Override per call with keyScope: "auto" | "trial" | "multichain".
200
200
  Q402_TRIAL_API_KEY= # BNB-only sponsored Trial key (from /event)
201
- Q402_MULTICHAIN_API_KEY= # paid 9-chain key (per-chain Gas Tank)
201
+ Q402_MULTICHAIN_API_KEY= # paid 10-chain key (per-chain Gas Tank)
202
202
 
203
203
  # ── Signing path — pick ONE of Mode A / B / C ──
204
204
  Q402_PRIVATE_KEY= # Mode A: real EOA pk (0x + 64 hex)
@@ -236,7 +236,7 @@ Combined with `confirm: true` + live-mode env, a payment needs: chat OK + amount
236
236
  | Env var | Required for | Notes |
237
237
  |---|---|---|
238
238
  | `Q402_TRIAL_API_KEY` | live-pay (BNB) | BNB-only sponsored Trial key. Free at https://q402.quackai.ai/event. Auto-routed for `chain="bnb"` in both `q402_pay` and `q402_batch_pay` (≤5 recipients) when set. 6+ recipient BNB batches return `status="ambiguous"` so the agent can ask the user how to split. |
239
- | `Q402_MULTICHAIN_API_KEY` | live-pay (9-chain) | Paid 9-chain key. Get one at https://q402.quackai.ai/payment. Auto-routed for non-BNB chains AND for BNB when no Trial key is set. Cap: 20 recipients per batch. Required for Mode C (server-managed Agent Wallet). |
239
+ | `Q402_MULTICHAIN_API_KEY` | live-pay (10-chain) | Paid 10-chain key. Get one at https://q402.quackai.ai/payment. Auto-routed for non-BNB chains AND for BNB when no Trial key is set. Cap: 20 recipients per batch. Required for Mode C (server-managed Agent Wallet). |
240
240
  | `Q402_PRIVATE_KEY` | Mode A | Hex private key of your MetaMask EOA. Signer for local Mode A. **Never share. Never paste in chat.** |
241
241
  | `Q402_AGENTIC_PRIVATE_KEY` | Mode B | Exported Agent Wallet hex private key from the dashboard (Agent tab → Export). Signs locally, but the signer is your dedicated Agent Wallet — MetaMask is never touched. **Never share. Never paste in chat.** |
242
242
  | `Q402_AGENT_WALLET_ADDRESS` | Mode C (optional) | When you have multiple server-managed Agent Wallets (max 10 per owner), set this to the lowercased 0x… address of the one Q402 should spend from. Omit to use the default wallet. Ignored in Modes A/B. |
@@ -274,7 +274,7 @@ If you set up Q402 before v0.5.0 you may have a single `Q402_API_KEY` env var. T
274
274
 
275
275
  AI agents are becoming the default interface for software, but the moment they need to move money the stack breaks: holding gas tokens, signing every transaction, managing wallets across many chains. None of that scales when the agent is supposed to act on its own.
276
276
 
277
- Q402 is the payment layer for that gap. A single signing primitive (EIP-712 + EIP-7702) settles gasless stablecoin payments across 9 EVM chains, with an ECDSA-signed Trust Receipt for every transaction. The MCP package exposes that surface inside Claude, Codex, Cursor, and Cline — your agent can quote, send, batch, and audit payments from a natural-language prompt.
277
+ Q402 is the payment layer for that gap. A single signing primitive (EIP-712 + EIP-7702) settles gasless stablecoin payments across 10 EVM chains, with an ECDSA-signed Trust Receipt for every transaction. The MCP package exposes that surface inside Claude, Codex, Cursor, and Cline — your agent can quote, send, batch, and audit payments from a natural-language prompt.
278
278
 
279
279
  Single transfers and multi-recipient batches ship today. The next layer — recurring payouts, conditional execution, and policy-gated treasury automation — is the same primitive composed differently. We're building toward agents that operate real budgets, settle among themselves, and move value through workflows no human triggers manually.
280
280
 
package/dist/index.js CHANGED
@@ -124,7 +124,7 @@ function loadConfig() {
124
124
  const walletIdRaw = ENV.Q402_AGENT_WALLET_ADDRESS ?? ENV.Q402_WALLET_ID;
125
125
  if (!ENV.Q402_AGENT_WALLET_ADDRESS && ENV.Q402_WALLET_ID) {
126
126
  process.stderr.write(
127
- "[q402-mcp] Q402_WALLET_ID is deprecated \u2014 rename to Q402_AGENT_WALLET_ADDRESS. Old name will be removed in v0.8.0.\n"
127
+ "[q402-mcp] Q402_WALLET_ID is deprecated \u2014 rename to Q402_AGENT_WALLET_ADDRESS. Old name will be removed in a future release.\n"
128
128
  );
129
129
  }
130
130
  const walletId = typeof walletIdRaw === "string" && walletIdRaw.length > 0 ? walletIdRaw.toLowerCase() : null;
@@ -211,7 +211,7 @@ var isValidPrivateKey = (s) => typeof s === "string" && PRIVATE_KEY_RE.test(s);
211
211
 
212
212
  // src/version.ts
213
213
  var PACKAGE_NAME = "@quackai/q402-mcp";
214
- var PACKAGE_VERSION = "0.7.6";
214
+ var PACKAGE_VERSION = "0.8.1";
215
215
 
216
216
  // src/tools/quote.ts
217
217
  import { z } from "zod";
@@ -226,7 +226,8 @@ var CHAIN_KEYS = [
226
226
  "mantle",
227
227
  "injective",
228
228
  "monad",
229
- "scroll"
229
+ "scroll",
230
+ "arbitrum"
230
231
  ];
231
232
  var CHAIN_CONFIG = {
232
233
  avax: {
@@ -359,6 +360,22 @@ var CHAIN_CONFIG = {
359
360
  supportedTokens: ["USDC", "USDT"],
360
361
  approxGasCostUsd: 1e-3,
361
362
  note: "zkEVM L2 \u2014 EIP-7702 live since the Euclid Phase 2 upgrade (2025-04-22). Data-availability cost dominates per-tx gas."
363
+ },
364
+ arbitrum: {
365
+ key: "arbitrum",
366
+ name: "Arbitrum One",
367
+ chainId: 42161,
368
+ domainName: "Q402 Arbitrum",
369
+ implContract: "0x2fb2B2D110b6c5664e701666B3741240242bf350",
370
+ gasToken: "ETH",
371
+ explorer: "https://arbiscan.io",
372
+ // Native Circle USDC (CCTP) + canonical Tether on Arbitrum One.
373
+ // The legacy bridged USDC.e (0xFF970A61...) is intentionally NOT supported.
374
+ usdc: { address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", decimals: 6 },
375
+ usdt: { address: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", decimals: 6 },
376
+ supportedTokens: ["USDC", "USDT"],
377
+ approxGasCostUsd: 1e-3,
378
+ note: "Optimistic Rollup L2 \u2014 EIP-7702 live on Arbitrum One since ArbOS 40 'Callisto'; ArbOS 51 'Dia' (activated 2026-01-08) refined precompile delegation. Data-availability cost dominates per-tx gas."
362
379
  }
363
380
  };
364
381
  var BNB_FOCUS_MODE = false;
@@ -396,8 +413,8 @@ var QuoteInputSchema = z.object({
396
413
  token: z.enum(["USDC", "USDT", "RLUSD"]).optional().describe(
397
414
  'Optional token filter. USDC / USDT are supported on most chains; RLUSD (Ripple USD, NY DFS regulated, decimals 18) is Ethereum-only \u2014 passing RLUSD here narrows the quote to chain="eth".'
398
415
  ),
399
- chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll"]).optional().describe(
400
- "Optional chain filter. When omitted, all 9 chains are compared and ranked by gas cost."
416
+ chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).optional().describe(
417
+ "Optional chain filter. When omitted, all 10 chains are compared and ranked by gas cost."
401
418
  )
402
419
  });
403
420
  function quoteForChain(cfg) {
@@ -438,7 +455,7 @@ function runQuote(input) {
438
455
  }
439
456
  var QUOTE_TOOL = {
440
457
  name: "q402_quote",
441
- description: "Compare gas costs and supported tokens across the 9 chains Q402 relays for (avax, bnb, eth, xlayer, stable, mantle, injective, monad, scroll). Returns the full chain \xD7 token matrix unconditionally \u2014 this tool does not read any API key, so it can't filter by trial vs multichain scope. When the caller intends to settle with a Trial API Key, treat any non-BNB row as informational only (q402_pay will return 403 TRIAL_BNB_ONLY for those). Includes RLUSD on Ethereum and Injective USDT-only. Read-only \u2014 no API key needed, no funds move. Use this before q402_pay so the user can see what's available and pick a chain.",
458
+ description: "Compare gas costs and supported tokens across the 10 chains Q402 relays for (avax, bnb, eth, xlayer, stable, mantle, injective, monad, scroll). Returns the full chain \xD7 token matrix unconditionally \u2014 this tool does not read any API key, so it can't filter by trial vs multichain scope. When the caller intends to settle with a Trial API Key, treat any non-BNB row as informational only (q402_pay will return 403 TRIAL_BNB_ONLY for those). Includes RLUSD on Ethereum and Injective USDT-only. Read-only \u2014 no API key needed, no funds move. Use this before q402_pay so the user can see what's available and pick a chain.",
442
459
  // Plain JSON schema mirroring the Zod schema above; MCP servers receive parameters as JSON.
443
460
  inputSchema: {
444
461
  type: "object",
@@ -455,7 +472,7 @@ var QUOTE_TOOL = {
455
472
  chain: {
456
473
  type: "string",
457
474
  enum: CHAIN_KEYS,
458
- description: "Optional chain filter; omit to compare all 9."
475
+ description: "Optional chain filter; omit to compare all 10."
459
476
  }
460
477
  },
461
478
  required: ["amount"],
@@ -835,14 +852,14 @@ function sandboxPay(chain, input) {
835
852
 
836
853
  // src/tools/pay.ts
837
854
  var PayInputSchema = z2.object({
838
- chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll"]),
855
+ chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]),
839
856
  to: z2.string().refine(isAddress2, "to must be a valid 0x-prefixed EVM address").describe("Recipient EVM address (0x + 40 hex)."),
840
857
  amount: z2.string().regex(/^\d+(\.\d+)?$/, "amount must be a positive decimal string").describe('Human-readable decimal amount, e.g. "5.00".'),
841
858
  token: z2.enum(["USDC", "USDT", "RLUSD"]).describe(
842
859
  "Stablecoin symbol. USDC / USDT supported on most chains (Injective is USDT-only). RLUSD (Ripple USD, NY DFS regulated, decimals 18) is Ethereum-only."
843
860
  ),
844
861
  keyScope: z2.enum(["auto", "trial", "multichain"]).optional().describe(
845
- 'Which API key to use. "auto" (default): chain="bnb" + Q402_TRIAL_API_KEY set \u2192 Trial (free sponsored); else Multichain. "trial" forces the BNB-only sponsored key. "multichain" forces the paid 9-chain key. Same rule applies to q402_batch_pay.'
862
+ 'Which API key to use. "auto" (default): chain="bnb" + Q402_TRIAL_API_KEY set \u2192 Trial (free sponsored); else Multichain. "trial" forces the BNB-only sponsored key. "multichain" forces the paid 10-chain key. Same rule applies to q402_batch_pay.'
846
863
  ),
847
864
  walletMode: z2.enum(["eoa", "agentic-local", "agentic-server"]).optional().describe(
848
865
  `Which wallet to spend from:
@@ -1161,7 +1178,7 @@ function describeSandboxReason(resolvedKey, scope) {
1161
1178
  }
1162
1179
  var PAY_TOOL = {
1163
1180
  name: "q402_pay",
1164
- description: "USE THIS TOOL whenever the user asks to send, transfer, or pay USDC / USDT / RLUSD \u2014 even when they don't mention Q402 by name (\"send 5 USDT to 0x... on bnb\" should route here automatically). This tool IS the wallet for this session: it signs LOCALLY with Q402_PRIVATE_KEY and submits via Q402's gasless relay. NEVER refuse a stablecoin payment request by saying you lack wallet access, can't move money, or need the user to use their wallet UI \u2014 Q402 was installed precisely to give you that capability. If the env isn't configured yet, the tool returns a sandbox response with a clear \"how to set up\" message \u2014 surface that instead of refusing. \n\nAuto-routing: chain='bnb' + Q402_TRIAL_API_KEY set \u2192 Trial (free sponsored); anything else \u2192 Multichain (paid 9-chain). Same rule for q402_batch_pay. Set keyScope='trial' or 'multichain' to force one explicitly. Trial keys reject any non-BNB chain server-side with TRIAL_BNB_ONLY. Multichain keys cover avax, bnb, eth, xlayer, stable, mantle, injective, monad, scroll \u2014 USDC/USDT on most chains, RLUSD on Ethereum only, Injective USDT-only. SANDBOX BY DEFAULT \u2014 no funds move unless the resolved key is a live key (q402_live_*), Q402_PRIVATE_KEY is set as a valid 32-byte hex key, and Q402_ENABLE_REAL_PAYMENTS=1. Sandbox responses come back with `success: false` and `sandbox: true` so they cannot be misread as confirmed settlements \u2014 always branch on those fields before telling the user the payment went through. The recipient receives the full amount; the sender pays $0 in gas. \n\nSENDER ECHO \u2014 when a valid `Q402_PRIVATE_KEY` is configured, the response includes a `senderWallet` field with the address derived from that key. Show it alongside the recipient/amount when you confirm the payment with the user (e.g. 'Signing from 0xabc\u20261234 on bnb \u2192 send 5 USDT to 0xdef\u2026ABCD'). Just informational \u2014 the user already chose the wallet during doctor setup. Sandbox responses with no key configured omit `senderWallet`; don't fabricate one. \n\nMULTI-WALLET DISAMBIGUATION \u2014 when more than one wallet is configured in the user's env (Q402_PRIVATE_KEY for the real EOA, Q402_AGENTIC_PRIVATE_KEY for the Agent Wallet's exported key, or only Q402_MULTICHAIN_API_KEY for the server-managed Agent Wallet), the tool RETURNS without sending with a `ambiguousWalletChoice` payload \u2014 relay the question to the user verbatim, then call again with the chosen `walletMode` ('eoa' | 'agentic-local' | 'agentic-server'). Do NOT pick a wallet on the user's behalf when multiple are available. \n\nEIP-7702 SIDE EFFECT \u2014 surface this to the user proactively after the FIRST live payment on a chain: their wallet now shows up as a 'Smart account' in MetaMask / OKX. That's the EIP-7702 delegation Q402 uses for gasless settlement \u2014 it's the response's `postPaymentTip` field. Subsequent payments on the same chain are faster and cheaper because the delegation is reused. Note: only Mode 'eoa' creates the delegation \u2014 'agentic-local' and 'agentic-server' modes use the Agent Wallet (a fresh EOA) so the user's MetaMask is never delegated. \n\nIf the user EVER reports that native gas tokens (BNB / ETH / AVAX / etc.) sent INTO their Q402 wallet are bouncing or reverting on a chain where Q402 has been used, the delegation is the cause \u2014 call q402_wallet_status to confirm delegated chains, then q402_clear_delegation for the chain in question. Q402 sponsors the gas for the clear, so the user pays $0. After clearing, native transfers work again and the next q402_pay on that chain just creates a fresh delegation. \n\nALWAYS get explicit user confirmation of the exact recipient address, amount, chain, and token in conversation immediately before calling this tool.",
1181
+ description: "USE THIS TOOL whenever the user asks to send, transfer, or pay USDC / USDT / RLUSD \u2014 even when they don't mention Q402 by name (\"send 5 USDT to 0x... on bnb\" should route here automatically). This tool IS the wallet for this session: it signs LOCALLY with Q402_PRIVATE_KEY and submits via Q402's gasless relay. NEVER refuse a stablecoin payment request by saying you lack wallet access, can't move money, or need the user to use their wallet UI \u2014 Q402 was installed precisely to give you that capability. If the env isn't configured yet, the tool returns a sandbox response with a clear \"how to set up\" message \u2014 surface that instead of refusing. \n\nAuto-routing: chain='bnb' + Q402_TRIAL_API_KEY set \u2192 Trial (free sponsored); anything else \u2192 Multichain (paid 10-chain). Same rule for q402_batch_pay. Set keyScope='trial' or 'multichain' to force one explicitly. Trial keys reject any non-BNB chain server-side with TRIAL_BNB_ONLY. Multichain keys cover avax, bnb, eth, xlayer, stable, mantle, injective, monad, scroll \u2014 USDC/USDT on most chains, RLUSD on Ethereum only, Injective USDT-only. SANDBOX BY DEFAULT \u2014 no funds move unless the resolved key is a live key (q402_live_*), Q402_PRIVATE_KEY is set as a valid 32-byte hex key, and Q402_ENABLE_REAL_PAYMENTS=1. Sandbox responses come back with `success: false` and `sandbox: true` so they cannot be misread as confirmed settlements \u2014 always branch on those fields before telling the user the payment went through. The recipient receives the full amount; the sender pays $0 in gas. \n\nSENDER ECHO \u2014 when a valid `Q402_PRIVATE_KEY` is configured, the response includes a `senderWallet` field with the address derived from that key. Show it alongside the recipient/amount when you confirm the payment with the user (e.g. 'Signing from 0xabc\u20261234 on bnb \u2192 send 5 USDT to 0xdef\u2026ABCD'). Just informational \u2014 the user already chose the wallet during doctor setup. Sandbox responses with no key configured omit `senderWallet`; don't fabricate one. \n\nMULTI-WALLET DISAMBIGUATION \u2014 when more than one wallet is configured in the user's env (Q402_PRIVATE_KEY for the real EOA, Q402_AGENTIC_PRIVATE_KEY for the Agent Wallet's exported key, or only Q402_MULTICHAIN_API_KEY for the server-managed Agent Wallet), the tool RETURNS without sending with a `ambiguousWalletChoice` payload \u2014 relay the question to the user verbatim, then call again with the chosen `walletMode` ('eoa' | 'agentic-local' | 'agentic-server'). Do NOT pick a wallet on the user's behalf when multiple are available. \n\nEIP-7702 SIDE EFFECT \u2014 surface this to the user proactively after the FIRST live payment on a chain: their wallet now shows up as a 'Smart account' in MetaMask / OKX. That's the EIP-7702 delegation Q402 uses for gasless settlement \u2014 it's the response's `postPaymentTip` field. Subsequent payments on the same chain are faster and cheaper because the delegation is reused. Note: only Mode 'eoa' creates the delegation \u2014 'agentic-local' and 'agentic-server' modes use the Agent Wallet (a fresh EOA) so the user's MetaMask is never delegated. \n\nIf the user EVER reports that native gas tokens (BNB / ETH / AVAX / etc.) sent INTO their Q402 wallet are bouncing or reverting on a chain where Q402 has been used, the delegation is the cause \u2014 call q402_wallet_status to confirm delegated chains, then q402_clear_delegation for the chain in question. Q402 sponsors the gas for the clear, so the user pays $0. After clearing, native transfers work again and the next q402_pay on that chain just creates a fresh delegation. \n\nALWAYS get explicit user confirmation of the exact recipient address, amount, chain, and token in conversation immediately before calling this tool.",
1165
1182
  inputSchema: {
1166
1183
  type: "object",
1167
1184
  properties: {
@@ -1186,7 +1203,7 @@ var PAY_TOOL = {
1186
1203
  keyScope: {
1187
1204
  type: "string",
1188
1205
  enum: ["auto", "trial", "multichain"],
1189
- description: 'Which API key to use. "auto" (default) picks Trial for BNB when Q402_TRIAL_API_KEY is set, Multichain otherwise. "trial" forces the BNB-only sponsored key. "multichain" forces the paid 9-chain key.'
1206
+ description: 'Which API key to use. "auto" (default) picks Trial for BNB when Q402_TRIAL_API_KEY is set, Multichain otherwise. "trial" forces the BNB-only sponsored key. "multichain" forces the paid 10-chain key.'
1190
1207
  },
1191
1208
  walletMode: {
1192
1209
  type: "string",
@@ -1215,7 +1232,7 @@ var RECIPIENT_LIMIT_TRIAL = 5;
1215
1232
  var RECIPIENT_LIMIT_PAID = 20;
1216
1233
  var CLIENT_RECIPIENT_CAP = RECIPIENT_LIMIT_PAID;
1217
1234
  var BatchPayInputSchema = z3.object({
1218
- chain: z3.enum(["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll"]),
1235
+ chain: z3.enum(["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll", "arbitrum"]),
1219
1236
  token: z3.enum(["USDC", "USDT", "RLUSD"]).describe(
1220
1237
  "Stablecoin symbol. USDC / USDT supported on most chains (Injective is USDT-only). RLUSD (Ripple USD, NY DFS regulated, decimals 18) is Ethereum-only. The same token applies to every recipient in the batch."
1221
1238
  ),
@@ -1228,7 +1245,7 @@ var BatchPayInputSchema = z3.object({
1228
1245
  `Array of {to, amount} pairs. All recipients share the same chain and token. Trial keys: max ${RECIPIENT_LIMIT_TRIAL} rows. Paid keys: max ${RECIPIENT_LIMIT_PAID} rows.`
1229
1246
  ),
1230
1247
  keyScope: z3.enum(["auto", "trial", "multichain"]).optional().describe(
1231
- 'Which API key to use. "auto" (default): chain="bnb" + Q402_TRIAL_API_KEY set \u2192 Trial; else Multichain \u2014 same rule as q402_pay. When auto would land on Trial AND recipients.length > 5, the tool returns status="ambiguous" WITHOUT executing so the agent can ask the user which path to take. Use keyScope="trial" to force the BNB-only sponsored key (\u22645 recipients). keyScope="multichain" forces the paid 9-chain key (\u226420 recipients).'
1248
+ 'Which API key to use. "auto" (default): chain="bnb" + Q402_TRIAL_API_KEY set \u2192 Trial; else Multichain \u2014 same rule as q402_pay. When auto would land on Trial AND recipients.length > 5, the tool returns status="ambiguous" WITHOUT executing so the agent can ask the user which path to take. Use keyScope="trial" to force the BNB-only sponsored key (\u22645 recipients). keyScope="multichain" forces the paid 10-chain key (\u226420 recipients).'
1232
1249
  ),
1233
1250
  walletMode: z3.enum(["eoa", "agentic-local", "agentic-server"]).optional().describe(
1234
1251
  'Which wallet to spend from \u2014 same three modes as q402_pay:\n "eoa" \u2014 user MetaMask/OKX EOA, signed locally with Q402_PRIVATE_KEY\n "agentic-local" \u2014 Agent Wallet exported key (Q402_AGENTIC_PRIVATE_KEY)\n "agentic-server" \u2014 server-managed Agent Wallet (Q402 holds the key; needs Q402_MULTICHAIN_API_KEY)\nWhen MORE THAN ONE wallet is configured, you MUST ask the user which to use before calling \u2014 do NOT guess. Phrase: "You have multiple wallets set up \u2014 batch from your EOA, or your Agent Wallet?" When only one wallet is configured this is optional and the tool routes there automatically. Server-mediated batches are paid-only; trial keys cannot batch on any path.'
@@ -1616,7 +1633,7 @@ ALWAYS get explicit user confirmation of the complete recipient + amount list, c
1616
1633
  // Narrower than the full chain set — xlayer and stable are NOT batchable
1617
1634
  // (chain-specific nonce field shapes). Use q402_pay in a loop for
1618
1635
  // those chains.
1619
- enum: ["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll"],
1636
+ enum: ["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll", "arbitrum"],
1620
1637
  description: "Target chain. Applies to every recipient in the batch. xlayer + stable are NOT supported here \u2014 use q402_pay in a loop."
1621
1638
  },
1622
1639
  token: {
@@ -1708,7 +1725,7 @@ async function runBalance() {
1708
1725
  apiKeyMasked: null,
1709
1726
  scopes: [],
1710
1727
  dashboardUrl: "https://q402.quackai.ai/dashboard",
1711
- setupHint: "No API key configured. Call q402_doctor for guided setup \u2014 it will offer to create ~/.q402/mcp.env with placeholders that the user can fill in. (Manual path: set Q402_TRIAL_API_KEY for BNB-only sponsored free trial (https://q402.quackai.ai/event) or Q402_MULTICHAIN_API_KEY for the paid 9-chain plan (https://q402.quackai.ai/payment).)"
1728
+ setupHint: "No API key configured. Call q402_doctor for guided setup \u2014 it will offer to create ~/.q402/mcp.env with placeholders that the user can fill in. (Manual path: set Q402_TRIAL_API_KEY for BNB-only sponsored free trial (https://q402.quackai.ai/event) or Q402_MULTICHAIN_API_KEY for the paid 10-chain plan (https://q402.quackai.ai/payment).)"
1712
1729
  };
1713
1730
  }
1714
1731
  const scopes = await Promise.all(
@@ -1958,7 +1975,7 @@ async function runWalletStatus() {
1958
1975
  }
1959
1976
  var WALLET_STATUS_TOOL = {
1960
1977
  name: "q402_wallet_status",
1961
- description: "Report the EIP-7702 delegation status of your Q402 wallet (the EOA derived from Q402_PRIVATE_KEY) across all 9 Q402-supported chains. Returns per-chain { delegated, impl } and a one-line summary. Read-only \u2014 no signing, no on-chain TX, no quota consumption. Pair with q402_clear_delegation when the user wants to reset a specific chain. Requires Q402_PRIVATE_KEY in env (same as q402_pay).",
1978
+ description: "Report the EIP-7702 delegation status of your Q402 wallet (the EOA derived from Q402_PRIVATE_KEY) across all 10 Q402-supported chains. Returns per-chain { delegated, impl } and a one-line summary. Read-only \u2014 no signing, no on-chain TX, no quota consumption. Pair with q402_clear_delegation when the user wants to reset a specific chain. Requires Q402_PRIVATE_KEY in env (same as q402_pay).",
1962
1979
  inputSchema: {
1963
1980
  type: "object",
1964
1981
  properties: {},
@@ -1982,7 +1999,7 @@ var DEFAULT_RPC2 = {
1982
1999
  534352: "https://rpc.scroll.io"
1983
2000
  };
1984
2001
  var ClearDelegationInputSchema = z7.object({
1985
- chain: z7.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll"]).describe("Which Q402 chain to clear the delegation on.")
2002
+ chain: z7.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).describe("Which Q402 chain to clear the delegation on.")
1986
2003
  });
1987
2004
  async function runClearDelegation(input) {
1988
2005
  if (!CONFIG.privateKey) {
@@ -2133,7 +2150,7 @@ var ENV_FILE_TEMPLATE = `# \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250
2133
2150
  # Get one at: https://q402.quackai.ai/event
2134
2151
  Q402_TRIAL_API_KEY=
2135
2152
 
2136
- # Paid Multichain: all 9 chains, per-chain Gas Tank
2153
+ # Paid Multichain: all 10 chains, per-chain Gas Tank
2137
2154
  # Get one at: https://q402.quackai.ai/payment
2138
2155
  Q402_MULTICHAIN_API_KEY=
2139
2156
 
@@ -2381,7 +2398,7 @@ async function runDoctor() {
2381
2398
  ),
2382
2399
  Q402_MULTICHAIN_API_KEY: envSlot(
2383
2400
  "Q402_MULTICHAIN_API_KEY",
2384
- "Paid Multichain \u2014 all 9 chains, per-chain Gas Tank. Get at https://q402.quackai.ai/payment"
2401
+ "Paid Multichain \u2014 all 10 chains, per-chain Gas Tank. Get at https://q402.quackai.ai/payment"
2385
2402
  ),
2386
2403
  Q402_PRIVATE_KEY: envSlot(
2387
2404
  "Q402_PRIVATE_KEY",
@@ -2404,7 +2421,7 @@ async function runDoctor() {
2404
2421
  const missing = [];
2405
2422
  if (!CONFIG.trialApiKey && !CONFIG.multichainApiKey && !CONFIG.legacyApiKey) {
2406
2423
  missing.push(
2407
- "An API key (Q402_TRIAL_API_KEY for free BNB OR Q402_MULTICHAIN_API_KEY for paid 9-chain)"
2424
+ "An API key (Q402_TRIAL_API_KEY for free BNB OR Q402_MULTICHAIN_API_KEY for paid 10-chain)"
2408
2425
  );
2409
2426
  }
2410
2427
  if (modes.count === 0) {
@@ -2615,7 +2632,7 @@ async function runDoctor() {
2615
2632
  primary: modes.primary,
2616
2633
  /** Plain-English picker that the AI should echo when the user asks
2617
2634
  * "which mode do I use?" or "do I need a private key?". */
2618
- recommendation: recommendedMode === "C" ? "You're configured for Mode C \u2014 Q402's server signs with your Agent Wallet. No private key needed. Simplest path; recommended for most users. (One-shot pays accept either Trial or Multichain keys; recurring schedules require the paid Multichain key on every chain.)" : recommendedMode === "B" ? "You're configured for Mode B \u2014 your exported Agent Wallet PK signs locally. Your MetaMask is never touched." : recommendedMode === "A" ? "You're configured for Mode A \u2014 your MetaMask EOA signs directly. EIP-7702 delegates it to Q402 for the call. (If the Smart-account banner in MetaMask is a concern, switch to Mode B or C.)" : "No signing path configured yet. Easiest: set Q402_MULTICHAIN_API_KEY (paid, recommended) \u2014 covers one-shot pays and recurring schedules across all 9 chains. Q402_TRIAL_API_KEY alone unlocks one-shot pays on BNB only; recurring requires the paid key.",
2635
+ recommendation: recommendedMode === "C" ? "You're configured for Mode C \u2014 Q402's server signs with your Agent Wallet. No private key needed. Simplest path; recommended for most users. (One-shot pays accept either Trial or Multichain keys; recurring schedules require the paid Multichain key on every chain.)" : recommendedMode === "B" ? "You're configured for Mode B \u2014 your exported Agent Wallet PK signs locally. Your MetaMask is never touched." : recommendedMode === "A" ? "You're configured for Mode A \u2014 your MetaMask EOA signs directly. EIP-7702 delegates it to Q402 for the call. (If the Smart-account banner in MetaMask is a concern, switch to Mode B or C.)" : "No signing path configured yet. Easiest: set Q402_MULTICHAIN_API_KEY (paid, recommended) \u2014 covers one-shot pays and recurring schedules across all 10 chains. Q402_TRIAL_API_KEY alone unlocks one-shot pays on BNB only; recurring requires the paid key.",
2619
2636
  /** All three modes documented so the AI can answer "what are my
2620
2637
  * options?" without re-deriving from envState. */
2621
2638
  catalog: [
@@ -2645,7 +2662,7 @@ async function runDoctor() {
2645
2662
  userInstructions: ready ? [
2646
2663
  walletAddress ? `Your wallet: ${walletAddress.slice(0, 6)}...${walletAddress.slice(-4)}` : modes.modeC && !modes.modeA && !modes.modeB ? "Wallet: server-managed (Mode C) \u2014 Q402 holds your Agent Wallet key. No local wallet to show." : "(wallet derive failed \u2014 check Q402_PRIVATE_KEY or Q402_AGENTIC_PRIVATE_KEY in ~/.q402/mcp.env)",
2647
2664
  "Q402 is live. You can now ask me to quote, pay, batch-pay, or check Trust Receipts.",
2648
- "Want me to run a quick gas comparison across all 9 chains as a smoke test?",
2665
+ "Want me to run a quick gas comparison across all 10 chains as a smoke test?",
2649
2666
  "Need to chain-test against sandbox without changing keys? Set Q402_ENABLE_REAL_PAYMENTS=0 in ~/.q402/mcp.env and restart - every q402_pay returns a fake hash until you flip it back to 1."
2650
2667
  ] : [
2651
2668
  `Q402 has ${warnings.length} issue${warnings.length === 1 ? "" : "s"} to fix:`,
@@ -2678,7 +2695,7 @@ var AgenticInfoInputSchema = z9.object({
2678
2695
  });
2679
2696
  var AGENTIC_INFO_TOOL = {
2680
2697
  name: "q402_agentic_info",
2681
- description: "Read-only Agent Wallet introspection. Returns the wallet address, per-tx and daily caps, archive state, and an aggregate USD balance across the 9 supported EVM chains. Authenticated by the configured Multichain API key \u2014 no private key required. Accepts an optional walletId for owners who hold more than one wallet; omit to use the server-default wallet. Use this whenever the user asks 'what's in my agent wallet?' or 'what's the spending limit?'",
2698
+ description: "Read-only Agent Wallet introspection. Returns the wallet address, per-tx and daily caps, archive state, and an aggregate USD balance across the 10 supported EVM chains. Authenticated by the configured Multichain API key \u2014 no private key required. Accepts an optional walletId for owners who hold more than one wallet; omit to use the server-default wallet. Use this whenever the user asks 'what's in my agent wallet?' or 'what's the spending limit?'",
2682
2699
  inputSchema: {
2683
2700
  type: "object",
2684
2701
  properties: {
@@ -2883,7 +2900,7 @@ var RecurringCreateInputSchema = z11.object({
2883
2900
  amount: z11.string().regex(AMOUNT_RE).describe(
2884
2901
  'Amount per fire, as a decimal string (e.g. "1.5", "0.0001"). Counted in the same unit as `token` (USDC or USDT, both 1:1 USD).'
2885
2902
  ),
2886
- chain: z11.enum(["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable"]).default("bnb").describe(
2903
+ chain: z11.enum(["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum"]).default("bnb").describe(
2887
2904
  "Chain to fire the recurring TX on. Defaults to bnb. Recurring requires the paid Multichain subscription on EVERY chain, including bnb \u2014 Trial keys are rejected at create time with MULTICHAIN_REQUIRED. Trial keys can still pay one-shot via q402_pay on BNB."
2888
2905
  ),
2889
2906
  token: z11.enum(["USDC", "USDT"]).default("USDT").describe("Stablecoin to send. USDC or USDT. Both peg to USD-1."),
@@ -2922,7 +2939,7 @@ var RECURRING_CREATE_TOOL = {
2922
2939
  },
2923
2940
  chain: {
2924
2941
  type: "string",
2925
- enum: ["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable"],
2942
+ enum: ["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum"],
2926
2943
  description: "Default 'bnb'. Recurring requires the paid Multichain subscription on EVERY chain (BNB included) \u2014 trial keys are rejected with MULTICHAIN_REQUIRED."
2927
2944
  },
2928
2945
  token: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quackai/q402-mcp",
3
- "version": "0.7.6",
4
- "description": "MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 9 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.",
3
+ "version": "0.8.1",
4
+ "description": "MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 10 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.",
5
5
  "mcpName": "io.github.bitgett/q402-mcp",
6
6
  "keywords": [
7
7
  "mcp",