@quackai/q402-mcp 0.6.3 → 0.6.5
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 +14 -0
- package/dist/index.js +108 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,6 +157,20 @@ Then export the values in `~/.zshrc` / `~/.bashrc`. See the [Codex config refere
|
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
160
|
+
## Wallet modes — which signing path?
|
|
161
|
+
|
|
162
|
+
Three signing paths. Pick one when `q402_doctor` asks on first install. You can change later by editing `~/.q402/mcp.env` and restarting your client.
|
|
163
|
+
|
|
164
|
+
| Mode | Best for | Env to set | Private key in env? |
|
|
165
|
+
|---|---|---|---|
|
|
166
|
+
| **C — Server-managed** (recommended) | Most users. AI agents, automations, anyone who wants payments to "just work". Q402 holds an encrypted Agent Wallet for you; no MetaMask popup, no Smart-account marker. | `Q402_MULTICHAIN_API_KEY` (paid) **or** `Q402_TRIAL_API_KEY` (free BNB) | **No** |
|
|
167
|
+
| **B — Local Agent Wallet PK** | You want Agent Wallet automation but prefer to hold the PK yourself. Export from the dashboard once. MCP signs locally — key never leaves your machine. Your MetaMask is never touched. | `Q402_AGENTIC_PRIVATE_KEY` + an API key | Yes (Agent Wallet's exported PK) |
|
|
168
|
+
| **A — Your own EOA** | Power users who want their existing MetaMask address to be the on-chain payer. Your EOA signs directly via EIP-7702; the "Smart account" marker after first use is normal + reversible with `q402_clear_delegation`. **Use a fresh wallet.** | `Q402_PRIVATE_KEY` + an API key | Yes (your EOA's PK) |
|
|
169
|
+
|
|
170
|
+
`q402_doctor` on first install reads your env and recommends one of these based on what's already configured. The default for an empty install is Mode C — simplest path. If multiple modes are configured at once (e.g. both `Q402_PRIVATE_KEY` and `Q402_AGENTIC_PRIVATE_KEY` set), `q402_pay` will ask which one to use before sending so the agent never silently picks the wrong wallet.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
160
174
|
## Tools exposed
|
|
161
175
|
|
|
162
176
|
| Tool | Auth | Purpose |
|
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.6.
|
|
214
|
+
var PACKAGE_VERSION = "0.6.5";
|
|
215
215
|
|
|
216
216
|
// src/tools/quote.ts
|
|
217
217
|
import { z } from "zod";
|
|
@@ -2869,6 +2869,108 @@ async function runRecurringCancel(input) {
|
|
|
2869
2869
|
}
|
|
2870
2870
|
}
|
|
2871
2871
|
|
|
2872
|
+
// src/tools/recurring-fires.ts
|
|
2873
|
+
import { z as z13 } from "zod";
|
|
2874
|
+
var RecurringFiresInputSchema = z13.object({
|
|
2875
|
+
ruleId: z13.string().min(1).describe(
|
|
2876
|
+
"Rule id whose fire history to fetch. Obtain from q402_recurring_list \u2014 each entry's `ruleId` field."
|
|
2877
|
+
),
|
|
2878
|
+
limit: z13.number().int().min(1).max(50).optional().describe(
|
|
2879
|
+
"Max number of fires to return (newest first). Defaults to 50 (the server cap). Pass a smaller number when you only need the most recent few."
|
|
2880
|
+
),
|
|
2881
|
+
walletId: z13.string().optional().describe(
|
|
2882
|
+
"Optional lowercased Agent Wallet address when the user holds multiple wallets. Defaults to Q402_AGENT_WALLET_ADDRESS env, then the owner's default wallet."
|
|
2883
|
+
)
|
|
2884
|
+
});
|
|
2885
|
+
var RECURRING_FIRES_TOOL = {
|
|
2886
|
+
name: "q402_recurring_fires",
|
|
2887
|
+
description: "Read the past-fire history of a specific recurring-payment rule. Returns up to 50 entries (newest first), each with the timestamp, scheduled slot, total USD amount that settled, on-chain tx hashes, and a partial-failure flag if some recipient rows didn't make it. Use this when the user asks 'when was the last fire?', 'did Friday's payout go out?', 'how much has rule X spent?', or before claiming a fire is missing. Authenticated by the configured Multichain API key. Read-only \u2014 does not trigger or modify anything. Call q402_recurring_list first to find the ruleId.",
|
|
2888
|
+
inputSchema: {
|
|
2889
|
+
type: "object",
|
|
2890
|
+
properties: {
|
|
2891
|
+
ruleId: {
|
|
2892
|
+
type: "string",
|
|
2893
|
+
description: "Rule id from q402_recurring_list. Required."
|
|
2894
|
+
},
|
|
2895
|
+
limit: {
|
|
2896
|
+
type: "number",
|
|
2897
|
+
description: "Max number of fires to return (1-50, newest first). Defaults to 50."
|
|
2898
|
+
},
|
|
2899
|
+
walletId: {
|
|
2900
|
+
type: "string",
|
|
2901
|
+
description: "Optional. Lowercased Agent Wallet address when the user holds multiple wallets. Defaults to Q402_AGENT_WALLET_ADDRESS env, then the owner's default wallet on the server."
|
|
2902
|
+
}
|
|
2903
|
+
},
|
|
2904
|
+
required: ["ruleId"],
|
|
2905
|
+
additionalProperties: false
|
|
2906
|
+
}
|
|
2907
|
+
};
|
|
2908
|
+
async function runRecurringFires(input) {
|
|
2909
|
+
const base = CONFIG.relayBaseUrl;
|
|
2910
|
+
const dashboardUrl = base.replace(/\/api$/, "") + "/dashboard?tab=agent";
|
|
2911
|
+
if (!CONFIG.apiKey || !CONFIG.apiKey.startsWith("q402_live_")) {
|
|
2912
|
+
return {
|
|
2913
|
+
configured: false,
|
|
2914
|
+
walletId: null,
|
|
2915
|
+
ruleId: input.ruleId,
|
|
2916
|
+
rule: null,
|
|
2917
|
+
fires: [],
|
|
2918
|
+
count: 0,
|
|
2919
|
+
dashboardUrl,
|
|
2920
|
+
setupHint: "No live Q402 API key configured. Run q402_doctor to set one up, or open the dashboard to view fire history from the UI."
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
const explicitWalletId = typeof input.walletId === "string" && input.walletId.length > 0 ? input.walletId.toLowerCase() : CONFIG.walletId;
|
|
2924
|
+
try {
|
|
2925
|
+
const res = await fetch(`${base}/wallet/agentic/recurring-by-key`, {
|
|
2926
|
+
method: "POST",
|
|
2927
|
+
headers: { "Content-Type": "application/json" },
|
|
2928
|
+
body: JSON.stringify({
|
|
2929
|
+
apiKey: CONFIG.apiKey,
|
|
2930
|
+
action: "fires",
|
|
2931
|
+
ruleId: input.ruleId,
|
|
2932
|
+
...typeof input.limit === "number" ? { limit: input.limit } : {},
|
|
2933
|
+
...explicitWalletId ? { walletId: explicitWalletId } : {}
|
|
2934
|
+
})
|
|
2935
|
+
});
|
|
2936
|
+
const data = await res.json().catch(() => ({}));
|
|
2937
|
+
if (!res.ok) {
|
|
2938
|
+
return {
|
|
2939
|
+
configured: true,
|
|
2940
|
+
walletId: explicitWalletId,
|
|
2941
|
+
ruleId: input.ruleId,
|
|
2942
|
+
rule: null,
|
|
2943
|
+
fires: [],
|
|
2944
|
+
count: 0,
|
|
2945
|
+
dashboardUrl,
|
|
2946
|
+
error: data.error ?? `HTTP_${res.status}`,
|
|
2947
|
+
message: data.message ?? `Fires fetch failed with HTTP ${res.status}.`
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
return {
|
|
2951
|
+
configured: true,
|
|
2952
|
+
walletId: data.walletId ?? explicitWalletId,
|
|
2953
|
+
ruleId: data.ruleId ?? input.ruleId,
|
|
2954
|
+
rule: data.rule ?? null,
|
|
2955
|
+
fires: Array.isArray(data.fires) ? data.fires : [],
|
|
2956
|
+
count: typeof data.count === "number" ? data.count : data.fires?.length ?? 0,
|
|
2957
|
+
dashboardUrl
|
|
2958
|
+
};
|
|
2959
|
+
} catch (e) {
|
|
2960
|
+
return {
|
|
2961
|
+
configured: true,
|
|
2962
|
+
walletId: explicitWalletId,
|
|
2963
|
+
ruleId: input.ruleId,
|
|
2964
|
+
rule: null,
|
|
2965
|
+
fires: [],
|
|
2966
|
+
count: 0,
|
|
2967
|
+
dashboardUrl,
|
|
2968
|
+
error: "NETWORK_ERROR",
|
|
2969
|
+
message: e instanceof Error ? e.message : String(e)
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2872
2974
|
// src/index.ts
|
|
2873
2975
|
function jsonText(value) {
|
|
2874
2976
|
return { type: "text", text: JSON.stringify(value, null, 2) };
|
|
@@ -2892,6 +2994,7 @@ async function main() {
|
|
|
2892
2994
|
AGENTIC_INFO_TOOL,
|
|
2893
2995
|
RECURRING_LIST_TOOL,
|
|
2894
2996
|
RECURRING_CREATE_TOOL,
|
|
2997
|
+
RECURRING_FIRES_TOOL,
|
|
2895
2998
|
RECURRING_CANCEL_TOOL,
|
|
2896
2999
|
CLEAR_DELEGATION_TOOL
|
|
2897
3000
|
]
|
|
@@ -2948,6 +3051,10 @@ async function main() {
|
|
|
2948
3051
|
const parsed = RecurringCancelInputSchema.parse(args ?? {});
|
|
2949
3052
|
return { content: [jsonText(await runRecurringCancel(parsed))] };
|
|
2950
3053
|
}
|
|
3054
|
+
case "q402_recurring_fires": {
|
|
3055
|
+
const parsed = RecurringFiresInputSchema.parse(args ?? {});
|
|
3056
|
+
return { content: [jsonText(await runRecurringFires(parsed))] };
|
|
3057
|
+
}
|
|
2951
3058
|
default:
|
|
2952
3059
|
return {
|
|
2953
3060
|
isError: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quackai/q402-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "MCP server for Q402 — gasless USDC, USDT, and RLUSD payments across 9 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": [
|