@quackai/q402-mcp 0.8.36 → 0.8.38
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.
- package/README.md +1 -0
- package/dist/index.js +12 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -301,6 +301,7 @@ If you set up Q402 before v0.5.0 you may have a single `Q402_API_KEY` env var. T
|
|
|
301
301
|
| Monad | 143 | USDC, USDT0 | Native Circle USDC (CCTP V2) + USDT0 (LayerZero OFT). |
|
|
302
302
|
| Scroll | 534352 | USDC, USDT | zkEVM L2 — EIP-7702 live since the Euclid Phase 2 upgrade (2025-04-22). |
|
|
303
303
|
| Arbitrum One | 42161 | USDC, USDT | Optimistic rollup — same EIP-7702 signing path as Ethereum. CCIP bridge endpoint (eth ⇄ avax ⇄ arbitrum). |
|
|
304
|
+
| Base | 8453 | USDC, USDT | OP Stack L2 — same EIP-7702 signing path as Ethereum. Native Circle USDC + bridged Tether USD. |
|
|
304
305
|
|
|
305
306
|
---
|
|
306
307
|
|
package/dist/index.js
CHANGED
|
@@ -211,8 +211,8 @@ var isValidPrivateKey = (s) => typeof s === "string" && PRIVATE_KEY_RE.test(s);
|
|
|
211
211
|
// package.json
|
|
212
212
|
var package_default = {
|
|
213
213
|
name: "@quackai/q402-mcp",
|
|
214
|
-
version: "0.8.
|
|
215
|
-
description: "MCP server for Q402 \u2014 gasless USDC/USDT/RLUSD payments on
|
|
214
|
+
version: "0.8.38",
|
|
215
|
+
description: "MCP server for Q402 \u2014 gasless USDC/USDT/RLUSD payments on 11 EVM chains + Chainlink CCIP USDC bridge on the eth/avax/arbitrum triangle, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.",
|
|
216
216
|
mcpName: "io.github.bitgett/q402-mcp",
|
|
217
217
|
keywords: [
|
|
218
218
|
"mcp",
|
|
@@ -508,7 +508,7 @@ var QuoteInputSchema = z.object({
|
|
|
508
508
|
token: z.enum(["USDC", "USDT", "RLUSD"]).optional().describe(
|
|
509
509
|
'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".'
|
|
510
510
|
),
|
|
511
|
-
chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).optional().describe(
|
|
511
|
+
chain: z.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum", "base"]).optional().describe(
|
|
512
512
|
"Optional chain filter. When omitted, all 11 chains are compared and ranked by gas cost."
|
|
513
513
|
)
|
|
514
514
|
});
|
|
@@ -596,6 +596,7 @@ var DEFAULT_RPC = {
|
|
|
596
596
|
988: "https://rpc.stable.xyz",
|
|
597
597
|
1776: "https://sentry.evm-rpc.injective.network/",
|
|
598
598
|
5e3: "https://rpc.mantle.xyz",
|
|
599
|
+
8453: "https://mainnet.base.org",
|
|
599
600
|
42161: "https://arb1.arbitrum.io/rpc",
|
|
600
601
|
43114: "https://api.avax.network/ext/bc/C/rpc",
|
|
601
602
|
534352: "https://rpc.scroll.io"
|
|
@@ -972,7 +973,7 @@ function checkConsent(intent, provided) {
|
|
|
972
973
|
|
|
973
974
|
// src/tools/pay.ts
|
|
974
975
|
var PayInputSchema = z2.object({
|
|
975
|
-
chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]),
|
|
976
|
+
chain: z2.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum", "base"]),
|
|
976
977
|
to: z2.string().refine(isAddress2, "to must be a valid 0x-prefixed EVM address").describe("Recipient EVM address (0x + 40 hex)."),
|
|
977
978
|
amount: z2.string().regex(/^\d+(\.\d+)?$/, "amount must be a positive decimal string").describe('Human-readable decimal amount, e.g. "5.00".'),
|
|
978
979
|
token: z2.enum(["USDC", "USDT", "RLUSD"]).describe(
|
|
@@ -1403,7 +1404,7 @@ function describeSandboxReason(resolvedKey, scope) {
|
|
|
1403
1404
|
}
|
|
1404
1405
|
var PAY_TOOL = {
|
|
1405
1406
|
name: "q402_pay",
|
|
1406
|
-
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 11-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, arbitrum \u2014 USDC/USDT on most chains, RLUSD on Ethereum 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. \n\nTWO-PHASE CONSENT: confirm:true alone does NOT send. Call this tool first WITHOUT consentToken \u2014 it returns status=\"needs_confirmation\" with a `preview` of the exact payment and a `consentToken`, and moves no money. Relay that preview to the user, get their explicit yes, then re-call with the SAME args plus that `consentToken` to execute. The token is re-derived from the params about to run, so a previewed payment can't be swapped for a different one.",
|
|
1407
|
+
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 11-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, arbitrum, base \u2014 USDC/USDT on most chains, RLUSD on Ethereum 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. \n\nTWO-PHASE CONSENT: confirm:true alone does NOT send. Call this tool first WITHOUT consentToken \u2014 it returns status=\"needs_confirmation\" with a `preview` of the exact payment and a `consentToken`, and moves no money. Relay that preview to the user, get their explicit yes, then re-call with the SAME args plus that `consentToken` to execute. The token is re-derived from the params about to run, so a previewed payment can't be swapped for a different one.",
|
|
1407
1408
|
inputSchema: {
|
|
1408
1409
|
type: "object",
|
|
1409
1410
|
properties: {
|
|
@@ -2309,12 +2310,13 @@ var DEFAULT_RPC2 = {
|
|
|
2309
2310
|
988: "https://rpc.stable.xyz",
|
|
2310
2311
|
1776: "https://sentry.evm-rpc.injective.network/",
|
|
2311
2312
|
5e3: "https://rpc.mantle.xyz",
|
|
2313
|
+
8453: "https://mainnet.base.org",
|
|
2312
2314
|
42161: "https://arb1.arbitrum.io/rpc",
|
|
2313
2315
|
43114: "https://api.avax.network/ext/bc/C/rpc",
|
|
2314
2316
|
534352: "https://rpc.scroll.io"
|
|
2315
2317
|
};
|
|
2316
2318
|
var ClearDelegationInputSchema = z7.object({
|
|
2317
|
-
chain: z7.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).describe("Which Q402 chain to clear the delegation on.")
|
|
2319
|
+
chain: z7.enum(["avax", "bnb", "eth", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum", "base"]).describe("Which Q402 chain to clear the delegation on.")
|
|
2318
2320
|
});
|
|
2319
2321
|
async function runClearDelegation(input) {
|
|
2320
2322
|
if (!CONFIG.privateKey) {
|
|
@@ -4165,7 +4167,7 @@ var RecurringCreateInputSchema = z19.object({
|
|
|
4165
4167
|
amount: z19.string().regex(AMOUNT_RE).describe(
|
|
4166
4168
|
'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).'
|
|
4167
4169
|
),
|
|
4168
|
-
chain: z19.enum(["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum"]).default("bnb").describe(
|
|
4170
|
+
chain: z19.enum(["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum", "base"]).default("bnb").describe(
|
|
4169
4171
|
"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."
|
|
4170
4172
|
),
|
|
4171
4173
|
token: z19.enum(["USDC", "USDT"]).default("USDT").describe("Stablecoin to send. USDC or USDT. Both peg to USD-1."),
|
|
@@ -4204,7 +4206,7 @@ var RECURRING_CREATE_TOOL = {
|
|
|
4204
4206
|
},
|
|
4205
4207
|
chain: {
|
|
4206
4208
|
type: "string",
|
|
4207
|
-
enum: ["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum"],
|
|
4209
|
+
enum: ["bnb", "eth", "avax", "xlayer", "mantle", "injective", "monad", "scroll", "stable", "arbitrum", "base"],
|
|
4208
4210
|
description: "Default 'bnb'. Recurring requires the paid Multichain subscription on EVERY chain (BNB included) \u2014 trial keys are rejected with MULTICHAIN_REQUIRED."
|
|
4209
4211
|
},
|
|
4210
4212
|
token: {
|
|
@@ -4815,7 +4817,7 @@ var AMOUNT_RE2 = /^\d+(\.\d{1,18})?$/;
|
|
|
4815
4817
|
var RequestCreateInputSchema = z25.object({
|
|
4816
4818
|
amount: z25.string().regex(AMOUNT_RE2).describe('Amount to request, as a decimal string (e.g. "5", "1.50"). Counted in `token` (USDC or USDT, both USD-1).'),
|
|
4817
4819
|
token: z25.enum(["USDC", "USDT"]).default("USDT").describe("Stablecoin to be paid. USDC or USDT. Both peg USD-1."),
|
|
4818
|
-
chain: z25.enum(["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).default("bnb").describe("Chain the request settles on. Defaults to bnb."),
|
|
4820
|
+
chain: z25.enum(["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum", "base"]).default("bnb").describe("Chain the request settles on. Defaults to bnb."),
|
|
4819
4821
|
recipient: z25.string().regex(ADDRESS_RE2).optional().describe("0x address that receives the funds. Defaults to Q402_AGENT_WALLET_ADDRESS (the agent bills itself) when omitted."),
|
|
4820
4822
|
memo: z25.string().max(200).optional().describe("Optional note shown to the payer (\u2264200 chars), e.g. an invoice number or service description."),
|
|
4821
4823
|
ttlDays: z25.number().int().min(1).max(90).optional().describe("Days until the request expires. Defaults to 7 (max 90).")
|
|
@@ -4904,7 +4906,7 @@ var REQUEST_CREATE_TOOL = {
|
|
|
4904
4906
|
},
|
|
4905
4907
|
chain: {
|
|
4906
4908
|
type: "string",
|
|
4907
|
-
enum: ["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"],
|
|
4909
|
+
enum: ["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum", "base"],
|
|
4908
4910
|
description: "Default 'bnb'. Chain the request settles on."
|
|
4909
4911
|
},
|
|
4910
4912
|
recipient: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quackai/q402-mcp",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "MCP server for Q402 — gasless USDC/USDT/RLUSD payments on
|
|
3
|
+
"version": "0.8.38",
|
|
4
|
+
"description": "MCP server for Q402 — gasless USDC/USDT/RLUSD payments on 11 EVM chains + Chainlink CCIP USDC bridge on the eth/avax/arbitrum triangle, 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",
|