@quackai/q402-mcp 0.4.9 → 0.5.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 +12 -11
  2. package/dist/index.js +35 -17
  3. package/package.json +73 -73
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 8 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 9 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 8-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 9-chain matrix at all times.**
11
11
 
12
- Claude can now reason about stablecoin payments end to end — quote a transfer across 8 chains, pick the cheapest route, and (optionally) settle the transaction over [Q402](https://q402.quackai.ai)'s EIP-7702 relayer infrastructure. The recipient receives the full amount; the sender pays $0 in gas.
12
+ Claude can now reason about stablecoin payments end to end — quote a transfer across 9 chains, pick the cheapest route, and (optionally) settle the transaction over [Q402](https://q402.quackai.ai)'s EIP-7702 relayer infrastructure. The recipient receives the full amount; the sender pays $0 in gas.
13
13
 
14
14
  ---
15
15
 
@@ -38,7 +38,7 @@ Or edit `claude_desktop_config.json` directly:
38
38
 
39
39
  Restart Claude Desktop and ask:
40
40
 
41
- > *"Compare gas costs to send 50 USDC to vitalik.eth across all 8 Q402 chains."*
41
+ > *"Compare gas costs to send 50 USDC to vitalik.eth across all 9 Q402 chains."*
42
42
 
43
43
  ### OpenAI Codex CLI
44
44
 
@@ -79,7 +79,7 @@ env = {
79
79
  # Two-key model: set whichever applies — both is best.
80
80
  # Auto-routing rule (same for q402_pay AND q402_batch_pay):
81
81
  # chain="bnb" + Q402_TRIAL_API_KEY set → Trial (free sponsored)
82
- # anything else → Multichain (paid 8-chain)
82
+ # anything else → Multichain (paid 9-chain)
83
83
  # Batch ambiguity: when auto would land on Trial AND recipients.length > 5,
84
84
  # q402_batch_pay returns status="ambiguous" WITHOUT executing so the agent
85
85
  # can ask the user — pass keyScope="trial" (first 5), "multichain" (all
@@ -88,7 +88,7 @@ env = {
88
88
  # carries the scope, not the key string. Get the values from the
89
89
  # dashboard (each key has its own copy button per view).
90
90
  Q402_TRIAL_API_KEY = "q402_live_...", # BNB-only sponsored (from /event)
91
- Q402_MULTICHAIN_API_KEY = "q402_live_...", # paid 8-chain (from /payment)
91
+ Q402_MULTICHAIN_API_KEY = "q402_live_...", # paid 9-chain (from /payment)
92
92
  # Legacy fallback — used if neither scoped key above is set.
93
93
  Q402_API_KEY = "q402_live_...",
94
94
  Q402_PRIVATE_KEY = "0xabc...",
@@ -118,7 +118,7 @@ The server has no client-specific code. If your client speaks stdio MCP, point i
118
118
  | `q402_quote` | none | Compare gas cost and supported tokens across chains. Read-only. |
119
119
  | `q402_balance` | API key | Verify the API key and report its plan tier + remaining quota credits (live vs sandbox). |
120
120
  | `q402_pay` | API key + private key + flag | Send a gasless payment to a single recipient. **Sandbox by default** — see [Sandbox vs live mode](#sandbox-vs-live-mode). |
121
- | `q402_batch_pay` | API key + private key + flag | Send a gasless payment to **multiple** recipients in one call on a single chain × token. Trial keys: 5 rows max. Paid keys: 20 rows max. **Auto-routing:** same rule as `q402_pay` (BNB + Trial key set ⇒ Trial, else Multichain). **Ambiguity gate:** 6+ recipient BNB batches with Trial set return `status="ambiguous"` instead of executing — the agent asks the user to pick `keyScope="trial"` (first 5), `"multichain"` (all paid), or two calls (5 free + remainder paid). **Supported chains: avax, bnb, eth, mantle, injective, monad** (default EIP-7702 mode). xlayer + stable are NOT batchable — use `q402_pay` in a loop for those. Same sandbox gating as `q402_pay`. **Rate-limit note:** the inner `/api/relay` budget (30/min per key) is consumed per row, so a paid 20-row batch leaves ~10 inner slots for the next minute. |
121
+ | `q402_batch_pay` | API key + private key + flag | Send a gasless payment to **multiple** recipients in one call on a single chain × token. Trial keys: 5 rows max. Paid keys: 20 rows max. **Auto-routing:** same rule as `q402_pay` (BNB + Trial key set ⇒ Trial, else Multichain). **Ambiguity gate:** 6+ recipient BNB batches with Trial set return `status="ambiguous"` instead of executing — the agent asks the user to pick `keyScope="trial"` (first 5), `"multichain"` (all paid), or two calls (5 free + remainder paid). **Supported chains: avax, bnb, eth, mantle, injective, monad, scroll** (default EIP-7702 mode). xlayer + stable are NOT batchable — use `q402_pay` in a loop for those. Same sandbox gating as `q402_pay`. **Rate-limit note:** the inner `/api/relay` budget (30/min per key) is consumed per row, so a paid 20-row batch leaves ~10 inner slots for the next minute. |
122
122
  | `q402_receipt` | none | Look up a Trust Receipt by `rct_…` id and locally verify its ECDSA signature against the relayer EOA. Returns the public settlement record + a `verified` boolean. *receiptId-only today; tx-hash lookup reserved for a future release.* |
123
123
 
124
124
  `q402_pay` and `q402_batch_pay` follow a "confirm in chat first" contract: the tool description instructs the model to never call it without explicit user approval of the recipient address(es), amount(s), chain, and token. For batch calls the user must approve the **full batch**, not the individual rows.
@@ -142,12 +142,12 @@ To enable real on-chain transactions, the resolved API key must be live (`q402_l
142
142
  # Two-key model — set whichever applies. Both is best.
143
143
  # Auto-routing (same for q402_pay AND q402_batch_pay):
144
144
  # chain="bnb" + Q402_TRIAL_API_KEY set → Trial (free sponsored)
145
- # anything else → Multichain (paid 8-chain)
145
+ # anything else → Multichain (paid 9-chain)
146
146
  # Batch ambiguity: 6+ recipient BNB batch with Trial set returns
147
147
  # status="ambiguous" instead of executing — agent asks user to pick.
148
148
  # Override per call with keyScope: "auto" | "trial" | "multichain".
149
149
  Q402_TRIAL_API_KEY=q402_live_... # BNB-only sponsored Trial key (from /event)
150
- Q402_MULTICHAIN_API_KEY=q402_live_... # paid 8-chain key (per-chain Gas Tank)
150
+ Q402_MULTICHAIN_API_KEY=q402_live_... # paid 9-chain key (per-chain Gas Tank)
151
151
 
152
152
  # Legacy fallback. Used for both scopes when the two above are unset —
153
153
  # single-env setups (only Q402_API_KEY set) keep working unchanged.
@@ -181,7 +181,7 @@ Combined with the `confirm: true` argument the tool requires, this means the mod
181
181
  | Env var | Required for | Notes |
182
182
  |---|---|---|
183
183
  | `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. |
184
- | `Q402_MULTICHAIN_API_KEY` | live-pay (8-chain) | Paid 8-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. |
184
+ | `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. |
185
185
  | `Q402_API_KEY` | legacy fallback | Single-env legacy path. Used for both scopes when the two above are unset. Keep set if you only have one key. |
186
186
  | `Q402_PRIVATE_KEY` | live-pay | Signer for the payer EOA. **Never share. Never paste in chat.** |
187
187
  | `Q402_ENABLE_REAL_PAYMENTS` | live-pay | Set to `1` to opt in. Any other value (or unset) → sandbox. |
@@ -203,6 +203,7 @@ Combined with the `confirm: true` argument the tool requires, this means the mod
203
203
  | Mantle | 5000 | USDC, USDT0 | LayerZero OFT USDT0 since 2025-11-27. |
204
204
  | Injective EVM | 1776 | USDT only | Native USDC via Circle CCTP announced for Q2 2026. |
205
205
  | Monad | 143 | USDC, USDT0 | Native Circle USDC (CCTP V2) + USDT0 (LayerZero OFT). |
206
+ | Scroll | 534352 | USDC, USDT | zkEVM L2 — EIP-7702 live since the Euclid Phase 2 upgrade (2025-04-22). |
206
207
 
207
208
  ---
208
209
 
@@ -210,7 +211,7 @@ Combined with the `confirm: true` argument the tool requires, this means the mod
210
211
 
211
212
  x402 standardised "402 Payment Required" semantics for AI agents but the official Coinbase facilitator only covers a few chains and assumes ERC-3009 token support — which excludes BNB USDT, Mantle USDT0, Injective USDT, and the chains where most stablecoin volume actually lives.
212
213
 
213
- Q402 implements the same payer experience (single signature, $0 gas, instant settlement) on all 8 of those chains using EIP-7702 delegated execution, which works with any ERC-20. This MCP server makes that infrastructure addressable from Claude itself.
214
+ Q402 implements the same payer experience (single signature, $0 gas, instant settlement) on all 9 of those chains using EIP-7702 delegated execution, which works with any ERC-20. This MCP server makes that infrastructure addressable from Claude itself.
214
215
 
215
216
  If you want to dig into how the wire protocol differs from x402, see [Q402 docs](https://q402.quackai.ai/docs).
216
217
 
package/dist/index.js CHANGED
@@ -109,7 +109,8 @@ var CHAIN_KEYS = [
109
109
  "stable",
110
110
  "mantle",
111
111
  "injective",
112
- "monad"
112
+ "monad",
113
+ "scroll"
113
114
  ];
114
115
  var CHAIN_CONFIG = {
115
116
  avax: {
@@ -226,6 +227,22 @@ var CHAIN_CONFIG = {
226
227
  usdt: { address: "0xe7cd86e13AC4309349F30B3435a9d337750fC82D", decimals: 6 },
227
228
  supportedTokens: ["USDC", "USDT"],
228
229
  approxGasCostUsd: 2e-3
230
+ },
231
+ scroll: {
232
+ key: "scroll",
233
+ name: "Scroll",
234
+ chainId: 534352,
235
+ domainName: "Q402 Scroll",
236
+ implContract: "0x2fb2B2D110b6c5664e701666B3741240242bf350",
237
+ gasToken: "ETH",
238
+ explorer: "https://scrollscan.com",
239
+ // Native Circle USDC + canonical Tether on Scroll mainnet (addresses
240
+ // confirmed with Scroll team during integration handshake).
241
+ usdc: { address: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4", decimals: 6 },
242
+ usdt: { address: "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df", decimals: 6 },
243
+ supportedTokens: ["USDC", "USDT"],
244
+ approxGasCostUsd: 1e-3,
245
+ note: "zkEVM L2 \u2014 EIP-7702 live since the Euclid Phase 2 upgrade (2025-04-22). Data-availability cost dominates per-tx gas."
229
246
  }
230
247
  };
231
248
  var BNB_FOCUS_MODE = false;
@@ -263,8 +280,8 @@ var QuoteInputSchema = z.object({
263
280
  token: z.enum(["USDC", "USDT", "RLUSD"]).optional().describe(
264
281
  '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".'
265
282
  ),
266
- chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad"]).optional().describe(
267
- "Optional chain filter. When omitted, all 8 chains are compared and ranked by gas cost."
283
+ chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll"]).optional().describe(
284
+ "Optional chain filter. When omitted, all 9 chains are compared and ranked by gas cost."
268
285
  )
269
286
  });
270
287
  function quoteForChain(cfg) {
@@ -305,7 +322,7 @@ function runQuote(input) {
305
322
  }
306
323
  var QUOTE_TOOL = {
307
324
  name: "q402_quote",
308
- description: "Compare gas costs and supported tokens across the 8 chains Q402 relays for (avax, bnb, eth, xlayer, stable, mantle, injective, monad). 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.",
325
+ 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.",
309
326
  // Plain JSON schema mirroring the Zod schema above; MCP servers receive parameters as JSON.
310
327
  inputSchema: {
311
328
  type: "object",
@@ -322,7 +339,7 @@ var QUOTE_TOOL = {
322
339
  chain: {
323
340
  type: "string",
324
341
  enum: CHAIN_KEYS,
325
- description: "Optional chain filter; omit to compare all 8."
342
+ description: "Optional chain filter; omit to compare all 9."
326
343
  }
327
344
  },
328
345
  required: ["amount"],
@@ -351,7 +368,8 @@ var DEFAULT_RPC = {
351
368
  988: "https://rpc.stable.xyz",
352
369
  1776: "https://sentry.evm-rpc.injective.network/",
353
370
  5e3: "https://rpc.mantle.xyz",
354
- 43114: "https://api.avax.network/ext/bc/C/rpc"
371
+ 43114: "https://api.avax.network/ext/bc/C/rpc",
372
+ 534352: "https://rpc.scroll.io"
355
373
  };
356
374
  var TRANSFER_AUTH_TYPES = {
357
375
  TransferAuthorization: [
@@ -546,7 +564,7 @@ var Q402NodeClient = class _Q402NodeClient {
546
564
  }
547
565
  if (chain.key === "xlayer" || chain.key === "stable") {
548
566
  throw new Error(
549
- `batchPay does not yet support chain "${chain.key}". Supported batch chains: avax, bnb, eth, mantle, injective, monad (default EIP-7702 mode). For "${chain.key}" use pay() in a client-side loop.`
567
+ `batchPay does not yet support chain "${chain.key}". Supported batch chains: avax, bnb, eth, mantle, injective, monad, scroll (default EIP-7702 mode). For "${chain.key}" use pay() in a client-side loop.`
550
568
  );
551
569
  }
552
570
  const rpcUrl = this.opts.rpcUrl ?? DEFAULT_RPC[chain.chainId];
@@ -672,14 +690,14 @@ function sandboxPay(chain, input) {
672
690
 
673
691
  // src/tools/pay.ts
674
692
  var PayInputSchema = z2.object({
675
- chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad"]),
693
+ chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll"]),
676
694
  to: z2.string().refine(isAddress2, "to must be a valid 0x-prefixed EVM address").describe("Recipient EVM address (0x + 40 hex)."),
677
695
  amount: z2.string().regex(/^\d+(\.\d+)?$/, "amount must be a positive decimal string").describe('Human-readable decimal amount, e.g. "5.00".'),
678
696
  token: z2.enum(["USDC", "USDT", "RLUSD"]).describe(
679
697
  "Stablecoin symbol. USDC / USDT supported on most chains (Injective is USDT-only). RLUSD (Ripple USD, NY DFS regulated, decimals 18) is Ethereum-only."
680
698
  ),
681
699
  keyScope: z2.enum(["auto", "trial", "multichain"]).optional().describe(
682
- '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 8-chain key. Same rule applies to q402_batch_pay.'
700
+ '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.'
683
701
  ),
684
702
  confirm: z2.literal(true).describe(
685
703
  "MUST be true. Prove the user explicitly approved this exact recipient and amount in the conversation right before this tool was called. Setting this to true on behalf of the user without confirmation is a violation of the tool contract."
@@ -757,7 +775,7 @@ function describeSandboxReason(resolvedKey) {
757
775
  }
758
776
  var PAY_TOOL = {
759
777
  name: "q402_pay",
760
- description: "Send a gasless USDC, USDT, or RLUSD payment via Q402. Auto-routing: chain='bnb' + Q402_TRIAL_API_KEY set \u2192 Trial (free sponsored); anything else \u2192 Multichain (paid 8-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 \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, and Q402_ENABLE_REAL_PAYMENTS=1. The recipient receives the full amount; the sender pays $0 in gas. ALWAYS get explicit user confirmation of the exact recipient address, amount, chain, and token in conversation immediately before calling this tool.",
778
+ description: "Send a gasless USDC, USDT, or RLUSD payment via Q402. Auto-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, and Q402_ENABLE_REAL_PAYMENTS=1. The recipient receives the full amount; the sender pays $0 in gas. ALWAYS get explicit user confirmation of the exact recipient address, amount, chain, and token in conversation immediately before calling this tool.",
761
779
  inputSchema: {
762
780
  type: "object",
763
781
  properties: {
@@ -782,7 +800,7 @@ var PAY_TOOL = {
782
800
  keyScope: {
783
801
  type: "string",
784
802
  enum: ["auto", "trial", "multichain"],
785
- 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 8-chain key.'
803
+ 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.'
786
804
  },
787
805
  confirm: {
788
806
  type: "boolean",
@@ -802,7 +820,7 @@ var RECIPIENT_LIMIT_TRIAL = 5;
802
820
  var RECIPIENT_LIMIT_PAID = 20;
803
821
  var CLIENT_RECIPIENT_CAP = RECIPIENT_LIMIT_PAID;
804
822
  var BatchPayInputSchema = z3.object({
805
- chain: z3.enum(["avax", "bnb", "eth", "mantle", "injective", "monad"]),
823
+ chain: z3.enum(["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll"]),
806
824
  token: z3.enum(["USDC", "USDT", "RLUSD"]).describe(
807
825
  "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."
808
826
  ),
@@ -815,7 +833,7 @@ var BatchPayInputSchema = z3.object({
815
833
  `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.`
816
834
  ),
817
835
  keyScope: z3.enum(["auto", "trial", "multichain"]).optional().describe(
818
- '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 8-chain key (\u226420 recipients).'
836
+ '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).'
819
837
  ),
820
838
  confirm: z3.literal(true).describe(
821
839
  "MUST be true. The user must have explicitly approved this exact set of recipients, amounts, chain, and token in the conversation right before this tool was called. Setting confirm=true on behalf of the user without that approval is a violation of the tool contract."
@@ -942,7 +960,7 @@ function describeSandboxReason2(resolvedKey) {
942
960
  }
943
961
  var BATCH_PAY_TOOL = {
944
962
  name: "q402_batch_pay",
945
- description: `Send gasless payments to MULTIPLE recipients on a single chain \xD7 token in one call. Auto-routing follows the same rule as q402_pay: chain='bnb' + Q402_TRIAL_API_KEY set \u2192 Trial; else Multichain. Trial keys: max ${RECIPIENT_LIMIT_TRIAL} recipients per call, BNB Chain + USDC/USDT only. Multichain keys: max ${RECIPIENT_LIMIT_PAID} recipients per call across 6 EIP-7702 default chains (avax, bnb, eth, mantle, injective, monad). xlayer + stable are NOT batchable \u2014 use q402_pay in a loop. AMBIGUITY GATE: when auto would land on Trial AND recipients.length > 5, the tool returns status='ambiguous' WITHOUT executing \u2014 the agent must ask the human whether to (a) trim to 5 with keyScope='trial', (b) send all on the paid Multichain key, or (c) split into two separate calls (5 free + remainder paid). Re-invoke with explicit keyScope after the choice. SANDBOX BY DEFAULT \u2014 real on-chain TX only when the resolved key is live (q402_live_*), Q402_PRIVATE_KEY is set, and Q402_ENABLE_REAL_PAYMENTS=1. Every recipient receives the full amount; the sender pays $0 in gas for the entire batch. ALWAYS get explicit user confirmation of the complete recipient + amount list, chain, and token in conversation immediately before calling this tool \u2014 the user must approve the full batch, not the individual rows.`,
963
+ description: `Send gasless payments to MULTIPLE recipients on a single chain \xD7 token in one call. Auto-routing follows the same rule as q402_pay: chain='bnb' + Q402_TRIAL_API_KEY set \u2192 Trial; else Multichain. Trial keys: max ${RECIPIENT_LIMIT_TRIAL} recipients per call, BNB Chain + USDC/USDT only. Multichain keys: max ${RECIPIENT_LIMIT_PAID} recipients per call across 7 EIP-7702 default chains (avax, bnb, eth, mantle, injective, monad, scroll). xlayer + stable are NOT batchable \u2014 use q402_pay in a loop. AMBIGUITY GATE: when auto would land on Trial AND recipients.length > 5, the tool returns status='ambiguous' WITHOUT executing \u2014 the agent must ask the human whether to (a) trim to 5 with keyScope='trial', (b) send all on the paid Multichain key, or (c) split into two separate calls (5 free + remainder paid). Re-invoke with explicit keyScope after the choice. SANDBOX BY DEFAULT \u2014 real on-chain TX only when the resolved key is live (q402_live_*), Q402_PRIVATE_KEY is set, and Q402_ENABLE_REAL_PAYMENTS=1. Every recipient receives the full amount; the sender pays $0 in gas for the entire batch. ALWAYS get explicit user confirmation of the complete recipient + amount list, chain, and token in conversation immediately before calling this tool \u2014 the user must approve the full batch, not the individual rows.`,
946
964
  inputSchema: {
947
965
  type: "object",
948
966
  properties: {
@@ -951,7 +969,7 @@ var BATCH_PAY_TOOL = {
951
969
  // Narrower than the full chain set — xlayer and stable are NOT batchable
952
970
  // (chain-specific nonce field shapes). Use q402_pay in a loop for
953
971
  // those chains.
954
- enum: ["avax", "bnb", "eth", "mantle", "injective", "monad"],
972
+ enum: ["avax", "bnb", "eth", "mantle", "injective", "monad", "scroll"],
955
973
  description: "Target chain. Applies to every recipient in the batch. xlayer + stable are NOT supported here \u2014 use q402_pay in a loop."
956
974
  },
957
975
  token: {
@@ -1034,7 +1052,7 @@ async function runBalance() {
1034
1052
  apiKeyMasked: null,
1035
1053
  scopes: [],
1036
1054
  dashboardUrl: "https://q402.quackai.ai/dashboard",
1037
- setupHint: "Set Q402_TRIAL_API_KEY (BNB-only sponsored, free at /event) and/or Q402_MULTICHAIN_API_KEY (paid 8-chain from /dashboard). Single-env legacy: Q402_API_KEY also works."
1055
+ setupHint: "Set Q402_TRIAL_API_KEY (BNB-only sponsored, free at /event) and/or Q402_MULTICHAIN_API_KEY (paid 9-chain from /dashboard). Single-env legacy: Q402_API_KEY also works."
1038
1056
  };
1039
1057
  }
1040
1058
  const scopes = await Promise.all(
@@ -1233,7 +1251,7 @@ var RECEIPT_TOOL = {
1233
1251
 
1234
1252
  // src/index.ts
1235
1253
  var PACKAGE_NAME = "@quackai/q402-mcp";
1236
- var PACKAGE_VERSION = "0.4.9";
1254
+ var PACKAGE_VERSION = "0.5.1";
1237
1255
  function jsonText(value) {
1238
1256
  return { type: "text", text: JSON.stringify(value, null, 2) };
1239
1257
  }
package/package.json CHANGED
@@ -1,73 +1,73 @@
1
- {
2
- "name": "@quackai/q402-mcp",
3
- "version": "0.4.9",
4
- "description": "MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 8 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.",
5
- "mcpName": "io.github.bitgett/q402-mcp",
6
- "keywords": [
7
- "mcp",
8
- "model-context-protocol",
9
- "claude",
10
- "claude-desktop",
11
- "claude-code",
12
- "codex",
13
- "openai-codex",
14
- "cline",
15
- "q402",
16
- "x402",
17
- "stablecoin",
18
- "usdc",
19
- "usdt",
20
- "rlusd",
21
- "ripple",
22
- "gasless",
23
- "eip-7702",
24
- "payments",
25
- "ai-agents"
26
- ],
27
- "type": "module",
28
- "main": "dist/index.js",
29
- "bin": {
30
- "q402-mcp": "dist/index.js"
31
- },
32
- "files": [
33
- "dist",
34
- "README.md",
35
- "LICENSE"
36
- ],
37
- "engines": {
38
- "node": ">=18.18"
39
- },
40
- "scripts": {
41
- "build": "tsup",
42
- "dev": "tsup --watch",
43
- "lint": "tsc --noEmit",
44
- "prepublishOnly": "npm run lint && npm run build",
45
- "start": "node dist/index.js"
46
- },
47
- "dependencies": {
48
- "@modelcontextprotocol/sdk": "^1.29.0",
49
- "ethers": "^6.16.0",
50
- "zod": "^3.23.8"
51
- },
52
- "devDependencies": {
53
- "@types/node": "^20.11.0",
54
- "tsup": "^8.3.0",
55
- "typescript": "^5.5.0"
56
- },
57
- "repository": {
58
- "type": "git",
59
- "url": "git+https://github.com/bitgett/q402-mcp.git"
60
- },
61
- "homepage": "https://q402.quackai.ai/claude",
62
- "bugs": {
63
- "url": "https://github.com/bitgett/q402-mcp/issues"
64
- },
65
- "license": "Apache-2.0",
66
- "author": "David Lee <davidlee@quackai.ai>",
67
- "publishConfig": {
68
- "access": "public"
69
- },
70
- "overrides": {
71
- "ws": "^8.20.1"
72
- }
73
- }
1
+ {
2
+ "name": "@quackai/q402-mcp",
3
+ "version": "0.5.1",
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.",
5
+ "mcpName": "io.github.bitgett/q402-mcp",
6
+ "keywords": [
7
+ "mcp",
8
+ "model-context-protocol",
9
+ "claude",
10
+ "claude-desktop",
11
+ "claude-code",
12
+ "codex",
13
+ "openai-codex",
14
+ "cline",
15
+ "q402",
16
+ "x402",
17
+ "stablecoin",
18
+ "usdc",
19
+ "usdt",
20
+ "rlusd",
21
+ "ripple",
22
+ "gasless",
23
+ "eip-7702",
24
+ "payments",
25
+ "ai-agents"
26
+ ],
27
+ "type": "module",
28
+ "main": "dist/index.js",
29
+ "bin": {
30
+ "q402-mcp": "dist/index.js"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18.18"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "dev": "tsup --watch",
43
+ "lint": "tsc --noEmit",
44
+ "prepublishOnly": "npm run lint && npm run build",
45
+ "start": "node dist/index.js"
46
+ },
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.29.0",
49
+ "ethers": "^6.16.0",
50
+ "zod": "^3.23.8"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^20.11.0",
54
+ "tsup": "^8.3.0",
55
+ "typescript": "^5.5.0"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://github.com/bitgett/q402-mcp.git"
60
+ },
61
+ "homepage": "https://q402.quackai.ai/claude",
62
+ "bugs": {
63
+ "url": "https://github.com/bitgett/q402-mcp/issues"
64
+ },
65
+ "license": "Apache-2.0",
66
+ "author": "David Lee <davidlee@quackai.ai>",
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
70
+ "overrides": {
71
+ "ws": "^8.20.1"
72
+ }
73
+ }