@quackai/q402-mcp 0.8.5 → 0.8.7

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 +3 -3
  2. package/dist/index.js +32 -10
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -174,9 +174,9 @@ Then export the values in `~/.zshrc` / `~/.bashrc`. See the [Codex config refere
174
174
  | `q402_recurring_skip_next` | api key | Skip only the next scheduled fire. |
175
175
  | `q402_recurring_cancel` | api key | Permanently stop a rule. |
176
176
  | `q402_bridge_quote` | none | Quote a Chainlink CCIP USDC bridge across eth/avax/arbitrum. Returns LINK + native fee. |
177
- | `q402_bridge_send` | live mode | Execute the bridge. Sandbox-only today; live execution lands once session-binding ships. |
178
- | `q402_bridge_history` | api key | Recent CCIP bridges (50 most recent). |
179
- | `q402_bridge_gas_tank` | api key | Per-chain LINK + native Gas Tank balance for bridge fees. |
177
+ | `q402_bridge_send` | sandbox only | Plan-and-quote a bridge end-to-end. `sandbox: false` returns `isError:true` with a dashboard pointer until session-binding lands. |
178
+ | `q402_bridge_history` | not yet wired | Pointer to the dashboard. Returns `{ implemented: false, dashboardUrl, dashboardPath }` — read-only guidance until owner-sig auth lands in MCP. |
179
+ | `q402_bridge_gas_tank` | not yet wired | Static guidance + dashboard pointer for the Bridge Gas Tank top-up flow. Live balance lookup needs owner-sig auth (dashboard for now). |
180
180
 
181
181
  `q402_pay` + `q402_batch_pay` + `q402_bridge_send` require explicit in-chat confirmation. Batch confirmation = full batch, not per-row.
182
182
 
package/dist/index.js CHANGED
@@ -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.8.5";
214
+ var PACKAGE_VERSION = "0.8.7";
215
215
 
216
216
  // src/tools/quote.ts
217
217
  import { z } from "zod";
@@ -2255,7 +2255,7 @@ Q402_MAX_AMOUNT_PER_CALL=200
2255
2255
  # Comma-separated lowercase recipient allowlist (unset = any address OK)
2256
2256
  # Q402_ALLOWED_RECIPIENTS=0xabc...,0xdef...
2257
2257
  `;
2258
- var SECURITY_NOTICE = "Q402 never asks you to paste your private key into chat. The MCP server signs payments LOCALLY on your machine \u2014 your key never leaves your device, never goes to a remote server. If a key was already pasted in chat by mistake, treat the wallet as exposed: move funds to a fresh wallet and use that new key in ~/.q402/mcp.env going forward.";
2258
+ var SECURITY_NOTICE = "Q402 never asks you to paste your private key into chat. Custody depends on which wallet mode you picked: Mode A (Q402_PRIVATE_KEY) and Mode B (Q402_AGENTIC_PRIVATE_KEY) sign LOCALLY on your machine \u2014 those keys never leave your device. Mode C (Q402_MULTICHAIN_API_KEY only, no private-key env) is server-managed: Q402 holds the Agent Wallet's encrypted private key (AES-256-GCM) and signs on your behalf \u2014 your MetaMask key is never involved on this side either. If a key was already pasted in chat by mistake, treat that wallet as exposed: move funds to a fresh wallet and use that new key in ~/.q402/mcp.env going forward.";
2259
2259
  var FIRST_INSTALL_ADVISORY = [
2260
2260
  `Tip: a separate MetaMask account dedicated to Q402 keeps your existing balances and history tidy \u2014 it's a quick "+ Add account" in MetaMask. Q402 works with any EOA you control, though.`,
2261
2261
  "After your first payment, that wallet will show 'Smart account' in MetaMask / OKX. That's EIP-7702 delegation (Q402's gasless settlement mechanism), reversible anytime via q402_clear_delegation.",
@@ -2804,8 +2804,16 @@ import { z as z10 } from "zod";
2804
2804
  var BridgeQuoteInputSchema = z10.object({
2805
2805
  src: z10.enum(["eth", "avax", "arbitrum"]).describe("Source chain"),
2806
2806
  dst: z10.enum(["eth", "avax", "arbitrum"]).describe("Destination chain"),
2807
- amount: z10.string().regex(/^\d+$/).describe("USDC amount in raw 6-decimal units (e.g. '1000000' = 1 USDC)"),
2807
+ // Same `> 0` requirement as bridge-send so the quote doesn't
2808
+ // return a meaningless "fee for 0 USDC" envelope.
2809
+ amount: z10.string().regex(/^\d*[1-9]\d*$/).describe("USDC amount in raw 6-decimal units, > 0 (e.g. '1000000' = 1 USDC)"),
2808
2810
  destReceiver: z10.string().regex(/^0x[0-9a-fA-F]{40}$/).describe("Destination receiver address (Agentic Wallet on destination)")
2811
+ }).refine((d) => d.src !== d.dst, {
2812
+ // Mirror the rejection in BridgeSendInputSchema so an agent that
2813
+ // accidentally quotes a same-chain "bridge" fails locally instead of
2814
+ // burning a round-trip through /api/ccip/quote.
2815
+ message: "src must differ from dst",
2816
+ path: ["dst"]
2809
2817
  });
2810
2818
  var BRIDGE_QUOTE_TOOL = {
2811
2819
  name: "q402_bridge_quote",
@@ -2868,14 +2876,24 @@ import { z as z11 } from "zod";
2868
2876
  var BridgeSendInputSchema = z11.object({
2869
2877
  src: z11.enum(["eth", "avax", "arbitrum"]).describe("Source chain"),
2870
2878
  dst: z11.enum(["eth", "avax", "arbitrum"]).describe("Destination chain"),
2871
- amount: z11.string().regex(/^\d+$/).describe("USDC amount in raw 6-decimal units"),
2879
+ // `^\d+$` accepts "0" which is a no-op bridge. Require at least one
2880
+ // non-zero digit (^\d*[1-9]\d*$ also accepts e.g. "10", "100") so an
2881
+ // accidental amount=0 fails locally instead of returning a synthetic
2882
+ // "success" envelope in sandbox.
2883
+ amount: z11.string().regex(/^\d*[1-9]\d*$/).describe("USDC amount in raw 6-decimal units, > 0"),
2872
2884
  walletId: z11.string().describe("Agentic Wallet ID (from q402_agentic_info)"),
2873
2885
  feeToken: z11.enum(["LINK", "native", "auto"]).optional().describe("Fee token. 'auto' picks cheaper of the two; defaults to LINK."),
2874
2886
  sandbox: z11.boolean().optional().describe("Sandbox mode (default true). Set to false for live bridge.")
2887
+ }).refine((d) => d.src !== d.dst, {
2888
+ // Local Zod rejection saves a network round-trip + a Q402 backend log
2889
+ // entry. The /api/ccip/send route also rejects same-chain bridges but
2890
+ // the agent only finds out after burning a request.
2891
+ message: "src must differ from dst",
2892
+ path: ["dst"]
2875
2893
  });
2876
2894
  var BRIDGE_SEND_TOOL = {
2877
2895
  name: "q402_bridge_send",
2878
- description: "Execute a Chainlink CCIP USDC bridge between two of the 3 supported chains (eth/avax/arbitrum). The Q402 server signs ccipSend on behalf of the user's Agentic Wallet. Fee is debited from the user's Gas Tank (LINK slot or native, per the feeToken arg). SANDBOX BY DEFAULT: returns a synthetic messageId unless `sandbox: false` is passed AND the server env has Q402_ENABLE_REAL_PAYMENTS=1. ALWAYS confirm the bridge details with the user before setting sandbox: false. Recommended flow: q402_bridge_quote first \u2192 show user the cost \u2192 get user confirmation \u2192 call q402_bridge_send with sandbox: false.",
2896
+ description: "PLAN-AND-QUOTE TOOL (sandbox-only at this release). Execute a Chainlink CCIP USDC bridge plan between two of the 3 supported chains (eth/avax/arbitrum). Returns a synthetic messageId so the agent can preview the bridge end-to-end without moving funds. LIVE EXECUTION via MCP is NOT yet wired \u2014 it requires an owner-EIP-712 signature on the `ccip.bridge` intent which the MCP CLI cannot produce (the dashboard or a future session-binding flow is the live path). Calling with `sandbox: false` returns isError:true regardless of Q402_ENABLE_REAL_PAYMENTS. Recommended flow: q402_bridge_quote \u2192 show user the cost \u2192 if they want to bridge live, point them at https://q402.quackai.ai/dashboard \u2192 Agent tab \u2192 Bridge.",
2879
2897
  inputSchema: {
2880
2898
  type: "object",
2881
2899
  properties: {
@@ -2905,7 +2923,7 @@ var BRIDGE_SEND_TOOL = {
2905
2923
  },
2906
2924
  sandbox: {
2907
2925
  type: "boolean",
2908
- description: "Sandbox-only at the current release (live bridging requires dashboard session-binding). Default true."
2926
+ description: "Sandbox-only at the current release. Passing false returns isError:true with a pointer to the dashboard's Bridge UI \u2014 live MCP execution lands once session-binding is plumbed."
2909
2927
  }
2910
2928
  },
2911
2929
  required: ["src", "dst", "amount", "walletId"]
@@ -2961,9 +2979,13 @@ async function runBridgeHistory(_input) {
2961
2979
  return {
2962
2980
  content: [{
2963
2981
  type: "text",
2964
- text: "Bridge history via MCP requires owner-sig auth, which is dashboard-managed at the current release. View at https://q402.quackai.ai/dashboard \u2192 Agent tab \u2192 Bridge History."
2965
- }],
2966
- isError: true
2982
+ text: JSON.stringify({
2983
+ implemented: false,
2984
+ reason: "Bridge history via MCP requires owner-sig auth, which is dashboard-bound until session-binding lands in a follow-up release.",
2985
+ dashboardUrl: "https://q402.quackai.ai/dashboard",
2986
+ dashboardPath: "Agent tab \u2192 Bridge History"
2987
+ }, null, 2)
2988
+ }]
2967
2989
  };
2968
2990
  }
2969
2991
 
@@ -2974,7 +2996,7 @@ var BridgeGasTankInputSchema = z13.object({
2974
2996
  });
2975
2997
  var BRIDGE_GAS_TANK_TOOL = {
2976
2998
  name: "q402_bridge_gas_tank",
2977
- description: "Report the user's Bridge Gas Tank state \u2014 LINK + native balance per CCIP chain (eth/avax/arbitrum). Q402 charges no markup on bridges; users pay only the actual Chainlink CCIP fee, debited from this Gas Tank. LINK fees are ~10% cheaper than native. Tool returns guidance + dashboard URL until owner-sig wiring lands.",
2999
+ description: "READ-ONLY GUIDANCE TOOL \u2014 Bridge Gas Tank live balance via MCP is not yet wired (requires owner-sig auth which is dashboard-bound until session-binding lands, same follow-up as q402_bridge_history). Tool returns static guidance: the LINK/native fee model, the 3-chain CCIP triangle (eth/avax/arbitrum), the canonical Gas Tank deposit address, and a dashboard pointer for the live balance and per-chain deposit detail. Use this to route a user to the right top-up flow; don't expect numbers in the response.",
2978
3000
  inputSchema: {
2979
3001
  type: "object",
2980
3002
  properties: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quackai/q402-mcp",
3
- "version": "0.8.5",
4
- "description": "MCP server for Q402 — gasless USDC/USDT/RLUSD payments + Chainlink CCIP bridge across 10 EVM chains, callable from Claude (Desktop / Code), OpenAI Codex CLI, and any other Model Context Protocol client.",
3
+ "version": "0.8.7",
4
+ "description": "MCP server for Q402 — gasless USDC/USDT/RLUSD payments on 10 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",
@@ -69,6 +69,7 @@
69
69
  },
70
70
  "overrides": {
71
71
  "ws": "^8.20.1",
72
- "qs": "^6.15.2"
72
+ "qs": "^6.15.2",
73
+ "hono": "^4.12.21"
73
74
  }
74
75
  }