@aura-payments/mcp-server 1.0.1 → 1.1.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.d.ts CHANGED
@@ -1,6 +1,66 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { AuraClient } from '@aura-payments/sdk';
3
3
 
4
+ /**
5
+ * API key parsing and validation for the Aura MCP server.
6
+ *
7
+ * Deliberately dependency-free: this module imports nothing (not even the
8
+ * Aura SDK) so it can be unit-tested in isolation and imported from the
9
+ * startup banner without pulling the whole client graph into scope.
10
+ *
11
+ * SECURITY: no function here ever returns the full key. `maskApiKey` reveals
12
+ * at most half of the key (capped at 8 characters) so a malformed-key error
13
+ * can identify WHICH key is wrong without ever writing the secret into a log,
14
+ * a stderr banner, or an MCP tool result.
15
+ */
16
+ /**
17
+ * Recognized API key prefixes.
18
+ *
19
+ * `sk_` = secret key (server-side), `pk_` = publishable key. The middle
20
+ * segment selects the environment the key is bound to; a key issued for one
21
+ * environment is never valid in the other.
22
+ */
23
+ declare const API_KEY_PREFIXES: readonly ["sk_test_", "sk_live_", "pk_test_", "pk_live_"];
24
+ type AuraApiKeyPrefix = (typeof API_KEY_PREFIXES)[number];
25
+ /** Which Aura environment a key is bound to. */
26
+ type AuraKeyMode = 'test' | 'live';
27
+ interface ParsedAuraApiKey {
28
+ /** The matched prefix, e.g. `pk_test_`. Safe to log — carries no secret. */
29
+ prefix: AuraApiKeyPrefix;
30
+ /** Resolved environment, derived from the prefix. */
31
+ mode: AuraKeyMode;
32
+ }
33
+ /**
34
+ * Redact a key for display.
35
+ *
36
+ * Reveals `min(8, floor(length / 2))` leading characters, so the result can
37
+ * never contain the whole key for any input of length >= 1. The length is
38
+ * appended because "wrong length" is the most common misconfiguration (a
39
+ * truncated paste) and it leaks nothing.
40
+ */
41
+ declare function maskApiKey(apiKey: string): string;
42
+ /**
43
+ * Parse and validate `AURA_API_KEY`.
44
+ *
45
+ * @throws {MissingAuraApiKeyError} when the key is absent or blank.
46
+ * @throws {MalformedAuraApiKeyError} when the key carries no recognized prefix.
47
+ */
48
+ declare function parseApiKey(apiKey: string | undefined): ParsedAuraApiKey;
49
+ /**
50
+ * Resolve the environment for display without throwing.
51
+ *
52
+ * The startup banner must never crash the process — an unusable key still has
53
+ * to produce a running server whose FIRST TOOL CALL returns a clear error, so
54
+ * the MCP host surfaces something actionable instead of a dead subprocess.
55
+ */
56
+ declare function resolveKeyMode(apiKey: string | undefined): AuraKeyMode | 'unconfigured' | 'invalid';
57
+ declare class MissingAuraApiKeyError extends Error {
58
+ constructor();
59
+ }
60
+ declare class MalformedAuraApiKeyError extends Error {
61
+ constructor(apiKey: string);
62
+ }
63
+
4
64
  /**
5
65
  * Aura SDK client factory for the MCP server.
6
66
  *
@@ -9,20 +69,22 @@ import { AuraClient } from '@aura-payments/sdk';
9
69
  * the `env` field in mcp.json). The client is created lazily on first tool
10
70
  * invocation so missing env doesn't crash the server during the MCP handshake
11
71
  * — instead, the FIRST tool call returns a clear error the LLM can act on.
72
+ *
73
+ * The key is validated for BOTH presence and format before it is ever put on
74
+ * the wire. A malformed key would otherwise fail as an opaque 401 from the
75
+ * platform, which is indistinguishable from a revoked key — the local check
76
+ * turns that into an actionable configuration error.
12
77
  */
13
78
 
14
79
  declare function getClient(): AuraClient;
15
- declare class MissingAuraApiKeyError extends Error {
16
- constructor();
17
- }
18
80
 
19
81
  /**
20
82
  * Aura Payments MCP Server — programmatic entry point.
21
83
  *
22
- * The MCP server exposes Aura's escrow, agent, mandate, and wallet primitives
23
- * as Model Context Protocol tools and resources, so AI agents (Claude,
24
- * Cursor, Continue, custom orchestrators) can drive Aura natively over
25
- * stdio without writing HTTP boilerplate.
84
+ * The MCP server exposes Aura's escrow, agent, mandate, wallet, and webhook
85
+ * primitives as Model Context Protocol tools and resources, so AI agents
86
+ * (Claude, Cursor, Continue, custom orchestrators) can drive Aura natively
87
+ * over stdio without writing HTTP boilerplate.
26
88
  *
27
89
  * This file exports `createServer()` for programmatic use (tests, custom
28
90
  * transports, embedding in other MCP hosts). For the standalone binary,
@@ -33,10 +95,17 @@ declare class MissingAuraApiKeyError extends Error {
33
95
  * shape, idempotency, retries, and error mapping.
34
96
  */
35
97
 
98
+ declare const SERVER_NAME = "aura-payments";
99
+ declare const SERVER_VERSION = "1.1.0";
36
100
  interface CreateServerOptions {
37
101
  name?: string;
38
102
  version?: string;
39
103
  }
104
+ /**
105
+ * Names of the tools registered on `server`, in registration order.
106
+ * Returns an empty array for a server this module did not build.
107
+ */
108
+ declare function getRegisteredToolNames(server: McpServer): readonly string[];
40
109
  /**
41
110
  * Build a fully-configured MCP server with all Aura tools and resources
42
111
  * registered. The caller is responsible for connecting it to a transport
@@ -44,4 +113,4 @@ interface CreateServerOptions {
44
113
  */
45
114
  declare function createServer(options?: CreateServerOptions): McpServer;
46
115
 
47
- export { type CreateServerOptions, MissingAuraApiKeyError, createServer, getClient };
116
+ export { API_KEY_PREFIXES, type AuraKeyMode, type CreateServerOptions, MalformedAuraApiKeyError, MissingAuraApiKeyError, type ParsedAuraApiKey, SERVER_NAME, SERVER_VERSION, createServer, getClient, getRegisteredToolNames, maskApiKey, parseApiKey, resolveKeyMode };
package/dist/index.js CHANGED
@@ -5,13 +5,58 @@ var sdk = require('@aura-payments/sdk');
5
5
  var zod = require('zod');
6
6
 
7
7
  // src/index.ts
8
+
9
+ // src/api-key.ts
10
+ var API_KEY_PREFIXES = [
11
+ "sk_test_",
12
+ "sk_live_",
13
+ "pk_test_",
14
+ "pk_live_"
15
+ ];
16
+ function maskApiKey(apiKey) {
17
+ const revealed = Math.min(8, Math.floor(apiKey.length / 2));
18
+ return `${apiKey.slice(0, revealed)}\u2026(${apiKey.length} chars)`;
19
+ }
20
+ function parseApiKey(apiKey) {
21
+ if (!apiKey || apiKey.trim() === "") {
22
+ throw new MissingAuraApiKeyError();
23
+ }
24
+ const prefix = API_KEY_PREFIXES.find((p) => apiKey.startsWith(p));
25
+ if (!prefix) {
26
+ throw new MalformedAuraApiKeyError(apiKey);
27
+ }
28
+ return { prefix, mode: prefix.includes("_test_") ? "test" : "live" };
29
+ }
30
+ function resolveKeyMode(apiKey) {
31
+ try {
32
+ return parseApiKey(apiKey).mode;
33
+ } catch (err) {
34
+ return err instanceof MissingAuraApiKeyError ? "unconfigured" : "invalid";
35
+ }
36
+ }
37
+ var MissingAuraApiKeyError = class extends Error {
38
+ constructor() {
39
+ super(
40
+ 'AURA_API_KEY not set. Configure it in your MCP client config \u2014 for example in mcp.json: { "mcpServers": { "aura": { "command": "aura-mcp", "env": { "AURA_API_KEY": "pk_live_..." } } } }. Get a key at https://getaura.sh.'
41
+ );
42
+ this.name = "MissingAuraApiKeyError";
43
+ }
44
+ };
45
+ var MalformedAuraApiKeyError = class extends Error {
46
+ constructor(apiKey) {
47
+ super(
48
+ `AURA_API_KEY is malformed (got ${maskApiKey(apiKey)}). An Aura API key must start with one of: ${API_KEY_PREFIXES.join(", ")}. Check for a truncated copy/paste, a shell-quoting problem, or a key from a different service. Issue a new key at https://getaura.sh.`
49
+ );
50
+ this.name = "MalformedAuraApiKeyError";
51
+ }
52
+ };
53
+
54
+ // src/client.ts
8
55
  var cached = null;
9
56
  function getClient() {
10
57
  if (cached) return cached;
11
58
  const apiKey = process.env.AURA_API_KEY;
12
- if (!apiKey) {
13
- throw new MissingAuraApiKeyError();
14
- }
59
+ parseApiKey(apiKey);
15
60
  cached = new sdk.AuraClient({
16
61
  apiKey,
17
62
  baseUrl: process.env.AURA_BASE_URL,
@@ -20,14 +65,6 @@ function getClient() {
20
65
  });
21
66
  return cached;
22
67
  }
23
- var MissingAuraApiKeyError = class extends Error {
24
- constructor() {
25
- super(
26
- 'AURA_API_KEY not set. Configure it in your MCP client config \u2014 for example in mcp.json: { "mcpServers": { "aura": { "command": "aura-mcp", "env": { "AURA_API_KEY": "pk_live_..." } } } }. Get a key at https://getaura.sh.'
27
- );
28
- this.name = "MissingAuraApiKeyError";
29
- }
30
- };
31
68
 
32
69
  // src/resources/agents.ts
33
70
  function registerAgentResources(server) {
@@ -66,6 +103,39 @@ function registerAgentResources(server) {
66
103
  }
67
104
  );
68
105
  }
106
+ var COLLECTION_LIMIT = 50;
107
+ function registerEscrowResources(server) {
108
+ server.resource("escrows", "aura://escrows", async (uri) => {
109
+ const client = getClient();
110
+ const page = await client.escrows.list({ limit: COLLECTION_LIMIT });
111
+ return {
112
+ contents: [
113
+ {
114
+ uri: uri.href,
115
+ mimeType: "application/json",
116
+ text: JSON.stringify(page, null, 2)
117
+ }
118
+ ]
119
+ };
120
+ });
121
+ server.resource(
122
+ "escrow",
123
+ new mcp_js.ResourceTemplate("aura://escrows/{id}", { list: void 0 }),
124
+ async (uri, { id }) => {
125
+ const client = getClient();
126
+ const escrow = await client.escrows.get(String(id));
127
+ return {
128
+ contents: [
129
+ {
130
+ uri: uri.href,
131
+ mimeType: "application/json",
132
+ text: JSON.stringify(escrow, null, 2)
133
+ }
134
+ ]
135
+ };
136
+ }
137
+ );
138
+ }
69
139
  function registerMandateResources(server) {
70
140
  server.resource(
71
141
  "mandates-pending",
@@ -102,6 +172,72 @@ function registerMandateResources(server) {
102
172
  }
103
173
  );
104
174
  }
175
+ var COLLECTION_LIMIT2 = 50;
176
+ function registerWalletResources(server) {
177
+ server.resource("wallets", "aura://wallets", async (uri) => {
178
+ const client = getClient();
179
+ const page = await client.wallets.list({ limit: COLLECTION_LIMIT2 });
180
+ return {
181
+ contents: [
182
+ {
183
+ uri: uri.href,
184
+ mimeType: "application/json",
185
+ text: JSON.stringify(page, null, 2)
186
+ }
187
+ ]
188
+ };
189
+ });
190
+ server.resource(
191
+ "wallet",
192
+ new mcp_js.ResourceTemplate("aura://wallets/{id}", { list: void 0 }),
193
+ async (uri, { id }) => {
194
+ const client = getClient();
195
+ const wallet = await client.wallets.get(String(id));
196
+ return {
197
+ contents: [
198
+ {
199
+ uri: uri.href,
200
+ mimeType: "application/json",
201
+ text: JSON.stringify(wallet, null, 2)
202
+ }
203
+ ]
204
+ };
205
+ }
206
+ );
207
+ server.resource(
208
+ "wallet-balance",
209
+ new mcp_js.ResourceTemplate("aura://wallets/{id}/balance", { list: void 0 }),
210
+ async (uri, { id }) => {
211
+ const client = getClient();
212
+ const balance = await client.wallets.getBalance(String(id));
213
+ return {
214
+ contents: [
215
+ {
216
+ uri: uri.href,
217
+ mimeType: "application/json",
218
+ text: JSON.stringify(balance, null, 2)
219
+ }
220
+ ]
221
+ };
222
+ }
223
+ );
224
+ }
225
+
226
+ // src/annotations.ts
227
+ function readOnly(title) {
228
+ return { title, readOnlyHint: true };
229
+ }
230
+ function write(title, idempotent = false) {
231
+ return {
232
+ title,
233
+ readOnlyHint: false,
234
+ destructiveHint: false,
235
+ ...idempotent ? { idempotentHint: true } : {}
236
+ };
237
+ }
238
+ function destructive(title) {
239
+ return { title, readOnlyHint: false, destructiveHint: true };
240
+ }
105
241
  async function withToolErrorHandling(body, successFormatter = defaultJsonFormatter) {
106
242
  try {
107
243
  const result = await body();
@@ -116,7 +252,7 @@ function defaultJsonFormatter(data) {
116
252
  return JSON.stringify(data, null, 2);
117
253
  }
118
254
  function formatError(err) {
119
- if (err instanceof MissingAuraApiKeyError) {
255
+ if (err instanceof MissingAuraApiKeyError || err instanceof MalformedAuraApiKeyError) {
120
256
  return errorResult("CONFIG_ERROR", err.message);
121
257
  }
122
258
  if (err instanceof sdk.AuraAuthenticationError) {
@@ -204,6 +340,8 @@ function registerAgentTools(server) {
204
340
  autoApproveBelow: zod.z.string().optional()
205
341
  }).optional()
206
342
  },
343
+ // Additive: provisions a new agent and its wallet. No funds move.
344
+ write("Create Agent"),
207
345
  async (args) => withToolErrorHandling(async () => {
208
346
  const client = getClient();
209
347
  return client.agents.create(args);
@@ -218,6 +356,7 @@ function registerAgentTools(server) {
218
356
  limit: zod.z.number().int().min(1).max(200).optional(),
219
357
  offset: zod.z.number().int().min(0).optional()
220
358
  },
359
+ readOnly("List Agents"),
221
360
  async (args) => withToolErrorHandling(async () => {
222
361
  const client = getClient();
223
362
  return client.agents.list(args);
@@ -229,6 +368,7 @@ function registerAgentTools(server) {
229
368
  {
230
369
  agentId: zod.z.string().uuid()
231
370
  },
371
+ readOnly("Get Agent"),
232
372
  async ({ agentId }) => withToolErrorHandling(async () => {
233
373
  const client = getClient();
234
374
  return client.agents.get(agentId);
@@ -240,6 +380,7 @@ function registerAgentTools(server) {
240
380
  {
241
381
  agentId: zod.z.string().uuid()
242
382
  },
383
+ readOnly("Get Agent Balance"),
243
384
  async ({ agentId }) => withToolErrorHandling(async () => {
244
385
  const client = getClient();
245
386
  return client.agents.getBalance(agentId);
@@ -252,6 +393,8 @@ function registerAgentTools(server) {
252
393
  agentId: zod.z.string().uuid(),
253
394
  reason: zod.z.string().max(500).optional().describe("Surfaced in activity event metadata for audit trail")
254
395
  },
396
+ // Halts an existing agent AND cascade-rejects its in-flight mandates.
397
+ destructive("Freeze Agent (kill switch)"),
255
398
  async (args) => withToolErrorHandling(async () => {
256
399
  const client = getClient();
257
400
  return client.agents.freeze(args);
@@ -263,6 +406,8 @@ function registerAgentTools(server) {
263
406
  {
264
407
  agentId: zod.z.string().uuid()
265
408
  },
409
+ // Re-enables autonomous spending on an existing agent.
410
+ destructive("Unfreeze Agent (resumes autonomous spending)"),
266
411
  async (args) => withToolErrorHandling(async () => {
267
412
  const client = getClient();
268
413
  return client.agents.unfreeze(args);
@@ -279,11 +424,24 @@ function registerAgentTools(server) {
279
424
  reasoning: zod.z.string().optional(),
280
425
  metadata: zod.z.record(zod.z.unknown()).optional()
281
426
  },
427
+ // NOT read-only despite being a dry run: when the decision requires human
428
+ // approval the engine persists a new mandate row. Additive, never
429
+ // destructive — it cannot execute the transaction it evaluates.
430
+ write("Evaluate Policy (dry run, may create a mandate)"),
282
431
  async (args) => withToolErrorHandling(async () => {
283
432
  const client = getClient();
284
433
  return client.agents.evaluate(args);
285
434
  })
286
435
  );
436
+ return [
437
+ "aura_create_agent",
438
+ "aura_list_agents",
439
+ "aura_get_agent",
440
+ "aura_get_agent_balance",
441
+ "aura_freeze_agent",
442
+ "aura_unfreeze_agent",
443
+ "aura_evaluate_policy"
444
+ ];
287
445
  }
288
446
  var ChainSchema2 = zod.z.enum(["ARC", "ARB", "BASE", "ETH", "MATIC"]);
289
447
  var SplitInputSchema = zod.z.object({
@@ -320,6 +478,8 @@ function registerEscrowTools(server) {
320
478
  chain: ChainSchema2.optional().describe("Target chain. Defaults to ARC"),
321
479
  splits: zod.z.array(SplitInputSchema).min(1).describe("Payment splits. Percentages must sum to 100.")
322
480
  },
481
+ // Additive: creates a new escrow record. No funds move until `fund`.
482
+ write("Create Escrow"),
323
483
  async (args) => withToolErrorHandling(async () => {
324
484
  const client = getClient();
325
485
  return client.escrows.create(args);
@@ -331,6 +491,7 @@ function registerEscrowTools(server) {
331
491
  {
332
492
  escrowId: zod.z.string().uuid()
333
493
  },
494
+ readOnly("Get Escrow"),
334
495
  async ({ escrowId }) => withToolErrorHandling(async () => {
335
496
  const client = getClient();
336
497
  return client.escrows.get(escrowId);
@@ -355,6 +516,7 @@ function registerEscrowTools(server) {
355
516
  limit: zod.z.number().int().min(1).max(200).optional(),
356
517
  offset: zod.z.number().int().min(0).optional()
357
518
  },
519
+ readOnly("List Escrows"),
358
520
  async (args) => withToolErrorHandling(async () => {
359
521
  const client = getClient();
360
522
  return client.escrows.list(args);
@@ -369,6 +531,8 @@ function registerEscrowTools(server) {
369
531
  amount: zod.z.string().describe("USDC amount to fund (whole-number string)"),
370
532
  correlationId: zod.z.string().optional()
371
533
  },
534
+ // Moves USDC out of the buyer wallet.
535
+ destructive("Fund Escrow (moves USDC)"),
372
536
  async (args) => withToolErrorHandling(async () => {
373
537
  const client = getClient();
374
538
  return client.escrows.fund(args);
@@ -383,6 +547,8 @@ function registerEscrowTools(server) {
383
547
  reason: zod.z.string().optional(),
384
548
  correlationId: zod.z.string().optional()
385
549
  },
550
+ // Irreversible payout to the split recipients.
551
+ destructive("Release Escrow (pays out USDC)"),
386
552
  async (args) => withToolErrorHandling(async () => {
387
553
  const client = getClient();
388
554
  return client.escrows.release(args);
@@ -396,6 +562,8 @@ function registerEscrowTools(server) {
396
562
  reason: zod.z.string().min(10),
397
563
  actorId: zod.z.string().uuid()
398
564
  },
565
+ // Irreversible return of funds to the buyer.
566
+ destructive("Refund Escrow (returns USDC to buyer)"),
399
567
  async (args) => withToolErrorHandling(async () => {
400
568
  const client = getClient();
401
569
  return client.escrows.refund(args);
@@ -415,11 +583,22 @@ function registerEscrowTools(server) {
415
583
  waitForDeploymentMs: zod.z.number().int().min(0).optional().describe("Max ms to wait for on-chain deployment. Default 60000."),
416
584
  waitForFundingMs: zod.z.number().int().min(0).optional().describe("Max ms to wait for funds to settle (funded/locked) before releasing. Default 60000.")
417
585
  },
586
+ // Composes create -> fund -> release: money moves and is paid out.
587
+ destructive("Receive and Split (moves and pays out USDC)"),
418
588
  async (args) => withToolErrorHandling(async () => {
419
589
  const client = getClient();
420
590
  return client.escrows.receiveAndSplit(args);
421
591
  })
422
592
  );
593
+ return [
594
+ "aura_create_escrow",
595
+ "aura_get_escrow",
596
+ "aura_list_escrows",
597
+ "aura_fund_escrow",
598
+ "aura_release_escrow",
599
+ "aura_refund_escrow",
600
+ "aura_receive_and_split"
601
+ ];
423
602
  }
424
603
  function registerMandateTools(server) {
425
604
  server.tool(
@@ -431,6 +610,7 @@ function registerMandateTools(server) {
431
610
  limit: zod.z.number().int().min(1).max(200).optional(),
432
611
  cursor: zod.z.string().uuid().optional().describe("Last mandate id from the previous page")
433
612
  },
613
+ readOnly("List Mandates (approval inbox)"),
434
614
  async (args) => withToolErrorHandling(async () => {
435
615
  const client = getClient();
436
616
  return client.mandates.list(args);
@@ -442,6 +622,7 @@ function registerMandateTools(server) {
442
622
  {
443
623
  mandateId: zod.z.string().uuid()
444
624
  },
625
+ readOnly("Get Mandate"),
445
626
  async ({ mandateId }) => withToolErrorHandling(async () => {
446
627
  const client = getClient();
447
628
  return client.mandates.get(mandateId);
@@ -456,6 +637,8 @@ function registerMandateTools(server) {
456
637
  decisionSignature: zod.z.string().min(16).describe("HMAC-SHA256 hex digest, computed by the caller"),
457
638
  decidedAt: zod.z.string().datetime().optional().describe('ISO-8601 timestamp the signature commits to. Defaults to "now" server-side.')
458
639
  },
640
+ // Authorizes the agent's intended payment — the money-moving decision.
641
+ destructive("Approve Mandate (authorizes payment)"),
459
642
  async (args) => withToolErrorHandling(async () => {
460
643
  const client = getClient();
461
644
  return client.mandates.approve(args);
@@ -471,11 +654,19 @@ function registerMandateTools(server) {
471
654
  decidedAt: zod.z.string().datetime().optional(),
472
655
  reason: zod.z.string().optional().describe("Human-readable reason logged to the activity feed")
473
656
  },
657
+ // Terminal decision on an existing mandate — the agent cannot resume it.
658
+ destructive("Reject Mandate"),
474
659
  async (args) => withToolErrorHandling(async () => {
475
660
  const client = getClient();
476
661
  return client.mandates.reject(args);
477
662
  })
478
663
  );
664
+ return [
665
+ "aura_list_mandates",
666
+ "aura_get_mandate",
667
+ "aura_approve_mandate",
668
+ "aura_reject_mandate"
669
+ ];
479
670
  }
480
671
  var TestnetChainSchema = zod.z.enum(["ARC", "ARB", "BASE"]);
481
672
  function walletCreateEnabled() {
@@ -489,6 +680,7 @@ function registerWalletTools(server) {
489
680
  {
490
681
  walletId: zod.z.string().uuid()
491
682
  },
683
+ readOnly("Get Wallet Balance"),
492
684
  async ({ walletId }) => withToolErrorHandling(async () => {
493
685
  const client = getClient();
494
686
  return client.wallets.getBalance(walletId);
@@ -512,6 +704,8 @@ function registerWalletTools(server) {
512
704
  "tax"
513
705
  ]).optional().describe("Wallet owner type. Defaults to BUSINESS.")
514
706
  },
707
+ // Additive and create-or-get: provisions a receive address, moves no money.
708
+ write("Create Wallet (receive address)", true),
515
709
  async ({ entityId, chain, type }) => {
516
710
  if (!walletCreateEnabled()) {
517
711
  return toolError(
@@ -533,28 +727,118 @@ function registerWalletTools(server) {
533
727
  token: zod.z.string().optional().describe("Token to drip. Defaults to 'USDC'."),
534
728
  chain: TestnetChainSchema.optional().describe("Override the wallet's chain.")
535
729
  },
730
+ // Additive: testnet-only drip that adds play funds, destroys nothing.
731
+ write("Request Testnet Funds"),
536
732
  async ({ walletId, token, chain }) => withToolErrorHandling(async () => {
537
733
  const client = getClient();
538
734
  return client.wallets.requestTestnetFunds(walletId, { token, chain });
539
735
  })
540
736
  );
737
+ return [
738
+ "aura_get_wallet_balance",
739
+ "aura_create_wallet",
740
+ "aura_request_testnet_funds"
741
+ ];
742
+ }
743
+ var WebhookEventTypeSchema = zod.z.enum([
744
+ "*",
745
+ "escrow.created",
746
+ "escrow.funded",
747
+ "escrow.locked",
748
+ "escrow.released",
749
+ "escrow.refunded",
750
+ "escrow.disputed",
751
+ "transfer.completed",
752
+ "transfer.failed",
753
+ "withdrawal.created",
754
+ "withdrawal.processing",
755
+ "withdrawal.completed",
756
+ "withdrawal.failed",
757
+ "account.kyc_approved",
758
+ "account.kyc_rejected",
759
+ "account.tier_upgraded",
760
+ "security.api_key_created",
761
+ "security.api_key_revoked"
762
+ ]);
763
+ function registerWebhookTools(server) {
764
+ server.tool(
765
+ "aura_get_webhook_config",
766
+ "Get the current webhook configuration for the authenticated account: delivery URL, subscribed event types, and status. The signing secret is never returned by this endpoint.",
767
+ {},
768
+ readOnly("Get Webhook Config"),
769
+ async () => withToolErrorHandling(async () => {
770
+ const client = getClient();
771
+ return client.webhooks.getConfig();
772
+ })
773
+ );
774
+ server.tool(
775
+ "aura_set_webhook_config",
776
+ "Set the webhook delivery endpoint for the account. An account has ONE configuration, so this REPLACES any existing one \u2014 events stop going to the previous URL. Must be an https:// URL you control. Returns the signing secret; store it, it is shown only on initial configuration.",
777
+ {
778
+ url: zod.z.string().url().describe("HTTPS endpoint that will receive event POSTs"),
779
+ events: zod.z.array(WebhookEventTypeSchema).min(1).optional().describe(
780
+ "Event types to subscribe to. Omit to subscribe to all events, or pass ['*'] explicitly."
781
+ ),
782
+ description: zod.z.string().optional().describe("Optional human-readable label")
783
+ },
784
+ destructive("Set Webhook Config (replaces existing)"),
785
+ async (args) => withToolErrorHandling(async () => {
786
+ const client = getClient();
787
+ return client.webhooks.configure(args);
788
+ })
789
+ );
790
+ server.tool(
791
+ "aura_delete_webhook_config",
792
+ "Delete the account webhook configuration. Event delivery stops immediately and the signing secret is invalidated \u2014 reconfiguring issues a new secret.",
793
+ {},
794
+ destructive("Delete Webhook Config"),
795
+ async () => withToolErrorHandling(async () => {
796
+ const client = getClient();
797
+ return client.webhooks.delete();
798
+ })
799
+ );
800
+ return [
801
+ "aura_get_webhook_config",
802
+ "aura_set_webhook_config",
803
+ "aura_delete_webhook_config"
804
+ ];
541
805
  }
542
806
 
543
807
  // src/index.ts
808
+ var SERVER_NAME = "aura-payments";
809
+ var SERVER_VERSION = "1.1.0";
810
+ var toolManifests = /* @__PURE__ */ new WeakMap();
811
+ function getRegisteredToolNames(server) {
812
+ return toolManifests.get(server) ?? [];
813
+ }
544
814
  function createServer(options = {}) {
545
815
  const server = new mcp_js.McpServer({
546
- name: options.name ?? "aura-payments",
547
- version: options.version ?? "1.0.1"
816
+ name: options.name ?? SERVER_NAME,
817
+ version: options.version ?? SERVER_VERSION
548
818
  });
549
- registerEscrowTools(server);
550
- registerAgentTools(server);
551
- registerMandateTools(server);
552
- registerWalletTools(server);
819
+ const toolNames = [
820
+ ...registerEscrowTools(server),
821
+ ...registerAgentTools(server),
822
+ ...registerMandateTools(server),
823
+ ...registerWalletTools(server),
824
+ ...registerWebhookTools(server)
825
+ ];
826
+ toolManifests.set(server, Object.freeze(toolNames));
553
827
  registerAgentResources(server);
554
828
  registerMandateResources(server);
829
+ registerEscrowResources(server);
830
+ registerWalletResources(server);
555
831
  return server;
556
832
  }
557
833
 
834
+ exports.API_KEY_PREFIXES = API_KEY_PREFIXES;
835
+ exports.MalformedAuraApiKeyError = MalformedAuraApiKeyError;
558
836
  exports.MissingAuraApiKeyError = MissingAuraApiKeyError;
837
+ exports.SERVER_NAME = SERVER_NAME;
838
+ exports.SERVER_VERSION = SERVER_VERSION;
559
839
  exports.createServer = createServer;
560
840
  exports.getClient = getClient;
841
+ exports.getRegisteredToolNames = getRegisteredToolNames;
842
+ exports.maskApiKey = maskApiKey;
843
+ exports.parseApiKey = parseApiKey;
844
+ exports.resolveKeyMode = resolveKeyMode;