@agentwonderland/mcp 0.1.51 → 0.1.53
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/core/__tests__/api-client.test.js +6 -2
- package/dist/core/__tests__/link-cli.test.d.ts +1 -0
- package/dist/core/__tests__/link-cli.test.js +102 -0
- package/dist/core/__tests__/principal.test.js +25 -0
- package/dist/core/api-client.js +4 -2
- package/dist/core/link-cli.d.ts +5 -0
- package/dist/core/link-cli.js +25 -25
- package/dist/core/principal.d.ts +1 -0
- package/dist/core/principal.js +49 -1
- package/dist/index.js +3 -0
- package/dist/tools/__tests__/rebates.test.d.ts +1 -0
- package/dist/tools/__tests__/rebates.test.js +72 -0
- package/dist/tools/__tests__/run.test.js +26 -0
- package/dist/tools/__tests__/wallet.test.js +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/observability.d.ts +2 -0
- package/dist/tools/observability.js +20 -0
- package/dist/tools/rebates.d.ts +2 -0
- package/dist/tools/rebates.js +51 -0
- package/dist/tools/run.js +6 -0
- package/dist/tools/solve.js +8 -1
- package/dist/tools/wallet.js +4 -4
- package/package.json +1 -1
- package/src/core/__tests__/api-client.test.ts +8 -1
- package/src/core/__tests__/link-cli.test.ts +125 -0
- package/src/core/__tests__/principal.test.ts +31 -0
- package/src/core/api-client.ts +4 -2
- package/src/core/link-cli.ts +25 -27
- package/src/core/principal.ts +54 -1
- package/src/index.ts +3 -0
- package/src/tools/__tests__/rebates.test.ts +91 -0
- package/src/tools/__tests__/run.test.ts +33 -0
- package/src/tools/__tests__/wallet.test.ts +1 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/rebates.ts +102 -0
- package/src/tools/run.ts +7 -0
- package/src/tools/solve.ts +8 -1
- package/src/tools/wallet.ts +4 -4
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { apiGet } from "../core/api-client.js";
|
|
3
|
+
|
|
4
|
+
type RebateStatus = {
|
|
5
|
+
consumer_principal: string;
|
|
6
|
+
principal_type: string;
|
|
7
|
+
principal_value: string;
|
|
8
|
+
payout_address: string | null;
|
|
9
|
+
payout_chain: string;
|
|
10
|
+
auto_payout_threshold_usd: string;
|
|
11
|
+
totals: {
|
|
12
|
+
lifetime_earned_usd: string;
|
|
13
|
+
pending_usd: string;
|
|
14
|
+
paid_usd: string;
|
|
15
|
+
blocked_usd: string;
|
|
16
|
+
total_count: number;
|
|
17
|
+
pending_count: number;
|
|
18
|
+
paid_count: number;
|
|
19
|
+
blocked_count: number;
|
|
20
|
+
};
|
|
21
|
+
by_source: Array<{
|
|
22
|
+
source_type: string;
|
|
23
|
+
status: string;
|
|
24
|
+
count: number;
|
|
25
|
+
rebate_usd: string;
|
|
26
|
+
}>;
|
|
27
|
+
recent_payouts: Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
status: string;
|
|
30
|
+
amount_usd: string;
|
|
31
|
+
earning_count: number;
|
|
32
|
+
tx_hash: string | null;
|
|
33
|
+
processed_at: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function text(t: string) {
|
|
38
|
+
return { content: [{ type: "text" as const, text: t }] };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function money(value: string | number): string {
|
|
42
|
+
const numeric = Number(value);
|
|
43
|
+
return Number.isFinite(numeric) ? `$${numeric.toFixed(4)}` : `$${value}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function sourceLabel(value: string): string {
|
|
47
|
+
return value.replace(/_/g, " ");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function registerRebateTools(server: McpServer): void {
|
|
51
|
+
server.tool(
|
|
52
|
+
"rebate_status",
|
|
53
|
+
"Show your Agent Wonderland consumer rebate balance, payout threshold, blocked rebates, and recent payout transactions.",
|
|
54
|
+
{},
|
|
55
|
+
async () => {
|
|
56
|
+
const status = await apiGet<RebateStatus>("/rebates/status", { ensureConsumerPrincipal: true });
|
|
57
|
+
const threshold = Number(status.auto_payout_threshold_usd);
|
|
58
|
+
const pending = Number(status.totals.pending_usd);
|
|
59
|
+
const remaining = Math.max(0, threshold - pending);
|
|
60
|
+
|
|
61
|
+
const lines = [
|
|
62
|
+
"Rebate status",
|
|
63
|
+
`Consumer principal: ${status.consumer_principal}`,
|
|
64
|
+
`Base payout address: ${status.payout_address ?? "not configured"}`,
|
|
65
|
+
"",
|
|
66
|
+
`Lifetime earned: ${money(status.totals.lifetime_earned_usd)} across ${status.totals.total_count} rebate(s)`,
|
|
67
|
+
`Paid out: ${money(status.totals.paid_usd)} across ${status.totals.paid_count} rebate(s)`,
|
|
68
|
+
`Pending: ${money(status.totals.pending_usd)} across ${status.totals.pending_count} rebate(s)`,
|
|
69
|
+
`Blocked: ${money(status.totals.blocked_usd)} across ${status.totals.blocked_count} rebate(s)`,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
if (Number.isFinite(threshold) && threshold > 0) {
|
|
73
|
+
lines.push(
|
|
74
|
+
pending >= threshold
|
|
75
|
+
? `Auto payout: eligible for the next processor run (threshold ${money(threshold)})`
|
|
76
|
+
: `Auto payout: ${money(remaining)} until the ${money(threshold)} threshold`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (status.by_source.length > 0) {
|
|
81
|
+
lines.push("", "By source:");
|
|
82
|
+
for (const row of status.by_source) {
|
|
83
|
+
lines.push(` ${sourceLabel(row.source_type)} / ${row.status}: ${money(row.rebate_usd)} (${row.count})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (status.recent_payouts.length > 0) {
|
|
88
|
+
lines.push("", "Recent payouts:");
|
|
89
|
+
for (const payout of status.recent_payouts.slice(0, 5)) {
|
|
90
|
+
const tx = payout.tx_hash ? ` tx=${payout.tx_hash}` : "";
|
|
91
|
+
lines.push(` ${payout.status}: ${money(payout.amount_usd)} (${payout.earning_count})${tx}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!status.payout_address) {
|
|
96
|
+
lines.push("", "No Base payout address is configured, so new rebates may be blocked.");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return text(lines.join("\n"));
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
}
|
package/src/tools/run.ts
CHANGED
|
@@ -220,6 +220,10 @@ export function registerRunTools(server: McpServer): void {
|
|
|
220
220
|
` Payment: ${formatPaymentLabel(method)}`,
|
|
221
221
|
];
|
|
222
222
|
|
|
223
|
+
if (method === "link") {
|
|
224
|
+
quoteLines.push(" Link: after confirming here, approve the Link spend request and rerun the confirmed call.");
|
|
225
|
+
}
|
|
226
|
+
|
|
223
227
|
const creditPackLines = buildCreditPackOfferLines(agent);
|
|
224
228
|
if (creditPackLines.length > 0) {
|
|
225
229
|
quoteLines.push("", ...creditPackLines);
|
|
@@ -299,6 +303,9 @@ export function registerRunTools(server: McpServer): void {
|
|
|
299
303
|
);
|
|
300
304
|
}
|
|
301
305
|
const msg = apiErr?.message ?? "Failed to run agent";
|
|
306
|
+
if (msg.includes("Link approval required.")) {
|
|
307
|
+
return text(msg);
|
|
308
|
+
}
|
|
302
309
|
if (msg.includes("Missing required field") || msg.includes("validation failed")) {
|
|
303
310
|
return text(`Error: ${msg}\n\nUse get_agent("${agent_id}") to see the required input fields.`);
|
|
304
311
|
}
|
package/src/tools/solve.ts
CHANGED
|
@@ -292,6 +292,9 @@ export function registerSolveTools(server: McpServer): void {
|
|
|
292
292
|
`Best match: ${selected.name}`,
|
|
293
293
|
`Cost: $${estimatedCost.toFixed(2)}`,
|
|
294
294
|
`Payment: ${formatPaymentLabel(method)}`,
|
|
295
|
+
...(method === "link"
|
|
296
|
+
? ["Link: after confirming here, approve the Link spend request and rerun the confirmed call."]
|
|
297
|
+
: []),
|
|
295
298
|
...(() => {
|
|
296
299
|
const summary = buildCreditPackSummary(selected);
|
|
297
300
|
return summary.length > 0 ? ["", ...summary] : [];
|
|
@@ -361,7 +364,11 @@ export function registerSolveTools(server: McpServer): void {
|
|
|
361
364
|
].join("\n"),
|
|
362
365
|
);
|
|
363
366
|
}
|
|
364
|
-
|
|
367
|
+
const msg = apiErr?.message ?? "Failed to run agent";
|
|
368
|
+
if (msg.includes("Link approval required.")) {
|
|
369
|
+
return text(msg);
|
|
370
|
+
}
|
|
371
|
+
return text(`Error: ${msg}`);
|
|
365
372
|
}
|
|
366
373
|
|
|
367
374
|
pendingSolves.delete(pendingKey);
|
package/src/tools/wallet.ts
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
installOws,
|
|
40
40
|
platformSupportsOws,
|
|
41
41
|
} from "../core/ows-adapter.js";
|
|
42
|
-
import { ensureConsumerPrincipal, getConsumerPrincipal } from "../core/principal.js";
|
|
42
|
+
import { ensureConsumerPrincipal, ensureConsumerPrincipalForMethod, getConsumerPrincipal } from "../core/principal.js";
|
|
43
43
|
import { MCP_PACKAGE_VERSION } from "../core/version.js";
|
|
44
44
|
|
|
45
45
|
function text(t: string) {
|
|
@@ -292,7 +292,7 @@ export function registerWalletTools(server: McpServer): void {
|
|
|
292
292
|
paymentMethodId: selected.id,
|
|
293
293
|
label: name ?? selected.label,
|
|
294
294
|
});
|
|
295
|
-
const principal = await
|
|
295
|
+
const principal = await ensureConsumerPrincipalForMethod("link");
|
|
296
296
|
return text(
|
|
297
297
|
[
|
|
298
298
|
"Link payment method connected.",
|
|
@@ -330,7 +330,7 @@ export function registerWalletTools(server: McpServer): void {
|
|
|
330
330
|
paymentMethodId: method.id,
|
|
331
331
|
label: method.label,
|
|
332
332
|
});
|
|
333
|
-
const principal = await
|
|
333
|
+
const principal = await ensureConsumerPrincipalForMethod("link");
|
|
334
334
|
return text(
|
|
335
335
|
[
|
|
336
336
|
"Link payment method connected.",
|
|
@@ -380,7 +380,7 @@ export function registerWalletTools(server: McpServer): void {
|
|
|
380
380
|
const result = await pollCardSetup(pendingToken, 250);
|
|
381
381
|
|
|
382
382
|
if (result) {
|
|
383
|
-
const principal = await
|
|
383
|
+
const principal = await ensureConsumerPrincipalForMethod("card");
|
|
384
384
|
return text(
|
|
385
385
|
`Connected! ${result.brand} ****${result.last4} is ready for payments.\n\n` +
|
|
386
386
|
`Consumer principal: ${principal}`,
|