@quackai/q402-mcp 0.8.24 → 0.8.26
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 +55 -8
- 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.26",
|
|
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,7 +1116,16 @@ async function runPay(input) {
|
|
|
1116
1116
|
to: input.to.toLowerCase(),
|
|
1117
1117
|
amount: input.amount,
|
|
1118
1118
|
token: input.token,
|
|
1119
|
-
|
|
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(),
|
|
1123
|
+
...input.hookParams?.splits ? { splits: input.hookParams.splits.map((s) => ({ r: s.recipient.toLowerCase(), bps: s.bps })) } : {},
|
|
1124
|
+
// Bind the settlement-gating hooks too — a ConditionalOracle gate or a
|
|
1125
|
+
// ReputationGate materially changes WHEN/IF money moves, so dropping or
|
|
1126
|
+
// altering them after the preview must invalidate consent.
|
|
1127
|
+
...input.hookParams?.condition ? { cond: { kind: input.hookParams.condition.kind, op: input.hookParams.condition.op, value: input.hookParams.condition.value, feed: input.hookParams.condition.feed ?? null } } : {},
|
|
1128
|
+
...input.hookParams?.recipientAgentId ? { ragent: input.hookParams.recipientAgentId } : {}
|
|
1120
1129
|
};
|
|
1121
1130
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
1122
1131
|
if (!consent.ok) {
|
|
@@ -1530,7 +1539,10 @@ async function runBatchPay(input) {
|
|
|
1530
1539
|
t: "batch",
|
|
1531
1540
|
chain: input.chain,
|
|
1532
1541
|
token: input.token,
|
|
1533
|
-
recipients: input.recipients.map((r) => ({ to: r.to.toLowerCase(), amount: r.amount }))
|
|
1542
|
+
recipients: input.recipients.map((r) => ({ to: r.to.toLowerCase(), amount: r.amount })),
|
|
1543
|
+
// Bind the funding source too (see q402_pay).
|
|
1544
|
+
wm: input.walletMode ?? "",
|
|
1545
|
+
wid: (input.walletId ?? "").toLowerCase()
|
|
1534
1546
|
};
|
|
1535
1547
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
1536
1548
|
if (!consent.ok) {
|
|
@@ -3262,7 +3274,12 @@ async function runBridgeSend(input) {
|
|
|
3262
3274
|
src: input.src,
|
|
3263
3275
|
dst: input.dst,
|
|
3264
3276
|
amount: input.amount,
|
|
3265
|
-
feeToken: input.feeToken === "native" ? "native" : "LINK"
|
|
3277
|
+
feeToken: input.feeToken === "native" ? "native" : "LINK",
|
|
3278
|
+
// Bind the fee ceiling too — it bounds what the user actually pays, so it
|
|
3279
|
+
// must not be addable/changeable after the preview.
|
|
3280
|
+
maxFeeRaw: input.maxFeeRaw ?? null,
|
|
3281
|
+
// Bind the funding wallet too (see q402_pay).
|
|
3282
|
+
wid: (input.walletId ?? "").toLowerCase()
|
|
3266
3283
|
};
|
|
3267
3284
|
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3268
3285
|
if (input.confirm !== true || !consent.ok) {
|
|
@@ -3641,6 +3658,9 @@ var YieldDepositInputSchema = z16.object({
|
|
|
3641
3658
|
),
|
|
3642
3659
|
confirm: z16.boolean().optional().describe(
|
|
3643
3660
|
"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."
|
|
3661
|
+
),
|
|
3662
|
+
consentToken: z16.string().optional().describe(
|
|
3663
|
+
"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
3664
|
)
|
|
3645
3665
|
});
|
|
3646
3666
|
var YIELD_DEPOSIT_TOOL = {
|
|
@@ -3674,6 +3694,10 @@ var YIELD_DEPOSIT_TOOL = {
|
|
|
3674
3694
|
confirm: {
|
|
3675
3695
|
type: "boolean",
|
|
3676
3696
|
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."
|
|
3697
|
+
},
|
|
3698
|
+
consentToken: {
|
|
3699
|
+
type: "string",
|
|
3700
|
+
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
3701
|
}
|
|
3678
3702
|
},
|
|
3679
3703
|
required: ["token", "amount"],
|
|
@@ -3692,12 +3716,20 @@ async function runYieldDeposit(input) {
|
|
|
3692
3716
|
}
|
|
3693
3717
|
const walletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId ?? void 0;
|
|
3694
3718
|
const idempotencyKey = typeof input.idempotencyKey === "string" && input.idempotencyKey.length > 0 ? input.idempotencyKey : hexlify2(randomBytes2(32));
|
|
3695
|
-
|
|
3719
|
+
const consentIntent = {
|
|
3720
|
+
t: "yield-deposit",
|
|
3721
|
+
chain: input.chain,
|
|
3722
|
+
token: input.token,
|
|
3723
|
+
amount: input.amount,
|
|
3724
|
+
walletId: walletId ?? null
|
|
3725
|
+
};
|
|
3726
|
+
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3727
|
+
if (input.confirm !== true || !consent.ok) {
|
|
3696
3728
|
const walletDesc = walletId ? `wallet ${walletId}` : "your default Agent Wallet";
|
|
3697
3729
|
return {
|
|
3698
3730
|
content: [{
|
|
3699
3731
|
type: "text",
|
|
3700
|
-
text: `Will supply ${input.amount} ${input.token} into Aave on ${input.chain} from ${walletDesc}. This MOVES FUNDS.
|
|
3732
|
+
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
3733
|
}]
|
|
3702
3734
|
};
|
|
3703
3735
|
}
|
|
@@ -3821,6 +3853,9 @@ var YieldWithdrawInputSchema = z17.object({
|
|
|
3821
3853
|
),
|
|
3822
3854
|
confirm: z17.boolean().optional().describe(
|
|
3823
3855
|
"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."
|
|
3856
|
+
),
|
|
3857
|
+
consentToken: z17.string().optional().describe(
|
|
3858
|
+
"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
3859
|
)
|
|
3825
3860
|
});
|
|
3826
3861
|
var YIELD_WITHDRAW_TOOL = {
|
|
@@ -3854,6 +3889,10 @@ var YIELD_WITHDRAW_TOOL = {
|
|
|
3854
3889
|
confirm: {
|
|
3855
3890
|
type: "boolean",
|
|
3856
3891
|
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."
|
|
3892
|
+
},
|
|
3893
|
+
consentToken: {
|
|
3894
|
+
type: "string",
|
|
3895
|
+
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
3896
|
}
|
|
3858
3897
|
},
|
|
3859
3898
|
required: ["token", "amount"],
|
|
@@ -3873,12 +3912,20 @@ async function runYieldWithdraw(input) {
|
|
|
3873
3912
|
const walletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId ?? void 0;
|
|
3874
3913
|
const idempotencyKey = typeof input.idempotencyKey === "string" && input.idempotencyKey.length > 0 ? input.idempotencyKey : hexlify3(randomBytes3(32));
|
|
3875
3914
|
const amountDesc = input.amount === "max" ? "the FULL position" : `${input.amount} ${input.token}`;
|
|
3876
|
-
|
|
3915
|
+
const consentIntent = {
|
|
3916
|
+
t: "yield-withdraw",
|
|
3917
|
+
chain: input.chain,
|
|
3918
|
+
token: input.token,
|
|
3919
|
+
amount: input.amount,
|
|
3920
|
+
walletId: walletId ?? null
|
|
3921
|
+
};
|
|
3922
|
+
const consent = checkConsent(consentIntent, input.consentToken);
|
|
3923
|
+
if (input.confirm !== true || !consent.ok) {
|
|
3877
3924
|
const walletDesc = walletId ? `wallet ${walletId}` : "your default Agent Wallet";
|
|
3878
3925
|
return {
|
|
3879
3926
|
content: [{
|
|
3880
3927
|
type: "text",
|
|
3881
|
-
text: `Will withdraw ${amountDesc} from Aave on ${input.chain} back to ${walletDesc}. This MOVES FUNDS.
|
|
3928
|
+
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
3929
|
}]
|
|
3883
3930
|
};
|
|
3884
3931
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quackai/q402-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.26",
|
|
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": [
|