@aura-payments/mcp-server 1.0.1 → 1.2.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/bin.js +593 -18
- package/dist/bin.mjs +593 -18
- package/dist/index.d.mts +77 -8
- package/dist/index.d.ts +77 -8
- package/dist/index.js +586 -18
- package/dist/index.mjs +579 -19
- package/package.json +6 -4
package/dist/bin.mjs
CHANGED
|
@@ -4,13 +4,55 @@ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mc
|
|
|
4
4
|
import { AuraClient, AuraAuthenticationError, AuraNotFoundError, AuraValidationError, AuraRateLimitError, AuraTimeoutError, AuraAPIError, AuraError } from '@aura-payments/sdk';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
|
+
// src/api-key.ts
|
|
8
|
+
var API_KEY_PREFIXES = [
|
|
9
|
+
"sk_test_",
|
|
10
|
+
"sk_live_",
|
|
11
|
+
"pk_test_",
|
|
12
|
+
"pk_live_"
|
|
13
|
+
];
|
|
14
|
+
function maskApiKey(apiKey) {
|
|
15
|
+
const revealed = Math.min(8, Math.floor(apiKey.length / 2));
|
|
16
|
+
return `${apiKey.slice(0, revealed)}\u2026(${apiKey.length} chars)`;
|
|
17
|
+
}
|
|
18
|
+
function parseApiKey(apiKey) {
|
|
19
|
+
if (!apiKey || apiKey.trim() === "") {
|
|
20
|
+
throw new MissingAuraApiKeyError();
|
|
21
|
+
}
|
|
22
|
+
const prefix = API_KEY_PREFIXES.find((p) => apiKey.startsWith(p));
|
|
23
|
+
if (!prefix) {
|
|
24
|
+
throw new MalformedAuraApiKeyError(apiKey);
|
|
25
|
+
}
|
|
26
|
+
return { prefix, mode: prefix.includes("_test_") ? "test" : "live" };
|
|
27
|
+
}
|
|
28
|
+
function resolveKeyMode(apiKey) {
|
|
29
|
+
try {
|
|
30
|
+
return parseApiKey(apiKey).mode;
|
|
31
|
+
} catch (err) {
|
|
32
|
+
return err instanceof MissingAuraApiKeyError ? "unconfigured" : "invalid";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
var MissingAuraApiKeyError = class extends Error {
|
|
36
|
+
constructor() {
|
|
37
|
+
super(
|
|
38
|
+
'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.'
|
|
39
|
+
);
|
|
40
|
+
this.name = "MissingAuraApiKeyError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var MalformedAuraApiKeyError = class extends Error {
|
|
44
|
+
constructor(apiKey) {
|
|
45
|
+
super(
|
|
46
|
+
`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.`
|
|
47
|
+
);
|
|
48
|
+
this.name = "MalformedAuraApiKeyError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
7
51
|
var cached = null;
|
|
8
52
|
function getClient() {
|
|
9
53
|
if (cached) return cached;
|
|
10
54
|
const apiKey = process.env.AURA_API_KEY;
|
|
11
|
-
|
|
12
|
-
throw new MissingAuraApiKeyError();
|
|
13
|
-
}
|
|
55
|
+
parseApiKey(apiKey);
|
|
14
56
|
cached = new AuraClient({
|
|
15
57
|
apiKey,
|
|
16
58
|
baseUrl: process.env.AURA_BASE_URL,
|
|
@@ -19,14 +61,6 @@ function getClient() {
|
|
|
19
61
|
});
|
|
20
62
|
return cached;
|
|
21
63
|
}
|
|
22
|
-
var MissingAuraApiKeyError = class extends Error {
|
|
23
|
-
constructor() {
|
|
24
|
-
super(
|
|
25
|
-
'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.'
|
|
26
|
-
);
|
|
27
|
-
this.name = "MissingAuraApiKeyError";
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
64
|
|
|
31
65
|
// src/resources/agents.ts
|
|
32
66
|
function registerAgentResources(server) {
|
|
@@ -65,6 +99,55 @@ function registerAgentResources(server) {
|
|
|
65
99
|
}
|
|
66
100
|
);
|
|
67
101
|
}
|
|
102
|
+
var COLLECTION_LIMIT = 50;
|
|
103
|
+
function registerEscrowResources(server) {
|
|
104
|
+
server.resource("escrows", "aura://escrows", async (uri) => {
|
|
105
|
+
const client = getClient();
|
|
106
|
+
const page = await client.escrows.list({ limit: COLLECTION_LIMIT });
|
|
107
|
+
return {
|
|
108
|
+
contents: [
|
|
109
|
+
{
|
|
110
|
+
uri: uri.href,
|
|
111
|
+
mimeType: "application/json",
|
|
112
|
+
text: JSON.stringify(page, null, 2)
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
server.resource(
|
|
118
|
+
"escrow",
|
|
119
|
+
new ResourceTemplate("aura://escrows/{id}", { list: void 0 }),
|
|
120
|
+
async (uri, { id }) => {
|
|
121
|
+
const client = getClient();
|
|
122
|
+
const escrow = await client.escrows.get(String(id));
|
|
123
|
+
return {
|
|
124
|
+
contents: [
|
|
125
|
+
{
|
|
126
|
+
uri: uri.href,
|
|
127
|
+
mimeType: "application/json",
|
|
128
|
+
text: JSON.stringify(escrow, null, 2)
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/resources/insights.ts
|
|
137
|
+
function registerInsightsResources(server, clientFactory = getClient) {
|
|
138
|
+
server.resource("insights-overview", "aura://insights/overview", async (uri) => {
|
|
139
|
+
const overview = await clientFactory().insights.overview();
|
|
140
|
+
return {
|
|
141
|
+
contents: [
|
|
142
|
+
{
|
|
143
|
+
uri: uri.href,
|
|
144
|
+
mimeType: "application/json",
|
|
145
|
+
text: JSON.stringify(overview, null, 2)
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
68
151
|
function registerMandateResources(server) {
|
|
69
152
|
server.resource(
|
|
70
153
|
"mandates-pending",
|
|
@@ -101,6 +184,108 @@ function registerMandateResources(server) {
|
|
|
101
184
|
}
|
|
102
185
|
);
|
|
103
186
|
}
|
|
187
|
+
var COLLECTION_LIMIT2 = 50;
|
|
188
|
+
function registerWalletResources(server) {
|
|
189
|
+
server.resource("wallets", "aura://wallets", async (uri) => {
|
|
190
|
+
const client = getClient();
|
|
191
|
+
const page = await client.wallets.list({ limit: COLLECTION_LIMIT2 });
|
|
192
|
+
return {
|
|
193
|
+
contents: [
|
|
194
|
+
{
|
|
195
|
+
uri: uri.href,
|
|
196
|
+
mimeType: "application/json",
|
|
197
|
+
text: JSON.stringify(page, null, 2)
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
server.resource(
|
|
203
|
+
"wallet",
|
|
204
|
+
new ResourceTemplate("aura://wallets/{id}", { list: void 0 }),
|
|
205
|
+
async (uri, { id }) => {
|
|
206
|
+
const client = getClient();
|
|
207
|
+
const wallet = await client.wallets.get(String(id));
|
|
208
|
+
return {
|
|
209
|
+
contents: [
|
|
210
|
+
{
|
|
211
|
+
uri: uri.href,
|
|
212
|
+
mimeType: "application/json",
|
|
213
|
+
text: JSON.stringify(wallet, null, 2)
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
server.resource(
|
|
220
|
+
"wallet-balance",
|
|
221
|
+
new ResourceTemplate("aura://wallets/{id}/balance", { list: void 0 }),
|
|
222
|
+
async (uri, { id }) => {
|
|
223
|
+
const client = getClient();
|
|
224
|
+
const balance = await client.wallets.getBalance(String(id));
|
|
225
|
+
return {
|
|
226
|
+
contents: [
|
|
227
|
+
{
|
|
228
|
+
uri: uri.href,
|
|
229
|
+
mimeType: "application/json",
|
|
230
|
+
text: JSON.stringify(balance, null, 2)
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
var COLLECTION_LIMIT3 = 50;
|
|
238
|
+
var WithdrawalIdSchema = z.string().uuid();
|
|
239
|
+
function registerWithdrawalResources(server, clientFactory = getClient) {
|
|
240
|
+
server.resource("withdrawals", "aura://withdrawals", async (uri) => {
|
|
241
|
+
const page = await clientFactory().withdrawals.list({ limit: COLLECTION_LIMIT3 });
|
|
242
|
+
return {
|
|
243
|
+
contents: [
|
|
244
|
+
{
|
|
245
|
+
uri: uri.href,
|
|
246
|
+
mimeType: "application/json",
|
|
247
|
+
text: JSON.stringify(page, null, 2)
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
server.resource(
|
|
253
|
+
"withdrawal",
|
|
254
|
+
new ResourceTemplate("aura://withdrawals/{id}", { list: void 0 }),
|
|
255
|
+
async (uri, { id }) => {
|
|
256
|
+
const parsed = WithdrawalIdSchema.safeParse(Array.isArray(id) ? id[0] : id);
|
|
257
|
+
if (!parsed.success) {
|
|
258
|
+
throw new Error(`Invalid withdrawal id in ${uri.href}: expected a UUID`);
|
|
259
|
+
}
|
|
260
|
+
const withdrawal = await clientFactory().withdrawals.get(parsed.data);
|
|
261
|
+
return {
|
|
262
|
+
contents: [
|
|
263
|
+
{
|
|
264
|
+
uri: uri.href,
|
|
265
|
+
mimeType: "application/json",
|
|
266
|
+
text: JSON.stringify(withdrawal, null, 2)
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/annotations.ts
|
|
275
|
+
function readOnly(title) {
|
|
276
|
+
return { title, readOnlyHint: true };
|
|
277
|
+
}
|
|
278
|
+
function write(title, idempotent = false) {
|
|
279
|
+
return {
|
|
280
|
+
title,
|
|
281
|
+
readOnlyHint: false,
|
|
282
|
+
destructiveHint: false,
|
|
283
|
+
...idempotent ? { idempotentHint: true } : {}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function destructive(title) {
|
|
287
|
+
return { title, readOnlyHint: false, destructiveHint: true };
|
|
288
|
+
}
|
|
104
289
|
async function withToolErrorHandling(body, successFormatter = defaultJsonFormatter) {
|
|
105
290
|
try {
|
|
106
291
|
const result = await body();
|
|
@@ -115,7 +300,7 @@ function defaultJsonFormatter(data) {
|
|
|
115
300
|
return JSON.stringify(data, null, 2);
|
|
116
301
|
}
|
|
117
302
|
function formatError(err) {
|
|
118
|
-
if (err instanceof MissingAuraApiKeyError) {
|
|
303
|
+
if (err instanceof MissingAuraApiKeyError || err instanceof MalformedAuraApiKeyError) {
|
|
119
304
|
return errorResult("CONFIG_ERROR", err.message);
|
|
120
305
|
}
|
|
121
306
|
if (err instanceof AuraAuthenticationError) {
|
|
@@ -203,6 +388,8 @@ function registerAgentTools(server) {
|
|
|
203
388
|
autoApproveBelow: z.string().optional()
|
|
204
389
|
}).optional()
|
|
205
390
|
},
|
|
391
|
+
// Additive: provisions a new agent and its wallet. No funds move.
|
|
392
|
+
write("Create Agent"),
|
|
206
393
|
async (args) => withToolErrorHandling(async () => {
|
|
207
394
|
const client = getClient();
|
|
208
395
|
return client.agents.create(args);
|
|
@@ -217,6 +404,7 @@ function registerAgentTools(server) {
|
|
|
217
404
|
limit: z.number().int().min(1).max(200).optional(),
|
|
218
405
|
offset: z.number().int().min(0).optional()
|
|
219
406
|
},
|
|
407
|
+
readOnly("List Agents"),
|
|
220
408
|
async (args) => withToolErrorHandling(async () => {
|
|
221
409
|
const client = getClient();
|
|
222
410
|
return client.agents.list(args);
|
|
@@ -228,6 +416,7 @@ function registerAgentTools(server) {
|
|
|
228
416
|
{
|
|
229
417
|
agentId: z.string().uuid()
|
|
230
418
|
},
|
|
419
|
+
readOnly("Get Agent"),
|
|
231
420
|
async ({ agentId }) => withToolErrorHandling(async () => {
|
|
232
421
|
const client = getClient();
|
|
233
422
|
return client.agents.get(agentId);
|
|
@@ -239,6 +428,7 @@ function registerAgentTools(server) {
|
|
|
239
428
|
{
|
|
240
429
|
agentId: z.string().uuid()
|
|
241
430
|
},
|
|
431
|
+
readOnly("Get Agent Balance"),
|
|
242
432
|
async ({ agentId }) => withToolErrorHandling(async () => {
|
|
243
433
|
const client = getClient();
|
|
244
434
|
return client.agents.getBalance(agentId);
|
|
@@ -251,6 +441,8 @@ function registerAgentTools(server) {
|
|
|
251
441
|
agentId: z.string().uuid(),
|
|
252
442
|
reason: z.string().max(500).optional().describe("Surfaced in activity event metadata for audit trail")
|
|
253
443
|
},
|
|
444
|
+
// Halts an existing agent AND cascade-rejects its in-flight mandates.
|
|
445
|
+
destructive("Freeze Agent (kill switch)"),
|
|
254
446
|
async (args) => withToolErrorHandling(async () => {
|
|
255
447
|
const client = getClient();
|
|
256
448
|
return client.agents.freeze(args);
|
|
@@ -262,6 +454,8 @@ function registerAgentTools(server) {
|
|
|
262
454
|
{
|
|
263
455
|
agentId: z.string().uuid()
|
|
264
456
|
},
|
|
457
|
+
// Re-enables autonomous spending on an existing agent.
|
|
458
|
+
destructive("Unfreeze Agent (resumes autonomous spending)"),
|
|
265
459
|
async (args) => withToolErrorHandling(async () => {
|
|
266
460
|
const client = getClient();
|
|
267
461
|
return client.agents.unfreeze(args);
|
|
@@ -278,11 +472,24 @@ function registerAgentTools(server) {
|
|
|
278
472
|
reasoning: z.string().optional(),
|
|
279
473
|
metadata: z.record(z.unknown()).optional()
|
|
280
474
|
},
|
|
475
|
+
// NOT read-only despite being a dry run: when the decision requires human
|
|
476
|
+
// approval the engine persists a new mandate row. Additive, never
|
|
477
|
+
// destructive — it cannot execute the transaction it evaluates.
|
|
478
|
+
write("Evaluate Policy (dry run, may create a mandate)"),
|
|
281
479
|
async (args) => withToolErrorHandling(async () => {
|
|
282
480
|
const client = getClient();
|
|
283
481
|
return client.agents.evaluate(args);
|
|
284
482
|
})
|
|
285
483
|
);
|
|
484
|
+
return [
|
|
485
|
+
"aura_create_agent",
|
|
486
|
+
"aura_list_agents",
|
|
487
|
+
"aura_get_agent",
|
|
488
|
+
"aura_get_agent_balance",
|
|
489
|
+
"aura_freeze_agent",
|
|
490
|
+
"aura_unfreeze_agent",
|
|
491
|
+
"aura_evaluate_policy"
|
|
492
|
+
];
|
|
286
493
|
}
|
|
287
494
|
var ChainSchema2 = z.enum(["ARC", "ARB", "BASE", "ETH", "MATIC"]);
|
|
288
495
|
var SplitInputSchema = z.object({
|
|
@@ -319,6 +526,8 @@ function registerEscrowTools(server) {
|
|
|
319
526
|
chain: ChainSchema2.optional().describe("Target chain. Defaults to ARC"),
|
|
320
527
|
splits: z.array(SplitInputSchema).min(1).describe("Payment splits. Percentages must sum to 100.")
|
|
321
528
|
},
|
|
529
|
+
// Additive: creates a new escrow record. No funds move until `fund`.
|
|
530
|
+
write("Create Escrow"),
|
|
322
531
|
async (args) => withToolErrorHandling(async () => {
|
|
323
532
|
const client = getClient();
|
|
324
533
|
return client.escrows.create(args);
|
|
@@ -330,6 +539,7 @@ function registerEscrowTools(server) {
|
|
|
330
539
|
{
|
|
331
540
|
escrowId: z.string().uuid()
|
|
332
541
|
},
|
|
542
|
+
readOnly("Get Escrow"),
|
|
333
543
|
async ({ escrowId }) => withToolErrorHandling(async () => {
|
|
334
544
|
const client = getClient();
|
|
335
545
|
return client.escrows.get(escrowId);
|
|
@@ -354,6 +564,7 @@ function registerEscrowTools(server) {
|
|
|
354
564
|
limit: z.number().int().min(1).max(200).optional(),
|
|
355
565
|
offset: z.number().int().min(0).optional()
|
|
356
566
|
},
|
|
567
|
+
readOnly("List Escrows"),
|
|
357
568
|
async (args) => withToolErrorHandling(async () => {
|
|
358
569
|
const client = getClient();
|
|
359
570
|
return client.escrows.list(args);
|
|
@@ -368,6 +579,8 @@ function registerEscrowTools(server) {
|
|
|
368
579
|
amount: z.string().describe("USDC amount to fund (whole-number string)"),
|
|
369
580
|
correlationId: z.string().optional()
|
|
370
581
|
},
|
|
582
|
+
// Moves USDC out of the buyer wallet.
|
|
583
|
+
destructive("Fund Escrow (moves USDC)"),
|
|
371
584
|
async (args) => withToolErrorHandling(async () => {
|
|
372
585
|
const client = getClient();
|
|
373
586
|
return client.escrows.fund(args);
|
|
@@ -382,6 +595,8 @@ function registerEscrowTools(server) {
|
|
|
382
595
|
reason: z.string().optional(),
|
|
383
596
|
correlationId: z.string().optional()
|
|
384
597
|
},
|
|
598
|
+
// Irreversible payout to the split recipients.
|
|
599
|
+
destructive("Release Escrow (pays out USDC)"),
|
|
385
600
|
async (args) => withToolErrorHandling(async () => {
|
|
386
601
|
const client = getClient();
|
|
387
602
|
return client.escrows.release(args);
|
|
@@ -395,6 +610,8 @@ function registerEscrowTools(server) {
|
|
|
395
610
|
reason: z.string().min(10),
|
|
396
611
|
actorId: z.string().uuid()
|
|
397
612
|
},
|
|
613
|
+
// Irreversible return of funds to the buyer.
|
|
614
|
+
destructive("Refund Escrow (returns USDC to buyer)"),
|
|
398
615
|
async (args) => withToolErrorHandling(async () => {
|
|
399
616
|
const client = getClient();
|
|
400
617
|
return client.escrows.refund(args);
|
|
@@ -414,11 +631,134 @@ function registerEscrowTools(server) {
|
|
|
414
631
|
waitForDeploymentMs: z.number().int().min(0).optional().describe("Max ms to wait for on-chain deployment. Default 60000."),
|
|
415
632
|
waitForFundingMs: z.number().int().min(0).optional().describe("Max ms to wait for funds to settle (funded/locked) before releasing. Default 60000.")
|
|
416
633
|
},
|
|
634
|
+
// Composes create -> fund -> release: money moves and is paid out.
|
|
635
|
+
destructive("Receive and Split (moves and pays out USDC)"),
|
|
417
636
|
async (args) => withToolErrorHandling(async () => {
|
|
418
637
|
const client = getClient();
|
|
419
638
|
return client.escrows.receiveAndSplit(args);
|
|
420
639
|
})
|
|
421
640
|
);
|
|
641
|
+
return [
|
|
642
|
+
"aura_create_escrow",
|
|
643
|
+
"aura_get_escrow",
|
|
644
|
+
"aura_list_escrows",
|
|
645
|
+
"aura_fund_escrow",
|
|
646
|
+
"aura_release_escrow",
|
|
647
|
+
"aura_refund_escrow",
|
|
648
|
+
"aura_receive_and_split"
|
|
649
|
+
];
|
|
650
|
+
}
|
|
651
|
+
function validationError(error) {
|
|
652
|
+
const detail = error.issues.map((issue) => `${issue.path.join(".") || "(input)"}: ${issue.message}`).join("; ");
|
|
653
|
+
return toolError("VALIDATION_ERROR", detail);
|
|
654
|
+
}
|
|
655
|
+
function addCustomRangeIssues(ctx, field, selector, start, end) {
|
|
656
|
+
if (selector === "custom" && (start === void 0 || end === void 0)) {
|
|
657
|
+
ctx.addIssue({
|
|
658
|
+
code: z.ZodIssueCode.custom,
|
|
659
|
+
path: [start === void 0 ? "start" : "end"],
|
|
660
|
+
message: `start and end are both required when ${field} is 'custom'`
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
if (start !== void 0 && end !== void 0 && Date.parse(start) > Date.parse(end)) {
|
|
664
|
+
ctx.addIssue({
|
|
665
|
+
code: z.ZodIssueCode.custom,
|
|
666
|
+
path: ["end"],
|
|
667
|
+
message: "end must be at or after start"
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/tools/insights.ts
|
|
673
|
+
var PeriodSchema = z.enum(["today", "7d", "30d", "90d", "custom"]);
|
|
674
|
+
var DateTimeSchema = z.string().datetime();
|
|
675
|
+
var overviewShape = {
|
|
676
|
+
period: PeriodSchema.optional().describe(
|
|
677
|
+
"Window to report on (default 7d). 'custom' requires start and end."
|
|
678
|
+
),
|
|
679
|
+
start: DateTimeSchema.optional().describe("ISO 8601 datetime; required when period is custom"),
|
|
680
|
+
end: DateTimeSchema.optional().describe("ISO 8601 datetime; required when period is custom")
|
|
681
|
+
};
|
|
682
|
+
var InsightsOverviewInput = z.object(overviewShape).superRefine(
|
|
683
|
+
(value, ctx) => addCustomRangeIssues(ctx, "period", value.period, value.start, value.end)
|
|
684
|
+
);
|
|
685
|
+
var auditShape = {
|
|
686
|
+
action: z.string().min(1).optional().describe("Audit action name, e.g. escrow.released"),
|
|
687
|
+
actor: z.enum(["user", "system", "api", "cron", "webhook"]).optional(),
|
|
688
|
+
resourceType: z.string().min(1).optional().describe("Resource kind, e.g. escrow"),
|
|
689
|
+
// `.min(1)`, not `.uuid()`: the route accepts any string here
|
|
690
|
+
// (`resourceId: z.string().optional()`, insights/audit/route.ts:26) and the
|
|
691
|
+
// audit log records ids from several subsystems, not all of them UUIDs.
|
|
692
|
+
resourceId: z.string().min(1).optional().describe("Id of the audited resource"),
|
|
693
|
+
range: PeriodSchema.optional().describe(
|
|
694
|
+
"Window to query (default 30d). 'custom' requires start and end."
|
|
695
|
+
),
|
|
696
|
+
start: DateTimeSchema.optional().describe("ISO 8601 datetime; required when range is custom"),
|
|
697
|
+
end: DateTimeSchema.optional().describe("ISO 8601 datetime; required when range is custom"),
|
|
698
|
+
page: z.number().int().min(1).optional().describe("1-based page number (default 1)"),
|
|
699
|
+
limit: z.number().int().min(1).max(100).optional().describe("Page size, 1-100 (default 50)")
|
|
700
|
+
};
|
|
701
|
+
var InsightsAuditInput = z.object(auditShape).superRefine(
|
|
702
|
+
(value, ctx) => addCustomRangeIssues(ctx, "range", value.range, value.start, value.end)
|
|
703
|
+
);
|
|
704
|
+
function registerInsightsTools(server, clientFactory = getClient) {
|
|
705
|
+
server.tool(
|
|
706
|
+
"aura_insights_overview",
|
|
707
|
+
"Revenue, transaction count, active escrows and commissions for a period, each with its change against the previous period, plus sparkline and success-rate charts.",
|
|
708
|
+
overviewShape,
|
|
709
|
+
readOnly("Insights Overview"),
|
|
710
|
+
async (args) => {
|
|
711
|
+
const parsed = InsightsOverviewInput.safeParse(args);
|
|
712
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
713
|
+
const { period, start, end } = parsed.data;
|
|
714
|
+
return withToolErrorHandling(
|
|
715
|
+
async () => clientFactory().insights.overview(period, start, end)
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
server.tool(
|
|
720
|
+
"aura_insights_forecast",
|
|
721
|
+
"Project a metric forward over a horizon using the requested algorithm. Requires a Growth or higher plan \u2014 lower tiers return feature_not_available.",
|
|
722
|
+
{
|
|
723
|
+
metric: z.enum([
|
|
724
|
+
"revenue",
|
|
725
|
+
"transaction_count",
|
|
726
|
+
"escrow_count",
|
|
727
|
+
"commission",
|
|
728
|
+
"avg_transaction_value"
|
|
729
|
+
]),
|
|
730
|
+
algorithm: z.enum([
|
|
731
|
+
"linear_regression",
|
|
732
|
+
"moving_average",
|
|
733
|
+
"exponential_smoothing",
|
|
734
|
+
"arima",
|
|
735
|
+
"prophet",
|
|
736
|
+
"ensemble"
|
|
737
|
+
]).optional(),
|
|
738
|
+
period: z.enum(["daily", "weekly", "monthly"]).optional().describe("Granularity of each projected point"),
|
|
739
|
+
horizon: z.number().int().min(1).max(365).optional().describe("Number of periods to project"),
|
|
740
|
+
// Known platform quirk: the route parses this with `z.coerce.boolean()`
|
|
741
|
+
// on a query string, where any non-empty value — including "false" —
|
|
742
|
+
// coerces to true. Passing false therefore does not currently suppress
|
|
743
|
+
// history; that is a platform-side fix, not one to paper over here.
|
|
744
|
+
includeHistory: z.boolean().optional().describe("Include the historical series alongside the projection"),
|
|
745
|
+
historyPeriods: z.number().int().min(1).max(365).optional()
|
|
746
|
+
},
|
|
747
|
+
readOnly("Insights Forecast"),
|
|
748
|
+
async (args) => withToolErrorHandling(async () => clientFactory().insights.forecast(args))
|
|
749
|
+
);
|
|
750
|
+
server.tool(
|
|
751
|
+
"aura_insights_audit",
|
|
752
|
+
"Query the account audit log by action, actor, resource and date range. Paginated, most recent first.",
|
|
753
|
+
auditShape,
|
|
754
|
+
readOnly("Insights Audit"),
|
|
755
|
+
async (args) => {
|
|
756
|
+
const parsed = InsightsAuditInput.safeParse(args);
|
|
757
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
758
|
+
return withToolErrorHandling(async () => clientFactory().insights.audit(parsed.data));
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
return ["aura_insights_overview", "aura_insights_forecast", "aura_insights_audit"];
|
|
422
762
|
}
|
|
423
763
|
function registerMandateTools(server) {
|
|
424
764
|
server.tool(
|
|
@@ -430,6 +770,7 @@ function registerMandateTools(server) {
|
|
|
430
770
|
limit: z.number().int().min(1).max(200).optional(),
|
|
431
771
|
cursor: z.string().uuid().optional().describe("Last mandate id from the previous page")
|
|
432
772
|
},
|
|
773
|
+
readOnly("List Mandates (approval inbox)"),
|
|
433
774
|
async (args) => withToolErrorHandling(async () => {
|
|
434
775
|
const client = getClient();
|
|
435
776
|
return client.mandates.list(args);
|
|
@@ -441,6 +782,7 @@ function registerMandateTools(server) {
|
|
|
441
782
|
{
|
|
442
783
|
mandateId: z.string().uuid()
|
|
443
784
|
},
|
|
785
|
+
readOnly("Get Mandate"),
|
|
444
786
|
async ({ mandateId }) => withToolErrorHandling(async () => {
|
|
445
787
|
const client = getClient();
|
|
446
788
|
return client.mandates.get(mandateId);
|
|
@@ -455,6 +797,8 @@ function registerMandateTools(server) {
|
|
|
455
797
|
decisionSignature: z.string().min(16).describe("HMAC-SHA256 hex digest, computed by the caller"),
|
|
456
798
|
decidedAt: z.string().datetime().optional().describe('ISO-8601 timestamp the signature commits to. Defaults to "now" server-side.')
|
|
457
799
|
},
|
|
800
|
+
// Authorizes the agent's intended payment — the money-moving decision.
|
|
801
|
+
destructive("Approve Mandate (authorizes payment)"),
|
|
458
802
|
async (args) => withToolErrorHandling(async () => {
|
|
459
803
|
const client = getClient();
|
|
460
804
|
return client.mandates.approve(args);
|
|
@@ -470,11 +814,31 @@ function registerMandateTools(server) {
|
|
|
470
814
|
decidedAt: z.string().datetime().optional(),
|
|
471
815
|
reason: z.string().optional().describe("Human-readable reason logged to the activity feed")
|
|
472
816
|
},
|
|
817
|
+
// Terminal decision on an existing mandate — the agent cannot resume it.
|
|
818
|
+
destructive("Reject Mandate"),
|
|
473
819
|
async (args) => withToolErrorHandling(async () => {
|
|
474
820
|
const client = getClient();
|
|
475
821
|
return client.mandates.reject(args);
|
|
476
822
|
})
|
|
477
823
|
);
|
|
824
|
+
return [
|
|
825
|
+
"aura_list_mandates",
|
|
826
|
+
"aura_get_mandate",
|
|
827
|
+
"aura_approve_mandate",
|
|
828
|
+
"aura_reject_mandate"
|
|
829
|
+
];
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// src/tools/treasury.ts
|
|
833
|
+
function registerTreasuryTools(server, clientFactory = getClient) {
|
|
834
|
+
server.tool(
|
|
835
|
+
"aura_treasury_optimize",
|
|
836
|
+
"Analyze treasury balances, active escrows and pending payouts, and return an AI recommendation on how to rebalance. Read-only: it recommends, it does not move funds. Requires a Growth or higher plan \u2014 lower tiers return feature_not_available.",
|
|
837
|
+
{},
|
|
838
|
+
readOnly("Treasury Optimize"),
|
|
839
|
+
async () => withToolErrorHandling(async () => clientFactory().treasury.optimize())
|
|
840
|
+
);
|
|
841
|
+
return ["aura_treasury_optimize"];
|
|
478
842
|
}
|
|
479
843
|
var TestnetChainSchema = z.enum(["ARC", "ARB", "BASE"]);
|
|
480
844
|
function walletCreateEnabled() {
|
|
@@ -488,6 +852,7 @@ function registerWalletTools(server) {
|
|
|
488
852
|
{
|
|
489
853
|
walletId: z.string().uuid()
|
|
490
854
|
},
|
|
855
|
+
readOnly("Get Wallet Balance"),
|
|
491
856
|
async ({ walletId }) => withToolErrorHandling(async () => {
|
|
492
857
|
const client = getClient();
|
|
493
858
|
return client.wallets.getBalance(walletId);
|
|
@@ -511,6 +876,8 @@ function registerWalletTools(server) {
|
|
|
511
876
|
"tax"
|
|
512
877
|
]).optional().describe("Wallet owner type. Defaults to BUSINESS.")
|
|
513
878
|
},
|
|
879
|
+
// Additive and create-or-get: provisions a receive address, moves no money.
|
|
880
|
+
write("Create Wallet (receive address)", true),
|
|
514
881
|
async ({ entityId, chain, type }) => {
|
|
515
882
|
if (!walletCreateEnabled()) {
|
|
516
883
|
return toolError(
|
|
@@ -532,31 +899,239 @@ function registerWalletTools(server) {
|
|
|
532
899
|
token: z.string().optional().describe("Token to drip. Defaults to 'USDC'."),
|
|
533
900
|
chain: TestnetChainSchema.optional().describe("Override the wallet's chain.")
|
|
534
901
|
},
|
|
902
|
+
// Additive: testnet-only drip that adds play funds, destroys nothing.
|
|
903
|
+
write("Request Testnet Funds"),
|
|
535
904
|
async ({ walletId, token, chain }) => withToolErrorHandling(async () => {
|
|
536
905
|
const client = getClient();
|
|
537
906
|
return client.wallets.requestTestnetFunds(walletId, { token, chain });
|
|
538
907
|
})
|
|
539
908
|
);
|
|
909
|
+
return [
|
|
910
|
+
"aura_get_wallet_balance",
|
|
911
|
+
"aura_create_wallet",
|
|
912
|
+
"aura_request_testnet_funds"
|
|
913
|
+
];
|
|
914
|
+
}
|
|
915
|
+
var WebhookEventTypeSchema = z.enum([
|
|
916
|
+
"*",
|
|
917
|
+
"escrow.created",
|
|
918
|
+
"escrow.funded",
|
|
919
|
+
"escrow.locked",
|
|
920
|
+
"escrow.released",
|
|
921
|
+
"escrow.refunded",
|
|
922
|
+
"escrow.disputed",
|
|
923
|
+
"transfer.completed",
|
|
924
|
+
"transfer.failed",
|
|
925
|
+
"withdrawal.created",
|
|
926
|
+
"withdrawal.processing",
|
|
927
|
+
"withdrawal.completed",
|
|
928
|
+
"withdrawal.failed",
|
|
929
|
+
"account.kyc_approved",
|
|
930
|
+
"account.kyc_rejected",
|
|
931
|
+
"account.tier_upgraded",
|
|
932
|
+
"security.api_key_created",
|
|
933
|
+
"security.api_key_revoked"
|
|
934
|
+
]);
|
|
935
|
+
function registerWebhookTools(server) {
|
|
936
|
+
server.tool(
|
|
937
|
+
"aura_get_webhook_config",
|
|
938
|
+
"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.",
|
|
939
|
+
{},
|
|
940
|
+
readOnly("Get Webhook Config"),
|
|
941
|
+
async () => withToolErrorHandling(async () => {
|
|
942
|
+
const client = getClient();
|
|
943
|
+
return client.webhooks.getConfig();
|
|
944
|
+
})
|
|
945
|
+
);
|
|
946
|
+
server.tool(
|
|
947
|
+
"aura_set_webhook_config",
|
|
948
|
+
"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.",
|
|
949
|
+
{
|
|
950
|
+
url: z.string().url().describe("HTTPS endpoint that will receive event POSTs"),
|
|
951
|
+
events: z.array(WebhookEventTypeSchema).min(1).optional().describe(
|
|
952
|
+
"Event types to subscribe to. Omit to subscribe to all events, or pass ['*'] explicitly."
|
|
953
|
+
),
|
|
954
|
+
description: z.string().optional().describe("Optional human-readable label")
|
|
955
|
+
},
|
|
956
|
+
destructive("Set Webhook Config (replaces existing)"),
|
|
957
|
+
async (args) => withToolErrorHandling(async () => {
|
|
958
|
+
const client = getClient();
|
|
959
|
+
return client.webhooks.configure(args);
|
|
960
|
+
})
|
|
961
|
+
);
|
|
962
|
+
server.tool(
|
|
963
|
+
"aura_delete_webhook_config",
|
|
964
|
+
"Delete the account webhook configuration. Event delivery stops immediately and the signing secret is invalidated \u2014 reconfiguring issues a new secret.",
|
|
965
|
+
{},
|
|
966
|
+
destructive("Delete Webhook Config"),
|
|
967
|
+
async () => withToolErrorHandling(async () => {
|
|
968
|
+
const client = getClient();
|
|
969
|
+
return client.webhooks.delete();
|
|
970
|
+
})
|
|
971
|
+
);
|
|
972
|
+
return [
|
|
973
|
+
"aura_get_webhook_config",
|
|
974
|
+
"aura_set_webhook_config",
|
|
975
|
+
"aura_delete_webhook_config"
|
|
976
|
+
];
|
|
977
|
+
}
|
|
978
|
+
var ChainSchema3 = z.enum(["ARC", "ETH", "BASE", "ARB", "MATIC"]);
|
|
979
|
+
var AmountSchema = z.string().regex(
|
|
980
|
+
/^\d+(\.\d{1,6})?$/,
|
|
981
|
+
'Amount must be a number string with up to 6 decimal places, e.g. "100.00"'
|
|
982
|
+
);
|
|
983
|
+
var EvmAddressSchema = z.string().regex(
|
|
984
|
+
/^0x[a-fA-F0-9]{40}$/,
|
|
985
|
+
"Must be an EVM address: 0x followed by 40 hexadecimal characters"
|
|
986
|
+
);
|
|
987
|
+
var ExchangeSchema = z.enum(["binance", "coinbase", "kraken", "other"]);
|
|
988
|
+
var FeeConfigSchema = z.enum(["FREE", "GAS_ONLY", "STANDARD"]);
|
|
989
|
+
var StatusSchema = z.enum(["pending", "submitted", "confirmed", "failed", "cancelled"]);
|
|
990
|
+
var WithdrawalIdSchema2 = z.string().uuid("Withdrawal id must be a UUID");
|
|
991
|
+
var estimateShape = {
|
|
992
|
+
// `.min(1)`, not `.uuid()`: the route accepts any non-empty string here
|
|
993
|
+
// (`walletId: z.string().min(1)`, estimate/route.ts:56). Requiring a UUID
|
|
994
|
+
// would make this tool reject wallet ids the platform itself accepts.
|
|
995
|
+
walletId: z.string().min(1).describe("Source wallet id to debit"),
|
|
996
|
+
amount: AmountSchema.describe('USDC amount as a string, e.g. "100.00"'),
|
|
997
|
+
destinationType: z.enum(["exchange", "wallet"]).describe("Where the funds land. 'exchange' also requires `exchange`."),
|
|
998
|
+
destinationAddress: EvmAddressSchema.describe("Destination EVM address"),
|
|
999
|
+
chain: ChainSchema3.describe("Chain the funds are delivered on"),
|
|
1000
|
+
exchange: ExchangeSchema.optional().describe(
|
|
1001
|
+
"Required when destinationType is 'exchange'"
|
|
1002
|
+
),
|
|
1003
|
+
sourceChain: ChainSchema3.optional().describe(
|
|
1004
|
+
"Chain the funds start on. Differs from `chain` for a bridged withdrawal; defaults to ARC."
|
|
1005
|
+
),
|
|
1006
|
+
feeConfig: FeeConfigSchema.optional()
|
|
1007
|
+
};
|
|
1008
|
+
var EstimateWithdrawalInput = z.object(estimateShape).superRefine((value, ctx) => {
|
|
1009
|
+
if (value.destinationType === "exchange" && value.exchange === void 0) {
|
|
1010
|
+
ctx.addIssue({
|
|
1011
|
+
code: z.ZodIssueCode.custom,
|
|
1012
|
+
path: ["exchange"],
|
|
1013
|
+
message: "exchange is required when destinationType is 'exchange'"
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
function registerWithdrawalTools(server, clientFactory = getClient) {
|
|
1018
|
+
server.tool(
|
|
1019
|
+
"aura_get_withdrawal",
|
|
1020
|
+
"Get a single withdrawal by id: status, amount, fees, destination, chain and transaction hash.",
|
|
1021
|
+
{ withdrawalId: WithdrawalIdSchema2.describe("The withdrawal id (UUID)") },
|
|
1022
|
+
readOnly("Get Withdrawal"),
|
|
1023
|
+
async ({ withdrawalId }) => withToolErrorHandling(async () => clientFactory().withdrawals.get(withdrawalId))
|
|
1024
|
+
);
|
|
1025
|
+
server.tool(
|
|
1026
|
+
"aura_list_withdrawals",
|
|
1027
|
+
"List withdrawals for the account, most recent first. Filter by status, chain and date range.",
|
|
1028
|
+
{
|
|
1029
|
+
limit: z.number().int().min(1).max(100).optional().describe("Page size, 1-100 (default 50)"),
|
|
1030
|
+
offset: z.number().int().min(0).optional().describe("Rows to skip (default 0)"),
|
|
1031
|
+
status: StatusSchema.optional(),
|
|
1032
|
+
chain: ChainSchema3.optional(),
|
|
1033
|
+
fromDate: z.string().datetime().optional().describe("ISO 8601 datetime, inclusive lower bound"),
|
|
1034
|
+
toDate: z.string().datetime().optional().describe("ISO 8601 datetime, inclusive upper bound")
|
|
1035
|
+
},
|
|
1036
|
+
readOnly("List Withdrawals"),
|
|
1037
|
+
async (args) => withToolErrorHandling(async () => clientFactory().withdrawals.list(args))
|
|
1038
|
+
);
|
|
1039
|
+
server.tool(
|
|
1040
|
+
"aura_estimate_withdrawal",
|
|
1041
|
+
"Preview the fees, net amount and confirmation time for a withdrawal WITHOUT creating it. Moves no funds. Use this before quoting a payout to a user.",
|
|
1042
|
+
estimateShape,
|
|
1043
|
+
readOnly("Estimate Withdrawal"),
|
|
1044
|
+
async (args) => {
|
|
1045
|
+
const parsed = EstimateWithdrawalInput.safeParse(args);
|
|
1046
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
1047
|
+
return withToolErrorHandling(
|
|
1048
|
+
async () => clientFactory().withdrawals.estimate(parsed.data)
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
);
|
|
1052
|
+
server.tool(
|
|
1053
|
+
"aura_get_withdrawal_limits",
|
|
1054
|
+
"Get the account KYC-tier withdrawal limits and how much of the daily and monthly allowance is still available.",
|
|
1055
|
+
{},
|
|
1056
|
+
readOnly("Get Withdrawal Limits"),
|
|
1057
|
+
async () => withToolErrorHandling(async () => clientFactory().withdrawals.limits())
|
|
1058
|
+
);
|
|
1059
|
+
server.tool(
|
|
1060
|
+
"aura_validate_withdrawal_address",
|
|
1061
|
+
"Check that a destination address is well-formed and usable on a chain, and preview the fee when an amount is given. Moves no funds.",
|
|
1062
|
+
{
|
|
1063
|
+
address: EvmAddressSchema.describe("Destination EVM address to check"),
|
|
1064
|
+
chain: ChainSchema3,
|
|
1065
|
+
amount: AmountSchema.optional().describe(
|
|
1066
|
+
"Optional \u2014 when supplied the response includes a fee preview"
|
|
1067
|
+
),
|
|
1068
|
+
feeConfig: FeeConfigSchema.optional()
|
|
1069
|
+
},
|
|
1070
|
+
readOnly("Validate Withdrawal Address"),
|
|
1071
|
+
async (args) => withToolErrorHandling(async () => clientFactory().withdrawals.validate(args))
|
|
1072
|
+
);
|
|
1073
|
+
return [
|
|
1074
|
+
"aura_get_withdrawal",
|
|
1075
|
+
"aura_list_withdrawals",
|
|
1076
|
+
"aura_estimate_withdrawal",
|
|
1077
|
+
"aura_get_withdrawal_limits",
|
|
1078
|
+
"aura_validate_withdrawal_address"
|
|
1079
|
+
];
|
|
540
1080
|
}
|
|
541
1081
|
|
|
542
1082
|
// src/index.ts
|
|
1083
|
+
var SERVER_NAME = "aura-payments";
|
|
1084
|
+
var SERVER_VERSION = "1.2.0";
|
|
1085
|
+
var toolManifests = /* @__PURE__ */ new WeakMap();
|
|
1086
|
+
function getRegisteredToolNames(server) {
|
|
1087
|
+
return toolManifests.get(server) ?? [];
|
|
1088
|
+
}
|
|
543
1089
|
function createServer(options = {}) {
|
|
544
1090
|
const server = new McpServer({
|
|
545
|
-
name: options.name ??
|
|
546
|
-
version: options.version ??
|
|
1091
|
+
name: options.name ?? SERVER_NAME,
|
|
1092
|
+
version: options.version ?? SERVER_VERSION
|
|
547
1093
|
});
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
1094
|
+
const toolNames = [
|
|
1095
|
+
...registerEscrowTools(server),
|
|
1096
|
+
...registerAgentTools(server),
|
|
1097
|
+
...registerMandateTools(server),
|
|
1098
|
+
...registerWalletTools(server),
|
|
1099
|
+
...registerWebhookTools(server),
|
|
1100
|
+
...registerWithdrawalTools(server),
|
|
1101
|
+
...registerTreasuryTools(server),
|
|
1102
|
+
...registerInsightsTools(server)
|
|
1103
|
+
];
|
|
1104
|
+
toolManifests.set(server, Object.freeze(toolNames));
|
|
552
1105
|
registerAgentResources(server);
|
|
553
1106
|
registerMandateResources(server);
|
|
1107
|
+
registerEscrowResources(server);
|
|
1108
|
+
registerWalletResources(server);
|
|
1109
|
+
registerWithdrawalResources(server);
|
|
1110
|
+
registerInsightsResources(server);
|
|
554
1111
|
return server;
|
|
555
1112
|
}
|
|
556
1113
|
|
|
557
1114
|
// src/bin.ts
|
|
1115
|
+
var DEFAULT_BASE_URL = "https://getaura.sh/api";
|
|
1116
|
+
function emitBanner(toolCount) {
|
|
1117
|
+
const mode = resolveKeyMode(process.env.AURA_API_KEY);
|
|
1118
|
+
const baseUrl = process.env.AURA_BASE_URL || DEFAULT_BASE_URL;
|
|
1119
|
+
console.error(
|
|
1120
|
+
`${SERVER_NAME} v${SERVER_VERSION} | mode=${mode} | baseUrl=${baseUrl} | tools=${toolCount}`
|
|
1121
|
+
);
|
|
1122
|
+
if (mode === "unconfigured") {
|
|
1123
|
+
console.error(
|
|
1124
|
+
`${SERVER_NAME}: AURA_API_KEY is not set \u2014 tool calls will fail until you add it to the \`env\` block of your MCP client config.`
|
|
1125
|
+
);
|
|
1126
|
+
} else if (mode === "invalid") {
|
|
1127
|
+
console.error(
|
|
1128
|
+
`${SERVER_NAME}: AURA_API_KEY is malformed \u2014 expected an sk_test_ / sk_live_ / pk_test_ / pk_live_ prefix. Tool calls will fail until it is corrected.`
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
558
1132
|
async function main() {
|
|
559
1133
|
const server = createServer();
|
|
1134
|
+
emitBanner(getRegisteredToolNames(server).length);
|
|
560
1135
|
const transport = new StdioServerTransport();
|
|
561
1136
|
await server.connect(transport);
|
|
562
1137
|
}
|