@quackai/q402-mcp 0.8.31 → 0.8.32
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 +5 -2
- package/dist/index.js +289 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,7 +156,7 @@ Then export the values in `~/.zshrc` / `~/.bashrc`. See the [Codex config refere
|
|
|
156
156
|
|
|
157
157
|
## Tools exposed
|
|
158
158
|
|
|
159
|
-
**
|
|
159
|
+
**27 tools** — read-only by default; live mode needs an API key + signing path + `Q402_ENABLE_REAL_PAYMENTS=1`.
|
|
160
160
|
|
|
161
161
|
| Tool | Auth | Purpose |
|
|
162
162
|
|---|---|---|
|
|
@@ -184,8 +184,11 @@ Then export the values in `~/.zshrc` / `~/.bashrc`. See the [Codex config refere
|
|
|
184
184
|
| `q402_yield_positions` | api key | Show the Agent Wallet's open Q402 Yield positions (balance, principal, accrued interest, APY) + total supplied in USD. Mode C. |
|
|
185
185
|
| `q402_yield_deposit` | live mode | Supply the Agent Wallet's USDC/USDT into Aave V3 (Q402 Yield) to earn supply APY. Mode C, BNB-only. Requires `confirm: true`; sandbox-by-default. |
|
|
186
186
|
| `q402_yield_withdraw` | live mode | Withdraw supplied USDC/USDT out of Aave V3 back to the Agent Wallet (`amount: "max"` = full position). Mode C, BNB-only. Requires `confirm: true`; sandbox-by-default. |
|
|
187
|
+
| `q402_request_create` | api key | Publish a payment request (invoice). No funds move — returns a shareable `/pay` link + `req_…` id. Recipient defaults to the Agent Wallet. |
|
|
188
|
+
| `q402_request_status` | none | Look up a payment request by `req_…` id (amount, token, chain, recipient, status). Read-only; `notFound` instead of throwing. |
|
|
189
|
+
| `q402_request_pay` | live mode | Pay a request gaslessly from the payer's own Agent Wallet (Mode C). Terms come from the stored request — can't be redirected. Requires `confirm: true`. |
|
|
187
190
|
|
|
188
|
-
`q402_pay` + `q402_batch_pay` + `q402_bridge_send` + `q402_yield_deposit` + `q402_yield_withdraw` require explicit in-chat confirmation. Batch confirmation = full batch, not per-row.
|
|
191
|
+
`q402_pay` + `q402_batch_pay` + `q402_bridge_send` + `q402_yield_deposit` + `q402_yield_withdraw` + `q402_request_pay` require explicit in-chat confirmation. Batch confirmation = full batch, not per-row.
|
|
189
192
|
|
|
190
193
|
> ℹ️ `q402_pay` expects a 0x address — ENS isn't resolved server-side. Resolve client-side first.
|
|
191
194
|
> Per-chain Gas Tank balances + full TX history live in the [dashboard](https://q402.quackai.ai/dashboard) (wallet-signature only).
|
package/dist/index.js
CHANGED
|
@@ -211,7 +211,7 @@ 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.
|
|
214
|
+
version: "0.8.32",
|
|
215
215
|
description: "MCP server for Q402 \u2014 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.",
|
|
216
216
|
mcpName: "io.github.bitgett/q402-mcp",
|
|
217
217
|
keywords: [
|
|
@@ -4778,6 +4778,274 @@ async function runRecurringSkipNext(input) {
|
|
|
4778
4778
|
}
|
|
4779
4779
|
}
|
|
4780
4780
|
|
|
4781
|
+
// src/tools/request-create.ts
|
|
4782
|
+
import { z as z25 } from "zod";
|
|
4783
|
+
var ADDRESS_RE2 = /^0x[0-9a-fA-F]{40}$/;
|
|
4784
|
+
var AMOUNT_RE2 = /^\d+(\.\d{1,18})?$/;
|
|
4785
|
+
var RequestCreateInputSchema = z25.object({
|
|
4786
|
+
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).'),
|
|
4787
|
+
token: z25.enum(["USDC", "USDT"]).default("USDT").describe("Stablecoin to be paid. USDC or USDT. Both peg USD-1."),
|
|
4788
|
+
chain: z25.enum(["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"]).default("bnb").describe("Chain the request settles on. Defaults to bnb."),
|
|
4789
|
+
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."),
|
|
4790
|
+
memo: z25.string().max(200).optional().describe("Optional note shown to the payer (\u2264200 chars), e.g. an invoice number or service description."),
|
|
4791
|
+
ttlDays: z25.number().int().min(1).max(90).optional().describe("Days until the request expires. Defaults to 7 (max 90).")
|
|
4792
|
+
});
|
|
4793
|
+
async function runRequestCreate(input) {
|
|
4794
|
+
const base = CONFIG.relayBaseUrl;
|
|
4795
|
+
if (!CONFIG.apiKey) {
|
|
4796
|
+
return {
|
|
4797
|
+
ok: false,
|
|
4798
|
+
requestId: null,
|
|
4799
|
+
payUrl: null,
|
|
4800
|
+
request: null,
|
|
4801
|
+
error: "API_KEY_REQUIRED",
|
|
4802
|
+
message: "No Q402 API key configured. Run q402_doctor to set one up."
|
|
4803
|
+
};
|
|
4804
|
+
}
|
|
4805
|
+
const recipient = input.recipient?.toLowerCase() ?? CONFIG.walletId;
|
|
4806
|
+
if (!recipient) {
|
|
4807
|
+
return {
|
|
4808
|
+
ok: false,
|
|
4809
|
+
requestId: null,
|
|
4810
|
+
payUrl: null,
|
|
4811
|
+
request: null,
|
|
4812
|
+
error: "RECIPIENT_REQUIRED",
|
|
4813
|
+
message: "No recipient given and no Q402_AGENT_WALLET_ADDRESS configured. Pass `recipient` (the 0x address that should receive the funds)."
|
|
4814
|
+
};
|
|
4815
|
+
}
|
|
4816
|
+
try {
|
|
4817
|
+
const res = await fetch(`${base}/request`, {
|
|
4818
|
+
method: "POST",
|
|
4819
|
+
headers: { "Content-Type": "application/json" },
|
|
4820
|
+
body: JSON.stringify({
|
|
4821
|
+
apiKey: CONFIG.apiKey,
|
|
4822
|
+
chain: input.chain ?? "bnb",
|
|
4823
|
+
token: input.token ?? "USDT",
|
|
4824
|
+
amount: input.amount,
|
|
4825
|
+
recipient,
|
|
4826
|
+
...input.memo !== void 0 ? { memo: input.memo } : {},
|
|
4827
|
+
...input.ttlDays !== void 0 ? { ttlDays: input.ttlDays } : {}
|
|
4828
|
+
}),
|
|
4829
|
+
signal: AbortSignal.timeout(15e3)
|
|
4830
|
+
});
|
|
4831
|
+
const data = await res.json().catch(() => ({}));
|
|
4832
|
+
if (!res.ok || !data.requestId) {
|
|
4833
|
+
return {
|
|
4834
|
+
ok: false,
|
|
4835
|
+
requestId: null,
|
|
4836
|
+
payUrl: null,
|
|
4837
|
+
request: null,
|
|
4838
|
+
error: data.error ?? `HTTP_${res.status}`,
|
|
4839
|
+
message: data.error ?? `Create failed with HTTP ${res.status}.`
|
|
4840
|
+
};
|
|
4841
|
+
}
|
|
4842
|
+
return {
|
|
4843
|
+
ok: true,
|
|
4844
|
+
requestId: data.requestId,
|
|
4845
|
+
payUrl: data.payUrl ?? null,
|
|
4846
|
+
request: data.request ?? null
|
|
4847
|
+
};
|
|
4848
|
+
} catch (e) {
|
|
4849
|
+
return {
|
|
4850
|
+
ok: false,
|
|
4851
|
+
requestId: null,
|
|
4852
|
+
payUrl: null,
|
|
4853
|
+
request: null,
|
|
4854
|
+
error: "NETWORK_ERROR",
|
|
4855
|
+
message: e instanceof Error ? e.message : String(e)
|
|
4856
|
+
};
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
var REQUEST_CREATE_TOOL = {
|
|
4860
|
+
name: "q402_request_create",
|
|
4861
|
+
description: "Publish a Q402 payment request (an invoice / bill). Moves no funds \u2014 it creates a shareable request to RECEIVE money \u2014 so no confirmation is needed and a Trial key works. Returns a req_ id + a /pay link you can share with a human, or hand the requestId to another agent that pays it gaslessly via q402_request_pay. The recipient defaults to your configured Agent Wallet, so you can bill yourself with just an amount. Pair with q402_request_status to poll for payment.",
|
|
4862
|
+
inputSchema: {
|
|
4863
|
+
type: "object",
|
|
4864
|
+
properties: {
|
|
4865
|
+
amount: {
|
|
4866
|
+
type: "string",
|
|
4867
|
+
pattern: "^\\d+(\\.\\d{1,18})?$",
|
|
4868
|
+
description: 'Required. Amount to request as a decimal string (e.g. "5", "1.50").'
|
|
4869
|
+
},
|
|
4870
|
+
token: {
|
|
4871
|
+
type: "string",
|
|
4872
|
+
enum: ["USDC", "USDT"],
|
|
4873
|
+
description: "Default 'USDT'. Both peg USD-1."
|
|
4874
|
+
},
|
|
4875
|
+
chain: {
|
|
4876
|
+
type: "string",
|
|
4877
|
+
enum: ["bnb", "eth", "avax", "xlayer", "stable", "mantle", "injective", "monad", "scroll", "arbitrum"],
|
|
4878
|
+
description: "Default 'bnb'. Chain the request settles on."
|
|
4879
|
+
},
|
|
4880
|
+
recipient: {
|
|
4881
|
+
type: "string",
|
|
4882
|
+
pattern: "^0x[0-9a-fA-F]{40}$",
|
|
4883
|
+
description: "Optional 0x address to receive funds. Defaults to Q402_AGENT_WALLET_ADDRESS (bill yourself)."
|
|
4884
|
+
},
|
|
4885
|
+
memo: {
|
|
4886
|
+
type: "string",
|
|
4887
|
+
maxLength: 200,
|
|
4888
|
+
description: "Optional note shown to the payer (\u2264200 chars)."
|
|
4889
|
+
},
|
|
4890
|
+
ttlDays: {
|
|
4891
|
+
type: "number",
|
|
4892
|
+
minimum: 1,
|
|
4893
|
+
maximum: 90,
|
|
4894
|
+
description: "Days until expiry. Default 7."
|
|
4895
|
+
}
|
|
4896
|
+
},
|
|
4897
|
+
required: ["amount"],
|
|
4898
|
+
additionalProperties: false
|
|
4899
|
+
}
|
|
4900
|
+
};
|
|
4901
|
+
|
|
4902
|
+
// src/tools/request-status.ts
|
|
4903
|
+
import { z as z26 } from "zod";
|
|
4904
|
+
var RequestStatusInputSchema = z26.object({
|
|
4905
|
+
requestId: z26.string().regex(/^req_[0-9a-f]{24}$/, "requestId must match req_<24-hex>").describe("Payment request id (req_ + 24 hex chars). Returned by q402_request_create; also the tail of any /pay/ URL.")
|
|
4906
|
+
});
|
|
4907
|
+
async function runRequestStatus(input) {
|
|
4908
|
+
const base = CONFIG.relayBaseUrl;
|
|
4909
|
+
const pageBase2 = base.replace(/\/api\/?$/, "");
|
|
4910
|
+
const resp = await fetch(`${base}/request/${input.requestId}`, {
|
|
4911
|
+
signal: AbortSignal.timeout(1e4)
|
|
4912
|
+
});
|
|
4913
|
+
if (resp.status === 404) {
|
|
4914
|
+
return { found: false, request: null, payUrl: null, notFound: true };
|
|
4915
|
+
}
|
|
4916
|
+
if (!resp.ok) {
|
|
4917
|
+
throw new Error(`request status fetch failed: HTTP ${resp.status}`);
|
|
4918
|
+
}
|
|
4919
|
+
const data = await resp.json();
|
|
4920
|
+
return {
|
|
4921
|
+
found: true,
|
|
4922
|
+
request: data.request,
|
|
4923
|
+
payUrl: `${pageBase2}/pay/${data.request.id}`
|
|
4924
|
+
};
|
|
4925
|
+
}
|
|
4926
|
+
var REQUEST_STATUS_TOOL = {
|
|
4927
|
+
name: "q402_request_status",
|
|
4928
|
+
description: "Look up a Q402 payment request by its req_ id. Read-only, no API key. Returns the amount, token, chain, recipient, status (open | paid | expired | cancelled) and a shareable pay URL. Use it to poll a request you created, or to inspect a requestId before paying it with q402_request_pay. An unknown or expired id returns notFound:true (no throw).",
|
|
4929
|
+
inputSchema: {
|
|
4930
|
+
type: "object",
|
|
4931
|
+
properties: {
|
|
4932
|
+
requestId: {
|
|
4933
|
+
type: "string",
|
|
4934
|
+
pattern: "^req_[0-9a-f]{24}$",
|
|
4935
|
+
description: "Payment request id (req_ + 24 hex). Returned by q402_request_create; also the tail of a /pay/ URL."
|
|
4936
|
+
}
|
|
4937
|
+
},
|
|
4938
|
+
required: ["requestId"],
|
|
4939
|
+
additionalProperties: false
|
|
4940
|
+
}
|
|
4941
|
+
};
|
|
4942
|
+
|
|
4943
|
+
// src/tools/request-pay.ts
|
|
4944
|
+
import { z as z27 } from "zod";
|
|
4945
|
+
var RequestPayInputSchema = z27.object({
|
|
4946
|
+
requestId: z27.string().regex(/^req_[0-9a-f]{24}$/, "requestId must match req_<24-hex>").describe("The payment request to pay (req_ + 24 hex). Get it from a /pay link, a 402 response, or whoever billed you."),
|
|
4947
|
+
confirm: z27.literal(true).describe(
|
|
4948
|
+
"REQUIRED. Must be literally `true`. Paying a request moves real funds from your Agent Wallet. Echo back the amount + token + recipient + chain from q402_request_status, get an explicit user yes, and ONLY then call with confirm:true. Same guard as q402_pay."
|
|
4949
|
+
),
|
|
4950
|
+
walletId: z27.string().optional().describe("Optional lowercased Agent Wallet address to pay from when you hold multiple. Defaults to Q402_AGENT_WALLET_ADDRESS, then the server default.")
|
|
4951
|
+
});
|
|
4952
|
+
async function runRequestPay(input) {
|
|
4953
|
+
const base = CONFIG.relayBaseUrl;
|
|
4954
|
+
let req;
|
|
4955
|
+
try {
|
|
4956
|
+
const r = await fetch(`${base}/request/${input.requestId}`, { signal: AbortSignal.timeout(1e4) });
|
|
4957
|
+
if (r.status === 404) {
|
|
4958
|
+
return { ok: false, status: "not_payable", requestId: input.requestId, txHash: null, receiptId: null, error: "NOT_FOUND", message: "No request with that id." };
|
|
4959
|
+
}
|
|
4960
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
4961
|
+
req = (await r.json()).request;
|
|
4962
|
+
} catch (e) {
|
|
4963
|
+
return { ok: false, status: "failed", requestId: input.requestId, txHash: null, receiptId: null, error: "LOOKUP_FAILED", message: e instanceof Error ? e.message : String(e) };
|
|
4964
|
+
}
|
|
4965
|
+
const terms = { amount: req.amount, token: req.token, chain: req.chain, recipient: req.recipient };
|
|
4966
|
+
if (req.status !== "open") {
|
|
4967
|
+
return { ok: false, status: "not_payable", requestId: req.id, txHash: null, receiptId: null, ...terms, error: req.status.toUpperCase(), message: `Request is ${req.status} \u2014 nothing to pay.` };
|
|
4968
|
+
}
|
|
4969
|
+
const amountNum = Number(req.amount);
|
|
4970
|
+
if (Number.isFinite(amountNum) && amountNum > CONFIG.maxAmountPerCallUsd) {
|
|
4971
|
+
return { ok: false, status: "not_payable", requestId: req.id, txHash: null, receiptId: null, ...terms, error: "AMOUNT_EXCEEDS_CAP", message: `Request amount $${req.amount} exceeds your Q402_MAX_AMOUNT_PER_CALL cap of $${CONFIG.maxAmountPerCallUsd}.` };
|
|
4972
|
+
}
|
|
4973
|
+
if (CONFIG.allowedRecipients.length > 0 && !CONFIG.allowedRecipients.includes(req.recipient.toLowerCase())) {
|
|
4974
|
+
return { ok: false, status: "not_payable", requestId: req.id, txHash: null, receiptId: null, ...terms, error: "RECIPIENT_NOT_ALLOWED", message: `Recipient ${req.recipient} is not in Q402_ALLOWED_RECIPIENTS.` };
|
|
4975
|
+
}
|
|
4976
|
+
const resolved = resolveApiKey(req.chain, "auto");
|
|
4977
|
+
if (!resolved.apiKey || !resolved.apiKey.startsWith("q402_live_")) {
|
|
4978
|
+
return {
|
|
4979
|
+
ok: false,
|
|
4980
|
+
status: "sandbox",
|
|
4981
|
+
requestId: req.id,
|
|
4982
|
+
txHash: null,
|
|
4983
|
+
receiptId: null,
|
|
4984
|
+
...terms,
|
|
4985
|
+
error: "LIVE_KEY_REQUIRED",
|
|
4986
|
+
message: "Paying a request settles real funds and needs a live Q402 API key.",
|
|
4987
|
+
setupHint: resolved.sandboxReason ?? "Configure a live Q402_MULTICHAIN_API_KEY (or Q402_TRIAL_API_KEY for BNB) to pay requests."
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
if (!CONFIG.realPaymentsRequested) {
|
|
4991
|
+
return {
|
|
4992
|
+
ok: false,
|
|
4993
|
+
status: "sandbox",
|
|
4994
|
+
requestId: req.id,
|
|
4995
|
+
txHash: null,
|
|
4996
|
+
receiptId: null,
|
|
4997
|
+
...terms,
|
|
4998
|
+
error: "REAL_PAYMENTS_DISABLED",
|
|
4999
|
+
message: "Real payments are off, so this request was not paid.",
|
|
5000
|
+
setupHint: "Set Q402_ENABLE_REAL_PAYMENTS=1 to let q402_request_pay settle real funds."
|
|
5001
|
+
};
|
|
5002
|
+
}
|
|
5003
|
+
const walletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId;
|
|
5004
|
+
try {
|
|
5005
|
+
const res = await fetch(`${base}/request/${req.id}/pay`, {
|
|
5006
|
+
method: "POST",
|
|
5007
|
+
headers: { "Content-Type": "application/json" },
|
|
5008
|
+
body: JSON.stringify({
|
|
5009
|
+
payerApiKey: resolved.apiKey,
|
|
5010
|
+
...walletId ? { walletId } : {}
|
|
5011
|
+
}),
|
|
5012
|
+
signal: AbortSignal.timeout(6e4)
|
|
5013
|
+
});
|
|
5014
|
+
const data = await res.json().catch(() => ({}));
|
|
5015
|
+
if (!res.ok || !data.txHash) {
|
|
5016
|
+
return { ok: false, status: "failed", requestId: req.id, txHash: null, receiptId: null, ...terms, error: data.error ?? `HTTP_${res.status}`, message: data.message ?? data.error ?? `Settlement failed (HTTP ${res.status}).` };
|
|
5017
|
+
}
|
|
5018
|
+
return { ok: true, status: "paid", requestId: req.id, txHash: data.txHash, receiptId: data.receiptId ?? null, ...terms };
|
|
5019
|
+
} catch (e) {
|
|
5020
|
+
return { ok: false, status: "failed", requestId: req.id, txHash: null, receiptId: null, ...terms, error: "NETWORK_ERROR", message: e instanceof Error ? e.message : String(e) };
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
var REQUEST_PAY_TOOL = {
|
|
5024
|
+
name: "q402_request_pay",
|
|
5025
|
+
description: "Pay a Q402 payment request from your own Agent Wallet, gaslessly. Give it a req_ id (from a /pay link, a 402 Payment Required response, or whoever billed you) and it settles the exact amount + token + recipient the request specifies \u2014 you cannot redirect or change them. MOVES FUNDS: requires confirm:true, a live API key, and Q402_ENABLE_REAL_PAYMENTS=1, same as q402_pay. Call q402_request_status first to show the user what they're paying. This is the agent-to-agent billing path: agent A bills with q402_request_create, agent B settles here.",
|
|
5026
|
+
inputSchema: {
|
|
5027
|
+
type: "object",
|
|
5028
|
+
properties: {
|
|
5029
|
+
requestId: {
|
|
5030
|
+
type: "string",
|
|
5031
|
+
pattern: "^req_[0-9a-f]{24}$",
|
|
5032
|
+
description: "Required. The req_ id to pay."
|
|
5033
|
+
},
|
|
5034
|
+
confirm: {
|
|
5035
|
+
type: "boolean",
|
|
5036
|
+
const: true,
|
|
5037
|
+
description: "REQUIRED. Must be literally true. Paying moves real funds \u2014 get an explicit user yes first."
|
|
5038
|
+
},
|
|
5039
|
+
walletId: {
|
|
5040
|
+
type: "string",
|
|
5041
|
+
description: "Optional. Agent Wallet address to pay from. Defaults to the configured / server-default wallet."
|
|
5042
|
+
}
|
|
5043
|
+
},
|
|
5044
|
+
required: ["requestId", "confirm"],
|
|
5045
|
+
additionalProperties: false
|
|
5046
|
+
}
|
|
5047
|
+
};
|
|
5048
|
+
|
|
4781
5049
|
// src/index.ts
|
|
4782
5050
|
function jsonText(value) {
|
|
4783
5051
|
return { type: "text", text: JSON.stringify(value, null, 2) };
|
|
@@ -4827,7 +5095,14 @@ async function main() {
|
|
|
4827
5095
|
// (like q402_pay). Mode C: apiKey in the body, server signs the supply
|
|
4828
5096
|
// / withdraw with the encrypted key.
|
|
4829
5097
|
YIELD_DEPOSIT_TOOL,
|
|
4830
|
-
YIELD_WITHDRAW_TOOL
|
|
5098
|
+
YIELD_WITHDRAW_TOOL,
|
|
5099
|
+
// Payment Requests — the receive side. create publishes an invoice
|
|
5100
|
+
// (no funds move, apiKey only), status is a public id lookup, pay
|
|
5101
|
+
// settles a request gaslessly from the payer's own Agent Wallet
|
|
5102
|
+
// (Mode C, confirm-gated like q402_pay). Enables agent-to-agent billing.
|
|
5103
|
+
REQUEST_CREATE_TOOL,
|
|
5104
|
+
REQUEST_STATUS_TOOL,
|
|
5105
|
+
REQUEST_PAY_TOOL
|
|
4831
5106
|
]
|
|
4832
5107
|
}));
|
|
4833
5108
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
@@ -4930,6 +5205,18 @@ async function main() {
|
|
|
4930
5205
|
const parsed = YieldWithdrawInputSchema.parse(args ?? {});
|
|
4931
5206
|
return await runYieldWithdraw(parsed);
|
|
4932
5207
|
}
|
|
5208
|
+
case "q402_request_create": {
|
|
5209
|
+
const parsed = RequestCreateInputSchema.parse(args ?? {});
|
|
5210
|
+
return { content: [jsonText(await runRequestCreate(parsed))] };
|
|
5211
|
+
}
|
|
5212
|
+
case "q402_request_status": {
|
|
5213
|
+
const parsed = RequestStatusInputSchema.parse(args ?? {});
|
|
5214
|
+
return { content: [jsonText(await runRequestStatus(parsed))] };
|
|
5215
|
+
}
|
|
5216
|
+
case "q402_request_pay": {
|
|
5217
|
+
const parsed = RequestPayInputSchema.parse(args ?? {});
|
|
5218
|
+
return { content: [jsonText(await runRequestPay(parsed))] };
|
|
5219
|
+
}
|
|
4933
5220
|
default:
|
|
4934
5221
|
return {
|
|
4935
5222
|
isError: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quackai/q402-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.32",
|
|
4
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": [
|