@quackai/q402-mcp 0.3.11 → 0.3.12

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 CHANGED
@@ -100,7 +100,7 @@ The server has no client-specific code. If your client speaks stdio MCP, point i
100
100
  | `q402_quote` | none | Compare gas cost and supported tokens across chains. Read-only. |
101
101
  | `q402_balance` | API key | Verify the API key and report its plan tier + remaining quota credits (live vs sandbox). |
102
102
  | `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). |
103
- | `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. **Supported chains: avax, bnb, eth, mantle, injective** (default EIP-7702 mode). xlayer + stable are NOT batchable — use `q402_pay` in a loop for those. Same sandbox gating as `q402_pay`. |
103
+ | `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. **Supported chains: avax, bnb, eth, mantle, injective** (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. |
104
104
  | `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.* |
105
105
 
106
106
  `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.
package/dist/index.js CHANGED
@@ -449,11 +449,10 @@ var Q402NodeClient = class _Q402NodeClient {
449
449
  * Signature shape: `{ token, recipients }`. The previous revision took
450
450
  * `PayInput[]` (with token on each row), which read as if rows could
451
451
  * carry different tokens — but the request body only ships one token
452
- * field, so the per-row token on rows 1..N was silently ignored.
453
- * Codex audit P2: surface the constraint in the type so consumers
454
- * can't accidentally build a "mixed-token batch" that quietly drops
455
- * the second token. Same chain + same token across one batch, full
456
- * stop.
452
+ * field, so the per-row token on rows 1..N was silently ignored. The
453
+ * new shape surfaces the constraint in the type so consumers can't
454
+ * accidentally build a "mixed-token batch" that quietly drops the
455
+ * second token. Same chain + same token across one batch, full stop.
457
456
  */
458
457
  async batchPay(input) {
459
458
  const { token, recipients: rows } = input;
@@ -551,6 +550,12 @@ var Q402NodeClient = class _Q402NodeClient {
551
550
  data.aborted ? `Batch aborted: recipient[0] failed (${data.results?.[0]?.error ?? "unknown"}). No transfers landed.` : data.totalFailed > 0 ? `Batch completed with ${data.totalFailed}/${data.results?.length ?? "?"} failed rows.` : data.error ?? `relay/batch failed (HTTP ${resp.status})`,
552
551
  {
553
552
  aborted: !!data.aborted,
553
+ // Preserve the server's scope/limit so the MCP tool surface can
554
+ // report the actual tier (trial vs paid) rather than guessing.
555
+ // Falls back to "paid" / row count only when the failure didn't
556
+ // come from the relay route (e.g. network-level error).
557
+ scope: data.scope ?? "paid",
558
+ limit: data.limit ?? signedRows.length,
554
559
  totalSuccess: data.totalSuccess ?? 0,
555
560
  totalFailed: data.totalFailed ?? signedRows.length,
556
561
  results: data.results ?? []
@@ -567,6 +572,8 @@ var Q402NodeClient = class _Q402NodeClient {
567
572
  };
568
573
  var BatchPayError = class extends Error {
569
574
  aborted;
575
+ scope;
576
+ limit;
570
577
  totalSuccess;
571
578
  totalFailed;
572
579
  results;
@@ -574,6 +581,8 @@ var BatchPayError = class extends Error {
574
581
  super(message);
575
582
  this.name = "BatchPayError";
576
583
  this.aborted = details.aborted;
584
+ this.scope = details.scope;
585
+ this.limit = details.limit;
577
586
  this.totalSuccess = details.totalSuccess;
578
587
  this.totalFailed = details.totalFailed;
579
588
  this.results = details.results;
@@ -802,6 +811,7 @@ async function runBatchPay(input) {
802
811
  } catch (err) {
803
812
  if (err instanceof BatchPayError) {
804
813
  guardsApplied.push("mode=live");
814
+ guardsApplied.push(`scope=${err.scope} (server enforced)`);
805
815
  guardsApplied.push(`batch_${err.aborted ? "aborted" : "partial_failure"}`);
806
816
  const status = err.aborted ? "aborted" : "partial_failure";
807
817
  return {
@@ -809,8 +819,8 @@ async function runBatchPay(input) {
809
819
  status,
810
820
  result: {
811
821
  ok: false,
812
- scope: "paid",
813
- limit: input.recipients.length,
822
+ scope: err.scope,
823
+ limit: err.limit,
814
824
  totalSuccess: err.totalSuccess,
815
825
  totalFailed: err.totalFailed,
816
826
  aborted: err.aborted,
@@ -1094,7 +1104,7 @@ var RECEIPT_TOOL = {
1094
1104
 
1095
1105
  // src/index.ts
1096
1106
  var PACKAGE_NAME = "@quackai/q402-mcp";
1097
- var PACKAGE_VERSION = "0.3.11";
1107
+ var PACKAGE_VERSION = "0.3.12";
1098
1108
  function jsonText(value) {
1099
1109
  return { type: "text", text: JSON.stringify(value, null, 2) };
1100
1110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quackai/q402-mcp",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "description": "MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 7 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": [