@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/bin.js +309 -18
- package/dist/bin.mjs +309 -18
- package/dist/index.d.mts +77 -8
- package/dist/index.d.ts +77 -8
- package/dist/index.js +302 -18
- package/dist/index.mjs +295 -19
- package/package.json +5 -3
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
|
|
23
|
-
* as Model Context Protocol tools and resources, so AI agents
|
|
24
|
-
* Cursor, Continue, custom orchestrators) can drive Aura natively
|
|
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
|
-
|
|
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 ??
|
|
547
|
-
version: options.version ??
|
|
816
|
+
name: options.name ?? SERVER_NAME,
|
|
817
|
+
version: options.version ?? SERVER_VERSION
|
|
548
818
|
});
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
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;
|