@quackai/q402-mcp 0.8.24 → 0.8.25
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/dist/index.js +46 -7
- package/package.json +1 -1
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.25",
|
|
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: [
|
|
@@ -1116,6 +1116,10 @@ async function runPay(input) {
|
|
|
1116
1116
|
to: input.to.toLowerCase(),
|
|
1117
1117
|
amount: input.amount,
|
|
1118
1118
|
token: input.token,
|
|
1119
|
+
// Bind the funding source too — the user is consenting to spend from THIS
|
|
1120
|
+
// wallet, so a different walletMode/walletId needs a fresh preview.
|
|
1121
|
+
wm: effectiveMode,
|
|
1122
|
+
wid: (input.walletId ?? "").toLowerCase(),
|
|
1119
1123
|
...input.hookParams?.splits ? { splits: input.hookParams.splits.map((s) => ({ r: s.recipient.toLowerCase(), bps: s.bps })) } : {}
|
|
1120
1124
|
};
|
|
1121
1125
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
@@ -1530,7 +1534,10 @@ async function runBatchPay(input) {
|
|
|
1530
1534
|
t: "batch",
|
|
1531
1535
|
chain: input.chain,
|
|
1532
1536
|
token: input.token,
|
|
1533
|
-
recipients: input.recipients.map((r) => ({ to: r.to.toLowerCase(), amount: r.amount }))
|
|
1537
|
+
recipients: input.recipients.map((r) => ({ to: r.to.toLowerCase(), amount: r.amount })),
|
|
1538
|
+
// Bind the funding source too (see q402_pay).
|
|
1539
|
+
wm: input.walletMode ?? "",
|
|
1540
|
+
wid: (input.walletId ?? "").toLowerCase()
|
|
1534
1541
|
};
|
|
1535
1542
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
1536
1543
|
if (!consent.ok) {
|
|
@@ -3262,7 +3269,9 @@ async function runBridgeSend(input) {
|
|
|
3262
3269
|
src: input.src,
|
|
3263
3270
|
dst: input.dst,
|
|
3264
3271
|
amount: input.amount,
|
|
3265
|
-
feeToken: input.feeToken === "native" ? "native" : "LINK"
|
|
3272
|
+
feeToken: input.feeToken === "native" ? "native" : "LINK",
|
|
3273
|
+
// Bind the funding wallet too (see q402_pay).
|
|
3274
|
+
wid: (input.walletId ?? "").toLowerCase()
|
|
3266
3275
|
};
|
|
3267
3276
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3268
3277
|
if (input.confirm !== true || !consent.ok) {
|
|
@@ -3641,6 +3650,9 @@ var YieldDepositInputSchema = z16.object({
|
|
|
3641
3650
|
),
|
|
3642
3651
|
confirm: z16.boolean().optional().describe(
|
|
3643
3652
|
"MUST be true to actually supply funds. Set this only after the user has explicitly approved this exact deposit (amount, token, chain, wallet) in the conversation. When omitted or false the tool previews the action and does NOT move any funds."
|
|
3653
|
+
),
|
|
3654
|
+
consentToken: z16.string().optional().describe(
|
|
3655
|
+
"Two-phase consent. LEAVE UNSET on the first call: the tool previews the deposit (no funds move) and returns a consentToken. Relay the preview to the user, get an explicit yes, then re-call with confirm:true AND this consentToken. The token is re-derived from (chain, token, amount, wallet) and refused on mismatch, so a previewed deposit can't be swapped."
|
|
3644
3656
|
)
|
|
3645
3657
|
});
|
|
3646
3658
|
var YIELD_DEPOSIT_TOOL = {
|
|
@@ -3674,6 +3686,10 @@ var YIELD_DEPOSIT_TOOL = {
|
|
|
3674
3686
|
confirm: {
|
|
3675
3687
|
type: "boolean",
|
|
3676
3688
|
description: "MUST be true to actually supply funds \u2014 set only after the user explicitly approved this exact deposit in chat. Omit (or false) to preview without moving funds."
|
|
3689
|
+
},
|
|
3690
|
+
consentToken: {
|
|
3691
|
+
type: "string",
|
|
3692
|
+
description: "Two-phase consent token. Leave unset on the first call to get a preview + token; re-call with confirm:true AND this token after the user approves. Bound to (chain, token, amount, wallet) and refused on mismatch."
|
|
3677
3693
|
}
|
|
3678
3694
|
},
|
|
3679
3695
|
required: ["token", "amount"],
|
|
@@ -3692,12 +3708,20 @@ async function runYieldDeposit(input) {
|
|
|
3692
3708
|
}
|
|
3693
3709
|
const walletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId ?? void 0;
|
|
3694
3710
|
const idempotencyKey = typeof input.idempotencyKey === "string" && input.idempotencyKey.length > 0 ? input.idempotencyKey : hexlify2(randomBytes2(32));
|
|
3695
|
-
|
|
3711
|
+
const consentIntent = {
|
|
3712
|
+
t: "yield-deposit",
|
|
3713
|
+
chain: input.chain,
|
|
3714
|
+
token: input.token,
|
|
3715
|
+
amount: input.amount,
|
|
3716
|
+
walletId: walletId ?? null
|
|
3717
|
+
};
|
|
3718
|
+
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3719
|
+
if (input.confirm !== true || !consent.ok) {
|
|
3696
3720
|
const walletDesc = walletId ? `wallet ${walletId}` : "your default Agent Wallet";
|
|
3697
3721
|
return {
|
|
3698
3722
|
content: [{
|
|
3699
3723
|
type: "text",
|
|
3700
|
-
text: `Will supply ${input.amount} ${input.token} into Aave on ${input.chain} from ${walletDesc}. This MOVES FUNDS.
|
|
3724
|
+
text: `Will supply ${input.amount} ${input.token} into Aave on ${input.chain} from ${walletDesc}. This MOVES FUNDS. Confirm with the user, then re-call with confirm:true AND consentToken="${consent.expected}".`
|
|
3701
3725
|
}]
|
|
3702
3726
|
};
|
|
3703
3727
|
}
|
|
@@ -3821,6 +3845,9 @@ var YieldWithdrawInputSchema = z17.object({
|
|
|
3821
3845
|
),
|
|
3822
3846
|
confirm: z17.boolean().optional().describe(
|
|
3823
3847
|
"MUST be true to actually withdraw funds. Set this only after the user has explicitly approved this exact withdrawal (amount, token, chain, wallet) in the conversation. When omitted or false the tool previews the action and does NOT move any funds."
|
|
3848
|
+
),
|
|
3849
|
+
consentToken: z17.string().optional().describe(
|
|
3850
|
+
"Two-phase consent. LEAVE UNSET on the first call: the tool previews the withdrawal (no funds move) and returns a consentToken. Relay the preview to the user, get an explicit yes, then re-call with confirm:true AND this consentToken. The token is re-derived from (chain, token, amount, wallet)."
|
|
3824
3851
|
)
|
|
3825
3852
|
});
|
|
3826
3853
|
var YIELD_WITHDRAW_TOOL = {
|
|
@@ -3854,6 +3881,10 @@ var YIELD_WITHDRAW_TOOL = {
|
|
|
3854
3881
|
confirm: {
|
|
3855
3882
|
type: "boolean",
|
|
3856
3883
|
description: "MUST be true to actually withdraw funds \u2014 set only after the user explicitly approved this exact withdrawal in chat. Omit (or false) to preview without moving funds."
|
|
3884
|
+
},
|
|
3885
|
+
consentToken: {
|
|
3886
|
+
type: "string",
|
|
3887
|
+
description: "Two-phase consent token. Leave unset on the first call to get a preview + token; re-call with confirm:true AND this token after the user approves. Bound to (chain, token, amount, wallet)."
|
|
3857
3888
|
}
|
|
3858
3889
|
},
|
|
3859
3890
|
required: ["token", "amount"],
|
|
@@ -3873,12 +3904,20 @@ async function runYieldWithdraw(input) {
|
|
|
3873
3904
|
const walletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId ?? void 0;
|
|
3874
3905
|
const idempotencyKey = typeof input.idempotencyKey === "string" && input.idempotencyKey.length > 0 ? input.idempotencyKey : hexlify3(randomBytes3(32));
|
|
3875
3906
|
const amountDesc = input.amount === "max" ? "the FULL position" : `${input.amount} ${input.token}`;
|
|
3876
|
-
|
|
3907
|
+
const consentIntent = {
|
|
3908
|
+
t: "yield-withdraw",
|
|
3909
|
+
chain: input.chain,
|
|
3910
|
+
token: input.token,
|
|
3911
|
+
amount: input.amount,
|
|
3912
|
+
walletId: walletId ?? null
|
|
3913
|
+
};
|
|
3914
|
+
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3915
|
+
if (input.confirm !== true || !consent.ok) {
|
|
3877
3916
|
const walletDesc = walletId ? `wallet ${walletId}` : "your default Agent Wallet";
|
|
3878
3917
|
return {
|
|
3879
3918
|
content: [{
|
|
3880
3919
|
type: "text",
|
|
3881
|
-
text: `Will withdraw ${amountDesc} from Aave on ${input.chain} back to ${walletDesc}. This MOVES FUNDS.
|
|
3920
|
+
text: `Will withdraw ${amountDesc} from Aave on ${input.chain} back to ${walletDesc}. This MOVES FUNDS. Confirm with the user, then re-call with confirm:true AND consentToken="${consent.expected}".`
|
|
3882
3921
|
}]
|
|
3883
3922
|
};
|
|
3884
3923
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quackai/q402-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.25",
|
|
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": [
|