@useagentpay/mcp-server 0.1.2 → 0.1.4
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 +124 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1301 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1301 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js
|
|
13
|
+
import path from "path";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
var init_esm_shims = __esm({
|
|
16
|
+
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js"() {
|
|
17
|
+
"use strict";
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// src/templates/agent-md.ts
|
|
22
|
+
function generateAgentMd() {
|
|
23
|
+
return `# AgentPay
|
|
24
|
+
|
|
25
|
+
You have access to AgentPay for making purchases on behalf of the user.
|
|
26
|
+
|
|
27
|
+
## Purchase Flow
|
|
28
|
+
|
|
29
|
+
1. **Check balance** \u2014 call \`agentpay_check_balance\` before proposing
|
|
30
|
+
2. **Propose** \u2014 call \`agentpay_propose_purchase\` with merchant, amount, description, and URL
|
|
31
|
+
3. **Open the dashboard** \u2014 run \`npx @useagentpay/mcp-server dashboard\` so the human can approve
|
|
32
|
+
4. **Wait** \u2014 call \`agentpay_wait_for_approval\` to poll until approved or rejected
|
|
33
|
+
5. **Execute** \u2014 call \`agentpay_execute_purchase\` once approved
|
|
34
|
+
6. **Receipt** \u2014 call \`agentpay_get_receipt\` and share the result with the human
|
|
35
|
+
|
|
36
|
+
## MCP Tools
|
|
37
|
+
|
|
38
|
+
- \`agentpay_status\` \u2014 check setup state, balance, and budget
|
|
39
|
+
- \`agentpay_check_balance\` \u2014 current balance and limits
|
|
40
|
+
- \`agentpay_propose_purchase\` \u2014 propose a new purchase
|
|
41
|
+
- \`agentpay_wait_for_approval\` \u2014 poll until human approves or rejects
|
|
42
|
+
- \`agentpay_execute_purchase\` \u2014 execute an approved purchase
|
|
43
|
+
- \`agentpay_get_receipt\` \u2014 get receipt after purchase
|
|
44
|
+
- \`agentpay_list_pending\` \u2014 list pending proposals
|
|
45
|
+
- \`agentpay_get_transaction\` \u2014 get transaction details
|
|
46
|
+
|
|
47
|
+
## Dashboard \u2014 Human-Only Configuration
|
|
48
|
+
|
|
49
|
+
Budget, spending limits, funds, and credentials can ONLY be changed through the browser dashboard. If the user wants to change any of these, open the dashboard for them:
|
|
50
|
+
|
|
51
|
+
\`\`\`
|
|
52
|
+
npx @useagentpay/mcp-server dashboard
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
If AgentPay isn't set up yet, run setup for them:
|
|
56
|
+
|
|
57
|
+
\`\`\`
|
|
58
|
+
npx @useagentpay/mcp-server setup
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
After setup completes, these files are created in \`agentpay/\`:
|
|
62
|
+
- \`credentials.enc\` \u2014 encrypted card and billing details
|
|
63
|
+
- \`keys/\` \u2014 Ed25519 keypair for signing approvals
|
|
64
|
+
- \`wallet.json\` \u2014 budget, per-transaction limit, and balance
|
|
65
|
+
- \`transactions.json\` \u2014 purchase log
|
|
66
|
+
- \`audit.log\` \u2014 action log
|
|
67
|
+
|
|
68
|
+
## Rules
|
|
69
|
+
|
|
70
|
+
- Always check balance before proposing
|
|
71
|
+
- Never propose a purchase without a clear reason
|
|
72
|
+
- Never skip the approval step \u2014 open the dashboard and wait
|
|
73
|
+
- If rejected, respect the decision and suggest alternatives
|
|
74
|
+
- You CANNOT modify budgets, spending limits, or credentials \u2014 open the dashboard for the human to do it
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
var init_agent_md = __esm({
|
|
78
|
+
"src/templates/agent-md.ts"() {
|
|
79
|
+
"use strict";
|
|
80
|
+
init_esm_shims();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// src/commands/init.ts
|
|
85
|
+
var init_exports = {};
|
|
86
|
+
__export(init_exports, {
|
|
87
|
+
initCommand: () => initCommand
|
|
88
|
+
});
|
|
89
|
+
import { mkdirSync, existsSync } from "fs";
|
|
90
|
+
import { writeFileSync } from "fs";
|
|
91
|
+
import { join } from "path";
|
|
92
|
+
function initCommand() {
|
|
93
|
+
const dir = join(process.cwd(), "agentpay");
|
|
94
|
+
if (existsSync(dir)) {
|
|
95
|
+
console.log(`AgentPay already initialized at ${dir}`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
mkdirSync(dir, { recursive: true });
|
|
99
|
+
writeFileSync(join(dir, "AGENT.md"), generateAgentMd(), "utf-8");
|
|
100
|
+
console.log("AgentPay initialized. Run `agentpay setup` to add your payment credentials.");
|
|
101
|
+
}
|
|
102
|
+
var init_init = __esm({
|
|
103
|
+
"src/commands/init.ts"() {
|
|
104
|
+
"use strict";
|
|
105
|
+
init_esm_shims();
|
|
106
|
+
init_agent_md();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// src/commands/setup.ts
|
|
111
|
+
var setup_exports = {};
|
|
112
|
+
__export(setup_exports, {
|
|
113
|
+
setupCommand: () => setupCommand
|
|
114
|
+
});
|
|
115
|
+
import { requestBrowserSetup } from "@useagentpay/sdk";
|
|
116
|
+
async function setupCommand() {
|
|
117
|
+
console.log("AgentPay Setup");
|
|
118
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
119
|
+
console.log("Opening setup form in browser...\n");
|
|
120
|
+
const result = await requestBrowserSetup();
|
|
121
|
+
if (result.completed) {
|
|
122
|
+
console.log("\nSetup complete! Next steps:");
|
|
123
|
+
console.log(" agentpay status Check your wallet");
|
|
124
|
+
console.log(" agentpay budget View/adjust budget");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var init_setup = __esm({
|
|
128
|
+
"src/commands/setup.ts"() {
|
|
129
|
+
"use strict";
|
|
130
|
+
init_esm_shims();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// src/commands/budget.ts
|
|
135
|
+
var budget_exports = {};
|
|
136
|
+
__export(budget_exports, {
|
|
137
|
+
budgetCommand: () => budgetCommand
|
|
138
|
+
});
|
|
139
|
+
import { BudgetManager, formatCurrency } from "@useagentpay/sdk";
|
|
140
|
+
function budgetCommand() {
|
|
141
|
+
const bm = new BudgetManager();
|
|
142
|
+
const balance = bm.getBalance();
|
|
143
|
+
console.log(`Budget: ${formatCurrency(balance.budget)}`);
|
|
144
|
+
console.log(`Balance: ${formatCurrency(balance.balance)}`);
|
|
145
|
+
console.log(`Spent: ${formatCurrency(balance.spent)}`);
|
|
146
|
+
console.log(`Per-tx limit: ${balance.limitPerTx > 0 ? formatCurrency(balance.limitPerTx) : "None"}`);
|
|
147
|
+
}
|
|
148
|
+
var init_budget = __esm({
|
|
149
|
+
"src/commands/budget.ts"() {
|
|
150
|
+
"use strict";
|
|
151
|
+
init_esm_shims();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// src/commands/pending.ts
|
|
156
|
+
var pending_exports = {};
|
|
157
|
+
__export(pending_exports, {
|
|
158
|
+
pendingCommand: () => pendingCommand
|
|
159
|
+
});
|
|
160
|
+
import { TransactionManager, formatCurrency as formatCurrency2 } from "@useagentpay/sdk";
|
|
161
|
+
function pendingCommand() {
|
|
162
|
+
const tm = new TransactionManager();
|
|
163
|
+
const pending = tm.getPending();
|
|
164
|
+
if (pending.length === 0) {
|
|
165
|
+
console.log("No pending purchases.");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
console.log("Pending Purchases:");
|
|
169
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
170
|
+
console.log("TX_ID MERCHANT AMOUNT DESCRIPTION");
|
|
171
|
+
for (const tx of pending) {
|
|
172
|
+
const id = tx.id.padEnd(14);
|
|
173
|
+
const merchant = tx.merchant.padEnd(16);
|
|
174
|
+
const amount = formatCurrency2(tx.amount).padStart(9);
|
|
175
|
+
console.log(`${id}${merchant}${amount} ${tx.description}`);
|
|
176
|
+
}
|
|
177
|
+
console.log(`
|
|
178
|
+
${pending.length} pending purchase${pending.length === 1 ? "" : "s"}. Use 'agentpay approve <txId>' or 'agentpay reject <txId>'.`);
|
|
179
|
+
}
|
|
180
|
+
var init_pending = __esm({
|
|
181
|
+
"src/commands/pending.ts"() {
|
|
182
|
+
"use strict";
|
|
183
|
+
init_esm_shims();
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// src/commands/propose.ts
|
|
188
|
+
var propose_exports = {};
|
|
189
|
+
__export(propose_exports, {
|
|
190
|
+
proposeCommand: () => proposeCommand
|
|
191
|
+
});
|
|
192
|
+
import {
|
|
193
|
+
BudgetManager as BudgetManager2,
|
|
194
|
+
TransactionManager as TransactionManager2,
|
|
195
|
+
AuditLogger,
|
|
196
|
+
formatCurrency as formatCurrency3
|
|
197
|
+
} from "@useagentpay/sdk";
|
|
198
|
+
function proposeCommand(options) {
|
|
199
|
+
const amount = parseFloat(options.amount);
|
|
200
|
+
if (isNaN(amount) || amount <= 0) {
|
|
201
|
+
console.error("Invalid amount. Must be a positive number.");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const bm = new BudgetManager2();
|
|
205
|
+
const tm = new TransactionManager2();
|
|
206
|
+
const audit = new AuditLogger();
|
|
207
|
+
try {
|
|
208
|
+
bm.checkProposal(amount);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
console.error(err instanceof Error ? err.message : "Budget check failed.");
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
const tx = tm.propose({
|
|
214
|
+
merchant: options.merchant,
|
|
215
|
+
amount,
|
|
216
|
+
description: options.description,
|
|
217
|
+
url: options.url
|
|
218
|
+
});
|
|
219
|
+
audit.log("PROPOSE", { txId: tx.id, merchant: tx.merchant, amount: tx.amount, source: "propose-command" });
|
|
220
|
+
console.log("Transaction proposed");
|
|
221
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
222
|
+
console.log(` ID: ${tx.id}`);
|
|
223
|
+
console.log(` Merchant: ${tx.merchant}`);
|
|
224
|
+
console.log(` Amount: ${formatCurrency3(tx.amount)}`);
|
|
225
|
+
console.log(` Description: ${tx.description}`);
|
|
226
|
+
console.log(` URL: ${options.url}`);
|
|
227
|
+
console.log(` Status: ${tx.status}`);
|
|
228
|
+
console.log();
|
|
229
|
+
console.log(`Next step: agentpay approve ${tx.id}`);
|
|
230
|
+
}
|
|
231
|
+
var init_propose = __esm({
|
|
232
|
+
"src/commands/propose.ts"() {
|
|
233
|
+
"use strict";
|
|
234
|
+
init_esm_shims();
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// src/commands/approve.ts
|
|
239
|
+
var approve_exports = {};
|
|
240
|
+
__export(approve_exports, {
|
|
241
|
+
approveCommand: () => approveCommand
|
|
242
|
+
});
|
|
243
|
+
import {
|
|
244
|
+
TransactionManager as TransactionManager3,
|
|
245
|
+
AuditLogger as AuditLogger2,
|
|
246
|
+
formatCurrency as formatCurrency4,
|
|
247
|
+
requestBrowserApproval
|
|
248
|
+
} from "@useagentpay/sdk";
|
|
249
|
+
async function approveCommand(txId) {
|
|
250
|
+
const tm = new TransactionManager3();
|
|
251
|
+
const audit = new AuditLogger2();
|
|
252
|
+
const tx = tm.get(txId);
|
|
253
|
+
if (!tx) {
|
|
254
|
+
console.error(`Transaction ${txId} not found.`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
if (tx.status !== "pending") {
|
|
258
|
+
console.error(`Cannot approve transaction in '${tx.status}' state.`);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
console.log(`Approve purchase:`);
|
|
262
|
+
console.log(` Merchant: ${tx.merchant}`);
|
|
263
|
+
console.log(` Amount: ${formatCurrency4(tx.amount)}`);
|
|
264
|
+
console.log(` Description: ${tx.description}`);
|
|
265
|
+
console.log();
|
|
266
|
+
const result = await requestBrowserApproval(tx, tm, audit);
|
|
267
|
+
if (result.action === "rejected") {
|
|
268
|
+
console.log(`Purchase denied${result.reason ? ": " + result.reason : "."}`);
|
|
269
|
+
process.exit(0);
|
|
270
|
+
}
|
|
271
|
+
console.log(`
|
|
272
|
+
Approved! Transaction ${txId} is now ready for execution.`);
|
|
273
|
+
}
|
|
274
|
+
var init_approve = __esm({
|
|
275
|
+
"src/commands/approve.ts"() {
|
|
276
|
+
"use strict";
|
|
277
|
+
init_esm_shims();
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// src/commands/reject.ts
|
|
282
|
+
var reject_exports = {};
|
|
283
|
+
__export(reject_exports, {
|
|
284
|
+
rejectCommand: () => rejectCommand
|
|
285
|
+
});
|
|
286
|
+
import { TransactionManager as TransactionManager4, AuditLogger as AuditLogger3 } from "@useagentpay/sdk";
|
|
287
|
+
function rejectCommand(txId, options) {
|
|
288
|
+
const tm = new TransactionManager4();
|
|
289
|
+
const audit = new AuditLogger3();
|
|
290
|
+
const tx = tm.get(txId);
|
|
291
|
+
if (!tx) {
|
|
292
|
+
console.error(`Transaction ${txId} not found.`);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
if (tx.status !== "pending") {
|
|
296
|
+
console.error(`Cannot reject transaction in '${tx.status}' state.`);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
tm.reject(txId, options.reason);
|
|
300
|
+
audit.log("REJECT", { txId, reason: options.reason });
|
|
301
|
+
console.log(`Rejected transaction ${txId}.${options.reason ? ` Reason: ${options.reason}` : ""}`);
|
|
302
|
+
}
|
|
303
|
+
var init_reject = __esm({
|
|
304
|
+
"src/commands/reject.ts"() {
|
|
305
|
+
"use strict";
|
|
306
|
+
init_esm_shims();
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// src/commands/status.ts
|
|
311
|
+
var status_exports = {};
|
|
312
|
+
__export(status_exports, {
|
|
313
|
+
statusCommand: () => statusCommand
|
|
314
|
+
});
|
|
315
|
+
import { AgentPay, formatStatus } from "@useagentpay/sdk";
|
|
316
|
+
function statusCommand() {
|
|
317
|
+
const ap = new AgentPay();
|
|
318
|
+
const s = ap.status();
|
|
319
|
+
if (!s.isSetup) {
|
|
320
|
+
console.log("AgentPay is not set up. Run `agentpay setup` first.");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
console.log(formatStatus({
|
|
324
|
+
balance: s.balance,
|
|
325
|
+
budget: s.budget,
|
|
326
|
+
limitPerTx: s.limitPerTx,
|
|
327
|
+
pending: s.pending,
|
|
328
|
+
recent: s.recent
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
var init_status = __esm({
|
|
332
|
+
"src/commands/status.ts"() {
|
|
333
|
+
"use strict";
|
|
334
|
+
init_esm_shims();
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// src/commands/history.ts
|
|
339
|
+
var history_exports = {};
|
|
340
|
+
__export(history_exports, {
|
|
341
|
+
historyCommand: () => historyCommand
|
|
342
|
+
});
|
|
343
|
+
import { TransactionManager as TransactionManager5, formatCurrency as formatCurrency5, formatTimestamp } from "@useagentpay/sdk";
|
|
344
|
+
function historyCommand() {
|
|
345
|
+
const tm = new TransactionManager5();
|
|
346
|
+
const history = tm.getHistory();
|
|
347
|
+
if (history.length === 0) {
|
|
348
|
+
console.log("No transaction history.");
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
console.log("Transaction History:");
|
|
352
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
353
|
+
console.log("STATUS TX_ID MERCHANT AMOUNT DATE DESCRIPTION");
|
|
354
|
+
for (const tx of history) {
|
|
355
|
+
const status = `[${tx.status}]`.padEnd(13);
|
|
356
|
+
const id = tx.id.padEnd(14);
|
|
357
|
+
const merchant = tx.merchant.padEnd(16);
|
|
358
|
+
const amount = formatCurrency5(tx.amount).padStart(9);
|
|
359
|
+
const date = formatTimestamp(tx.createdAt).padEnd(18);
|
|
360
|
+
console.log(`${status}${id}${merchant}${amount} ${date}${tx.description}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
var init_history = __esm({
|
|
364
|
+
"src/commands/history.ts"() {
|
|
365
|
+
"use strict";
|
|
366
|
+
init_esm_shims();
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// src/commands/reset.ts
|
|
371
|
+
var reset_exports = {};
|
|
372
|
+
__export(reset_exports, {
|
|
373
|
+
resetCommand: () => resetCommand
|
|
374
|
+
});
|
|
375
|
+
import { rmSync, existsSync as existsSync2 } from "fs";
|
|
376
|
+
import { getHomePath, promptInput } from "@useagentpay/sdk";
|
|
377
|
+
async function resetCommand() {
|
|
378
|
+
const home = getHomePath();
|
|
379
|
+
if (!existsSync2(home)) {
|
|
380
|
+
console.log("Nothing to reset. AgentPay data directory does not exist.");
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
console.log(`This will permanently delete all AgentPay data at: ${home}`);
|
|
384
|
+
console.log("This includes encrypted credentials, keys, wallet, transactions, and audit logs.");
|
|
385
|
+
const answer = await promptInput("\nType YES to confirm: ");
|
|
386
|
+
if (answer !== "YES") {
|
|
387
|
+
console.log("Cancelled.");
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
rmSync(home, { recursive: true, force: true });
|
|
391
|
+
console.log("All AgentPay data has been deleted.");
|
|
392
|
+
}
|
|
393
|
+
var init_reset = __esm({
|
|
394
|
+
"src/commands/reset.ts"() {
|
|
395
|
+
"use strict";
|
|
396
|
+
init_esm_shims();
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// src/commands/dashboard.ts
|
|
401
|
+
var dashboard_exports = {};
|
|
402
|
+
__export(dashboard_exports, {
|
|
403
|
+
dashboardCommand: () => dashboardCommand
|
|
404
|
+
});
|
|
405
|
+
import { startDashboardServer, openBrowser } from "@useagentpay/sdk";
|
|
406
|
+
async function dashboardCommand(options) {
|
|
407
|
+
const port = parseInt(options.port, 10) || 3141;
|
|
408
|
+
const url = `http://127.0.0.1:${port}`;
|
|
409
|
+
try {
|
|
410
|
+
const server = await startDashboardServer(port);
|
|
411
|
+
console.log(`AgentPay Dashboard running at ${url}`);
|
|
412
|
+
console.log("Press Ctrl+C to stop.\n");
|
|
413
|
+
openBrowser(url);
|
|
414
|
+
const shutdown = () => {
|
|
415
|
+
console.log("\nShutting down dashboard...");
|
|
416
|
+
server.close(() => process.exit(0));
|
|
417
|
+
setTimeout(() => process.exit(0), 3e3);
|
|
418
|
+
};
|
|
419
|
+
process.on("SIGINT", shutdown);
|
|
420
|
+
process.on("SIGTERM", shutdown);
|
|
421
|
+
} catch (err) {
|
|
422
|
+
const message = err instanceof Error ? err.message : "Failed to start server";
|
|
423
|
+
console.error(message);
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
var init_dashboard = __esm({
|
|
428
|
+
"src/commands/dashboard.ts"() {
|
|
429
|
+
"use strict";
|
|
430
|
+
init_esm_shims();
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// src/errors.ts
|
|
435
|
+
import {
|
|
436
|
+
NotSetupError,
|
|
437
|
+
DecryptError,
|
|
438
|
+
InsufficientBalanceError,
|
|
439
|
+
ExceedsTxLimitError,
|
|
440
|
+
NotApprovedError,
|
|
441
|
+
InvalidMandateError,
|
|
442
|
+
AlreadyExecutedError,
|
|
443
|
+
CheckoutFailedError,
|
|
444
|
+
TimeoutError
|
|
445
|
+
} from "@useagentpay/sdk";
|
|
446
|
+
function mapError(err) {
|
|
447
|
+
if (err instanceof Error) {
|
|
448
|
+
for (const mapping of ERROR_MAP) {
|
|
449
|
+
if (err instanceof mapping.type) {
|
|
450
|
+
return {
|
|
451
|
+
success: false,
|
|
452
|
+
error: mapping.error,
|
|
453
|
+
message: err.message,
|
|
454
|
+
nextAction: mapping.nextAction
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
success: false,
|
|
461
|
+
error: "UNKNOWN_ERROR",
|
|
462
|
+
message: err instanceof Error ? err.message : String(err)
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
var ERROR_MAP;
|
|
466
|
+
var init_errors = __esm({
|
|
467
|
+
"src/errors.ts"() {
|
|
468
|
+
"use strict";
|
|
469
|
+
init_esm_shims();
|
|
470
|
+
ERROR_MAP = [
|
|
471
|
+
{ type: NotSetupError, error: "NOT_SETUP", nextAction: "STOP - Human must run: agentpay setup" },
|
|
472
|
+
{ type: InsufficientBalanceError, error: "INSUFFICIENT_BALANCE", nextAction: "STOP - Human must add budget" },
|
|
473
|
+
{ type: ExceedsTxLimitError, error: "EXCEEDS_TX_LIMIT", nextAction: "STOP - Human must increase limit" },
|
|
474
|
+
{ type: NotApprovedError, error: "NOT_APPROVED", nextAction: "WAIT - Needs approval first" },
|
|
475
|
+
{ type: InvalidMandateError, error: "INVALID_MANDATE", nextAction: "STOP - Security error" },
|
|
476
|
+
{ type: AlreadyExecutedError, error: "ALREADY_EXECUTED", nextAction: "STOP - Already processed" },
|
|
477
|
+
{ type: CheckoutFailedError, error: "CHECKOUT_FAILED", nextAction: "ERROR - Human should review" },
|
|
478
|
+
{ type: TimeoutError, error: "TIMEOUT", nextAction: "RETRY - Try again later" },
|
|
479
|
+
{ type: DecryptError, error: "DECRYPT_FAILED", nextAction: "STOP - Wrong passphrase" }
|
|
480
|
+
];
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// src/tools/status.ts
|
|
485
|
+
function registerStatusTools(server, ap) {
|
|
486
|
+
server.tool(
|
|
487
|
+
"agentpay_status",
|
|
488
|
+
"Get AgentPay status: setup state, balance, budget, and pending transactions. Call this first.",
|
|
489
|
+
{},
|
|
490
|
+
async () => {
|
|
491
|
+
try {
|
|
492
|
+
const status = ap.status();
|
|
493
|
+
return {
|
|
494
|
+
content: [
|
|
495
|
+
{
|
|
496
|
+
type: "text",
|
|
497
|
+
text: JSON.stringify({
|
|
498
|
+
success: true,
|
|
499
|
+
...status,
|
|
500
|
+
pendingCount: status.pending.length,
|
|
501
|
+
nextAction: !status.isSetup ? "STOP - Human must run: agentpay setup" : status.pending.length > 0 ? "Review pending transactions with agentpay_list_pending" : "Ready for purchases. Use agentpay_check_balance before proposing."
|
|
502
|
+
})
|
|
503
|
+
}
|
|
504
|
+
]
|
|
505
|
+
};
|
|
506
|
+
} catch (err) {
|
|
507
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
server.tool(
|
|
512
|
+
"agentpay_check_balance",
|
|
513
|
+
"Check current balance, budget, and per-transaction limit. Call BEFORE proposing a purchase.",
|
|
514
|
+
{},
|
|
515
|
+
async () => {
|
|
516
|
+
try {
|
|
517
|
+
const wallet = ap.wallet.getBalance();
|
|
518
|
+
return {
|
|
519
|
+
content: [
|
|
520
|
+
{
|
|
521
|
+
type: "text",
|
|
522
|
+
text: JSON.stringify({
|
|
523
|
+
success: true,
|
|
524
|
+
...wallet,
|
|
525
|
+
nextAction: wallet.balance <= 0 ? "STOP - No balance remaining. Human must add budget." : `Ready. Max single purchase: $${Math.min(wallet.balance, wallet.limitPerTx).toFixed(2)}`
|
|
526
|
+
})
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
};
|
|
530
|
+
} catch (err) {
|
|
531
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
server.tool(
|
|
536
|
+
"agentpay_list_pending",
|
|
537
|
+
"List all pending transactions awaiting human approval.",
|
|
538
|
+
{},
|
|
539
|
+
async () => {
|
|
540
|
+
try {
|
|
541
|
+
const status = ap.status();
|
|
542
|
+
return {
|
|
543
|
+
content: [
|
|
544
|
+
{
|
|
545
|
+
type: "text",
|
|
546
|
+
text: JSON.stringify({
|
|
547
|
+
success: true,
|
|
548
|
+
pending: status.pending,
|
|
549
|
+
count: status.pending.length,
|
|
550
|
+
nextAction: status.pending.length > 0 ? "Human must approve/reject via CLI. Use agentpay_wait_for_approval to poll." : "No pending transactions."
|
|
551
|
+
})
|
|
552
|
+
}
|
|
553
|
+
]
|
|
554
|
+
};
|
|
555
|
+
} catch (err) {
|
|
556
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
var init_status2 = __esm({
|
|
562
|
+
"src/tools/status.ts"() {
|
|
563
|
+
"use strict";
|
|
564
|
+
init_esm_shims();
|
|
565
|
+
init_errors();
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// src/tools/propose.ts
|
|
570
|
+
import { z } from "zod";
|
|
571
|
+
function registerProposeTool(server, ap) {
|
|
572
|
+
server.tool(
|
|
573
|
+
"agentpay_propose_purchase",
|
|
574
|
+
"Propose a new purchase. Creates a pending transaction that requires human approval before execution.",
|
|
575
|
+
{
|
|
576
|
+
merchant: z.string().describe('Merchant name (e.g. "Amazon", "Target")'),
|
|
577
|
+
amount: z.number().positive().describe("Purchase amount in USD"),
|
|
578
|
+
description: z.string().describe("What is being purchased"),
|
|
579
|
+
url: z.string().url().describe("Product or checkout URL")
|
|
580
|
+
},
|
|
581
|
+
async ({ merchant, amount, description, url }) => {
|
|
582
|
+
try {
|
|
583
|
+
const tx = ap.transactions.propose({ merchant, amount, description, url });
|
|
584
|
+
return {
|
|
585
|
+
content: [
|
|
586
|
+
{
|
|
587
|
+
type: "text",
|
|
588
|
+
text: JSON.stringify({
|
|
589
|
+
success: true,
|
|
590
|
+
txId: tx.id,
|
|
591
|
+
status: tx.status,
|
|
592
|
+
merchant: tx.merchant,
|
|
593
|
+
amount: tx.amount,
|
|
594
|
+
nextAction: `Purchase proposed. Open the dashboard for the human to approve: npx @useagentpay/mcp-server dashboard \u2014 then call agentpay_wait_for_approval with txId "${tx.id}".`
|
|
595
|
+
})
|
|
596
|
+
}
|
|
597
|
+
]
|
|
598
|
+
};
|
|
599
|
+
} catch (err) {
|
|
600
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
var init_propose2 = __esm({
|
|
606
|
+
"src/tools/propose.ts"() {
|
|
607
|
+
"use strict";
|
|
608
|
+
init_esm_shims();
|
|
609
|
+
init_errors();
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
// src/tools/transactions.ts
|
|
614
|
+
import { z as z2 } from "zod";
|
|
615
|
+
function nextActionForStatus(status) {
|
|
616
|
+
switch (status) {
|
|
617
|
+
case "pending":
|
|
618
|
+
return "WAIT - Human must approve via CLI. Use agentpay_wait_for_approval to poll.";
|
|
619
|
+
case "approved":
|
|
620
|
+
return "READY - Use agentpay_execute_purchase to complete the purchase.";
|
|
621
|
+
case "rejected":
|
|
622
|
+
return "STOP - Transaction was rejected by human.";
|
|
623
|
+
case "executing":
|
|
624
|
+
return "WAIT - Purchase is being executed.";
|
|
625
|
+
case "completed":
|
|
626
|
+
return "DONE - Use agentpay_get_receipt for confirmation details.";
|
|
627
|
+
case "failed":
|
|
628
|
+
return "ERROR - Purchase failed. Human should review.";
|
|
629
|
+
default:
|
|
630
|
+
return "Unknown status.";
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function registerTransactionTools(server, ap) {
|
|
634
|
+
server.tool(
|
|
635
|
+
"agentpay_get_transaction",
|
|
636
|
+
"Get the current status and details of a transaction.",
|
|
637
|
+
{
|
|
638
|
+
txId: z2.string().describe('Transaction ID (e.g. "tx_abc123")')
|
|
639
|
+
},
|
|
640
|
+
async ({ txId }) => {
|
|
641
|
+
try {
|
|
642
|
+
const tx = ap.transactions.get(txId);
|
|
643
|
+
if (!tx) {
|
|
644
|
+
return {
|
|
645
|
+
content: [
|
|
646
|
+
{
|
|
647
|
+
type: "text",
|
|
648
|
+
text: JSON.stringify({
|
|
649
|
+
success: false,
|
|
650
|
+
error: "NOT_FOUND",
|
|
651
|
+
message: `Transaction ${txId} not found.`
|
|
652
|
+
})
|
|
653
|
+
}
|
|
654
|
+
]
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
return {
|
|
658
|
+
content: [
|
|
659
|
+
{
|
|
660
|
+
type: "text",
|
|
661
|
+
text: JSON.stringify({
|
|
662
|
+
success: true,
|
|
663
|
+
id: tx.id,
|
|
664
|
+
status: tx.status,
|
|
665
|
+
merchant: tx.merchant,
|
|
666
|
+
amount: tx.amount,
|
|
667
|
+
description: tx.description,
|
|
668
|
+
url: tx.url,
|
|
669
|
+
createdAt: tx.createdAt,
|
|
670
|
+
nextAction: nextActionForStatus(tx.status)
|
|
671
|
+
})
|
|
672
|
+
}
|
|
673
|
+
]
|
|
674
|
+
};
|
|
675
|
+
} catch (err) {
|
|
676
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
server.tool(
|
|
681
|
+
"agentpay_wait_for_approval",
|
|
682
|
+
"Long-poll for human approval of a pending transaction. Blocks until approved, rejected, or timeout.",
|
|
683
|
+
{
|
|
684
|
+
txId: z2.string().describe("Transaction ID to wait for"),
|
|
685
|
+
pollInterval: z2.number().positive().optional().describe("Poll interval in ms (default 2000)"),
|
|
686
|
+
timeout: z2.number().positive().optional().describe("Timeout in ms (default 300000 = 5 min)")
|
|
687
|
+
},
|
|
688
|
+
async ({ txId, pollInterval, timeout }) => {
|
|
689
|
+
try {
|
|
690
|
+
const result = await ap.transactions.waitForApproval(txId, {
|
|
691
|
+
pollInterval: pollInterval ?? 2e3,
|
|
692
|
+
timeout: timeout ?? 3e5
|
|
693
|
+
});
|
|
694
|
+
return {
|
|
695
|
+
content: [
|
|
696
|
+
{
|
|
697
|
+
type: "text",
|
|
698
|
+
text: JSON.stringify({
|
|
699
|
+
success: true,
|
|
700
|
+
txId,
|
|
701
|
+
status: result.status,
|
|
702
|
+
reason: result.reason,
|
|
703
|
+
nextAction: nextActionForStatus(result.status)
|
|
704
|
+
})
|
|
705
|
+
}
|
|
706
|
+
]
|
|
707
|
+
};
|
|
708
|
+
} catch (err) {
|
|
709
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
var init_transactions = __esm({
|
|
715
|
+
"src/tools/transactions.ts"() {
|
|
716
|
+
"use strict";
|
|
717
|
+
init_esm_shims();
|
|
718
|
+
init_errors();
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
// src/config.ts
|
|
723
|
+
function loadConfig(overrides) {
|
|
724
|
+
const passphrase = process.env.AGENTPAY_PASSPHRASE;
|
|
725
|
+
const passphraseServer = process.env.AGENTPAY_PASSPHRASE_SERVER;
|
|
726
|
+
let passphraseMode = "none";
|
|
727
|
+
if (passphrase) passphraseMode = "env";
|
|
728
|
+
else if (passphraseServer) passphraseMode = "server";
|
|
729
|
+
const executor = {
|
|
730
|
+
modelApiKey: process.env.ANTHROPIC_API_KEY
|
|
731
|
+
};
|
|
732
|
+
return {
|
|
733
|
+
home: process.env.AGENTPAY_HOME || void 0,
|
|
734
|
+
passphrase,
|
|
735
|
+
passphraseServer,
|
|
736
|
+
passphraseMode,
|
|
737
|
+
executor,
|
|
738
|
+
http: overrides?.http ?? process.env.MCP_TRANSPORT === "http"
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
async function getPassphrase(config) {
|
|
742
|
+
if (config.passphraseMode === "env" && config.passphrase) {
|
|
743
|
+
return config.passphrase;
|
|
744
|
+
}
|
|
745
|
+
if (config.passphraseMode === "server" && config.passphraseServer) {
|
|
746
|
+
const res = await fetch(config.passphraseServer);
|
|
747
|
+
if (!res.ok) throw new Error(`Passphrase server returned ${res.status}`);
|
|
748
|
+
const body = await res.text();
|
|
749
|
+
return body.trim();
|
|
750
|
+
}
|
|
751
|
+
throw new Error(
|
|
752
|
+
"No passphrase configured. Set AGENTPAY_PASSPHRASE or AGENTPAY_PASSPHRASE_SERVER to enable purchase execution."
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
var init_config = __esm({
|
|
756
|
+
"src/config.ts"() {
|
|
757
|
+
"use strict";
|
|
758
|
+
init_esm_shims();
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
// src/tools/execute.ts
|
|
763
|
+
import { z as z3 } from "zod";
|
|
764
|
+
import { AgentPay as AgentPay2 } from "@useagentpay/sdk";
|
|
765
|
+
function registerExecuteTool(server, ap, config) {
|
|
766
|
+
server.tool(
|
|
767
|
+
"agentpay_execute_purchase",
|
|
768
|
+
"Execute an approved purchase. Requires passphrase config. Decrypts credentials and completes checkout via browser.",
|
|
769
|
+
{
|
|
770
|
+
txId: z3.string().describe("Transaction ID of an approved purchase")
|
|
771
|
+
},
|
|
772
|
+
async ({ txId }) => {
|
|
773
|
+
try {
|
|
774
|
+
const passphrase = await getPassphrase(config);
|
|
775
|
+
const execAp = new AgentPay2({
|
|
776
|
+
home: ap.home,
|
|
777
|
+
passphrase,
|
|
778
|
+
executor: config.executor
|
|
779
|
+
});
|
|
780
|
+
const receipt = await execAp.transactions.execute(txId);
|
|
781
|
+
return {
|
|
782
|
+
content: [
|
|
783
|
+
{
|
|
784
|
+
type: "text",
|
|
785
|
+
text: JSON.stringify({
|
|
786
|
+
success: true,
|
|
787
|
+
receipt,
|
|
788
|
+
nextAction: "DONE - Purchase completed. Use agentpay_get_receipt for details."
|
|
789
|
+
})
|
|
790
|
+
}
|
|
791
|
+
]
|
|
792
|
+
};
|
|
793
|
+
} catch (err) {
|
|
794
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
var init_execute = __esm({
|
|
800
|
+
"src/tools/execute.ts"() {
|
|
801
|
+
"use strict";
|
|
802
|
+
init_esm_shims();
|
|
803
|
+
init_config();
|
|
804
|
+
init_errors();
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
// src/tools/receipt.ts
|
|
809
|
+
import { z as z4 } from "zod";
|
|
810
|
+
function registerReceiptTool(server, ap) {
|
|
811
|
+
server.tool(
|
|
812
|
+
"agentpay_get_receipt",
|
|
813
|
+
"Get the receipt for a completed purchase.",
|
|
814
|
+
{
|
|
815
|
+
txId: z4.string().describe("Transaction ID of a completed purchase")
|
|
816
|
+
},
|
|
817
|
+
async ({ txId }) => {
|
|
818
|
+
try {
|
|
819
|
+
const receipt = ap.transactions.getReceipt(txId);
|
|
820
|
+
if (!receipt) {
|
|
821
|
+
return {
|
|
822
|
+
content: [
|
|
823
|
+
{
|
|
824
|
+
type: "text",
|
|
825
|
+
text: JSON.stringify({
|
|
826
|
+
success: false,
|
|
827
|
+
error: "NO_RECEIPT",
|
|
828
|
+
message: `No receipt found for transaction ${txId}. Transaction may not be completed yet.`,
|
|
829
|
+
nextAction: "Check transaction status with agentpay_get_transaction"
|
|
830
|
+
})
|
|
831
|
+
}
|
|
832
|
+
]
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
return {
|
|
836
|
+
content: [
|
|
837
|
+
{
|
|
838
|
+
type: "text",
|
|
839
|
+
text: JSON.stringify({
|
|
840
|
+
success: true,
|
|
841
|
+
receipt,
|
|
842
|
+
nextAction: "DONE - Purchase confirmed."
|
|
843
|
+
})
|
|
844
|
+
}
|
|
845
|
+
]
|
|
846
|
+
};
|
|
847
|
+
} catch (err) {
|
|
848
|
+
return { content: [{ type: "text", text: JSON.stringify(mapError(err)) }] };
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
var init_receipt = __esm({
|
|
854
|
+
"src/tools/receipt.ts"() {
|
|
855
|
+
"use strict";
|
|
856
|
+
init_esm_shims();
|
|
857
|
+
init_errors();
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
// src/tools/index.ts
|
|
862
|
+
function registerTools(server, ap, config) {
|
|
863
|
+
registerStatusTools(server, ap);
|
|
864
|
+
registerProposeTool(server, ap);
|
|
865
|
+
registerTransactionTools(server, ap);
|
|
866
|
+
registerExecuteTool(server, ap, config);
|
|
867
|
+
registerReceiptTool(server, ap);
|
|
868
|
+
}
|
|
869
|
+
var init_tools = __esm({
|
|
870
|
+
"src/tools/index.ts"() {
|
|
871
|
+
"use strict";
|
|
872
|
+
init_esm_shims();
|
|
873
|
+
init_status2();
|
|
874
|
+
init_propose2();
|
|
875
|
+
init_transactions();
|
|
876
|
+
init_execute();
|
|
877
|
+
init_receipt();
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
// src/resources/wallet.ts
|
|
882
|
+
function registerWalletResource(server, ap) {
|
|
883
|
+
server.resource("wallet", "agentpay://wallet", async () => {
|
|
884
|
+
try {
|
|
885
|
+
const wallet = ap.wallet.getBalance();
|
|
886
|
+
return {
|
|
887
|
+
contents: [
|
|
888
|
+
{
|
|
889
|
+
uri: "agentpay://wallet",
|
|
890
|
+
mimeType: "application/json",
|
|
891
|
+
text: JSON.stringify(wallet, null, 2)
|
|
892
|
+
}
|
|
893
|
+
]
|
|
894
|
+
};
|
|
895
|
+
} catch {
|
|
896
|
+
return {
|
|
897
|
+
contents: [
|
|
898
|
+
{
|
|
899
|
+
uri: "agentpay://wallet",
|
|
900
|
+
mimeType: "application/json",
|
|
901
|
+
text: JSON.stringify({ budget: 0, balance: 0, limitPerTx: 0, spent: 0 })
|
|
902
|
+
}
|
|
903
|
+
]
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
var init_wallet = __esm({
|
|
909
|
+
"src/resources/wallet.ts"() {
|
|
910
|
+
"use strict";
|
|
911
|
+
init_esm_shims();
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
// src/resources/transaction.ts
|
|
916
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
917
|
+
function registerTransactionResource(server, ap) {
|
|
918
|
+
server.resource(
|
|
919
|
+
"transaction",
|
|
920
|
+
new ResourceTemplate("agentpay://transactions/{txId}", { list: void 0 }),
|
|
921
|
+
async (uri, { txId }) => {
|
|
922
|
+
const tx = ap.transactions.get(txId);
|
|
923
|
+
if (!tx) {
|
|
924
|
+
return {
|
|
925
|
+
contents: [
|
|
926
|
+
{
|
|
927
|
+
uri: uri.href,
|
|
928
|
+
mimeType: "application/json",
|
|
929
|
+
text: JSON.stringify({ error: "Transaction not found" })
|
|
930
|
+
}
|
|
931
|
+
]
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
const { mandate: _, ...safeTx } = tx;
|
|
935
|
+
return {
|
|
936
|
+
contents: [
|
|
937
|
+
{
|
|
938
|
+
uri: uri.href,
|
|
939
|
+
mimeType: "application/json",
|
|
940
|
+
text: JSON.stringify(safeTx, null, 2)
|
|
941
|
+
}
|
|
942
|
+
]
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
var init_transaction = __esm({
|
|
948
|
+
"src/resources/transaction.ts"() {
|
|
949
|
+
"use strict";
|
|
950
|
+
init_esm_shims();
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
// src/resources/audit.ts
|
|
955
|
+
function registerAuditResource(server, ap) {
|
|
956
|
+
server.resource("audit-log", "agentpay://audit-log", async () => {
|
|
957
|
+
const lines = ap.audit.getLog();
|
|
958
|
+
const last50 = lines.slice(-50);
|
|
959
|
+
const entries = last50.map((line) => {
|
|
960
|
+
const parts = line.split(" ");
|
|
961
|
+
return {
|
|
962
|
+
timestamp: parts[0] ?? "",
|
|
963
|
+
action: parts[1] ?? "",
|
|
964
|
+
details: parts[2] ? JSON.parse(parts[2]) : {}
|
|
965
|
+
};
|
|
966
|
+
});
|
|
967
|
+
return {
|
|
968
|
+
contents: [
|
|
969
|
+
{
|
|
970
|
+
uri: "agentpay://audit-log",
|
|
971
|
+
mimeType: "application/json",
|
|
972
|
+
text: JSON.stringify(entries, null, 2)
|
|
973
|
+
}
|
|
974
|
+
]
|
|
975
|
+
};
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
var init_audit = __esm({
|
|
979
|
+
"src/resources/audit.ts"() {
|
|
980
|
+
"use strict";
|
|
981
|
+
init_esm_shims();
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
// src/resources/index.ts
|
|
986
|
+
function registerResources(server, ap) {
|
|
987
|
+
registerWalletResource(server, ap);
|
|
988
|
+
registerTransactionResource(server, ap);
|
|
989
|
+
registerAuditResource(server, ap);
|
|
990
|
+
}
|
|
991
|
+
var init_resources = __esm({
|
|
992
|
+
"src/resources/index.ts"() {
|
|
993
|
+
"use strict";
|
|
994
|
+
init_esm_shims();
|
|
995
|
+
init_wallet();
|
|
996
|
+
init_transaction();
|
|
997
|
+
init_audit();
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
// src/prompts/buy.ts
|
|
1002
|
+
import { z as z5 } from "zod";
|
|
1003
|
+
function registerBuyPrompt(server) {
|
|
1004
|
+
server.prompt(
|
|
1005
|
+
"buy",
|
|
1006
|
+
"Step-by-step purchase flow: check balance, propose, wait for approval, execute.",
|
|
1007
|
+
{
|
|
1008
|
+
merchant: z5.string().describe("Merchant name"),
|
|
1009
|
+
amount: z5.string().describe('Purchase amount in USD (e.g. "29.99")'),
|
|
1010
|
+
description: z5.string().describe("What is being purchased"),
|
|
1011
|
+
url: z5.string().describe("Product or checkout URL")
|
|
1012
|
+
},
|
|
1013
|
+
async ({ merchant, amount, description, url }) => ({
|
|
1014
|
+
messages: [
|
|
1015
|
+
{
|
|
1016
|
+
role: "user",
|
|
1017
|
+
content: {
|
|
1018
|
+
type: "text",
|
|
1019
|
+
text: [
|
|
1020
|
+
`I need to purchase from ${merchant}.`,
|
|
1021
|
+
"",
|
|
1022
|
+
"Follow these steps exactly:",
|
|
1023
|
+
"",
|
|
1024
|
+
"1. Call agentpay_check_balance to verify sufficient funds",
|
|
1025
|
+
`2. Call agentpay_propose_purchase with:`,
|
|
1026
|
+
` - merchant: "${merchant}"`,
|
|
1027
|
+
` - amount: ${amount}`,
|
|
1028
|
+
` - description: "${description}"`,
|
|
1029
|
+
` - url: "${url}"`,
|
|
1030
|
+
"3. Tell me the transaction ID and that I need to approve it",
|
|
1031
|
+
"4. Call agentpay_wait_for_approval with the transaction ID",
|
|
1032
|
+
"5. Once approved, call agentpay_execute_purchase",
|
|
1033
|
+
"6. Call agentpay_get_receipt to confirm",
|
|
1034
|
+
"",
|
|
1035
|
+
"If any step fails, stop and explain what went wrong."
|
|
1036
|
+
].join("\n")
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
]
|
|
1040
|
+
})
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
var init_buy = __esm({
|
|
1044
|
+
"src/prompts/buy.ts"() {
|
|
1045
|
+
"use strict";
|
|
1046
|
+
init_esm_shims();
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
// src/prompts/budget-check.ts
|
|
1051
|
+
function registerBudgetCheckPrompt(server) {
|
|
1052
|
+
server.prompt(
|
|
1053
|
+
"budget-check",
|
|
1054
|
+
"Check current balance, spending limits, and pending transactions.",
|
|
1055
|
+
{},
|
|
1056
|
+
async () => ({
|
|
1057
|
+
messages: [
|
|
1058
|
+
{
|
|
1059
|
+
role: "user",
|
|
1060
|
+
content: {
|
|
1061
|
+
type: "text",
|
|
1062
|
+
text: [
|
|
1063
|
+
"Check my AgentPay budget status:",
|
|
1064
|
+
"",
|
|
1065
|
+
"1. Call agentpay_check_balance to get current balance and limits",
|
|
1066
|
+
"2. Call agentpay_list_pending to see any pending transactions",
|
|
1067
|
+
"3. Summarize:",
|
|
1068
|
+
" - Available balance",
|
|
1069
|
+
" - Per-transaction limit",
|
|
1070
|
+
" - Total budget and amount spent",
|
|
1071
|
+
" - Number of pending transactions (if any)"
|
|
1072
|
+
].join("\n")
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
]
|
|
1076
|
+
})
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
var init_budget_check = __esm({
|
|
1080
|
+
"src/prompts/budget-check.ts"() {
|
|
1081
|
+
"use strict";
|
|
1082
|
+
init_esm_shims();
|
|
1083
|
+
}
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1086
|
+
// src/prompts/purchase-status.ts
|
|
1087
|
+
import { z as z6 } from "zod";
|
|
1088
|
+
function registerPurchaseStatusPrompt(server) {
|
|
1089
|
+
server.prompt(
|
|
1090
|
+
"purchase-status",
|
|
1091
|
+
"Review recent transactions and their receipts.",
|
|
1092
|
+
{
|
|
1093
|
+
limit: z6.string().optional().describe("Number of recent transactions to show (default 5)")
|
|
1094
|
+
},
|
|
1095
|
+
async ({ limit }) => ({
|
|
1096
|
+
messages: [
|
|
1097
|
+
{
|
|
1098
|
+
role: "user",
|
|
1099
|
+
content: {
|
|
1100
|
+
type: "text",
|
|
1101
|
+
text: [
|
|
1102
|
+
`Show me the status of my recent AgentPay transactions (last ${limit ?? "5"}):`,
|
|
1103
|
+
"",
|
|
1104
|
+
"1. Call agentpay_status to get recent transactions",
|
|
1105
|
+
"2. For each completed transaction, call agentpay_get_receipt",
|
|
1106
|
+
"3. Present a summary table with:",
|
|
1107
|
+
" - Transaction ID",
|
|
1108
|
+
" - Merchant",
|
|
1109
|
+
" - Amount",
|
|
1110
|
+
" - Status",
|
|
1111
|
+
" - Confirmation ID (if completed)"
|
|
1112
|
+
].join("\n")
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
]
|
|
1116
|
+
})
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
var init_purchase_status = __esm({
|
|
1120
|
+
"src/prompts/purchase-status.ts"() {
|
|
1121
|
+
"use strict";
|
|
1122
|
+
init_esm_shims();
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
// src/prompts/index.ts
|
|
1127
|
+
function registerPrompts(server) {
|
|
1128
|
+
registerBuyPrompt(server);
|
|
1129
|
+
registerBudgetCheckPrompt(server);
|
|
1130
|
+
registerPurchaseStatusPrompt(server);
|
|
1131
|
+
}
|
|
1132
|
+
var init_prompts = __esm({
|
|
1133
|
+
"src/prompts/index.ts"() {
|
|
1134
|
+
"use strict";
|
|
1135
|
+
init_esm_shims();
|
|
1136
|
+
init_buy();
|
|
1137
|
+
init_budget_check();
|
|
1138
|
+
init_purchase_status();
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
// src/server.ts
|
|
1143
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1144
|
+
import { AgentPay as AgentPay3 } from "@useagentpay/sdk";
|
|
1145
|
+
function createServer(config) {
|
|
1146
|
+
const server = new McpServer({
|
|
1147
|
+
name: "agentpay",
|
|
1148
|
+
version: true ? "0.1.4" : "0.0.0"
|
|
1149
|
+
});
|
|
1150
|
+
const ap = new AgentPay3({
|
|
1151
|
+
home: config.home,
|
|
1152
|
+
executor: config.executor
|
|
1153
|
+
});
|
|
1154
|
+
registerTools(server, ap, config);
|
|
1155
|
+
registerResources(server, ap);
|
|
1156
|
+
registerPrompts(server);
|
|
1157
|
+
return server;
|
|
1158
|
+
}
|
|
1159
|
+
var init_server = __esm({
|
|
1160
|
+
"src/server.ts"() {
|
|
1161
|
+
"use strict";
|
|
1162
|
+
init_esm_shims();
|
|
1163
|
+
init_tools();
|
|
1164
|
+
init_resources();
|
|
1165
|
+
init_prompts();
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1169
|
+
// src/index.ts
|
|
1170
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1171
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1172
|
+
import { realpathSync } from "fs";
|
|
1173
|
+
async function startServer(overrides) {
|
|
1174
|
+
const config = loadConfig(overrides);
|
|
1175
|
+
const server = createServer(config);
|
|
1176
|
+
if (config.http) {
|
|
1177
|
+
const { createServer: createHttpServer } = await import("http");
|
|
1178
|
+
const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
1179
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID() });
|
|
1180
|
+
await server.connect(transport);
|
|
1181
|
+
const httpServer = createHttpServer((req, res) => {
|
|
1182
|
+
transport.handleRequest(req, res);
|
|
1183
|
+
});
|
|
1184
|
+
const port = parseInt(process.env.MCP_HTTP_PORT ?? "3100", 10);
|
|
1185
|
+
httpServer.listen(port, () => {
|
|
1186
|
+
console.error(`AgentPay MCP server listening on http://localhost:${port}`);
|
|
1187
|
+
});
|
|
1188
|
+
const shutdown = () => {
|
|
1189
|
+
httpServer.close();
|
|
1190
|
+
process.exit(0);
|
|
1191
|
+
};
|
|
1192
|
+
process.on("SIGINT", shutdown);
|
|
1193
|
+
process.on("SIGTERM", shutdown);
|
|
1194
|
+
} else {
|
|
1195
|
+
const transport = new StdioServerTransport();
|
|
1196
|
+
await server.connect(transport);
|
|
1197
|
+
const shutdown = async () => {
|
|
1198
|
+
await server.close();
|
|
1199
|
+
process.exit(0);
|
|
1200
|
+
};
|
|
1201
|
+
process.on("SIGINT", shutdown);
|
|
1202
|
+
process.on("SIGTERM", shutdown);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
var isDirectRun;
|
|
1206
|
+
var init_src = __esm({
|
|
1207
|
+
"src/index.ts"() {
|
|
1208
|
+
"use strict";
|
|
1209
|
+
init_esm_shims();
|
|
1210
|
+
init_server();
|
|
1211
|
+
init_config();
|
|
1212
|
+
init_server();
|
|
1213
|
+
init_config();
|
|
1214
|
+
isDirectRun = false;
|
|
1215
|
+
try {
|
|
1216
|
+
const thisFile = fileURLToPath2(import.meta.url);
|
|
1217
|
+
isDirectRun = !!process.argv[1] && realpathSync(process.argv[1]) === thisFile;
|
|
1218
|
+
} catch {
|
|
1219
|
+
}
|
|
1220
|
+
if (isDirectRun) {
|
|
1221
|
+
const httpFlag = process.argv.includes("--http");
|
|
1222
|
+
startServer({ http: httpFlag }).catch((err) => {
|
|
1223
|
+
console.error("Failed to start MCP server:", err);
|
|
1224
|
+
process.exit(1);
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
// src/commands/serve.ts
|
|
1231
|
+
var serve_exports = {};
|
|
1232
|
+
__export(serve_exports, {
|
|
1233
|
+
serveCommand: () => serveCommand
|
|
1234
|
+
});
|
|
1235
|
+
async function serveCommand(options) {
|
|
1236
|
+
await startServer({ http: options.http });
|
|
1237
|
+
}
|
|
1238
|
+
var init_serve = __esm({
|
|
1239
|
+
"src/commands/serve.ts"() {
|
|
1240
|
+
"use strict";
|
|
1241
|
+
init_esm_shims();
|
|
1242
|
+
init_src();
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1246
|
+
// src/cli.ts
|
|
1247
|
+
init_esm_shims();
|
|
1248
|
+
import { Command } from "commander";
|
|
1249
|
+
var VERSION = true ? "0.1.4" : "0.0.0";
|
|
1250
|
+
var program = new Command();
|
|
1251
|
+
program.name("agentpay").description("AgentPay \u2013 MCP server & CLI for AI agent payments").version(VERSION);
|
|
1252
|
+
program.command("init").description("Initialize AgentPay in the current directory").action(async () => {
|
|
1253
|
+
const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
1254
|
+
initCommand2();
|
|
1255
|
+
});
|
|
1256
|
+
program.command("setup").description("Set up AgentPay with your billing credentials").action(async () => {
|
|
1257
|
+
const { setupCommand: setupCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
1258
|
+
await setupCommand2();
|
|
1259
|
+
});
|
|
1260
|
+
program.command("budget").description("View current spending budget (configure via dashboard)").action(async () => {
|
|
1261
|
+
const { budgetCommand: budgetCommand2 } = await Promise.resolve().then(() => (init_budget(), budget_exports));
|
|
1262
|
+
budgetCommand2();
|
|
1263
|
+
});
|
|
1264
|
+
program.command("pending").description("List pending purchase proposals").action(async () => {
|
|
1265
|
+
const { pendingCommand: pendingCommand2 } = await Promise.resolve().then(() => (init_pending(), pending_exports));
|
|
1266
|
+
pendingCommand2();
|
|
1267
|
+
});
|
|
1268
|
+
program.command("propose").description("Propose a purchase (creates a pending transaction)").requiredOption("--merchant <name>", "Merchant name").requiredOption("--amount <amount>", "Purchase amount in USD").requiredOption("--description <desc>", "Purchase description").requiredOption("--url <url>", "Product/checkout URL").action(async (options) => {
|
|
1269
|
+
const { proposeCommand: proposeCommand2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
1270
|
+
proposeCommand2(options);
|
|
1271
|
+
});
|
|
1272
|
+
program.command("approve <txId>").description("Approve a pending purchase").action(async (txId) => {
|
|
1273
|
+
const { approveCommand: approveCommand2 } = await Promise.resolve().then(() => (init_approve(), approve_exports));
|
|
1274
|
+
await approveCommand2(txId);
|
|
1275
|
+
});
|
|
1276
|
+
program.command("reject <txId>").description("Reject a pending purchase").option("--reason <reason>", "Reason for rejection").action(async (txId, options) => {
|
|
1277
|
+
const { rejectCommand: rejectCommand2 } = await Promise.resolve().then(() => (init_reject(), reject_exports));
|
|
1278
|
+
rejectCommand2(txId, options);
|
|
1279
|
+
});
|
|
1280
|
+
program.command("status").description("Show wallet status and recent transactions").action(async () => {
|
|
1281
|
+
const { statusCommand: statusCommand2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
1282
|
+
statusCommand2();
|
|
1283
|
+
});
|
|
1284
|
+
program.command("history").description("Show full transaction history").action(async () => {
|
|
1285
|
+
const { historyCommand: historyCommand2 } = await Promise.resolve().then(() => (init_history(), history_exports));
|
|
1286
|
+
historyCommand2();
|
|
1287
|
+
});
|
|
1288
|
+
program.command("reset").description("Delete all AgentPay data").action(async () => {
|
|
1289
|
+
const { resetCommand: resetCommand2 } = await Promise.resolve().then(() => (init_reset(), reset_exports));
|
|
1290
|
+
await resetCommand2();
|
|
1291
|
+
});
|
|
1292
|
+
program.command("dashboard").description("Open the AgentPay dashboard in your browser").option("--port <port>", "Port for dashboard server", "3141").action(async (options) => {
|
|
1293
|
+
const { dashboardCommand: dashboardCommand2 } = await Promise.resolve().then(() => (init_dashboard(), dashboard_exports));
|
|
1294
|
+
await dashboardCommand2(options);
|
|
1295
|
+
});
|
|
1296
|
+
program.command("serve").description("Start AgentPay MCP server").option("--http", "Use HTTP transport instead of stdio").action(async (options) => {
|
|
1297
|
+
const { serveCommand: serveCommand2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
|
|
1298
|
+
await serveCommand2(options);
|
|
1299
|
+
});
|
|
1300
|
+
program.parse();
|
|
1301
|
+
//# sourceMappingURL=cli.js.map
|