@arispay/payagent-mcp 2.7.0 → 2.8.0

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 CHANGED
@@ -6,7 +6,6 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
6
6
  import {
7
7
  BootstrapError,
8
8
  DelegationClient,
9
- HostedTopupNotConfiguredError,
10
9
  bootstrapAgent,
11
10
  formatUSDC,
12
11
  getAgent,
@@ -29,6 +28,11 @@ function looksLikeInsufficientFunds(message) {
29
28
  );
30
29
  }
31
30
 
31
+ // src/profile.ts
32
+ function platformToolsEnabled(raw = process.env.PAYAGENT_MCP_PROFILE) {
33
+ return (raw ?? "all").trim().toLowerCase() !== "core";
34
+ }
35
+
32
36
  // src/index.ts
33
37
  var arispayUrl = getArispayUrl(process.env.ARISPAY_URL);
34
38
  var legacyAgentKey = process.env.ARISPAY_AGENT_KEY;
@@ -70,6 +74,7 @@ var server = new McpServer({
70
74
  });
71
75
  server.tool(
72
76
  "pay_api",
77
+ "Make an HTTP request to a paid API, transparently paying any x402 (HTTP 402) challenge with USDC under the agent's spend limits. THE tool for fetching paid resources \u2014 never bypass a 402 or hand-roll payment.",
73
78
  {
74
79
  url: z.string().describe("The full URL of the API endpoint to call"),
75
80
  method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).default("GET").describe("HTTP method"),
@@ -96,25 +101,28 @@ server.tool(
96
101
  );
97
102
  }
98
103
  try {
99
- const fetch402 = payFetchDelegated({ arispayUrl, apiKey: resolved.key });
104
+ let paymentInfo;
105
+ const fetch402 = payFetchDelegated({
106
+ arispayUrl,
107
+ apiKey: resolved.key,
108
+ onPayment: (info) => {
109
+ paymentInfo = info;
110
+ }
111
+ });
100
112
  const response = await fetch402(url, { method, headers, body });
101
113
  const responseBody = await response.text();
102
- return textResult(
103
- [`HTTP ${response.status} (paid via ${resolved.source})`, "", responseBody].join("\n")
104
- );
114
+ const statusLine = paymentInfo ? `HTTP ${response.status} (paid ${paymentInfo.amountCents}\xA2 via ${resolved.source} \u2014 budget left: ${paymentInfo.remainingDaily}\xA2 today, ${paymentInfo.remainingMonthly}\xA2 this month)` : `HTTP ${response.status} (paid via ${resolved.source})`;
115
+ return textResult([statusLine, "", responseBody].join("\n"));
105
116
  } catch (err) {
106
117
  const message = err instanceof Error ? err.message : String(err);
107
118
  if (looksLikeInsufficientFunds(message)) {
108
- const onrampHint = await tryGetOnrampHint(agent);
109
119
  return textResult(
110
120
  [
111
121
  `Error: ${message}`,
112
122
  "",
113
123
  "This looks like the agent wallet is out of USDC. Fund it and retry:",
114
- ...onrampHint ?? [
115
- " Use the `fund_agent` tool with hosted=true to mint a Coinbase Onramp URL,",
116
- " or send USDC on Base directly to the wallet address from `check_wallet`."
117
- ]
124
+ " Use the `fund_agent` tool (rail='usdc' for the wallet address,",
125
+ " or rail='europ' to fund via SEPA/EUR\xD8P in the browser)."
118
126
  ].join("\n"),
119
127
  true
120
128
  );
@@ -123,26 +131,9 @@ server.tool(
123
131
  }
124
132
  }
125
133
  );
126
- async function tryGetOnrampHint(agentName) {
127
- const stored = resolveAgent(agentName);
128
- if (!stored) return void 0;
129
- const devKey = getApiKey();
130
- if (!devKey) return void 0;
131
- try {
132
- const client = new DelegationClient(arispayUrl, devKey);
133
- const link = await client.getHostedTopup(stored.agentId, {});
134
- return [
135
- ` Coinbase Onramp: ${link.fundingUrl}`,
136
- ` URL valid until: ${link.expiresAt}`,
137
- ` Or send USDC on ${link.network} directly to ${link.walletAddress}`
138
- ];
139
- } catch (err) {
140
- if (err instanceof HostedTopupNotConfiguredError) return void 0;
141
- return void 0;
142
- }
143
- }
144
134
  server.tool(
145
135
  "check_wallet",
136
+ `Show the current agent's credentials, wallet address, and on-chain USDC balance \u2014 the quick "what state am I in" probe.`,
146
137
  {
147
138
  agent: z.string().optional().describe(
148
139
  "Optional: name of a locally-stored agent. Defaults to legacy ARISPAY_WALLET mode."
@@ -174,6 +165,7 @@ server.tool(
174
165
  );
175
166
  server.tool(
176
167
  "create_agent",
168
+ "Provision an additional x402 payment agent (wallet + spend limits) under the already-paired developer account.",
177
169
  {
178
170
  name: z.string().describe("Local identifier for this agent. Used by later tools."),
179
171
  perTx: z.number().int().positive().describe("Per-transaction spend cap in cents."),
@@ -211,63 +203,43 @@ server.tool(
211
203
  }
212
204
  }
213
205
  );
206
+ var buyformeUrl = process.env.BUYFORME_URL?.replace(/\/$/, "") ?? "https://buyforme.arispay.app";
214
207
  server.tool(
215
208
  "fund_agent",
209
+ "Get funding instructions for an agent's wallet. Use rail='usdc' for the direct USDC deposit address on Base, or rail='europ' for a browser handoff to complete Schuman identity verification and receive a SEPA vIBAN that credits EUR\xD8P.",
216
210
  {
217
211
  name: z.string().describe("Name of a locally-stored agent."),
218
- hosted: z.boolean().optional().describe(
219
- "If true, request a provider-hosted onramp URL (Coinbase, etc.) instead of the plain wallet address. Requires ARISPAY_ONRAMP_PROVIDER on the API deployment."
220
- ),
221
- amount: z.number().optional().describe("Preset top-up amount in dollars. Only meaningful with `hosted: true`.")
212
+ rail: z.enum(["usdc", "europ"]).default("usdc").describe(
213
+ "Funding rail: 'usdc' sends stablecoin directly to the agent wallet; 'europ' opens the BuyForMe EUR\xD8P onboarding flow in a browser to verify identity and get a vIBAN."
214
+ )
222
215
  },
223
- async ({ name, hosted, amount }) => {
216
+ async ({ name, rail }) => {
224
217
  const stored = getAgent(name);
225
218
  if (!stored) return textResult(`No locally-stored agent named \`${name}\`.`, true);
226
- if (hosted) {
227
- const devKey = getApiKey();
228
- if (!devKey) {
229
- return textResult("No ArisPay developer key found. Run `npx payagent init` first.", true);
230
- }
231
- const client = new DelegationClient(arispayUrl, devKey);
232
- try {
233
- const link = await client.getHostedTopup(stored.agentId, { amount });
234
- const lines2 = [
235
- `Top up \`${name}\` via ${link.provider}:`,
236
- "",
237
- ` ${link.fundingUrl}`,
238
- "",
239
- ` Wallet: ${link.walletAddress}`,
240
- ` Network: ${link.network}`,
241
- ` URL valid until: ${link.expiresAt}`,
242
- "",
243
- "Share that URL with the end-user; the onramp deposits USDC straight to the agent's wallet."
244
- ];
245
- return textResult(lines2.join("\n"));
246
- } catch (err) {
247
- if (err instanceof HostedTopupNotConfiguredError) {
248
- return textResult(
249
- [
250
- "Hosted onramp is not configured on this ArisPay deployment.",
251
- "Falling back to the manual path:",
252
- "",
253
- ` Send USDC on ${stored.network ?? "base"} to ${stored.walletAddress}`,
254
- "",
255
- "Ask the deployment owner to set ARISPAY_ONRAMP_PROVIDER=coinbase (+ COINBASE_ONRAMP_APP_ID) to enable hosted top-ups."
256
- ].join("\n")
257
- );
258
- }
259
- return textResult(
260
- `fund_agent (hosted) failed: ${err instanceof Error ? err.message : String(err)}`,
261
- true
262
- );
263
- }
219
+ if (rail === "europ") {
220
+ const handoffUrl = `${buyformeUrl}/onboarding/fund-europ?agentId=${encodeURIComponent(
221
+ stored.agentId
222
+ )}`;
223
+ const lines2 = [
224
+ `Fund \`${name}\` with EUR\xD8P via Schuman:`,
225
+ "",
226
+ ` ${handoffUrl}`,
227
+ "",
228
+ "Open that link in a browser to:",
229
+ " 1. Verify your identity with Schuman Financial (one-time KYC).",
230
+ " 2. Receive a dedicated SEPA vIBAN.",
231
+ " 3. Send EUR by bank transfer; Schuman mints EUR\xD8P to your wallet once it clears.",
232
+ "",
233
+ "After the deposit clears, call `get_balance` to confirm the agent's USDC balance."
234
+ ];
235
+ return textResult(lines2.join("\n"));
264
236
  }
265
237
  const lines = [
266
238
  `Fund \`${name}\` by sending USDC on ${stored.network ?? "base"} to:`,
267
239
  "",
268
240
  ` ${stored.walletAddress}`,
269
241
  "",
270
- "Pass `hosted: true` to get a Coinbase onramp URL instead (requires ARISPAY_ONRAMP_PROVIDER).",
242
+ "Only send USDC on the network shown above. Other tokens or networks may be lost.",
271
243
  "Call `get_balance` when the deposit lands."
272
244
  ];
273
245
  return textResult(lines.join("\n"));
@@ -275,6 +247,7 @@ server.tool(
275
247
  );
276
248
  server.tool(
277
249
  "get_balance",
250
+ "Server-side USDC balance + funding status for one named agent.",
278
251
  {
279
252
  name: z.string().describe("Name of a locally-stored agent.")
280
253
  },
@@ -300,206 +273,220 @@ server.tool(
300
273
  }
301
274
  }
302
275
  );
303
- server.tool(
304
- "create_enduser",
305
- {
306
- externalId: z.string().describe("Your own stable id for this customer (e.g. `tg:12345`)."),
307
- email: z.string().optional().describe("Optional email for compliance / receipts."),
308
- findOrCreate: z.boolean().optional().describe("If true, return the existing user instead of erroring on externalId collision.")
309
- },
310
- async ({ externalId, email, findOrCreate }) => {
311
- try {
312
- const devKey = requireDevKey();
313
- const client = new DelegationClient(arispayUrl, devKey);
314
- const user = await client.createEndUser({ externalId, email, findOrCreate });
315
- const lines = [
316
- `\u2713 End-user \`${externalId}\` ready.`,
317
- ` ArisPay id: ${user.id}`,
318
- ` Has card: ${user.hasPaymentMethod ? "yes" : "no"}`,
319
- ` Has wallet: ${user.hasWallet ? "yes" : "no"}`
320
- ];
321
- return textResult(lines.join("\n"));
322
- } catch (err) {
323
- return textResult(
324
- `create_enduser failed: ${err instanceof Error ? err.message : String(err)}`,
325
- true
326
- );
327
- }
328
- }
329
- );
330
- server.tool(
331
- "attach_card_for_user",
332
- {
333
- userId: z.string().describe("The ArisPay-internal end-user id (not externalId)."),
334
- agentName: z.string().optional().describe("Optional locally-stored agent name to scope the card-setup session to.")
335
- },
336
- async ({ userId, agentName }) => {
337
- try {
338
- const devKey = requireDevKey();
339
- const client = new DelegationClient(arispayUrl, devKey);
340
- const agentId = agentName ? getAgent(agentName)?.agentId : void 0;
341
- const session = await client.createCardSetupSession({ endUserId: userId, agentId });
342
- const lines = [
343
- `Card-entry URL for user \`${userId}\`:`,
344
- "",
345
- ` ${session.setupUrl}`,
346
- "",
347
- ` Expires at: ${session.expiresAt}`,
348
- "",
349
- "Share this URL with the end-user. They enter the card on ArisPay's hosted page; we handle tokenization + 3DS.",
350
- "Call `get_user_status` afterwards to confirm the card is attached."
351
- ];
352
- return textResult(lines.join("\n"));
353
- } catch (err) {
354
- return textResult(
355
- `attach_card_for_user failed: ${err instanceof Error ? err.message : String(err)}`,
356
- true
357
- );
276
+ if (platformToolsEnabled()) {
277
+ server.tool(
278
+ "create_enduser",
279
+ "Platform mode: register an end-customer (EndUser) under your account, keyed by your own externalId.",
280
+ {
281
+ externalId: z.string().describe("Your own stable id for this customer (e.g. `tg:12345`)."),
282
+ email: z.string().optional().describe("Optional email for compliance / receipts."),
283
+ findOrCreate: z.boolean().optional().describe("If true, return the existing user instead of erroring on externalId collision.")
284
+ },
285
+ async ({ externalId, email, findOrCreate }) => {
286
+ try {
287
+ const devKey = requireDevKey();
288
+ const client = new DelegationClient(arispayUrl, devKey);
289
+ const user = await client.createEndUser({ externalId, email, findOrCreate });
290
+ const lines = [
291
+ `\u2713 End-user \`${externalId}\` ready.`,
292
+ ` ArisPay id: ${user.id}`,
293
+ ` Has card: ${user.hasPaymentMethod ? "yes" : "no"}`,
294
+ ` Has wallet: ${user.hasWallet ? "yes" : "no"}`
295
+ ];
296
+ return textResult(lines.join("\n"));
297
+ } catch (err) {
298
+ return textResult(
299
+ `create_enduser failed: ${err instanceof Error ? err.message : String(err)}`,
300
+ true
301
+ );
302
+ }
358
303
  }
359
- }
360
- );
361
- server.tool(
362
- "set_user_limits",
363
- {
364
- userId: z.string().describe("ArisPay-internal end-user id."),
365
- agentName: z.string().describe("Locally-stored agent name."),
366
- perTx: z.number().int().optional().describe("Per-transaction cap in cents. Omit to inherit agent defaults."),
367
- daily: z.number().int().optional().describe("Daily cap in cents."),
368
- monthly: z.number().int().optional().describe("Monthly cap in cents."),
369
- allowedMcc: z.array(z.string()).optional().describe("Allowed Merchant Category Codes."),
370
- blockedMcc: z.array(z.string()).optional().describe("Blocked MCCs.")
371
- },
372
- async ({ userId, agentName, perTx, daily, monthly, allowedMcc, blockedMcc }) => {
373
- try {
374
- const stored = getAgent(agentName);
375
- if (!stored) {
376
- return textResult(`No locally-stored agent named \`${agentName}\`.`, true);
304
+ );
305
+ server.tool(
306
+ "attach_card_for_user",
307
+ "Platform mode: mint a hosted card-entry URL for an end-user (ArisPay handles tokenization + 3DS).",
308
+ {
309
+ userId: z.string().describe("The ArisPay-internal end-user id (not externalId)."),
310
+ agentName: z.string().optional().describe("Optional locally-stored agent name to scope the card-setup session to.")
311
+ },
312
+ async ({ userId, agentName }) => {
313
+ try {
314
+ const devKey = requireDevKey();
315
+ const client = new DelegationClient(arispayUrl, devKey);
316
+ const agentId = agentName ? getAgent(agentName)?.agentId : void 0;
317
+ const session = await client.createCardSetupSession({ endUserId: userId, agentId });
318
+ const lines = [
319
+ `Card-entry URL for user \`${userId}\`:`,
320
+ "",
321
+ ` ${session.setupUrl}`,
322
+ "",
323
+ ` Expires at: ${session.expiresAt}`,
324
+ "",
325
+ "Share this URL with the end-user. They enter the card on ArisPay's hosted page; we handle tokenization + 3DS.",
326
+ "Call `get_user_status` afterwards to confirm the card is attached."
327
+ ];
328
+ return textResult(lines.join("\n"));
329
+ } catch (err) {
330
+ return textResult(
331
+ `attach_card_for_user failed: ${err instanceof Error ? err.message : String(err)}`,
332
+ true
333
+ );
377
334
  }
378
- const devKey = requireDevKey();
379
- const client = new DelegationClient(arispayUrl, devKey);
380
- const limit = await client.setUserLimits(userId, {
381
- agentId: stored.agentId,
382
- maxPerTransaction: perTx ?? null,
383
- maxDaily: daily ?? null,
384
- maxMonthly: monthly ?? null,
385
- allowedMerchantCategories: allowedMcc,
386
- blockedMerchantCategories: blockedMcc
387
- });
388
- return textResult(
389
- [
390
- `\u2713 Limits set for \`${userId}\` on agent \`${agentName}\`.`,
391
- ` per-tx ${limit.maxPerTransaction ?? "inherit"}\xA2, daily ${limit.maxDaily ?? "inherit"}\xA2, monthly ${limit.maxMonthly ?? "inherit"}\xA2`
392
- ].join("\n")
393
- );
394
- } catch (err) {
395
- return textResult(
396
- `set_user_limits failed: ${err instanceof Error ? err.message : String(err)}`,
397
- true
398
- );
399
335
  }
400
- }
401
- );
402
- server.tool(
403
- "get_user_status",
404
- {
405
- userId: z.string().describe("ArisPay-internal end-user id.")
406
- },
407
- async ({ userId }) => {
408
- try {
409
- const devKey = requireDevKey();
410
- const client = new DelegationClient(arispayUrl, devKey);
411
- const user = await client.getEndUser(userId);
412
- const lines = [
413
- `${user.externalId} (${user.id})`,
414
- ` email: ${user.email ?? "\u2014"}`,
415
- ` card: ${user.hasPaymentMethod ? `${user.cardBrand ?? "card"} \u2026${user.cardLast4 ?? "????"}` : "\u2014"}`,
416
- ` wallet: ${user.walletAddress ?? "\u2014"}${user.walletChain ? ` on ${user.walletChain}` : ""}`
417
- ];
418
- if (user.hasWallet) {
419
- try {
420
- const w = await client.getWalletStatus(userId);
421
- lines.push(` balance: ${w.usdcBalance} USDC base units`);
422
- lines.push(
423
- ` allowance: ${w.usdcAllowance} (${w.allowanceSufficient ? "ok" : "insufficient"})`
424
- );
425
- lines.push(` ready: ${w.ready}`);
426
- } catch {
336
+ );
337
+ server.tool(
338
+ "set_user_limits",
339
+ "Platform mode: set per-(user, agent) spend caps in integer cents plus MCC allow/block rules.",
340
+ {
341
+ userId: z.string().describe("ArisPay-internal end-user id."),
342
+ agentName: z.string().describe("Locally-stored agent name."),
343
+ perTx: z.number().int().optional().describe("Per-transaction cap in cents. Omit to inherit agent defaults."),
344
+ daily: z.number().int().optional().describe("Daily cap in cents."),
345
+ monthly: z.number().int().optional().describe("Monthly cap in cents."),
346
+ allowedMcc: z.array(z.string()).optional().describe("Allowed Merchant Category Codes."),
347
+ blockedMcc: z.array(z.string()).optional().describe("Blocked MCCs.")
348
+ },
349
+ async ({ userId, agentName, perTx, daily, monthly, allowedMcc, blockedMcc }) => {
350
+ try {
351
+ const stored = getAgent(agentName);
352
+ if (!stored) {
353
+ return textResult(`No locally-stored agent named \`${agentName}\`.`, true);
427
354
  }
355
+ const devKey = requireDevKey();
356
+ const client = new DelegationClient(arispayUrl, devKey);
357
+ const limit = await client.setUserLimits(userId, {
358
+ agentId: stored.agentId,
359
+ maxPerTransaction: perTx ?? null,
360
+ maxDaily: daily ?? null,
361
+ maxMonthly: monthly ?? null,
362
+ allowedMerchantCategories: allowedMcc,
363
+ blockedMerchantCategories: blockedMcc
364
+ });
365
+ return textResult(
366
+ [
367
+ `\u2713 Limits set for \`${userId}\` on agent \`${agentName}\`.`,
368
+ ` per-tx ${limit.maxPerTransaction ?? "inherit"}\xA2, daily ${limit.maxDaily ?? "inherit"}\xA2, monthly ${limit.maxMonthly ?? "inherit"}\xA2`
369
+ ].join("\n")
370
+ );
371
+ } catch (err) {
372
+ return textResult(
373
+ `set_user_limits failed: ${err instanceof Error ? err.message : String(err)}`,
374
+ true
375
+ );
428
376
  }
429
- return textResult(lines.join("\n"));
430
- } catch (err) {
431
- return textResult(
432
- `get_user_status failed: ${err instanceof Error ? err.message : String(err)}`,
433
- true
434
- );
435
377
  }
436
- }
437
- );
438
- server.tool(
439
- "pay_merchant",
440
- {
441
- agentName: z.string().describe("Name of the locally-stored agent making the payment."),
442
- merchantUrl: z.string().describe("Canonical merchant URL (stored on the payment record)."),
443
- amount: z.number().int().positive().describe("Amount in cents."),
444
- memo: z.string().describe("Human-readable memo attached to the payment."),
445
- userId: z.string().optional().describe("Optional ArisPay end-user id. Required when the agent is in platform mode."),
446
- rail: z.enum(["card", "crypto", "balance", "mpp"]).optional().describe("Force a specific rail. Default: server-picked based on agent mode + userId."),
447
- merchantName: z.string().optional().describe("Optional human-readable merchant name."),
448
- merchantCategoryCode: z.string().optional().describe("MCC for spend-limit enforcement.")
449
- },
450
- async ({
451
- agentName,
452
- merchantUrl,
453
- amount,
454
- memo,
455
- userId,
456
- rail,
457
- merchantName,
458
- merchantCategoryCode
459
- }) => {
460
- try {
461
- const stored = getAgent(agentName);
462
- if (!stored) {
463
- return textResult(`No locally-stored agent named \`${agentName}\`.`, true);
464
- }
465
- const devKey = requireDevKey();
466
- const client = new DelegationClient(arispayUrl, devKey);
467
- const payment = await client.createPayment(stored.agentId, {
468
- amount,
469
- memo,
470
- merchantUrl,
471
- merchantName,
472
- merchantCategoryCode,
473
- userId,
474
- rail
475
- });
476
- const lines = [
477
- `Payment ${payment.id}: ${payment.status}`,
478
- ` rail: ${payment.rail}`,
479
- ` amount: ${payment.amount}\xA2 ${payment.currency}`
480
- ];
481
- if (payment.merchantName) lines.push(` merchant: ${payment.merchantName}`);
482
- if (payment.txHash) lines.push(` tx hash: ${payment.txHash}`);
483
- if (payment.nextAction) {
484
- lines.push(` next action: ${payment.nextAction.type}`);
485
- if (payment.nextAction.challengeUrl) {
486
- lines.push(` 3DS challenge URL: ${payment.nextAction.challengeUrl}`);
378
+ );
379
+ server.tool(
380
+ "get_user_status",
381
+ "Platform mode: report an end-user's card, wallet, and payment readiness.",
382
+ {
383
+ userId: z.string().describe("ArisPay-internal end-user id.")
384
+ },
385
+ async ({ userId }) => {
386
+ try {
387
+ const devKey = requireDevKey();
388
+ const client = new DelegationClient(arispayUrl, devKey);
389
+ const user = await client.getEndUser(userId);
390
+ const lines = [
391
+ `${user.externalId} (${user.id})`,
392
+ ` email: ${user.email ?? "\u2014"}`,
393
+ ` card: ${user.hasPaymentMethod ? `${user.cardBrand ?? "card"} \u2026${user.cardLast4 ?? "????"}` : "\u2014"}`,
394
+ ` wallet: ${user.walletAddress ?? "\u2014"}${user.walletChain ? ` on ${user.walletChain}` : ""}`
395
+ ];
396
+ if (user.hasWallet) {
397
+ try {
398
+ const w = await client.getWalletStatus(userId);
399
+ lines.push(` balance: ${w.usdcBalance} USDC base units`);
400
+ lines.push(
401
+ ` allowance: ${w.usdcAllowance} (${w.allowanceSufficient ? "ok" : "insufficient"})`
402
+ );
403
+ lines.push(` ready: ${w.ready}`);
404
+ } catch {
405
+ }
487
406
  }
407
+ return textResult(lines.join("\n"));
408
+ } catch (err) {
409
+ return textResult(
410
+ `get_user_status failed: ${err instanceof Error ? err.message : String(err)}`,
411
+ true
412
+ );
488
413
  }
489
- if (payment.error) {
490
- lines.push(` error: ${payment.error.code} \u2014 ${payment.error.message}`);
414
+ }
415
+ );
416
+ server.tool(
417
+ "pay_merchant",
418
+ "Direct payment to a known merchant via ArisPay rails (card / crypto / balance / MPP) when you already know the amount. For x402-protected HTTP resources use `pay_api` instead.",
419
+ {
420
+ agentName: z.string().describe("Name of the locally-stored agent making the payment."),
421
+ merchantUrl: z.string().describe("Canonical merchant URL (stored on the payment record)."),
422
+ amount: z.number().int().positive().describe("Amount in cents."),
423
+ memo: z.string().describe("Human-readable memo attached to the payment."),
424
+ userId: z.string().optional().describe("Optional ArisPay end-user id. Required when the agent is in platform mode."),
425
+ rail: z.enum(["card", "crypto", "balance", "mpp"]).optional().describe("Force a specific rail. Default: server-picked based on agent mode + userId."),
426
+ merchantName: z.string().optional().describe("Optional human-readable merchant name."),
427
+ merchantCategoryCode: z.string().optional().describe("MCC for spend-limit enforcement.")
428
+ },
429
+ async ({
430
+ agentName,
431
+ merchantUrl,
432
+ amount,
433
+ memo,
434
+ userId,
435
+ rail,
436
+ merchantName,
437
+ merchantCategoryCode
438
+ }) => {
439
+ try {
440
+ const stored = getAgent(agentName);
441
+ if (!stored) {
442
+ return textResult(`No locally-stored agent named \`${agentName}\`.`, true);
443
+ }
444
+ const devKey = requireDevKey();
445
+ const client = new DelegationClient(arispayUrl, devKey);
446
+ const payment = await client.createPayment(stored.agentId, {
447
+ amount,
448
+ memo,
449
+ merchantUrl,
450
+ merchantName,
451
+ merchantCategoryCode,
452
+ userId,
453
+ rail
454
+ });
455
+ const lines = [
456
+ `Payment ${payment.id}: ${payment.status}`,
457
+ ` rail: ${payment.rail}`,
458
+ ` amount: ${payment.amount}\xA2 ${payment.currency}`
459
+ ];
460
+ if (payment.merchantName) lines.push(` merchant: ${payment.merchantName}`);
461
+ if (payment.txHash) lines.push(` tx hash: ${payment.txHash}`);
462
+ if (payment.spend) {
463
+ const fmtCap = (v) => v == null ? "no cap" : `${v}\xA2`;
464
+ lines.push(
465
+ ` budget: ${fmtCap(payment.spend.remainingDaily)} left today, ${fmtCap(payment.spend.remainingMonthly)} this month`
466
+ );
467
+ }
468
+ if (payment.nextAction) {
469
+ lines.push(` next action: ${payment.nextAction.type}`);
470
+ if (payment.nextAction.challengeUrl) {
471
+ lines.push(` 3DS challenge URL: ${payment.nextAction.challengeUrl}`);
472
+ }
473
+ }
474
+ if (payment.error) {
475
+ lines.push(` error: ${payment.error.code} \u2014 ${payment.error.message}`);
476
+ }
477
+ return textResult(lines.join("\n"), payment.status === "failed");
478
+ } catch (err) {
479
+ return textResult(
480
+ `pay_merchant failed: ${err instanceof Error ? err.message : String(err)}`,
481
+ true
482
+ );
491
483
  }
492
- return textResult(lines.join("\n"), payment.status === "failed");
493
- } catch (err) {
494
- return textResult(
495
- `pay_merchant failed: ${err instanceof Error ? err.message : String(err)}`,
496
- true
497
- );
498
484
  }
499
- }
500
- );
485
+ );
486
+ }
501
487
  server.tool(
502
488
  "bootstrap_agent",
489
+ "Cold-start in one call: create (or recover) an ArisPay account plus a payment agent from just an email. Run this first on a fresh machine; safe to re-run \u2014 it recovers the existing agent and wallet set instead of creating duplicates.",
503
490
  {
504
491
  email: z.string().describe("Email for the new ArisPay developer account."),
505
492
  name: z.string().optional().describe("Human name. Falls back to the email local-part."),
@@ -508,10 +495,9 @@ server.tool(
508
495
  perTx: z.number().int().positive().optional().describe("Per-tx cap in cents. Default: 50."),
509
496
  daily: z.number().int().positive().optional().describe("Daily cap in cents. Default: 1000."),
510
497
  monthly: z.number().int().positive().optional().describe("Monthly cap in cents. Default: 10000."),
511
- allowedDomains: z.array(z.string()).optional().describe("Domains the agent may pay. Empty = unrestricted."),
512
- fund: z.number().positive().optional().describe("Optional preset USD amount; mints a Coinbase Onramp URL pre-set to this value.")
498
+ allowedDomains: z.array(z.string()).optional().describe("Domains the agent may pay. Empty = unrestricted.")
513
499
  },
514
- async ({ email, name, orgName, agentName, perTx, daily, monthly, allowedDomains, fund }) => {
500
+ async ({ email, name, orgName, agentName, perTx, daily, monthly, allowedDomains }) => {
515
501
  try {
516
502
  const result = await bootstrapAgent({
517
503
  email,
@@ -520,7 +506,6 @@ server.tool(
520
506
  agentName,
521
507
  limits: { perTx, daily, monthly },
522
508
  allowedDomains,
523
- fund,
524
509
  arispayUrl: process.env.ARISPAY_URL,
525
510
  clientId: "payagent-mcp-bootstrap"
526
511
  });
@@ -529,24 +514,10 @@ server.tool(
529
514
  `\u2713 Agent: ${result.agentName} (${result.agentId})`,
530
515
  ` Wallet: ${result.walletAddress} (${result.network})`,
531
516
  ` Limits: ${result.limits.perTx}\xA2 / tx, ${result.limits.daily}\xA2 / day, ${result.limits.monthly}\xA2 / month`,
532
- ""
517
+ "",
518
+ `Fund the wallet by sending USDC on ${result.network} to ${result.walletAddress}.`,
519
+ `Or call \`fund_agent\` with name="${result.agentName}" and rail="usdc" or rail="europ".`
533
520
  ];
534
- if (result.fundingUrl) {
535
- lines.push("Fund this wallet via Coinbase Onramp:");
536
- lines.push(` ${result.fundingUrl}`);
537
- if (result.fundingExpiresAt) lines.push(` URL valid until: ${result.fundingExpiresAt}`);
538
- lines.push(` Or send USDC on ${result.network} directly to ${result.walletAddress}.`);
539
- } else {
540
- if (result.fundingUrlError) {
541
- lines.push(`Onramp not available (${result.fundingUrlError}).`);
542
- }
543
- lines.push(
544
- `Fund the wallet by sending USDC on ${result.network} to ${result.walletAddress}.`
545
- );
546
- lines.push(
547
- `Or call \`fund_agent\` with name="${result.agentName}", hosted=true to mint a Coinbase Onramp URL on demand.`
548
- );
549
- }
550
521
  if (result.pairing) {
551
522
  lines.push("");
552
523
  lines.push("\u{1F4F1} Open BuyForMe on your phone (signs you into the same account):");
@@ -567,6 +538,7 @@ server.tool(
567
538
  );
568
539
  server.tool(
569
540
  "list_agents",
541
+ "List all wallets under this account (server-authoritative; rehydrates the local cache).",
570
542
  {
571
543
  withBalance: z.boolean().optional().describe(
572
544
  "When true, fetch on-chain USDC balance per agent (adds one round-trip per wallet)."
@@ -634,6 +606,7 @@ ${lines.join("\n\n")}`
634
606
  );
635
607
  server.tool(
636
608
  "rename_agent",
609
+ "Rename an agent on the server and in the local cache (names are unique per account).",
637
610
  {
638
611
  name: z.string().describe("Current local name of the agent to rename."),
639
612
  newName: z.string().describe(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/pay-api-helpers.ts"],"sourcesContent":["/**\n * payagent-mcp — MCP server for agent-side x402 payments + headless launch.\n *\n * Six tools over stdio:\n * - pay_api(url, ...) — paid HTTP request via delegated signing\n * - check_wallet() — report current agent credentials + on-chain balance\n * - create_agent(...) — provision a new x402 agent (calls /v1/agents/x402)\n * - fund_agent({ name }) — return the wallet address + instructions for deposit\n * - get_balance({ name }) — on-server USDC balance + fundedAt latch\n * - list_agents() — enumerate locally-cached agents\n *\n * Config store lives at ~/.payagent/config.json (shared with the `payagent`\n * CLI). Credentials created via `npx payagent init` + `payagent agent create`\n * are immediately available here; equally, agents created via\n * `create_agent` are immediately visible to the CLI.\n *\n * Two auth modes, picked at request time:\n * 1. Legacy single-agent: ARISPAY_AGENT_KEY set → pay_api + check_wallet use it directly.\n * 2. Multi-agent: no env var, credentials come from the shared config store.\n * Management tools (create / fund / get_balance / list) always use the\n * developer key from the config store (or ARISPAY_API_KEY env).\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n BootstrapError,\n DelegationClient,\n HostedTopupNotConfiguredError,\n type StoredAgent,\n bootstrapAgent,\n formatUSDC,\n getAgent,\n getApiKey,\n getArispayUrl,\n getUSDCBalance,\n launchAgent,\n listAgents,\n payFetchDelegated,\n renameStoredAgent,\n syncAgents,\n} from \"payagent\";\nimport { z } from \"zod\";\nimport { looksLikeInsufficientFunds } from \"./pay-api-helpers.js\";\n\n// ── Configuration ─────────────────────────────────────\n\nconst arispayUrl = getArispayUrl(process.env.ARISPAY_URL);\n/** Legacy single-agent key (kept for backwards compatibility). */\nconst legacyAgentKey = process.env.ARISPAY_AGENT_KEY;\nconst legacyWalletAddress = process.env.PAYAGENT_WALLET;\n\nfunction resolveAgent(name?: string): StoredAgent | undefined {\n if (name) return getAgent(name);\n const agents = listAgents();\n return agents[0];\n}\n\n/**\n * Look up the agent-scoped key to use for paid requests.\n * Priority: explicit agent name → legacy env var → first stored agent.\n */\nfunction resolveAgentKey(name?: string): { key: string; source: string } | undefined {\n if (name) {\n const stored = getAgent(name);\n if (stored) return { key: stored.apiKey, source: `agent \\`${name}\\`` };\n return undefined;\n }\n if (legacyAgentKey) return { key: legacyAgentKey, source: \"ARISPAY_AGENT_KEY\" };\n const first = listAgents()[0];\n if (first) return { key: first.apiKey, source: `agent \\`${first.name}\\`` };\n return undefined;\n}\n\nfunction requireDevKey(): string {\n const key = getApiKey();\n if (!key) {\n throw new Error(\n \"No ArisPay developer key found. Run `npx payagent init` or set ARISPAY_API_KEY.\",\n );\n }\n return key;\n}\n\nfunction textResult(text: string, isError = false) {\n return {\n content: [{ type: \"text\" as const, text }],\n ...(isError ? { isError } : {}),\n };\n}\n\n// ── MCP Server ────────────────────────────────────────\n\nconst server = new McpServer({\n name: \"payagent\",\n version: \"2.1.0\",\n});\n\n// --- pay_api ----------------------------------------------------------------\n\nserver.tool(\n \"pay_api\",\n {\n url: z.string().describe(\"The full URL of the API endpoint to call\"),\n method: z\n .enum([\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\"])\n .default(\"GET\")\n .describe(\"HTTP method\"),\n headers: z.record(z.string(), z.string()).optional().describe(\"Additional HTTP headers\"),\n body: z.string().optional().describe(\"Request body (for POST/PUT/PATCH)\"),\n agent: z\n .string()\n .optional()\n .describe(\n \"Optional: name of a locally-stored agent to pay with. Defaults to ARISPAY_AGENT_KEY or the first stored agent.\",\n ),\n },\n async ({ url, method, headers, body, agent }) => {\n const resolved = resolveAgentKey(agent);\n if (!resolved) {\n return textResult(\n [\n \"No agent available. Cold-start in one call:\",\n ' bootstrap_agent({ email: \"you@example.com\", name: \"<your-name>\" })',\n \"\",\n \"Or, if a developer key is already paired (`npx payagent init`):\",\n \" create_agent({ name, perTx, daily, monthly })\",\n \"\",\n \"Or set ARISPAY_AGENT_KEY for legacy single-agent mode.\",\n ].join(\"\\n\"),\n true,\n );\n }\n try {\n const fetch402 = payFetchDelegated({ arispayUrl, apiKey: resolved.key });\n const response = await fetch402(url, { method, headers, body });\n const responseBody = await response.text();\n return textResult(\n [`HTTP ${response.status} (paid via ${resolved.source})`, \"\", responseBody].join(\"\\n\"),\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // Detect \"agent wallet has no USDC\" — surface a Coinbase Onramp URL\n // inline so Claude / the host doesn't have to make a second tool\n // call to figure out the recovery path. We're conservative about\n // the trigger: only do this on a 402-after-signed-payment with a\n // funds-shaped error in the seller response. Other failures\n // (allowed-domain block, agent suspended, network) propagate as-is.\n if (looksLikeInsufficientFunds(message)) {\n const onrampHint = await tryGetOnrampHint(agent);\n return textResult(\n [\n `Error: ${message}`,\n \"\",\n \"This looks like the agent wallet is out of USDC. Fund it and retry:\",\n ...(onrampHint ?? [\n \" Use the `fund_agent` tool with hosted=true to mint a Coinbase Onramp URL,\",\n \" or send USDC on Base directly to the wallet address from `check_wallet`.\",\n ]),\n ].join(\"\\n\"),\n true,\n );\n }\n return textResult(`Error: ${message}`, true);\n }\n },\n);\n\n/**\n * Best-effort: mint an Onramp URL for the named agent (or the first one\n * in the local store). Returns the lines to append to the error message,\n * or `undefined` if we can't get one (no dev key, no Onramp configured,\n * no agent name resolvable).\n */\nasync function tryGetOnrampHint(agentName?: string): Promise<string[] | undefined> {\n const stored = resolveAgent(agentName);\n if (!stored) return undefined;\n const devKey = getApiKey();\n if (!devKey) return undefined;\n try {\n const client = new DelegationClient(arispayUrl, devKey);\n const link = await client.getHostedTopup(stored.agentId, {});\n return [\n ` Coinbase Onramp: ${link.fundingUrl}`,\n ` URL valid until: ${link.expiresAt}`,\n ` Or send USDC on ${link.network} directly to ${link.walletAddress}`,\n ];\n } catch (err) {\n if (err instanceof HostedTopupNotConfiguredError) return undefined;\n return undefined;\n }\n}\n\n// --- check_wallet ----------------------------------------------------------\n\nserver.tool(\n \"check_wallet\",\n {\n agent: z\n .string()\n .optional()\n .describe(\n \"Optional: name of a locally-stored agent. Defaults to legacy ARISPAY_WALLET mode.\",\n ),\n },\n async ({ agent }) => {\n const resolved = resolveAgent(agent);\n const walletAddress = resolved?.walletAddress ?? legacyWalletAddress;\n const keyTail =\n resolved?.apiKey.slice(-4) ?? (legacyAgentKey ? legacyAgentKey.slice(-4) : undefined);\n\n const lines = [`ArisPay URL: ${arispayUrl}`];\n if (resolved) lines.push(`Agent: ${resolved.name} (${resolved.agentId})`);\n if (keyTail) lines.push(`Agent key: ap_…${keyTail}`);\n\n if (walletAddress) {\n lines.push(`Wallet: ${walletAddress}`);\n try {\n const raw = await getUSDCBalance(walletAddress, (resolved?.network as \"base\") ?? \"base\");\n lines.push(`Balance: ${formatUSDC(raw)} USDC on ${resolved?.network ?? \"base\"}`);\n } catch (err) {\n lines.push(\n `Balance: unavailable (${err instanceof Error ? err.message : String(err)})`,\n );\n }\n } else {\n lines.push(\"\", \"No wallet known. Use `create_agent` or set PAYAGENT_WALLET for legacy mode.\");\n }\n\n lines.push(\"\", \"Manage limits + full history: https://arispay.app/dashboard\");\n return textResult(lines.join(\"\\n\"));\n },\n);\n\n// --- create_agent ----------------------------------------------------------\n\nserver.tool(\n \"create_agent\",\n {\n name: z.string().describe(\"Local identifier for this agent. Used by later tools.\"),\n perTx: z.number().int().positive().describe(\"Per-transaction spend cap in cents.\"),\n daily: z.number().int().positive().describe(\"Daily spend cap in cents.\"),\n monthly: z.number().int().positive().describe(\"Monthly spend cap in cents.\"),\n allowedDomains: z\n .array(z.string())\n .optional()\n .describe(\"If provided, restrict this agent to paying only these domains.\"),\n network: z\n .enum([\"base\", \"base-sepolia\", \"ethereum\", \"polygon\"])\n .default(\"base\")\n .describe(\"EVM network the agent pays on.\"),\n agentType: z.string().optional().describe('Optional metadata label (e.g. \"hermes\").'),\n },\n async ({ name, perTx, daily, monthly, allowedDomains, network, agentType }) => {\n try {\n requireDevKey(); // fail fast with a helpful message if not signed in\n const agent = await launchAgent({\n name,\n limits: { perTx, daily, monthly },\n allowedDomains,\n network,\n agentType,\n });\n const lines = [\n `✓ Agent \\`${name}\\` created.`,\n ` Agent ID: ${agent.agentId}`,\n ` Wallet: ${agent.walletAddress}`,\n ` Network: ${agent.network}`,\n ` Limits: ${perTx}¢ / tx, ${daily}¢ / day, ${monthly}¢ / month`,\n \"\",\n ` Fund the wallet with USDC on ${agent.network}, then call \\`get_balance\\` with name=\"${name}\".`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `create_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- fund_agent ------------------------------------------------------------\n\nserver.tool(\n \"fund_agent\",\n {\n name: z.string().describe(\"Name of a locally-stored agent.\"),\n hosted: z\n .boolean()\n .optional()\n .describe(\n \"If true, request a provider-hosted onramp URL (Coinbase, etc.) instead of the plain wallet address. Requires ARISPAY_ONRAMP_PROVIDER on the API deployment.\",\n ),\n amount: z\n .number()\n .optional()\n .describe(\"Preset top-up amount in dollars. Only meaningful with `hosted: true`.\"),\n },\n async ({ name, hosted, amount }) => {\n const stored = getAgent(name);\n if (!stored) return textResult(`No locally-stored agent named \\`${name}\\`.`, true);\n\n if (hosted) {\n const devKey = getApiKey();\n if (!devKey) {\n return textResult(\"No ArisPay developer key found. Run `npx payagent init` first.\", true);\n }\n const client = new DelegationClient(arispayUrl, devKey);\n try {\n const link = await client.getHostedTopup(stored.agentId, { amount });\n const lines = [\n `Top up \\`${name}\\` via ${link.provider}:`,\n \"\",\n ` ${link.fundingUrl}`,\n \"\",\n ` Wallet: ${link.walletAddress}`,\n ` Network: ${link.network}`,\n ` URL valid until: ${link.expiresAt}`,\n \"\",\n \"Share that URL with the end-user; the onramp deposits USDC straight to the agent's wallet.\",\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n if (err instanceof HostedTopupNotConfiguredError) {\n return textResult(\n [\n \"Hosted onramp is not configured on this ArisPay deployment.\",\n \"Falling back to the manual path:\",\n \"\",\n ` Send USDC on ${stored.network ?? \"base\"} to ${stored.walletAddress}`,\n \"\",\n \"Ask the deployment owner to set ARISPAY_ONRAMP_PROVIDER=coinbase (+ COINBASE_ONRAMP_APP_ID) to enable hosted top-ups.\",\n ].join(\"\\n\"),\n );\n }\n return textResult(\n `fund_agent (hosted) failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n }\n\n const lines = [\n `Fund \\`${name}\\` by sending USDC on ${stored.network ?? \"base\"} to:`,\n \"\",\n ` ${stored.walletAddress}`,\n \"\",\n \"Pass `hosted: true` to get a Coinbase onramp URL instead (requires ARISPAY_ONRAMP_PROVIDER).\",\n \"Call `get_balance` when the deposit lands.\",\n ];\n return textResult(lines.join(\"\\n\"));\n },\n);\n\n// --- get_balance -----------------------------------------------------------\n\nserver.tool(\n \"get_balance\",\n {\n name: z.string().describe(\"Name of a locally-stored agent.\"),\n },\n async ({ name }) => {\n const stored = getAgent(name);\n if (!stored) return textResult(`No locally-stored agent named \\`${name}\\`.`, true);\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const balance = await client.getBalance(stored.agentId);\n const human = formatUSDC(BigInt(balance.usdcBalance || \"0\"));\n const lines = [\n `${name}: ${human} USDC on ${balance.network}`,\n balance.fundedAt ? ` First funded at: ${balance.fundedAt}` : \" Not yet funded.\",\n ` Wallet: ${balance.walletAddress}`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `get_balance failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- create_enduser --------------------------------------------------------\n\nserver.tool(\n \"create_enduser\",\n {\n externalId: z.string().describe(\"Your own stable id for this customer (e.g. `tg:12345`).\"),\n email: z.string().optional().describe(\"Optional email for compliance / receipts.\"),\n findOrCreate: z\n .boolean()\n .optional()\n .describe(\"If true, return the existing user instead of erroring on externalId collision.\"),\n },\n async ({ externalId, email, findOrCreate }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const user = await client.createEndUser({ externalId, email, findOrCreate });\n const lines = [\n `✓ End-user \\`${externalId}\\` ready.`,\n ` ArisPay id: ${user.id}`,\n ` Has card: ${user.hasPaymentMethod ? \"yes\" : \"no\"}`,\n ` Has wallet: ${user.hasWallet ? \"yes\" : \"no\"}`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `create_enduser failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- attach_card_for_user -------------------------------------------------\n\nserver.tool(\n \"attach_card_for_user\",\n {\n userId: z.string().describe(\"The ArisPay-internal end-user id (not externalId).\"),\n agentName: z\n .string()\n .optional()\n .describe(\"Optional locally-stored agent name to scope the card-setup session to.\"),\n },\n async ({ userId, agentName }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const agentId = agentName ? getAgent(agentName)?.agentId : undefined;\n const session = await client.createCardSetupSession({ endUserId: userId, agentId });\n const lines = [\n `Card-entry URL for user \\`${userId}\\`:`,\n \"\",\n ` ${session.setupUrl}`,\n \"\",\n ` Expires at: ${session.expiresAt}`,\n \"\",\n \"Share this URL with the end-user. They enter the card on ArisPay's hosted page; we handle tokenization + 3DS.\",\n \"Call `get_user_status` afterwards to confirm the card is attached.\",\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `attach_card_for_user failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- set_user_limits -------------------------------------------------------\n\nserver.tool(\n \"set_user_limits\",\n {\n userId: z.string().describe(\"ArisPay-internal end-user id.\"),\n agentName: z.string().describe(\"Locally-stored agent name.\"),\n perTx: z\n .number()\n .int()\n .optional()\n .describe(\"Per-transaction cap in cents. Omit to inherit agent defaults.\"),\n daily: z.number().int().optional().describe(\"Daily cap in cents.\"),\n monthly: z.number().int().optional().describe(\"Monthly cap in cents.\"),\n allowedMcc: z.array(z.string()).optional().describe(\"Allowed Merchant Category Codes.\"),\n blockedMcc: z.array(z.string()).optional().describe(\"Blocked MCCs.\"),\n },\n async ({ userId, agentName, perTx, daily, monthly, allowedMcc, blockedMcc }) => {\n try {\n const stored = getAgent(agentName);\n if (!stored) {\n return textResult(`No locally-stored agent named \\`${agentName}\\`.`, true);\n }\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const limit = await client.setUserLimits(userId, {\n agentId: stored.agentId,\n maxPerTransaction: perTx ?? null,\n maxDaily: daily ?? null,\n maxMonthly: monthly ?? null,\n allowedMerchantCategories: allowedMcc,\n blockedMerchantCategories: blockedMcc,\n });\n return textResult(\n [\n `✓ Limits set for \\`${userId}\\` on agent \\`${agentName}\\`.`,\n ` per-tx ${limit.maxPerTransaction ?? \"inherit\"}¢, daily ${limit.maxDaily ?? \"inherit\"}¢, monthly ${limit.maxMonthly ?? \"inherit\"}¢`,\n ].join(\"\\n\"),\n );\n } catch (err) {\n return textResult(\n `set_user_limits failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- get_user_status -------------------------------------------------------\n\nserver.tool(\n \"get_user_status\",\n {\n userId: z.string().describe(\"ArisPay-internal end-user id.\"),\n },\n async ({ userId }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const user = await client.getEndUser(userId);\n const lines = [\n `${user.externalId} (${user.id})`,\n ` email: ${user.email ?? \"—\"}`,\n ` card: ${user.hasPaymentMethod ? `${user.cardBrand ?? \"card\"} …${user.cardLast4 ?? \"????\"}` : \"—\"}`,\n ` wallet: ${user.walletAddress ?? \"—\"}${user.walletChain ? ` on ${user.walletChain}` : \"\"}`,\n ];\n if (user.hasWallet) {\n try {\n const w = await client.getWalletStatus(userId);\n lines.push(` balance: ${w.usdcBalance} USDC base units`);\n lines.push(\n ` allowance: ${w.usdcAllowance} (${w.allowanceSufficient ? \"ok\" : \"insufficient\"})`,\n );\n lines.push(` ready: ${w.ready}`);\n } catch {\n // getWalletStatus fails if wallet not configured — ignore.\n }\n }\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `get_user_status failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- pay_merchant ----------------------------------------------------------\n\nserver.tool(\n \"pay_merchant\",\n {\n agentName: z.string().describe(\"Name of the locally-stored agent making the payment.\"),\n merchantUrl: z.string().describe(\"Canonical merchant URL (stored on the payment record).\"),\n amount: z.number().int().positive().describe(\"Amount in cents.\"),\n memo: z.string().describe(\"Human-readable memo attached to the payment.\"),\n userId: z\n .string()\n .optional()\n .describe(\"Optional ArisPay end-user id. Required when the agent is in platform mode.\"),\n rail: z\n .enum([\"card\", \"crypto\", \"balance\", \"mpp\"])\n .optional()\n .describe(\"Force a specific rail. Default: server-picked based on agent mode + userId.\"),\n merchantName: z.string().optional().describe(\"Optional human-readable merchant name.\"),\n merchantCategoryCode: z.string().optional().describe(\"MCC for spend-limit enforcement.\"),\n },\n async ({\n agentName,\n merchantUrl,\n amount,\n memo,\n userId,\n rail,\n merchantName,\n merchantCategoryCode,\n }) => {\n try {\n const stored = getAgent(agentName);\n if (!stored) {\n return textResult(`No locally-stored agent named \\`${agentName}\\`.`, true);\n }\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const payment = await client.createPayment(stored.agentId, {\n amount,\n memo,\n merchantUrl,\n merchantName,\n merchantCategoryCode,\n userId,\n rail,\n });\n const lines = [\n `Payment ${payment.id}: ${payment.status}`,\n ` rail: ${payment.rail}`,\n ` amount: ${payment.amount}¢ ${payment.currency}`,\n ];\n if (payment.merchantName) lines.push(` merchant: ${payment.merchantName}`);\n if (payment.txHash) lines.push(` tx hash: ${payment.txHash}`);\n if (payment.nextAction) {\n lines.push(` next action: ${payment.nextAction.type}`);\n if (payment.nextAction.challengeUrl) {\n lines.push(` 3DS challenge URL: ${payment.nextAction.challengeUrl}`);\n }\n }\n if (payment.error) {\n lines.push(` error: ${payment.error.code} — ${payment.error.message}`);\n }\n return textResult(lines.join(\"\\n\"), payment.status === \"failed\");\n } catch (err) {\n return textResult(\n `pay_merchant failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- bootstrap_agent -------------------------------------------------------\n//\n// Cold-start primitive: signs up a developer + provisions an agent in one\n// MCP tool call, no `payagent init` required first. Backed by\n// `POST /v1/bootstrap` on the API. Persists results to the same\n// ~/.payagent/config.json the CLI uses, so afterwards every other tool\n// (`pay_api`, `check_wallet`, `get_balance`, `fund_agent`) just works.\n\nserver.tool(\n \"bootstrap_agent\",\n {\n email: z.string().describe(\"Email for the new ArisPay developer account.\"),\n name: z.string().optional().describe(\"Human name. Falls back to the email local-part.\"),\n orgName: z\n .string()\n .optional()\n .describe('Workspace / org name. Falls back to \"<name>\\'s Team\".'),\n agentName: z\n .string()\n .optional()\n .describe('Local name for the provisioned agent. Default: \"default\".'),\n perTx: z.number().int().positive().optional().describe(\"Per-tx cap in cents. Default: 50.\"),\n daily: z.number().int().positive().optional().describe(\"Daily cap in cents. Default: 1000.\"),\n monthly: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Monthly cap in cents. Default: 10000.\"),\n allowedDomains: z\n .array(z.string())\n .optional()\n .describe(\"Domains the agent may pay. Empty = unrestricted.\"),\n fund: z\n .number()\n .positive()\n .optional()\n .describe(\"Optional preset USD amount; mints a Coinbase Onramp URL pre-set to this value.\"),\n },\n async ({ email, name, orgName, agentName, perTx, daily, monthly, allowedDomains, fund }) => {\n try {\n const result = await bootstrapAgent({\n email,\n name,\n orgName,\n agentName,\n limits: { perTx, daily, monthly },\n allowedDomains,\n fund,\n arispayUrl: process.env.ARISPAY_URL,\n clientId: \"payagent-mcp-bootstrap\",\n });\n const lines = [\n `✓ Account: ${result.email} (org \\`${result.orgName}\\`)`,\n `✓ Agent: ${result.agentName} (${result.agentId})`,\n ` Wallet: ${result.walletAddress} (${result.network})`,\n ` Limits: ${result.limits.perTx}¢ / tx, ${result.limits.daily}¢ / day, ${result.limits.monthly}¢ / month`,\n \"\",\n ];\n if (result.fundingUrl) {\n lines.push(\"Fund this wallet via Coinbase Onramp:\");\n lines.push(` ${result.fundingUrl}`);\n if (result.fundingExpiresAt) lines.push(` URL valid until: ${result.fundingExpiresAt}`);\n lines.push(` Or send USDC on ${result.network} directly to ${result.walletAddress}.`);\n } else {\n if (result.fundingUrlError) {\n lines.push(`Onramp not available (${result.fundingUrlError}).`);\n }\n lines.push(\n `Fund the wallet by sending USDC on ${result.network} to ${result.walletAddress}.`,\n );\n lines.push(\n `Or call \\`fund_agent\\` with name=\"${result.agentName}\", hosted=true to mint a Coinbase Onramp URL on demand.`,\n );\n }\n // BuyForMe phone-pairing handoff. Surface the URL prominently so\n // the user (or the AI host) can choose to open it directly or\n // pass it along to the human-on-the-phone.\n if (result.pairing) {\n lines.push(\"\");\n lines.push(\"📱 Open BuyForMe on your phone (signs you into the same account):\");\n lines.push(` ${result.pairing.url}`);\n lines.push(` Link expires: ${result.pairing.expiresAt}`);\n }\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n if (err instanceof BootstrapError) {\n return textResult(`bootstrap_agent failed (${err.code}): ${err.message}`, true);\n }\n return textResult(\n `bootstrap_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- list_agents -----------------------------------------------------------\n//\n// Server-authoritative. Hits `GET /v1/agents?withDelegation=1` and (when\n// `withBalance: true`) fans out per-agent balance checks. The local\n// `~/.payagent/config.json` is rehydrated as a side-effect so a subsequent\n// pay_api / fund_agent call sees the same wallet view. Falls back to the\n// local cache when no developer key is available — keeps the legacy\n// single-agent-via-ARISPAY_AGENT_KEY flow working without a dev key.\n\nserver.tool(\n \"list_agents\",\n {\n withBalance: z\n .boolean()\n .optional()\n .describe(\n \"When true, fetch on-chain USDC balance per agent (adds one round-trip per wallet).\",\n ),\n },\n async ({ withBalance }) => {\n // If the user has no developer key, we can't hit the server. Fall back\n // to the local cache so the tool stays useful for env-key-only setups.\n const devKey = getApiKey();\n if (!devKey) {\n const local = listAgents();\n if (!local.length) {\n return textResult(\n \"No developer key set and no agents cached locally. Run `bootstrap_agent` or set ARISPAY_API_KEY.\",\n );\n }\n const lines = local.map((a) =>\n [\n a.name,\n ` agent id: ${a.agentId}`,\n ` wallet: ${a.walletAddress}`,\n ` network: ${a.network ?? \"base\"}`,\n ` limits: ${a.limits.perTx}¢ / tx, ${a.limits.daily}¢ / day, ${a.limits.monthly}¢ / month`,\n ` created: ${a.createdAt}`,\n \" (local cache only — set ARISPAY_API_KEY to sync from the server)\",\n ].join(\"\\n\"),\n );\n return textResult(lines.join(\"\\n\\n\"));\n }\n\n try {\n const result = await syncAgents({ includeBalance: withBalance === true });\n if (!result.agents.length) {\n return textResult(\n \"No wallets found under this developer key. Create one with `create_agent` or `bootstrap_agent`.\",\n );\n }\n const lines = result.agents.map((a) => {\n const balanceLine =\n a.usdcBalance !== undefined\n ? ` balance: ${formatUSDC(BigInt(a.usdcBalance || \"0\"))} USDC`\n : null;\n const fundedLine = a.fundedAt ? ` funded: ${a.fundedAt}` : \" funded: not yet\";\n const domainsLine = a.allowedDomains.length\n ? ` domains: ${a.allowedDomains.join(\", \")}`\n : \" domains: (unrestricted)\";\n const suspendedLine = a.suspended ? \" status: SUSPENDED\" : null;\n return [\n a.name,\n ` agent id: ${a.agentId}`,\n ` wallet: ${a.walletAddress}`,\n ` network: ${a.network}`,\n ` limits: ${a.limits.maxPerTx}¢ / tx, ${a.limits.maxDaily}¢ / day, ${a.limits.maxMonthly}¢ / month`,\n domainsLine,\n fundedLine,\n ...(balanceLine ? [balanceLine] : []),\n ...(suspendedLine ? [suspendedLine] : []),\n ` created: ${a.createdAt}`,\n ].join(\"\\n\");\n });\n return textResult(\n `${result.agents.length} wallet${result.agents.length === 1 ? \"\" : \"s\"} under this account (synced from server):\\n\\n${lines.join(\"\\n\\n\")}`,\n );\n } catch (err) {\n return textResult(\n `list_agents failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- rename_agent ----------------------------------------------------------\n//\n// Renames the server-side Agent (PATCH /v1/agents/:id) AND the local\n// cache entry. The server enforces per-org name uniqueness — a 409 here\n// means another wallet under this account already uses that name.\n\nserver.tool(\n \"rename_agent\",\n {\n name: z.string().describe(\"Current local name of the agent to rename.\"),\n newName: z\n .string()\n .describe(\n \"New name. Letters, numbers, spaces, hyphens, underscores, dots. 1-64 chars. Must be unique per account.\",\n ),\n },\n async ({ name, newName }) => {\n if (name === newName) {\n return textResult(`Agent \\`${name}\\` already has that name — nothing to do.`);\n }\n const stored = getAgent(name);\n if (!stored) {\n return textResult(\n `No locally-cached agent named \\`${name}\\`. Run \\`list_agents\\` first to sync, or check the spelling.`,\n true,\n );\n }\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const result = await client.renameAgent(stored.agentId, newName);\n // Server accepted — mirror locally. `result.name` is the canonical\n // form (server may have trimmed it), so we use that, not the raw input.\n renameStoredAgent(name, result.name);\n return textResult(\n `✓ Renamed \\`${name}\\` → \\`${result.name}\\`. Wallet ${result.walletAddress ?? stored.walletAddress} is unchanged.`,\n );\n } catch (err) {\n return textResult(\n `rename_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// ── Start ─────────────────────────────────────────────\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"Fatal:\", err);\n process.exit(1);\n});\n","/**\n * Helpers for the `pay_api` MCP tool.\n *\n * Extracted into their own module so the heuristic that triggers\n * automatic Onramp-URL surfacing is unit-testable. The trigger has to\n * be conservative — false positives turn legitimate errors (allowed-\n * domain blocks, suspended agents) into misleading \"fund your wallet\"\n * suggestions.\n */\n\n/**\n * Does this error message look like the agent's USDC ran out?\n *\n * The signal we trust is `PaymentRejectedError(402, \"Server returned 402\n * after payment was signed and sent. Seller response: ...\")` from\n * `payFetchDelegated`, where the seller's body contains a funds- or\n * balance-shaped token. We do not pre-flight balance on every call —\n * that would add a round-trip to the warm path. Post-hoc detection\n * only, and only when both the 402 status AND a balance keyword\n * appear in the same message.\n */\nexport function looksLikeInsufficientFunds(message: string): boolean {\n if (!/402/.test(message)) return false;\n return /insufficient|insufficient_funds|insufficient_balance|exceeds_balance|invalid_transfer/i.test(\n message,\n );\n}\n"],"mappings":"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","names":["lines"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/pay-api-helpers.ts","../src/profile.ts"],"sourcesContent":["/**\n * payagent-mcp — MCP server for agent-side x402 payments + headless launch.\n *\n * Thirteen tools over stdio. Core (the 80% path):\n * - bootstrap_agent(...) — cold-start: sign up + provision an agent in one call\n * - pay_api(url, ...) — paid HTTP request via delegated signing\n * - check_wallet() — report current agent credentials + on-chain balance\n *\n * Wallet management:\n * - create_agent(...) — provision a new x402 agent (calls /v1/agents/x402)\n * - fund_agent({ name, rail }) — USDC deposit address, or EURØP browser handoff\n * - get_balance({ name }) — on-server USDC balance + fundedAt latch\n * - list_agents() — server-authoritative wallet enumeration\n * - rename_agent(...) — server-side rename + local cache mirror\n *\n * Platform (end-user) tools:\n * - create_enduser(...) — find-or-create an EndUser by externalId\n * - attach_card_for_user(...)— mint a hosted card-setup session URL\n * - set_user_limits(...) — per-(user, agent) spend caps + MCC rules\n * - get_user_status(...) — card / wallet / readiness report\n * - pay_merchant(...) — direct payment via POST /v1/payments\n *\n * Config store lives at ~/.payagent/config.json (shared with the `payagent`\n * CLI). Credentials created via `npx payagent init` + `payagent agent create`\n * are immediately available here; equally, agents created via\n * `create_agent` are immediately visible to the CLI.\n *\n * Two auth modes, picked at request time:\n * 1. Legacy single-agent: ARISPAY_AGENT_KEY set → pay_api + check_wallet use it directly.\n * 2. Multi-agent: no env var, credentials come from the shared config store.\n * Management tools (create / fund / get_balance / list) always use the\n * developer key from the config store (or ARISPAY_API_KEY env).\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n BootstrapError,\n type DelegatedPaymentInfo,\n DelegationClient,\n type StoredAgent,\n bootstrapAgent,\n formatUSDC,\n getAgent,\n getApiKey,\n getArispayUrl,\n getUSDCBalance,\n launchAgent,\n listAgents,\n payFetchDelegated,\n renameStoredAgent,\n syncAgents,\n} from \"payagent\";\nimport { z } from \"zod\";\nimport { looksLikeInsufficientFunds } from \"./pay-api-helpers.js\";\nimport { platformToolsEnabled } from \"./profile.js\";\n\n// ── Configuration ─────────────────────────────────────\n\nconst arispayUrl = getArispayUrl(process.env.ARISPAY_URL);\n/** Legacy single-agent key (kept for backwards compatibility). */\nconst legacyAgentKey = process.env.ARISPAY_AGENT_KEY;\nconst legacyWalletAddress = process.env.PAYAGENT_WALLET;\n\nfunction resolveAgent(name?: string): StoredAgent | undefined {\n if (name) return getAgent(name);\n const agents = listAgents();\n return agents[0];\n}\n\n/**\n * Look up the agent-scoped key to use for paid requests.\n * Priority: explicit agent name → legacy env var → first stored agent.\n */\nfunction resolveAgentKey(name?: string): { key: string; source: string } | undefined {\n if (name) {\n const stored = getAgent(name);\n if (stored) return { key: stored.apiKey, source: `agent \\`${name}\\`` };\n return undefined;\n }\n if (legacyAgentKey) return { key: legacyAgentKey, source: \"ARISPAY_AGENT_KEY\" };\n const first = listAgents()[0];\n if (first) return { key: first.apiKey, source: `agent \\`${first.name}\\`` };\n return undefined;\n}\n\nfunction requireDevKey(): string {\n const key = getApiKey();\n if (!key) {\n throw new Error(\n \"No ArisPay developer key found. Run `npx payagent init` or set ARISPAY_API_KEY.\",\n );\n }\n return key;\n}\n\nfunction textResult(text: string, isError = false) {\n return {\n content: [{ type: \"text\" as const, text }],\n ...(isError ? { isError } : {}),\n };\n}\n\n// ── MCP Server ────────────────────────────────────────\n\nconst server = new McpServer({\n name: \"payagent\",\n version: \"2.1.0\",\n});\n\n// --- pay_api ----------------------------------------------------------------\n\nserver.tool(\n \"pay_api\",\n \"Make an HTTP request to a paid API, transparently paying any x402 (HTTP 402) challenge with USDC under the agent's spend limits. THE tool for fetching paid resources — never bypass a 402 or hand-roll payment.\",\n {\n url: z.string().describe(\"The full URL of the API endpoint to call\"),\n method: z\n .enum([\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\"])\n .default(\"GET\")\n .describe(\"HTTP method\"),\n headers: z.record(z.string(), z.string()).optional().describe(\"Additional HTTP headers\"),\n body: z.string().optional().describe(\"Request body (for POST/PUT/PATCH)\"),\n agent: z\n .string()\n .optional()\n .describe(\n \"Optional: name of a locally-stored agent to pay with. Defaults to ARISPAY_AGENT_KEY or the first stored agent.\",\n ),\n },\n async ({ url, method, headers, body, agent }) => {\n const resolved = resolveAgentKey(agent);\n if (!resolved) {\n return textResult(\n [\n \"No agent available. Cold-start in one call:\",\n ' bootstrap_agent({ email: \"you@example.com\", name: \"<your-name>\" })',\n \"\",\n \"Or, if a developer key is already paired (`npx payagent init`):\",\n \" create_agent({ name, perTx, daily, monthly })\",\n \"\",\n \"Or set ARISPAY_AGENT_KEY for legacy single-agent mode.\",\n ].join(\"\\n\"),\n true,\n );\n }\n try {\n // Budget headroom rides the delegated-sign response — capture it so the\n // host learns its remaining budget without a second tool call.\n let paymentInfo: DelegatedPaymentInfo | undefined;\n const fetch402 = payFetchDelegated({\n arispayUrl,\n apiKey: resolved.key,\n onPayment: (info) => {\n paymentInfo = info;\n },\n });\n const response = await fetch402(url, { method, headers, body });\n const responseBody = await response.text();\n const statusLine = paymentInfo\n ? `HTTP ${response.status} (paid ${paymentInfo.amountCents}¢ via ${resolved.source} — budget left: ${paymentInfo.remainingDaily}¢ today, ${paymentInfo.remainingMonthly}¢ this month)`\n : `HTTP ${response.status} (paid via ${resolved.source})`;\n return textResult([statusLine, \"\", responseBody].join(\"\\n\"));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // Detect \"agent wallet has no USDC\" — point the host at fund_agent\n // so it can choose the USDC deposit address or the EURØP handoff.\n if (looksLikeInsufficientFunds(message)) {\n return textResult(\n [\n `Error: ${message}`,\n \"\",\n \"This looks like the agent wallet is out of USDC. Fund it and retry:\",\n \" Use the `fund_agent` tool (rail='usdc' for the wallet address,\",\n \" or rail='europ' to fund via SEPA/EURØP in the browser).\",\n ].join(\"\\n\"),\n true,\n );\n }\n return textResult(`Error: ${message}`, true);\n }\n },\n);\n\n// --- check_wallet ----------------------------------------------------------\n\nserver.tool(\n \"check_wallet\",\n 'Show the current agent\\'s credentials, wallet address, and on-chain USDC balance — the quick \"what state am I in\" probe.',\n {\n agent: z\n .string()\n .optional()\n .describe(\n \"Optional: name of a locally-stored agent. Defaults to legacy ARISPAY_WALLET mode.\",\n ),\n },\n async ({ agent }) => {\n const resolved = resolveAgent(agent);\n const walletAddress = resolved?.walletAddress ?? legacyWalletAddress;\n const keyTail =\n resolved?.apiKey.slice(-4) ?? (legacyAgentKey ? legacyAgentKey.slice(-4) : undefined);\n\n const lines = [`ArisPay URL: ${arispayUrl}`];\n if (resolved) lines.push(`Agent: ${resolved.name} (${resolved.agentId})`);\n if (keyTail) lines.push(`Agent key: ap_…${keyTail}`);\n\n if (walletAddress) {\n lines.push(`Wallet: ${walletAddress}`);\n try {\n const raw = await getUSDCBalance(walletAddress, (resolved?.network as \"base\") ?? \"base\");\n lines.push(`Balance: ${formatUSDC(raw)} USDC on ${resolved?.network ?? \"base\"}`);\n } catch (err) {\n lines.push(\n `Balance: unavailable (${err instanceof Error ? err.message : String(err)})`,\n );\n }\n } else {\n lines.push(\"\", \"No wallet known. Use `create_agent` or set PAYAGENT_WALLET for legacy mode.\");\n }\n\n lines.push(\"\", \"Manage limits + full history: https://arispay.app/dashboard\");\n return textResult(lines.join(\"\\n\"));\n },\n);\n\n// --- create_agent ----------------------------------------------------------\n\nserver.tool(\n \"create_agent\",\n \"Provision an additional x402 payment agent (wallet + spend limits) under the already-paired developer account.\",\n {\n name: z.string().describe(\"Local identifier for this agent. Used by later tools.\"),\n perTx: z.number().int().positive().describe(\"Per-transaction spend cap in cents.\"),\n daily: z.number().int().positive().describe(\"Daily spend cap in cents.\"),\n monthly: z.number().int().positive().describe(\"Monthly spend cap in cents.\"),\n allowedDomains: z\n .array(z.string())\n .optional()\n .describe(\"If provided, restrict this agent to paying only these domains.\"),\n network: z\n .enum([\"base\", \"base-sepolia\", \"ethereum\", \"polygon\"])\n .default(\"base\")\n .describe(\"EVM network the agent pays on.\"),\n agentType: z.string().optional().describe('Optional metadata label (e.g. \"hermes\").'),\n },\n async ({ name, perTx, daily, monthly, allowedDomains, network, agentType }) => {\n try {\n requireDevKey(); // fail fast with a helpful message if not signed in\n const agent = await launchAgent({\n name,\n limits: { perTx, daily, monthly },\n allowedDomains,\n network,\n agentType,\n });\n const lines = [\n `✓ Agent \\`${name}\\` created.`,\n ` Agent ID: ${agent.agentId}`,\n ` Wallet: ${agent.walletAddress}`,\n ` Network: ${agent.network}`,\n ` Limits: ${perTx}¢ / tx, ${daily}¢ / day, ${monthly}¢ / month`,\n \"\",\n ` Fund the wallet with USDC on ${agent.network}, then call \\`get_balance\\` with name=\"${name}\".`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `create_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- fund_agent ------------------------------------------------------------\n\n/** Browser handoff host for EURØP / Schuman KYC. */\nconst buyformeUrl =\n process.env.BUYFORME_URL?.replace(/\\/$/, \"\") ?? \"https://buyforme.arispay.app\";\n\nserver.tool(\n \"fund_agent\",\n \"Get funding instructions for an agent's wallet. Use rail='usdc' for the direct USDC deposit address on Base, or rail='europ' for a browser handoff to complete Schuman identity verification and receive a SEPA vIBAN that credits EURØP.\",\n {\n name: z.string().describe(\"Name of a locally-stored agent.\"),\n rail: z\n .enum([\"usdc\", \"europ\"])\n .default(\"usdc\")\n .describe(\n \"Funding rail: 'usdc' sends stablecoin directly to the agent wallet; 'europ' opens the BuyForMe EURØP onboarding flow in a browser to verify identity and get a vIBAN.\",\n ),\n },\n async ({ name, rail }) => {\n const stored = getAgent(name);\n if (!stored) return textResult(`No locally-stored agent named \\`${name}\\`.`, true);\n\n if (rail === \"europ\") {\n const handoffUrl = `${buyformeUrl}/onboarding/fund-europ?agentId=${encodeURIComponent(\n stored.agentId,\n )}`;\n const lines = [\n `Fund \\`${name}\\` with EURØP via Schuman:`,\n \"\",\n ` ${handoffUrl}`,\n \"\",\n \"Open that link in a browser to:\",\n \" 1. Verify your identity with Schuman Financial (one-time KYC).\",\n \" 2. Receive a dedicated SEPA vIBAN.\",\n \" 3. Send EUR by bank transfer; Schuman mints EURØP to your wallet once it clears.\",\n \"\",\n \"After the deposit clears, call `get_balance` to confirm the agent's USDC balance.\",\n ];\n return textResult(lines.join(\"\\n\"));\n }\n\n const lines = [\n `Fund \\`${name}\\` by sending USDC on ${stored.network ?? \"base\"} to:`,\n \"\",\n ` ${stored.walletAddress}`,\n \"\",\n \"Only send USDC on the network shown above. Other tokens or networks may be lost.\",\n \"Call `get_balance` when the deposit lands.\",\n ];\n return textResult(lines.join(\"\\n\"));\n },\n);\n\n// --- get_balance -----------------------------------------------------------\n\nserver.tool(\n \"get_balance\",\n \"Server-side USDC balance + funding status for one named agent.\",\n {\n name: z.string().describe(\"Name of a locally-stored agent.\"),\n },\n async ({ name }) => {\n const stored = getAgent(name);\n if (!stored) return textResult(`No locally-stored agent named \\`${name}\\`.`, true);\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const balance = await client.getBalance(stored.agentId);\n const human = formatUSDC(BigInt(balance.usdcBalance || \"0\"));\n const lines = [\n `${name}: ${human} USDC on ${balance.network}`,\n balance.fundedAt ? ` First funded at: ${balance.fundedAt}` : \" Not yet funded.\",\n ` Wallet: ${balance.walletAddress}`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `get_balance failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- Platform (end-user) tools ----------------------------------------------\n//\n// Skipped under PAYAGENT_MCP_PROFILE=core so pay-URL-only hosts load 8 tool\n// schemas instead of 13 (see src/profile.ts).\nif (platformToolsEnabled()) {\n // --- create_enduser --------------------------------------------------------\n\n server.tool(\n \"create_enduser\",\n \"Platform mode: register an end-customer (EndUser) under your account, keyed by your own externalId.\",\n {\n externalId: z.string().describe(\"Your own stable id for this customer (e.g. `tg:12345`).\"),\n email: z.string().optional().describe(\"Optional email for compliance / receipts.\"),\n findOrCreate: z\n .boolean()\n .optional()\n .describe(\"If true, return the existing user instead of erroring on externalId collision.\"),\n },\n async ({ externalId, email, findOrCreate }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const user = await client.createEndUser({ externalId, email, findOrCreate });\n const lines = [\n `✓ End-user \\`${externalId}\\` ready.`,\n ` ArisPay id: ${user.id}`,\n ` Has card: ${user.hasPaymentMethod ? \"yes\" : \"no\"}`,\n ` Has wallet: ${user.hasWallet ? \"yes\" : \"no\"}`,\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `create_enduser failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n );\n\n // --- attach_card_for_user -------------------------------------------------\n\n server.tool(\n \"attach_card_for_user\",\n \"Platform mode: mint a hosted card-entry URL for an end-user (ArisPay handles tokenization + 3DS).\",\n {\n userId: z.string().describe(\"The ArisPay-internal end-user id (not externalId).\"),\n agentName: z\n .string()\n .optional()\n .describe(\"Optional locally-stored agent name to scope the card-setup session to.\"),\n },\n async ({ userId, agentName }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const agentId = agentName ? getAgent(agentName)?.agentId : undefined;\n const session = await client.createCardSetupSession({ endUserId: userId, agentId });\n const lines = [\n `Card-entry URL for user \\`${userId}\\`:`,\n \"\",\n ` ${session.setupUrl}`,\n \"\",\n ` Expires at: ${session.expiresAt}`,\n \"\",\n \"Share this URL with the end-user. They enter the card on ArisPay's hosted page; we handle tokenization + 3DS.\",\n \"Call `get_user_status` afterwards to confirm the card is attached.\",\n ];\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `attach_card_for_user failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n );\n\n // --- set_user_limits -------------------------------------------------------\n\n server.tool(\n \"set_user_limits\",\n \"Platform mode: set per-(user, agent) spend caps in integer cents plus MCC allow/block rules.\",\n {\n userId: z.string().describe(\"ArisPay-internal end-user id.\"),\n agentName: z.string().describe(\"Locally-stored agent name.\"),\n perTx: z\n .number()\n .int()\n .optional()\n .describe(\"Per-transaction cap in cents. Omit to inherit agent defaults.\"),\n daily: z.number().int().optional().describe(\"Daily cap in cents.\"),\n monthly: z.number().int().optional().describe(\"Monthly cap in cents.\"),\n allowedMcc: z.array(z.string()).optional().describe(\"Allowed Merchant Category Codes.\"),\n blockedMcc: z.array(z.string()).optional().describe(\"Blocked MCCs.\"),\n },\n async ({ userId, agentName, perTx, daily, monthly, allowedMcc, blockedMcc }) => {\n try {\n const stored = getAgent(agentName);\n if (!stored) {\n return textResult(`No locally-stored agent named \\`${agentName}\\`.`, true);\n }\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const limit = await client.setUserLimits(userId, {\n agentId: stored.agentId,\n maxPerTransaction: perTx ?? null,\n maxDaily: daily ?? null,\n maxMonthly: monthly ?? null,\n allowedMerchantCategories: allowedMcc,\n blockedMerchantCategories: blockedMcc,\n });\n return textResult(\n [\n `✓ Limits set for \\`${userId}\\` on agent \\`${agentName}\\`.`,\n ` per-tx ${limit.maxPerTransaction ?? \"inherit\"}¢, daily ${limit.maxDaily ?? \"inherit\"}¢, monthly ${limit.maxMonthly ?? \"inherit\"}¢`,\n ].join(\"\\n\"),\n );\n } catch (err) {\n return textResult(\n `set_user_limits failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n );\n\n // --- get_user_status -------------------------------------------------------\n\n server.tool(\n \"get_user_status\",\n \"Platform mode: report an end-user's card, wallet, and payment readiness.\",\n {\n userId: z.string().describe(\"ArisPay-internal end-user id.\"),\n },\n async ({ userId }) => {\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const user = await client.getEndUser(userId);\n const lines = [\n `${user.externalId} (${user.id})`,\n ` email: ${user.email ?? \"—\"}`,\n ` card: ${user.hasPaymentMethod ? `${user.cardBrand ?? \"card\"} …${user.cardLast4 ?? \"????\"}` : \"—\"}`,\n ` wallet: ${user.walletAddress ?? \"—\"}${user.walletChain ? ` on ${user.walletChain}` : \"\"}`,\n ];\n if (user.hasWallet) {\n try {\n const w = await client.getWalletStatus(userId);\n lines.push(` balance: ${w.usdcBalance} USDC base units`);\n lines.push(\n ` allowance: ${w.usdcAllowance} (${w.allowanceSufficient ? \"ok\" : \"insufficient\"})`,\n );\n lines.push(` ready: ${w.ready}`);\n } catch {\n // getWalletStatus fails if wallet not configured — ignore.\n }\n }\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n return textResult(\n `get_user_status failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n );\n\n // --- pay_merchant ----------------------------------------------------------\n\n server.tool(\n \"pay_merchant\",\n \"Direct payment to a known merchant via ArisPay rails (card / crypto / balance / MPP) when you already know the amount. For x402-protected HTTP resources use `pay_api` instead.\",\n {\n agentName: z.string().describe(\"Name of the locally-stored agent making the payment.\"),\n merchantUrl: z.string().describe(\"Canonical merchant URL (stored on the payment record).\"),\n amount: z.number().int().positive().describe(\"Amount in cents.\"),\n memo: z.string().describe(\"Human-readable memo attached to the payment.\"),\n userId: z\n .string()\n .optional()\n .describe(\"Optional ArisPay end-user id. Required when the agent is in platform mode.\"),\n rail: z\n .enum([\"card\", \"crypto\", \"balance\", \"mpp\"])\n .optional()\n .describe(\"Force a specific rail. Default: server-picked based on agent mode + userId.\"),\n merchantName: z.string().optional().describe(\"Optional human-readable merchant name.\"),\n merchantCategoryCode: z.string().optional().describe(\"MCC for spend-limit enforcement.\"),\n },\n async ({\n agentName,\n merchantUrl,\n amount,\n memo,\n userId,\n rail,\n merchantName,\n merchantCategoryCode,\n }) => {\n try {\n const stored = getAgent(agentName);\n if (!stored) {\n return textResult(`No locally-stored agent named \\`${agentName}\\`.`, true);\n }\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const payment = await client.createPayment(stored.agentId, {\n amount,\n memo,\n merchantUrl,\n merchantName,\n merchantCategoryCode,\n userId,\n rail,\n });\n const lines = [\n `Payment ${payment.id}: ${payment.status}`,\n ` rail: ${payment.rail}`,\n ` amount: ${payment.amount}¢ ${payment.currency}`,\n ];\n if (payment.merchantName) lines.push(` merchant: ${payment.merchantName}`);\n if (payment.txHash) lines.push(` tx hash: ${payment.txHash}`);\n if (payment.spend) {\n const fmtCap = (v: number | null) => (v == null ? \"no cap\" : `${v}¢`);\n lines.push(\n ` budget: ${fmtCap(payment.spend.remainingDaily)} left today, ${fmtCap(payment.spend.remainingMonthly)} this month`,\n );\n }\n if (payment.nextAction) {\n lines.push(` next action: ${payment.nextAction.type}`);\n if (payment.nextAction.challengeUrl) {\n lines.push(` 3DS challenge URL: ${payment.nextAction.challengeUrl}`);\n }\n }\n if (payment.error) {\n lines.push(` error: ${payment.error.code} — ${payment.error.message}`);\n }\n return textResult(lines.join(\"\\n\"), payment.status === \"failed\");\n } catch (err) {\n return textResult(\n `pay_merchant failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n );\n}\n\n// --- bootstrap_agent -------------------------------------------------------\n//\n// Cold-start primitive: signs up a developer + provisions an agent in one\n// MCP tool call, no `payagent init` required first. Backed by\n// `POST /v1/bootstrap` on the API. Persists results to the same\n// ~/.payagent/config.json the CLI uses, so afterwards every other tool\n// (`pay_api`, `check_wallet`, `get_balance`, `fund_agent`) just works.\n\nserver.tool(\n \"bootstrap_agent\",\n \"Cold-start in one call: create (or recover) an ArisPay account plus a payment agent from just an email. Run this first on a fresh machine; safe to re-run — it recovers the existing agent and wallet set instead of creating duplicates.\",\n {\n email: z.string().describe(\"Email for the new ArisPay developer account.\"),\n name: z.string().optional().describe(\"Human name. Falls back to the email local-part.\"),\n orgName: z\n .string()\n .optional()\n .describe('Workspace / org name. Falls back to \"<name>\\'s Team\".'),\n agentName: z\n .string()\n .optional()\n .describe('Local name for the provisioned agent. Default: \"default\".'),\n perTx: z.number().int().positive().optional().describe(\"Per-tx cap in cents. Default: 50.\"),\n daily: z.number().int().positive().optional().describe(\"Daily cap in cents. Default: 1000.\"),\n monthly: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Monthly cap in cents. Default: 10000.\"),\n allowedDomains: z\n .array(z.string())\n .optional()\n .describe(\"Domains the agent may pay. Empty = unrestricted.\"),\n },\n async ({ email, name, orgName, agentName, perTx, daily, monthly, allowedDomains }) => {\n try {\n const result = await bootstrapAgent({\n email,\n name,\n orgName,\n agentName,\n limits: { perTx, daily, monthly },\n allowedDomains,\n arispayUrl: process.env.ARISPAY_URL,\n clientId: \"payagent-mcp-bootstrap\",\n });\n const lines = [\n `✓ Account: ${result.email} (org \\`${result.orgName}\\`)`,\n `✓ Agent: ${result.agentName} (${result.agentId})`,\n ` Wallet: ${result.walletAddress} (${result.network})`,\n ` Limits: ${result.limits.perTx}¢ / tx, ${result.limits.daily}¢ / day, ${result.limits.monthly}¢ / month`,\n \"\",\n `Fund the wallet by sending USDC on ${result.network} to ${result.walletAddress}.`,\n `Or call \\`fund_agent\\` with name=\"${result.agentName}\" and rail=\"usdc\" or rail=\"europ\".`,\n ];\n // BuyForMe phone-pairing handoff. Surface the URL prominently so\n // the user (or the AI host) can choose to open it directly or\n // pass it along to the human-on-the-phone.\n if (result.pairing) {\n lines.push(\"\");\n lines.push(\"📱 Open BuyForMe on your phone (signs you into the same account):\");\n lines.push(` ${result.pairing.url}`);\n lines.push(` Link expires: ${result.pairing.expiresAt}`);\n }\n return textResult(lines.join(\"\\n\"));\n } catch (err) {\n if (err instanceof BootstrapError) {\n return textResult(`bootstrap_agent failed (${err.code}): ${err.message}`, true);\n }\n return textResult(\n `bootstrap_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- list_agents -----------------------------------------------------------\n//\n// Server-authoritative. Hits `GET /v1/agents?withDelegation=1` and (when\n// `withBalance: true`) fans out per-agent balance checks. The local\n// `~/.payagent/config.json` is rehydrated as a side-effect so a subsequent\n// pay_api / fund_agent call sees the same wallet view. Falls back to the\n// local cache when no developer key is available — keeps the legacy\n// single-agent-via-ARISPAY_AGENT_KEY flow working without a dev key.\n\nserver.tool(\n \"list_agents\",\n \"List all wallets under this account (server-authoritative; rehydrates the local cache).\",\n {\n withBalance: z\n .boolean()\n .optional()\n .describe(\n \"When true, fetch on-chain USDC balance per agent (adds one round-trip per wallet).\",\n ),\n },\n async ({ withBalance }) => {\n // If the user has no developer key, we can't hit the server. Fall back\n // to the local cache so the tool stays useful for env-key-only setups.\n const devKey = getApiKey();\n if (!devKey) {\n const local = listAgents();\n if (!local.length) {\n return textResult(\n \"No developer key set and no agents cached locally. Run `bootstrap_agent` or set ARISPAY_API_KEY.\",\n );\n }\n const lines = local.map((a) =>\n [\n a.name,\n ` agent id: ${a.agentId}`,\n ` wallet: ${a.walletAddress}`,\n ` network: ${a.network ?? \"base\"}`,\n ` limits: ${a.limits.perTx}¢ / tx, ${a.limits.daily}¢ / day, ${a.limits.monthly}¢ / month`,\n ` created: ${a.createdAt}`,\n \" (local cache only — set ARISPAY_API_KEY to sync from the server)\",\n ].join(\"\\n\"),\n );\n return textResult(lines.join(\"\\n\\n\"));\n }\n\n try {\n const result = await syncAgents({ includeBalance: withBalance === true });\n if (!result.agents.length) {\n return textResult(\n \"No wallets found under this developer key. Create one with `create_agent` or `bootstrap_agent`.\",\n );\n }\n const lines = result.agents.map((a) => {\n const balanceLine =\n a.usdcBalance !== undefined\n ? ` balance: ${formatUSDC(BigInt(a.usdcBalance || \"0\"))} USDC`\n : null;\n const fundedLine = a.fundedAt ? ` funded: ${a.fundedAt}` : \" funded: not yet\";\n const domainsLine = a.allowedDomains.length\n ? ` domains: ${a.allowedDomains.join(\", \")}`\n : \" domains: (unrestricted)\";\n const suspendedLine = a.suspended ? \" status: SUSPENDED\" : null;\n return [\n a.name,\n ` agent id: ${a.agentId}`,\n ` wallet: ${a.walletAddress}`,\n ` network: ${a.network}`,\n ` limits: ${a.limits.maxPerTx}¢ / tx, ${a.limits.maxDaily}¢ / day, ${a.limits.maxMonthly}¢ / month`,\n domainsLine,\n fundedLine,\n ...(balanceLine ? [balanceLine] : []),\n ...(suspendedLine ? [suspendedLine] : []),\n ` created: ${a.createdAt}`,\n ].join(\"\\n\");\n });\n return textResult(\n `${result.agents.length} wallet${result.agents.length === 1 ? \"\" : \"s\"} under this account (synced from server):\\n\\n${lines.join(\"\\n\\n\")}`,\n );\n } catch (err) {\n return textResult(\n `list_agents failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// --- rename_agent ----------------------------------------------------------\n//\n// Renames the server-side Agent (PATCH /v1/agents/:id) AND the local\n// cache entry. The server enforces per-org name uniqueness — a 409 here\n// means another wallet under this account already uses that name.\n\nserver.tool(\n \"rename_agent\",\n \"Rename an agent on the server and in the local cache (names are unique per account).\",\n {\n name: z.string().describe(\"Current local name of the agent to rename.\"),\n newName: z\n .string()\n .describe(\n \"New name. Letters, numbers, spaces, hyphens, underscores, dots. 1-64 chars. Must be unique per account.\",\n ),\n },\n async ({ name, newName }) => {\n if (name === newName) {\n return textResult(`Agent \\`${name}\\` already has that name — nothing to do.`);\n }\n const stored = getAgent(name);\n if (!stored) {\n return textResult(\n `No locally-cached agent named \\`${name}\\`. Run \\`list_agents\\` first to sync, or check the spelling.`,\n true,\n );\n }\n try {\n const devKey = requireDevKey();\n const client = new DelegationClient(arispayUrl, devKey);\n const result = await client.renameAgent(stored.agentId, newName);\n // Server accepted — mirror locally. `result.name` is the canonical\n // form (server may have trimmed it), so we use that, not the raw input.\n renameStoredAgent(name, result.name);\n return textResult(\n `✓ Renamed \\`${name}\\` → \\`${result.name}\\`. Wallet ${result.walletAddress ?? stored.walletAddress} is unchanged.`,\n );\n } catch (err) {\n return textResult(\n `rename_agent failed: ${err instanceof Error ? err.message : String(err)}`,\n true,\n );\n }\n },\n);\n\n// ── Start ─────────────────────────────────────────────\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"Fatal:\", err);\n process.exit(1);\n});\n","/**\n * Helpers for the `pay_api` MCP tool.\n *\n * Extracted into their own module so the heuristic that triggers\n * automatic Onramp-URL surfacing is unit-testable. The trigger has to\n * be conservative — false positives turn legitimate errors (allowed-\n * domain blocks, suspended agents) into misleading \"fund your wallet\"\n * suggestions.\n */\n\n/**\n * Does this error message look like the agent's USDC ran out?\n *\n * The signal we trust is `PaymentRejectedError(402, \"Server returned 402\n * after payment was signed and sent. Seller response: ...\")` from\n * `payFetchDelegated`, where the seller's body contains a funds- or\n * balance-shaped token. We do not pre-flight balance on every call —\n * that would add a round-trip to the warm path. Post-hoc detection\n * only, and only when both the 402 status AND a balance keyword\n * appear in the same message.\n */\nexport function looksLikeInsufficientFunds(message: string): boolean {\n if (!/402/.test(message)) return false;\n return /insufficient|insufficient_funds|insufficient_balance|exceeds_balance|invalid_transfer/i.test(\n message,\n );\n}\n","/**\n * Tool-profile selection (docs/agent-discoverability.md, open question 2).\n *\n * Every registered tool's schema is resident in the MCP host's context on\n * every task. The common persona — \"an agent that pays URLs\" — never needs\n * the five platform (end-user) tools, so `PAYAGENT_MCP_PROFILE=core` skips\n * registering them and the host loads 8 schemas instead of 13:\n *\n * core profile: bootstrap_agent, pay_api, check_wallet, create_agent,\n * fund_agent, get_balance, list_agents, rename_agent\n * all (default): the above + create_enduser, attach_card_for_user,\n * set_user_limits, get_user_status, pay_merchant\n *\n * Default stays \"all\" for backward compatibility with existing host configs.\n */\nexport function platformToolsEnabled(raw = process.env.PAYAGENT_MCP_PROFILE): boolean {\n return (raw ?? \"all\").trim().toLowerCase() !== \"core\";\n}\n"],"mappings":";;;AAiCA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS;;;AC/BX,SAAS,2BAA2B,SAA0B;AACnE,MAAI,CAAC,MAAM,KAAK,OAAO,EAAG,QAAO;AACjC,SAAO,yFAAyF;AAAA,IAC9F;AAAA,EACF;AACF;;;ACXO,SAAS,qBAAqB,MAAM,QAAQ,IAAI,sBAA+B;AACpF,UAAQ,OAAO,OAAO,KAAK,EAAE,YAAY,MAAM;AACjD;;;AFyCA,IAAM,aAAa,cAAc,QAAQ,IAAI,WAAW;AAExD,IAAM,iBAAiB,QAAQ,IAAI;AACnC,IAAM,sBAAsB,QAAQ,IAAI;AAExC,SAAS,aAAa,MAAwC;AAC5D,MAAI,KAAM,QAAO,SAAS,IAAI;AAC9B,QAAM,SAAS,WAAW;AAC1B,SAAO,OAAO,CAAC;AACjB;AAMA,SAAS,gBAAgB,MAA4D;AACnF,MAAI,MAAM;AACR,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,OAAQ,QAAO,EAAE,KAAK,OAAO,QAAQ,QAAQ,WAAW,IAAI,KAAK;AACrE,WAAO;AAAA,EACT;AACA,MAAI,eAAgB,QAAO,EAAE,KAAK,gBAAgB,QAAQ,oBAAoB;AAC9E,QAAM,QAAQ,WAAW,EAAE,CAAC;AAC5B,MAAI,MAAO,QAAO,EAAE,KAAK,MAAM,QAAQ,QAAQ,WAAW,MAAM,IAAI,KAAK;AACzE,SAAO;AACT;AAEA,SAAS,gBAAwB;AAC/B,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,MAAc,UAAU,OAAO;AACjD,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,IACzC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;AAIA,IAAM,SAAS,IAAI,UAAU;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS;AACX,CAAC;AAID,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,KAAK,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,IACnE,QAAQ,EACL,KAAK,CAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,CAAC,EAC9C,QAAQ,KAAK,EACb,SAAS,aAAa;AAAA,IACzB,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACvF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mCAAmC;AAAA,IACxE,OAAO,EACJ,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,KAAK,QAAQ,SAAS,MAAM,MAAM,MAAM;AAC/C,UAAM,WAAW,gBAAgB,KAAK;AACtC,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,QACX;AAAA,MACF;AAAA,IACF;AACA,QAAI;AAGF,UAAI;AACJ,YAAM,WAAW,kBAAkB;AAAA,QACjC;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB,WAAW,CAAC,SAAS;AACnB,wBAAc;AAAA,QAChB;AAAA,MACF,CAAC;AACD,YAAM,WAAW,MAAM,SAAS,KAAK,EAAE,QAAQ,SAAS,KAAK,CAAC;AAC9D,YAAM,eAAe,MAAM,SAAS,KAAK;AACzC,YAAM,aAAa,cACf,QAAQ,SAAS,MAAM,UAAU,YAAY,WAAW,YAAS,SAAS,MAAM,wBAAmB,YAAY,cAAc,eAAY,YAAY,gBAAgB,qBACrK,QAAQ,SAAS,MAAM,cAAc,SAAS,MAAM;AACxD,aAAO,WAAW,CAAC,YAAY,IAAI,YAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IAC7D,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAG/D,UAAI,2BAA2B,OAAO,GAAG;AACvC,eAAO;AAAA,UACL;AAAA,YACE,UAAU,OAAO;AAAA,YACjB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE,KAAK,IAAI;AAAA,UACX;AAAA,QACF;AAAA,MACF;AACA,aAAO,WAAW,UAAU,OAAO,IAAI,IAAI;AAAA,IAC7C;AAAA,EACF;AACF;AAIA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,OAAO,EACJ,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,MAAM,MAAM;AACnB,UAAM,WAAW,aAAa,KAAK;AACnC,UAAM,gBAAgB,UAAU,iBAAiB;AACjD,UAAM,UACJ,UAAU,OAAO,MAAM,EAAE,MAAM,iBAAiB,eAAe,MAAM,EAAE,IAAI;AAE7E,UAAM,QAAQ,CAAC,gBAAgB,UAAU,EAAE;AAC3C,QAAI,SAAU,OAAM,KAAK,gBAAgB,SAAS,IAAI,KAAK,SAAS,OAAO,GAAG;AAC9E,QAAI,QAAS,OAAM,KAAK,yBAAoB,OAAO,EAAE;AAErD,QAAI,eAAe;AACjB,YAAM,KAAK,gBAAgB,aAAa,EAAE;AAC1C,UAAI;AACF,cAAM,MAAM,MAAM,eAAe,eAAgB,UAAU,WAAsB,MAAM;AACvF,cAAM,KAAK,gBAAgB,WAAW,GAAG,CAAC,YAAY,UAAU,WAAW,MAAM,EAAE;AAAA,MACrF,SAAS,KAAK;AACZ,cAAM;AAAA,UACJ,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAC/E;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,KAAK,IAAI,6EAA6E;AAAA,IAC9F;AAEA,UAAM,KAAK,IAAI,6DAA6D;AAC5E,WAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,EACpC;AACF;AAIA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,MAAM,EAAE,OAAO,EAAE,SAAS,uDAAuD;AAAA,IACjF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,qCAAqC;AAAA,IACjF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,2BAA2B;AAAA,IACvE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,6BAA6B;AAAA,IAC3E,gBAAgB,EACb,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,gEAAgE;AAAA,IAC5E,SAAS,EACN,KAAK,CAAC,QAAQ,gBAAgB,YAAY,SAAS,CAAC,EACpD,QAAQ,MAAM,EACd,SAAS,gCAAgC;AAAA,IAC5C,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,EACtF;AAAA,EACA,OAAO,EAAE,MAAM,OAAO,OAAO,SAAS,gBAAgB,SAAS,UAAU,MAAM;AAC7E,QAAI;AACF,oBAAc;AACd,YAAM,QAAQ,MAAM,YAAY;AAAA,QAC9B;AAAA,QACA,QAAQ,EAAE,OAAO,OAAO,QAAQ;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,QAAQ;AAAA,QACZ,kBAAa,IAAI;AAAA,QACjB,gBAAgB,MAAM,OAAO;AAAA,QAC7B,gBAAgB,MAAM,aAAa;AAAA,QACnC,gBAAgB,MAAM,OAAO;AAAA,QAC7B,gBAAgB,KAAK,cAAW,KAAK,eAAY,OAAO;AAAA,QACxD;AAAA,QACA,kCAAkC,MAAM,OAAO,0CAA0C,IAAI;AAAA,MAC/F;AACA,aAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,IACpC,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACxE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKA,IAAM,cACJ,QAAQ,IAAI,cAAc,QAAQ,OAAO,EAAE,KAAK;AAElD,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,MAAM,EAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,IAC3D,MAAM,EACH,KAAK,CAAC,QAAQ,OAAO,CAAC,EACtB,QAAQ,MAAM,EACd;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,MAAM,KAAK,MAAM;AACxB,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,CAAC,OAAQ,QAAO,WAAW,mCAAmC,IAAI,OAAO,IAAI;AAEjF,QAAI,SAAS,SAAS;AACpB,YAAM,aAAa,GAAG,WAAW,kCAAkC;AAAA,QACjE,OAAO;AAAA,MACT,CAAC;AACD,YAAMA,SAAQ;AAAA,QACZ,UAAU,IAAI;AAAA,QACd;AAAA,QACA,KAAK,UAAU;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,WAAWA,OAAM,KAAK,IAAI,CAAC;AAAA,IACpC;AAEA,UAAM,QAAQ;AAAA,MACZ,UAAU,IAAI,yBAAyB,OAAO,WAAW,MAAM;AAAA,MAC/D;AAAA,MACA,KAAK,OAAO,aAAa;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,EACpC;AACF;AAIA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,MAAM,EAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,EAC7D;AAAA,EACA,OAAO,EAAE,KAAK,MAAM;AAClB,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,CAAC,OAAQ,QAAO,WAAW,mCAAmC,IAAI,OAAO,IAAI;AACjF,QAAI;AACF,YAAM,SAAS,cAAc;AAC7B,YAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,YAAM,UAAU,MAAM,OAAO,WAAW,OAAO,OAAO;AACtD,YAAM,QAAQ,WAAW,OAAO,QAAQ,eAAe,GAAG,CAAC;AAC3D,YAAM,QAAQ;AAAA,QACZ,GAAG,IAAI,KAAK,KAAK,YAAY,QAAQ,OAAO;AAAA,QAC5C,QAAQ,WAAW,sBAAsB,QAAQ,QAAQ,KAAK;AAAA,QAC9D,aAAa,QAAQ,aAAa;AAAA,MACpC;AACA,aAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,IACpC,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMA,IAAI,qBAAqB,GAAG;AAG1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,YAAY,EAAE,OAAO,EAAE,SAAS,yDAAyD;AAAA,MACzF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2CAA2C;AAAA,MACjF,cAAc,EACX,QAAQ,EACR,SAAS,EACT,SAAS,gFAAgF;AAAA,IAC9F;AAAA,IACA,OAAO,EAAE,YAAY,OAAO,aAAa,MAAM;AAC7C,UAAI;AACF,cAAM,SAAS,cAAc;AAC7B,cAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,cAAM,OAAO,MAAM,OAAO,cAAc,EAAE,YAAY,OAAO,aAAa,CAAC;AAC3E,cAAM,QAAQ;AAAA,UACZ,qBAAgB,UAAU;AAAA,UAC1B,mBAAmB,KAAK,EAAE;AAAA,UAC1B,mBAAmB,KAAK,mBAAmB,QAAQ,IAAI;AAAA,UACvD,mBAAmB,KAAK,YAAY,QAAQ,IAAI;AAAA,QAClD;AACA,eAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,MACpC,SAAS,KAAK;AACZ,eAAO;AAAA,UACL,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC1E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,OAAO,EAAE,SAAS,oDAAoD;AAAA,MAChF,WAAW,EACR,OAAO,EACP,SAAS,EACT,SAAS,wEAAwE;AAAA,IACtF;AAAA,IACA,OAAO,EAAE,QAAQ,UAAU,MAAM;AAC/B,UAAI;AACF,cAAM,SAAS,cAAc;AAC7B,cAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,cAAM,UAAU,YAAY,SAAS,SAAS,GAAG,UAAU;AAC3D,cAAM,UAAU,MAAM,OAAO,uBAAuB,EAAE,WAAW,QAAQ,QAAQ,CAAC;AAClF,cAAM,QAAQ;AAAA,UACZ,6BAA6B,MAAM;AAAA,UACnC;AAAA,UACA,KAAK,QAAQ,QAAQ;AAAA,UACrB;AAAA,UACA,iBAAiB,QAAQ,SAAS;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,eAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,MACpC,SAAS,KAAK;AACZ,eAAO;AAAA,UACL,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAChF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,MAC3D,WAAW,EAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,MAC3D,OAAO,EACJ,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,+DAA+D;AAAA,MAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,qBAAqB;AAAA,MACjE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,MACrE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAAA,MACtF,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,eAAe;AAAA,IACrE;AAAA,IACA,OAAO,EAAE,QAAQ,WAAW,OAAO,OAAO,SAAS,YAAY,WAAW,MAAM;AAC9E,UAAI;AACF,cAAM,SAAS,SAAS,SAAS;AACjC,YAAI,CAAC,QAAQ;AACX,iBAAO,WAAW,mCAAmC,SAAS,OAAO,IAAI;AAAA,QAC3E;AACA,cAAM,SAAS,cAAc;AAC7B,cAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,cAAM,QAAQ,MAAM,OAAO,cAAc,QAAQ;AAAA,UAC/C,SAAS,OAAO;AAAA,UAChB,mBAAmB,SAAS;AAAA,UAC5B,UAAU,SAAS;AAAA,UACnB,YAAY,WAAW;AAAA,UACvB,2BAA2B;AAAA,UAC3B,2BAA2B;AAAA,QAC7B,CAAC;AACD,eAAO;AAAA,UACL;AAAA,YACE,2BAAsB,MAAM,iBAAiB,SAAS;AAAA,YACtD,YAAY,MAAM,qBAAqB,SAAS,eAAY,MAAM,YAAY,SAAS,iBAAc,MAAM,cAAc,SAAS;AAAA,UACpI,EAAE,KAAK,IAAI;AAAA,QACb;AAAA,MACF,SAAS,KAAK;AACZ,eAAO;AAAA,UACL,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC3E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,IAC7D;AAAA,IACA,OAAO,EAAE,OAAO,MAAM;AACpB,UAAI;AACF,cAAM,SAAS,cAAc;AAC7B,cAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,cAAM,OAAO,MAAM,OAAO,WAAW,MAAM;AAC3C,cAAM,QAAQ;AAAA,UACZ,GAAG,KAAK,UAAU,KAAK,KAAK,EAAE;AAAA,UAC9B,eAAe,KAAK,SAAS,QAAG;AAAA,UAChC,eAAe,KAAK,mBAAmB,GAAG,KAAK,aAAa,MAAM,UAAK,KAAK,aAAa,MAAM,KAAK,QAAG;AAAA,UACvG,eAAe,KAAK,iBAAiB,QAAG,GAAG,KAAK,cAAc,OAAO,KAAK,WAAW,KAAK,EAAE;AAAA,QAC9F;AACA,YAAI,KAAK,WAAW;AAClB,cAAI;AACF,kBAAM,IAAI,MAAM,OAAO,gBAAgB,MAAM;AAC7C,kBAAM,KAAK,gBAAgB,EAAE,WAAW,kBAAkB;AAC1D,kBAAM;AAAA,cACJ,gBAAgB,EAAE,aAAa,KAAK,EAAE,sBAAsB,OAAO,cAAc;AAAA,YACnF;AACA,kBAAM,KAAK,gBAAgB,EAAE,KAAK,EAAE;AAAA,UACtC,QAAQ;AAAA,UAER;AAAA,QACF;AACA,eAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,MACpC,SAAS,KAAK;AACZ,eAAO;AAAA,UACL,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC3E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,WAAW,EAAE,OAAO,EAAE,SAAS,sDAAsD;AAAA,MACrF,aAAa,EAAE,OAAO,EAAE,SAAS,wDAAwD;AAAA,MACzF,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,kBAAkB;AAAA,MAC/D,MAAM,EAAE,OAAO,EAAE,SAAS,8CAA8C;AAAA,MACxE,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SAAS,4EAA4E;AAAA,MACxF,MAAM,EACH,KAAK,CAAC,QAAQ,UAAU,WAAW,KAAK,CAAC,EACzC,SAAS,EACT,SAAS,6EAA6E;AAAA,MACzF,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,MACrF,sBAAsB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAAA,IACzF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAAM;AACJ,UAAI;AACF,cAAM,SAAS,SAAS,SAAS;AACjC,YAAI,CAAC,QAAQ;AACX,iBAAO,WAAW,mCAAmC,SAAS,OAAO,IAAI;AAAA,QAC3E;AACA,cAAM,SAAS,cAAc;AAC7B,cAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,cAAM,UAAU,MAAM,OAAO,cAAc,OAAO,SAAS;AAAA,UACzD;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,QAAQ;AAAA,UACZ,WAAW,QAAQ,EAAE,KAAK,QAAQ,MAAM;AAAA,UACxC,cAAc,QAAQ,IAAI;AAAA,UAC1B,cAAc,QAAQ,MAAM,QAAK,QAAQ,QAAQ;AAAA,QACnD;AACA,YAAI,QAAQ,aAAc,OAAM,KAAK,eAAe,QAAQ,YAAY,EAAE;AAC1E,YAAI,QAAQ,OAAQ,OAAM,KAAK,eAAe,QAAQ,MAAM,EAAE;AAC9D,YAAI,QAAQ,OAAO;AACjB,gBAAM,SAAS,CAAC,MAAsB,KAAK,OAAO,WAAW,GAAG,CAAC;AACjE,gBAAM;AAAA,YACJ,cAAc,OAAO,QAAQ,MAAM,cAAc,CAAC,gBAAgB,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAAA,UAC1G;AAAA,QACF;AACA,YAAI,QAAQ,YAAY;AACtB,gBAAM,KAAK,kBAAkB,QAAQ,WAAW,IAAI,EAAE;AACtD,cAAI,QAAQ,WAAW,cAAc;AACnC,kBAAM,KAAK,wBAAwB,QAAQ,WAAW,YAAY,EAAE;AAAA,UACtE;AAAA,QACF;AACA,YAAI,QAAQ,OAAO;AACjB,gBAAM,KAAK,cAAc,QAAQ,MAAM,IAAI,WAAM,QAAQ,MAAM,OAAO,EAAE;AAAA,QAC1E;AACA,eAAO,WAAW,MAAM,KAAK,IAAI,GAAG,QAAQ,WAAW,QAAQ;AAAA,MACjE,SAAS,KAAK;AACZ,eAAO;AAAA,UACL,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UACxE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAUA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,OAAO,EAAE,OAAO,EAAE,SAAS,8CAA8C;AAAA,IACzE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,IACtF,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,sDAAuD;AAAA,IACnE,WAAW,EACR,OAAO,EACP,SAAS,EACT,SAAS,2DAA2D;AAAA,IACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,mCAAmC;AAAA,IAC1F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,oCAAoC;AAAA,IAC3F,SAAS,EACN,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,uCAAuC;AAAA,IACnD,gBAAgB,EACb,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,kDAAkD;AAAA,EAChE;AAAA,EACA,OAAO,EAAE,OAAO,MAAM,SAAS,WAAW,OAAO,OAAO,SAAS,eAAe,MAAM;AACpF,QAAI;AACF,YAAM,SAAS,MAAM,eAAe;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,EAAE,OAAO,OAAO,QAAQ;AAAA,QAChC;AAAA,QACA,YAAY,QAAQ,IAAI;AAAA,QACxB,UAAU;AAAA,MACZ,CAAC;AACD,YAAM,QAAQ;AAAA,QACZ,mBAAc,OAAO,KAAK,YAAY,OAAO,OAAO;AAAA,QACpD,mBAAc,OAAO,SAAS,MAAM,OAAO,OAAO;AAAA,QAClD,cAAc,OAAO,aAAa,MAAM,OAAO,OAAO;AAAA,QACtD,cAAc,OAAO,OAAO,KAAK,cAAW,OAAO,OAAO,KAAK,eAAY,OAAO,OAAO,OAAO;AAAA,QAChG;AAAA,QACA,sCAAsC,OAAO,OAAO,OAAO,OAAO,aAAa;AAAA,QAC/E,qCAAqC,OAAO,SAAS;AAAA,MACvD;AAIA,UAAI,OAAO,SAAS;AAClB,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,0EAAmE;AAC9E,cAAM,KAAK,MAAM,OAAO,QAAQ,GAAG,EAAE;AACrC,cAAM,KAAK,oBAAoB,OAAO,QAAQ,SAAS,EAAE;AAAA,MAC3D;AACA,aAAO,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAgB;AACjC,eAAO,WAAW,2BAA2B,IAAI,IAAI,MAAM,IAAI,OAAO,IAAI,IAAI;AAAA,MAChF;AACA,aAAO;AAAA,QACL,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAC3E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAWA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,aAAa,EACV,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,YAAY,MAAM;AAGzB,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,QAAQ;AACX,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAM,QAAQ;AACjB,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,YAAM,QAAQ,MAAM;AAAA,QAAI,CAAC,MACvB;AAAA,UACE,EAAE;AAAA,UACF,gBAAgB,EAAE,OAAO;AAAA,UACzB,gBAAgB,EAAE,aAAa;AAAA,UAC/B,gBAAgB,EAAE,WAAW,MAAM;AAAA,UACnC,gBAAgB,EAAE,OAAO,KAAK,cAAW,EAAE,OAAO,KAAK,eAAY,EAAE,OAAO,OAAO;AAAA,UACnF,gBAAgB,EAAE,SAAS;AAAA,UAC3B;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,MACb;AACA,aAAO,WAAW,MAAM,KAAK,MAAM,CAAC;AAAA,IACtC;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,EAAE,gBAAgB,gBAAgB,KAAK,CAAC;AACxE,UAAI,CAAC,OAAO,OAAO,QAAQ;AACzB,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,YAAM,QAAQ,OAAO,OAAO,IAAI,CAAC,MAAM;AACrC,cAAM,cACJ,EAAE,gBAAgB,SACd,gBAAgB,WAAW,OAAO,EAAE,eAAe,GAAG,CAAC,CAAC,UACxD;AACN,cAAM,aAAa,EAAE,WAAW,gBAAgB,EAAE,QAAQ,KAAK;AAC/D,cAAM,cAAc,EAAE,eAAe,SACjC,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC,KAC3C;AACJ,cAAM,gBAAgB,EAAE,YAAY,2BAA2B;AAC/D,eAAO;AAAA,UACL,EAAE;AAAA,UACF,gBAAgB,EAAE,OAAO;AAAA,UACzB,gBAAgB,EAAE,aAAa;AAAA,UAC/B,gBAAgB,EAAE,OAAO;AAAA,UACzB,gBAAgB,EAAE,OAAO,QAAQ,cAAW,EAAE,OAAO,QAAQ,eAAY,EAAE,OAAO,UAAU;AAAA,UAC5F;AAAA,UACA;AAAA,UACA,GAAI,cAAc,CAAC,WAAW,IAAI,CAAC;AAAA,UACnC,GAAI,gBAAgB,CAAC,aAAa,IAAI,CAAC;AAAA,UACvC,gBAAgB,EAAE,SAAS;AAAA,QAC7B,EAAE,KAAK,IAAI;AAAA,MACb,CAAC;AACD,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,MAAM,UAAU,OAAO,OAAO,WAAW,IAAI,KAAK,GAAG;AAAA;AAAA,EAAgD,MAAM,KAAK,MAAM,CAAC;AAAA,MAC1I;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAQA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,MAAM,EAAE,OAAO,EAAE,SAAS,4CAA4C;AAAA,IACtE,SAAS,EACN,OAAO,EACP;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AAAA,EACA,OAAO,EAAE,MAAM,QAAQ,MAAM;AAC3B,QAAI,SAAS,SAAS;AACpB,aAAO,WAAW,WAAW,IAAI,gDAA2C;AAAA,IAC9E;AACA,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,mCAAmC,IAAI;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAAS,cAAc;AAC7B,YAAM,SAAS,IAAI,iBAAiB,YAAY,MAAM;AACtD,YAAM,SAAS,MAAM,OAAO,YAAY,OAAO,SAAS,OAAO;AAG/D,wBAAkB,MAAM,OAAO,IAAI;AACnC,aAAO;AAAA,QACL,oBAAe,IAAI,eAAU,OAAO,IAAI,cAAc,OAAO,iBAAiB,OAAO,aAAa;AAAA,MACpG;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACxE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAIA,eAAe,OAAO;AACpB,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["lines"]}
package/package.json CHANGED
@@ -1,22 +1,20 @@
1
1
  {
2
2
  "name": "@arispay/payagent-mcp",
3
- "version": "2.7.0",
4
- "description": "MCP server for ArisPay-delegated x402 USDC payments. Use with Claude Desktop, Cursor, or any MCP client — no private keys in your process.",
3
+ "version": "2.8.0",
4
+ "description": "MCP server that gives AI agents a wallet: pay x402 APIs (USD + EUR), check balances, self-onboard with one tool call. Use with Claude, Cursor, or any MCP client — delegated custody, no private keys on the agent.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "payagent-mcp": "dist/index.js"
8
8
  },
9
9
  "main": "./dist/index.js",
10
- "files": ["dist", "README.md", "LICENSE"],
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
11
15
  "publishConfig": {
12
16
  "access": "public"
13
17
  },
14
- "scripts": {
15
- "build": "tsup",
16
- "dev": "tsup --watch",
17
- "type-check": "tsc --noEmit",
18
- "prepublishOnly": "npm run build"
19
- },
20
18
  "keywords": [
21
19
  "arispay",
22
20
  "mcp",
@@ -32,7 +30,13 @@
32
30
  "cursor",
33
31
  "windsurf",
34
32
  "agent-tool",
35
- "delegated-custody"
33
+ "delegated-custody",
34
+ "agent-wallet",
35
+ "agent-payments",
36
+ "eurc",
37
+ "pay-for-api",
38
+ "agentic-commerce",
39
+ "bootstrap"
36
40
  ],
37
41
  "engines": {
38
42
  "node": ">=18"
@@ -47,12 +51,18 @@
47
51
  "homepage": "https://github.com/arispay-inc/ArisPay/tree/master/packages/payagent-mcp#readme",
48
52
  "dependencies": {
49
53
  "@modelcontextprotocol/sdk": "^1.12.1",
50
- "payagent": "workspace:^",
51
- "zod": "^3.25.0"
54
+ "zod": "^3.25.0",
55
+ "payagent": "^2.12.2"
52
56
  },
53
57
  "devDependencies": {
54
58
  "@types/node": "^22.0.0",
55
59
  "tsup": "^8.0.0",
56
60
  "typescript": "^5.7.0"
61
+ },
62
+ "private": false,
63
+ "scripts": {
64
+ "build": "tsup",
65
+ "dev": "tsup --watch",
66
+ "type-check": "tsc --noEmit"
57
67
  }
58
- }
68
+ }