@aura-payments/mcp-server 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/bin.js +288 -4
- package/dist/bin.mjs +288 -4
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +288 -4
- package/dist/index.mjs +288 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ function resolveKeyMode(apiKey) {
|
|
|
37
37
|
var MissingAuraApiKeyError = class extends Error {
|
|
38
38
|
constructor() {
|
|
39
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": "
|
|
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": "sk_test_..." } } } }. Get a key at https://getaura.sh.'
|
|
41
41
|
);
|
|
42
42
|
this.name = "MissingAuraApiKeyError";
|
|
43
43
|
}
|
|
@@ -136,6 +136,22 @@ function registerEscrowResources(server) {
|
|
|
136
136
|
}
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
|
+
|
|
140
|
+
// src/resources/insights.ts
|
|
141
|
+
function registerInsightsResources(server, clientFactory = getClient) {
|
|
142
|
+
server.resource("insights-overview", "aura://insights/overview", async (uri) => {
|
|
143
|
+
const overview = await clientFactory().insights.overview();
|
|
144
|
+
return {
|
|
145
|
+
contents: [
|
|
146
|
+
{
|
|
147
|
+
uri: uri.href,
|
|
148
|
+
mimeType: "application/json",
|
|
149
|
+
text: JSON.stringify(overview, null, 2)
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
}
|
|
139
155
|
function registerMandateResources(server) {
|
|
140
156
|
server.resource(
|
|
141
157
|
"mandates-pending",
|
|
@@ -222,6 +238,42 @@ function registerWalletResources(server) {
|
|
|
222
238
|
}
|
|
223
239
|
);
|
|
224
240
|
}
|
|
241
|
+
var COLLECTION_LIMIT3 = 50;
|
|
242
|
+
var WithdrawalIdSchema = zod.z.string().uuid();
|
|
243
|
+
function registerWithdrawalResources(server, clientFactory = getClient) {
|
|
244
|
+
server.resource("withdrawals", "aura://withdrawals", async (uri) => {
|
|
245
|
+
const page = await clientFactory().withdrawals.list({ limit: COLLECTION_LIMIT3 });
|
|
246
|
+
return {
|
|
247
|
+
contents: [
|
|
248
|
+
{
|
|
249
|
+
uri: uri.href,
|
|
250
|
+
mimeType: "application/json",
|
|
251
|
+
text: JSON.stringify(page, null, 2)
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
server.resource(
|
|
257
|
+
"withdrawal",
|
|
258
|
+
new mcp_js.ResourceTemplate("aura://withdrawals/{id}", { list: void 0 }),
|
|
259
|
+
async (uri, { id }) => {
|
|
260
|
+
const parsed = WithdrawalIdSchema.safeParse(Array.isArray(id) ? id[0] : id);
|
|
261
|
+
if (!parsed.success) {
|
|
262
|
+
throw new Error(`Invalid withdrawal id in ${uri.href}: expected a UUID`);
|
|
263
|
+
}
|
|
264
|
+
const withdrawal = await clientFactory().withdrawals.get(parsed.data);
|
|
265
|
+
return {
|
|
266
|
+
contents: [
|
|
267
|
+
{
|
|
268
|
+
uri: uri.href,
|
|
269
|
+
mimeType: "application/json",
|
|
270
|
+
text: JSON.stringify(withdrawal, null, 2)
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
225
277
|
|
|
226
278
|
// src/annotations.ts
|
|
227
279
|
function readOnly(title) {
|
|
@@ -421,7 +473,7 @@ function registerAgentTools(server) {
|
|
|
421
473
|
amount: zod.z.string().describe("USDC amount as decimal string"),
|
|
422
474
|
destination: zod.z.string().describe("Counterparty wallet (0x...) or merchant identifier"),
|
|
423
475
|
destinationType: zod.z.enum(["address", "domain", "category", "entity_id"]).optional(),
|
|
424
|
-
reasoning: zod.z.string().optional(),
|
|
476
|
+
reasoning: zod.z.string().optional().describe("Why the agent wants this; shown to the operator. Required for a mandate to be created when approval is needed."),
|
|
425
477
|
metadata: zod.z.record(zod.z.unknown()).optional()
|
|
426
478
|
},
|
|
427
479
|
// NOT read-only despite being a dry run: when the decision requires human
|
|
@@ -600,6 +652,118 @@ function registerEscrowTools(server) {
|
|
|
600
652
|
"aura_receive_and_split"
|
|
601
653
|
];
|
|
602
654
|
}
|
|
655
|
+
function validationError(error) {
|
|
656
|
+
const detail = error.issues.map((issue) => `${issue.path.join(".") || "(input)"}: ${issue.message}`).join("; ");
|
|
657
|
+
return toolError("VALIDATION_ERROR", detail);
|
|
658
|
+
}
|
|
659
|
+
function addCustomRangeIssues(ctx, field, selector, start, end) {
|
|
660
|
+
if (selector === "custom" && (start === void 0 || end === void 0)) {
|
|
661
|
+
ctx.addIssue({
|
|
662
|
+
code: zod.z.ZodIssueCode.custom,
|
|
663
|
+
path: [start === void 0 ? "start" : "end"],
|
|
664
|
+
message: `start and end are both required when ${field} is 'custom'`
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
if (start !== void 0 && end !== void 0 && Date.parse(start) > Date.parse(end)) {
|
|
668
|
+
ctx.addIssue({
|
|
669
|
+
code: zod.z.ZodIssueCode.custom,
|
|
670
|
+
path: ["end"],
|
|
671
|
+
message: "end must be at or after start"
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/tools/insights.ts
|
|
677
|
+
var PeriodSchema = zod.z.enum(["today", "7d", "30d", "90d", "custom"]);
|
|
678
|
+
var DateTimeSchema = zod.z.string().datetime();
|
|
679
|
+
var overviewShape = {
|
|
680
|
+
period: PeriodSchema.optional().describe(
|
|
681
|
+
"Window to report on (default 7d). 'custom' requires start and end."
|
|
682
|
+
),
|
|
683
|
+
start: DateTimeSchema.optional().describe("ISO 8601 datetime; required when period is custom"),
|
|
684
|
+
end: DateTimeSchema.optional().describe("ISO 8601 datetime; required when period is custom")
|
|
685
|
+
};
|
|
686
|
+
var InsightsOverviewInput = zod.z.object(overviewShape).superRefine(
|
|
687
|
+
(value, ctx) => addCustomRangeIssues(ctx, "period", value.period, value.start, value.end)
|
|
688
|
+
);
|
|
689
|
+
var auditShape = {
|
|
690
|
+
action: zod.z.string().min(1).optional().describe("Audit action name, e.g. escrow.released"),
|
|
691
|
+
actor: zod.z.enum(["user", "system", "api", "cron", "webhook"]).optional(),
|
|
692
|
+
resourceType: zod.z.string().min(1).optional().describe("Resource kind, e.g. escrow"),
|
|
693
|
+
// `.min(1)`, not `.uuid()`: the route accepts any string here
|
|
694
|
+
// (`resourceId: z.string().optional()`, insights/audit/route.ts:26) and the
|
|
695
|
+
// audit log records ids from several subsystems, not all of them UUIDs.
|
|
696
|
+
resourceId: zod.z.string().min(1).optional().describe("Id of the audited resource"),
|
|
697
|
+
range: PeriodSchema.optional().describe(
|
|
698
|
+
"Window to query (default 30d). 'custom' requires start and end."
|
|
699
|
+
),
|
|
700
|
+
start: DateTimeSchema.optional().describe("ISO 8601 datetime; required when range is custom"),
|
|
701
|
+
end: DateTimeSchema.optional().describe("ISO 8601 datetime; required when range is custom"),
|
|
702
|
+
page: zod.z.number().int().min(1).optional().describe("1-based page number (default 1)"),
|
|
703
|
+
limit: zod.z.number().int().min(1).max(100).optional().describe("Page size, 1-100 (default 50)")
|
|
704
|
+
};
|
|
705
|
+
var InsightsAuditInput = zod.z.object(auditShape).superRefine(
|
|
706
|
+
(value, ctx) => addCustomRangeIssues(ctx, "range", value.range, value.start, value.end)
|
|
707
|
+
);
|
|
708
|
+
function registerInsightsTools(server, clientFactory = getClient) {
|
|
709
|
+
server.tool(
|
|
710
|
+
"aura_insights_overview",
|
|
711
|
+
"Revenue, transaction count, active escrows and commissions for a period, each with its change against the previous period, plus sparkline and success-rate charts.",
|
|
712
|
+
overviewShape,
|
|
713
|
+
readOnly("Insights Overview"),
|
|
714
|
+
async (args) => {
|
|
715
|
+
const parsed = InsightsOverviewInput.safeParse(args);
|
|
716
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
717
|
+
const { period, start, end } = parsed.data;
|
|
718
|
+
return withToolErrorHandling(
|
|
719
|
+
async () => clientFactory().insights.overview(period, start, end)
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
server.tool(
|
|
724
|
+
"aura_insights_forecast",
|
|
725
|
+
"Project a metric forward over a horizon using the requested algorithm. Requires a Growth or higher plan \u2014 lower tiers return feature_not_available.",
|
|
726
|
+
{
|
|
727
|
+
metric: zod.z.enum([
|
|
728
|
+
"revenue",
|
|
729
|
+
"transaction_count",
|
|
730
|
+
"escrow_count",
|
|
731
|
+
"commission",
|
|
732
|
+
"avg_transaction_value"
|
|
733
|
+
]),
|
|
734
|
+
algorithm: zod.z.enum([
|
|
735
|
+
"linear_regression",
|
|
736
|
+
"moving_average",
|
|
737
|
+
"exponential_smoothing",
|
|
738
|
+
"arima",
|
|
739
|
+
"prophet",
|
|
740
|
+
"ensemble"
|
|
741
|
+
]).optional(),
|
|
742
|
+
period: zod.z.enum(["daily", "weekly", "monthly"]).optional().describe("Granularity of each projected point"),
|
|
743
|
+
horizon: zod.z.number().int().min(1).max(365).optional().describe("Number of periods to project"),
|
|
744
|
+
// Known platform quirk: the route parses this with `z.coerce.boolean()`
|
|
745
|
+
// on a query string, where any non-empty value — including "false" —
|
|
746
|
+
// coerces to true. Passing false therefore does not currently suppress
|
|
747
|
+
// history; that is a platform-side fix, not one to paper over here.
|
|
748
|
+
includeHistory: zod.z.boolean().optional().describe("Include the historical series alongside the projection"),
|
|
749
|
+
historyPeriods: zod.z.number().int().min(1).max(365).optional()
|
|
750
|
+
},
|
|
751
|
+
readOnly("Insights Forecast"),
|
|
752
|
+
async (args) => withToolErrorHandling(async () => clientFactory().insights.forecast(args))
|
|
753
|
+
);
|
|
754
|
+
server.tool(
|
|
755
|
+
"aura_insights_audit",
|
|
756
|
+
"Query the account audit log by action, actor, resource and date range. Paginated, most recent first.",
|
|
757
|
+
auditShape,
|
|
758
|
+
readOnly("Insights Audit"),
|
|
759
|
+
async (args) => {
|
|
760
|
+
const parsed = InsightsAuditInput.safeParse(args);
|
|
761
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
762
|
+
return withToolErrorHandling(async () => clientFactory().insights.audit(parsed.data));
|
|
763
|
+
}
|
|
764
|
+
);
|
|
765
|
+
return ["aura_insights_overview", "aura_insights_forecast", "aura_insights_audit"];
|
|
766
|
+
}
|
|
603
767
|
function registerMandateTools(server) {
|
|
604
768
|
server.tool(
|
|
605
769
|
"aura_list_mandates",
|
|
@@ -668,6 +832,18 @@ function registerMandateTools(server) {
|
|
|
668
832
|
"aura_reject_mandate"
|
|
669
833
|
];
|
|
670
834
|
}
|
|
835
|
+
|
|
836
|
+
// src/tools/treasury.ts
|
|
837
|
+
function registerTreasuryTools(server, clientFactory = getClient) {
|
|
838
|
+
server.tool(
|
|
839
|
+
"aura_treasury_optimize",
|
|
840
|
+
"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.",
|
|
841
|
+
{},
|
|
842
|
+
readOnly("Treasury Optimize"),
|
|
843
|
+
async () => withToolErrorHandling(async () => clientFactory().treasury.optimize())
|
|
844
|
+
);
|
|
845
|
+
return ["aura_treasury_optimize"];
|
|
846
|
+
}
|
|
671
847
|
var TestnetChainSchema = zod.z.enum(["ARC", "ARB", "BASE"]);
|
|
672
848
|
function walletCreateEnabled() {
|
|
673
849
|
const v = (process.env.AURA_MCP_ALLOW_WALLET_CREATE ?? "").trim().toLowerCase();
|
|
@@ -803,10 +979,113 @@ function registerWebhookTools(server) {
|
|
|
803
979
|
"aura_delete_webhook_config"
|
|
804
980
|
];
|
|
805
981
|
}
|
|
982
|
+
var ChainSchema3 = zod.z.enum(["ARC", "ETH", "BASE", "ARB", "MATIC"]);
|
|
983
|
+
var AmountSchema = zod.z.string().regex(
|
|
984
|
+
/^\d+(\.\d{1,6})?$/,
|
|
985
|
+
'Amount must be a number string with up to 6 decimal places, e.g. "100.00"'
|
|
986
|
+
);
|
|
987
|
+
var EvmAddressSchema = zod.z.string().regex(
|
|
988
|
+
/^0x[a-fA-F0-9]{40}$/,
|
|
989
|
+
"Must be an EVM address: 0x followed by 40 hexadecimal characters"
|
|
990
|
+
);
|
|
991
|
+
var ExchangeSchema = zod.z.enum(["binance", "coinbase", "kraken", "other"]);
|
|
992
|
+
var FeeConfigSchema = zod.z.enum(["FREE", "GAS_ONLY", "STANDARD"]);
|
|
993
|
+
var StatusSchema = zod.z.enum(["pending", "submitted", "confirmed", "failed", "cancelled"]);
|
|
994
|
+
var WithdrawalIdSchema2 = zod.z.string().uuid("Withdrawal id must be a UUID");
|
|
995
|
+
var estimateShape = {
|
|
996
|
+
// `.min(1)`, not `.uuid()`: the route accepts any non-empty string here
|
|
997
|
+
// (`walletId: z.string().min(1)`, estimate/route.ts:56). Requiring a UUID
|
|
998
|
+
// would make this tool reject wallet ids the platform itself accepts.
|
|
999
|
+
walletId: zod.z.string().min(1).describe("Source wallet id to debit"),
|
|
1000
|
+
amount: AmountSchema.describe('USDC amount as a string, e.g. "100.00"'),
|
|
1001
|
+
destinationType: zod.z.enum(["exchange", "wallet"]).describe("Where the funds land. 'exchange' also requires `exchange`."),
|
|
1002
|
+
destinationAddress: EvmAddressSchema.describe("Destination EVM address"),
|
|
1003
|
+
chain: ChainSchema3.describe("Chain the funds are delivered on"),
|
|
1004
|
+
exchange: ExchangeSchema.optional().describe(
|
|
1005
|
+
"Required when destinationType is 'exchange'"
|
|
1006
|
+
),
|
|
1007
|
+
sourceChain: ChainSchema3.optional().describe(
|
|
1008
|
+
"Chain the funds start on. Differs from `chain` for a bridged withdrawal; defaults to ARC."
|
|
1009
|
+
),
|
|
1010
|
+
feeConfig: FeeConfigSchema.optional()
|
|
1011
|
+
};
|
|
1012
|
+
var EstimateWithdrawalInput = zod.z.object(estimateShape).superRefine((value, ctx) => {
|
|
1013
|
+
if (value.destinationType === "exchange" && value.exchange === void 0) {
|
|
1014
|
+
ctx.addIssue({
|
|
1015
|
+
code: zod.z.ZodIssueCode.custom,
|
|
1016
|
+
path: ["exchange"],
|
|
1017
|
+
message: "exchange is required when destinationType is 'exchange'"
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
function registerWithdrawalTools(server, clientFactory = getClient) {
|
|
1022
|
+
server.tool(
|
|
1023
|
+
"aura_get_withdrawal",
|
|
1024
|
+
"Get a single withdrawal by id: status, amount, fees, destination, chain and transaction hash.",
|
|
1025
|
+
{ withdrawalId: WithdrawalIdSchema2.describe("The withdrawal id (UUID)") },
|
|
1026
|
+
readOnly("Get Withdrawal"),
|
|
1027
|
+
async ({ withdrawalId }) => withToolErrorHandling(async () => clientFactory().withdrawals.get(withdrawalId))
|
|
1028
|
+
);
|
|
1029
|
+
server.tool(
|
|
1030
|
+
"aura_list_withdrawals",
|
|
1031
|
+
"List withdrawals for the account, most recent first. Filter by status, chain and date range.",
|
|
1032
|
+
{
|
|
1033
|
+
limit: zod.z.number().int().min(1).max(100).optional().describe("Page size, 1-100 (default 50)"),
|
|
1034
|
+
offset: zod.z.number().int().min(0).optional().describe("Rows to skip (default 0)"),
|
|
1035
|
+
status: StatusSchema.optional(),
|
|
1036
|
+
chain: ChainSchema3.optional(),
|
|
1037
|
+
fromDate: zod.z.string().datetime().optional().describe("ISO 8601 datetime, inclusive lower bound"),
|
|
1038
|
+
toDate: zod.z.string().datetime().optional().describe("ISO 8601 datetime, inclusive upper bound")
|
|
1039
|
+
},
|
|
1040
|
+
readOnly("List Withdrawals"),
|
|
1041
|
+
async (args) => withToolErrorHandling(async () => clientFactory().withdrawals.list(args))
|
|
1042
|
+
);
|
|
1043
|
+
server.tool(
|
|
1044
|
+
"aura_estimate_withdrawal",
|
|
1045
|
+
"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.",
|
|
1046
|
+
estimateShape,
|
|
1047
|
+
readOnly("Estimate Withdrawal"),
|
|
1048
|
+
async (args) => {
|
|
1049
|
+
const parsed = EstimateWithdrawalInput.safeParse(args);
|
|
1050
|
+
if (!parsed.success) return validationError(parsed.error);
|
|
1051
|
+
return withToolErrorHandling(
|
|
1052
|
+
async () => clientFactory().withdrawals.estimate(parsed.data)
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
);
|
|
1056
|
+
server.tool(
|
|
1057
|
+
"aura_get_withdrawal_limits",
|
|
1058
|
+
"Get the account KYC-tier withdrawal limits and how much of the daily and monthly allowance is still available.",
|
|
1059
|
+
{},
|
|
1060
|
+
readOnly("Get Withdrawal Limits"),
|
|
1061
|
+
async () => withToolErrorHandling(async () => clientFactory().withdrawals.limits())
|
|
1062
|
+
);
|
|
1063
|
+
server.tool(
|
|
1064
|
+
"aura_validate_withdrawal_address",
|
|
1065
|
+
"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.",
|
|
1066
|
+
{
|
|
1067
|
+
address: EvmAddressSchema.describe("Destination EVM address to check"),
|
|
1068
|
+
chain: ChainSchema3,
|
|
1069
|
+
amount: AmountSchema.optional().describe(
|
|
1070
|
+
"Optional \u2014 when supplied the response includes a fee preview"
|
|
1071
|
+
),
|
|
1072
|
+
feeConfig: FeeConfigSchema.optional()
|
|
1073
|
+
},
|
|
1074
|
+
readOnly("Validate Withdrawal Address"),
|
|
1075
|
+
async (args) => withToolErrorHandling(async () => clientFactory().withdrawals.validate(args))
|
|
1076
|
+
);
|
|
1077
|
+
return [
|
|
1078
|
+
"aura_get_withdrawal",
|
|
1079
|
+
"aura_list_withdrawals",
|
|
1080
|
+
"aura_estimate_withdrawal",
|
|
1081
|
+
"aura_get_withdrawal_limits",
|
|
1082
|
+
"aura_validate_withdrawal_address"
|
|
1083
|
+
];
|
|
1084
|
+
}
|
|
806
1085
|
|
|
807
1086
|
// src/index.ts
|
|
808
1087
|
var SERVER_NAME = "aura-payments";
|
|
809
|
-
var SERVER_VERSION = "1.1
|
|
1088
|
+
var SERVER_VERSION = "1.2.1";
|
|
810
1089
|
var toolManifests = /* @__PURE__ */ new WeakMap();
|
|
811
1090
|
function getRegisteredToolNames(server) {
|
|
812
1091
|
return toolManifests.get(server) ?? [];
|
|
@@ -821,13 +1100,18 @@ function createServer(options = {}) {
|
|
|
821
1100
|
...registerAgentTools(server),
|
|
822
1101
|
...registerMandateTools(server),
|
|
823
1102
|
...registerWalletTools(server),
|
|
824
|
-
...registerWebhookTools(server)
|
|
1103
|
+
...registerWebhookTools(server),
|
|
1104
|
+
...registerWithdrawalTools(server),
|
|
1105
|
+
...registerTreasuryTools(server),
|
|
1106
|
+
...registerInsightsTools(server)
|
|
825
1107
|
];
|
|
826
1108
|
toolManifests.set(server, Object.freeze(toolNames));
|
|
827
1109
|
registerAgentResources(server);
|
|
828
1110
|
registerMandateResources(server);
|
|
829
1111
|
registerEscrowResources(server);
|
|
830
1112
|
registerWalletResources(server);
|
|
1113
|
+
registerWithdrawalResources(server);
|
|
1114
|
+
registerInsightsResources(server);
|
|
831
1115
|
return server;
|
|
832
1116
|
}
|
|
833
1117
|
|