@dominusnode/mastra-tools 1.0.1 → 1.3.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/toolkit.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Dominus Node Mastra AI Toolkit
4
4
  *
5
- * Implements 24 tools for interacting with Dominus Node's rotating proxy service
5
+ * Implements 53 tools for interacting with Dominus Node's rotating proxy service
6
6
  * from Mastra AI agents and workflows.
7
7
  *
8
8
  * Uses createTool() from @mastra/core/tools with Zod schemas.
@@ -51,7 +51,7 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  };
52
52
  })();
53
53
  Object.defineProperty(exports, "__esModule", { value: true });
54
- exports.DominusNodeToolkit = void 0;
54
+ exports.DominusNodeToolkit = exports.BLOCKED_HOSTNAMES = exports.SANCTIONED_COUNTRIES = void 0;
55
55
  exports.scrubCredentials = scrubCredentials;
56
56
  exports.truncate = truncate;
57
57
  exports.normalizeIpv4 = normalizeIpv4;
@@ -59,6 +59,7 @@ exports.isPrivateIp = isPrivateIp;
59
59
  exports.validateTargetUrl = validateTargetUrl;
60
60
  exports.validateCountry = validateCountry;
61
61
  exports.validateUuid = validateUuid;
62
+ exports.checkDnsRebinding = checkDnsRebinding;
62
63
  exports.stripDangerousKeys = stripDangerousKeys;
63
64
  exports.formatBytes = formatBytes;
64
65
  exports.formatCents = formatCents;
@@ -75,7 +76,7 @@ const MAX_RESPONSE_CHARS = 4000;
75
76
  const REQUEST_TIMEOUT_MS = 30_000;
76
77
  const MAX_RESPONSE_BYTES = 10 * 1024 * 1024; // 10 MB hard cap
77
78
  /** OFAC sanctioned countries -- must never be used as geo-targeting destinations. */
78
- const SANCTIONED_COUNTRIES = new Set(["CU", "IR", "KP", "RU", "SY"]);
79
+ exports.SANCTIONED_COUNTRIES = new Set(["CU", "IR", "KP", "RU", "SY"]);
79
80
  /** ISO 3166-1 alpha-2 country code pattern. */
80
81
  const COUNTRY_CODE_RE = /^[A-Z]{2}$/;
81
82
  /** UUID v4 pattern for wallet/team IDs. */
@@ -102,7 +103,7 @@ function truncate(text, max = MAX_RESPONSE_CHARS) {
102
103
  // ---------------------------------------------------------------------------
103
104
  // SSRF Protection
104
105
  // ---------------------------------------------------------------------------
105
- const BLOCKED_HOSTNAMES = new Set([
106
+ exports.BLOCKED_HOSTNAMES = new Set([
106
107
  "localhost",
107
108
  "localhost.localdomain",
108
109
  "ip6-localhost",
@@ -261,7 +262,7 @@ function validateTargetUrl(url) {
261
262
  throw new Error("URLs with embedded credentials are not allowed");
262
263
  }
263
264
  const hostname = parsed.hostname.toLowerCase();
264
- if (BLOCKED_HOSTNAMES.has(hostname)) {
265
+ if (exports.BLOCKED_HOSTNAMES.has(hostname)) {
265
266
  throw new Error("Requests to localhost/loopback addresses are blocked");
266
267
  }
267
268
  if (isPrivateIp(hostname)) {
@@ -291,7 +292,7 @@ function validateCountry(country) {
291
292
  if (!COUNTRY_CODE_RE.test(upper)) {
292
293
  throw new Error(`Invalid country code: "${country}". Must be a 2-letter ISO 3166-1 code.`);
293
294
  }
294
- if (SANCTIONED_COUNTRIES.has(upper)) {
295
+ if (exports.SANCTIONED_COUNTRIES.has(upper)) {
295
296
  throw new Error(`Country "${upper}" is OFAC sanctioned and cannot be used as a proxy target.`);
296
297
  }
297
298
  return upper;
@@ -383,6 +384,7 @@ class DominusNodeToolkit {
383
384
  baseUrl;
384
385
  proxyHost;
385
386
  proxyPort;
387
+ agentSecret;
386
388
  cachedJwt = null;
387
389
  jwtExpiresAt = 0;
388
390
  constructor(config = {}) {
@@ -392,6 +394,7 @@ class DominusNodeToolkit {
392
394
  const portStr = config.proxyPort?.toString() || process.env.DOMINUSNODE_PROXY_PORT || "8080";
393
395
  const port = parseInt(portStr, 10);
394
396
  this.proxyPort = isNaN(port) || port < 1 || port > 65535 ? 8080 : port;
397
+ this.agentSecret = config.agentSecret || process.env.DOMINUSNODE_AGENT_SECRET;
395
398
  }
396
399
  // -----------------------------------------------------------------------
397
400
  // Authentication
@@ -411,12 +414,17 @@ class DominusNodeToolkit {
411
414
  if (this.cachedJwt && Date.now() < this.jwtExpiresAt)
412
415
  return this.cachedJwt;
413
416
  const apiKey = this.getApiKey();
417
+ const authHeaders = {
418
+ "Content-Type": "application/json",
419
+ "User-Agent": "dominusnode-mastra/1.0.0",
420
+ };
421
+ if (this.agentSecret) {
422
+ authHeaders["X-DominusNode-Agent"] = "mcp";
423
+ authHeaders["X-DominusNode-Agent-Secret"] = this.agentSecret;
424
+ }
414
425
  const res = await fetch(`${this.baseUrl}/api/auth/verify-key`, {
415
426
  method: "POST",
416
- headers: {
417
- "Content-Type": "application/json",
418
- "User-Agent": "dominusnode-mastra/1.0.0",
419
- },
427
+ headers: authHeaders,
420
428
  body: JSON.stringify({ apiKey }),
421
429
  redirect: "error",
422
430
  });
@@ -441,6 +449,10 @@ class DominusNodeToolkit {
441
449
  Accept: "application/json",
442
450
  "User-Agent": "dominusnode-mastra/1.0.0",
443
451
  };
452
+ if (this.agentSecret) {
453
+ headers["X-DominusNode-Agent"] = "mcp";
454
+ headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
455
+ }
444
456
  const init = {
445
457
  method,
446
458
  headers,
@@ -511,6 +523,81 @@ class DominusNodeToolkit {
511
523
  async apiPatch(path, body) {
512
524
  return this.apiRequest("PATCH", path, body);
513
525
  }
526
+ async apiPut(path, body) {
527
+ return this.apiRequest("PUT", path, body);
528
+ }
529
+ /**
530
+ * Raw POST/GET for unauthenticated endpoints (register, login, verify-email).
531
+ * Does NOT use ensureAuth(). Includes agent headers if configured.
532
+ */
533
+ async rawRequest(method, path, body) {
534
+ const url = `${this.baseUrl}${path}`;
535
+ const headers = {
536
+ Accept: "application/json",
537
+ "User-Agent": "dominusnode-mastra/1.0.0",
538
+ };
539
+ if (this.agentSecret) {
540
+ headers["X-DominusNode-Agent"] = "mcp";
541
+ headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
542
+ }
543
+ const init = {
544
+ method,
545
+ headers,
546
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
547
+ redirect: "error",
548
+ };
549
+ if (body && (method === "POST" || method === "PUT" || method === "PATCH")) {
550
+ headers["Content-Type"] = "application/json";
551
+ init.body = JSON.stringify(body);
552
+ }
553
+ let res;
554
+ try {
555
+ res = await fetch(url, init);
556
+ }
557
+ catch (err) {
558
+ throw new Error(`API request failed: ${safeError(err)}`);
559
+ }
560
+ let rawText;
561
+ try {
562
+ rawText = await res.text();
563
+ }
564
+ catch {
565
+ rawText = "";
566
+ }
567
+ if (new TextEncoder().encode(rawText).length > MAX_RESPONSE_BYTES) {
568
+ throw new Error("API response too large");
569
+ }
570
+ if (!res.ok) {
571
+ let errorMsg = `API error ${res.status}`;
572
+ if (rawText) {
573
+ try {
574
+ const parsed = JSON.parse(rawText);
575
+ stripDangerousKeys(parsed);
576
+ if (parsed.error) {
577
+ errorMsg = `API error ${res.status}: ${scrubCredentials(String(parsed.error))}`;
578
+ }
579
+ else if (parsed.message) {
580
+ errorMsg = `API error ${res.status}: ${scrubCredentials(String(parsed.message))}`;
581
+ }
582
+ }
583
+ catch {
584
+ errorMsg = `API error ${res.status}: ${scrubCredentials(rawText.slice(0, 200))}`;
585
+ }
586
+ }
587
+ throw new Error(errorMsg);
588
+ }
589
+ if (!rawText || rawText.trim().length === 0) {
590
+ return {};
591
+ }
592
+ try {
593
+ const parsed = JSON.parse(rawText);
594
+ stripDangerousKeys(parsed);
595
+ return parsed;
596
+ }
597
+ catch {
598
+ throw new Error("Failed to parse API response as JSON");
599
+ }
600
+ }
514
601
  // -----------------------------------------------------------------------
515
602
  // Tool implementations
516
603
  // -----------------------------------------------------------------------
@@ -839,11 +926,185 @@ class DominusNodeToolkit {
839
926
  }
840
927
  return this.apiPost("/api/wallet/topup/paypal", { amountCents });
841
928
  }
929
+ async topupStripe(amountCents) {
930
+ if (!Number.isInteger(amountCents) || amountCents < 500 || amountCents > 100000) {
931
+ throw new Error("amount_cents must be an integer between 500 ($5) and 100000 ($1,000).");
932
+ }
933
+ return this.apiPost("/api/wallet/topup/stripe", { amountCents });
934
+ }
935
+ static VALID_CRYPTO_CURRENCIES = new Set([
936
+ "btc", "eth", "ltc", "xmr", "zec", "usdc", "sol", "usdt", "dai", "bnb", "link",
937
+ ]);
938
+ async topupCrypto(amountUsd, currency) {
939
+ if (typeof amountUsd !== "number" || !Number.isFinite(amountUsd) || amountUsd < 5 || amountUsd > 1000) {
940
+ throw new Error("amount_usd must be a number between 5 and 1,000.");
941
+ }
942
+ const cur = String(currency ?? "").toLowerCase();
943
+ if (!DominusNodeToolkit.VALID_CRYPTO_CURRENCIES.has(cur)) {
944
+ throw new Error(`currency must be one of: ${[...DominusNodeToolkit.VALID_CRYPTO_CURRENCIES].join(", ")}.`);
945
+ }
946
+ return this.apiPost("/api/wallet/topup/crypto", { amountUsd, currency: cur });
947
+ }
842
948
  async x402Info() {
843
949
  return this.apiGet("/api/x402/info");
844
950
  }
951
+ // -- Proxy --
952
+ async getProxyStatus() {
953
+ return this.apiGet("/api/proxy/status");
954
+ }
955
+ // -- Wallet --
956
+ async getTransactions(limit = 20) {
957
+ const safeLimit = Math.min(Math.max(limit, 1), 100);
958
+ return this.apiGet(`/api/wallet/transactions?limit=${safeLimit}`);
959
+ }
960
+ async getForecast() {
961
+ return this.apiGet("/api/wallet/forecast");
962
+ }
963
+ async checkPayment(invoiceId) {
964
+ validateUuid(invoiceId, "invoice_id");
965
+ return this.apiGet(`/api/wallet/topup/crypto/${encodeURIComponent(invoiceId)}/status`);
966
+ }
967
+ // -- Usage --
968
+ async getDailyUsage(days = 7) {
969
+ const safeDays = Math.min(Math.max(days, 1), 365);
970
+ return this.apiGet(`/api/usage/daily?days=${safeDays}`);
971
+ }
972
+ async getTopHosts(limit = 10) {
973
+ const safeLimit = Math.min(Math.max(limit, 1), 100);
974
+ return this.apiGet(`/api/usage/top-hosts?limit=${safeLimit}`);
975
+ }
976
+ // -- Account (unauthenticated) --
977
+ static EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
978
+ static validateEmail(email) {
979
+ const trimmed = email.trim();
980
+ if (!trimmed || !DominusNodeToolkit.EMAIL_RE.test(trimmed)) {
981
+ throw new Error("Invalid email address.");
982
+ }
983
+ if (trimmed.length > 254) {
984
+ throw new Error("Email address too long (max 254 characters).");
985
+ }
986
+ return trimmed;
987
+ }
988
+ static validatePassword(password) {
989
+ if (!password || password.length < 8) {
990
+ throw new Error("Password must be at least 8 characters.");
991
+ }
992
+ if (password.length > 128) {
993
+ throw new Error("Password must be at most 128 characters.");
994
+ }
995
+ return password;
996
+ }
997
+ async register(email, password) {
998
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
999
+ const safePassword = DominusNodeToolkit.validatePassword(password);
1000
+ return this.rawRequest("POST", "/api/auth/register", { email: safeEmail, password: safePassword });
1001
+ }
1002
+ async login(email, password) {
1003
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
1004
+ const safePassword = DominusNodeToolkit.validatePassword(password);
1005
+ return this.rawRequest("POST", "/api/auth/login", { email: safeEmail, password: safePassword });
1006
+ }
1007
+ async getAccountInfo() {
1008
+ return this.apiGet("/api/auth/me");
1009
+ }
1010
+ async verifyEmail(token) {
1011
+ if (!token || typeof token !== "string" || token.trim().length === 0) {
1012
+ throw new Error("Verification token is required.");
1013
+ }
1014
+ if (/[\x00-\x1f\x7f]/.test(token)) {
1015
+ throw new Error("Token contains invalid control characters.");
1016
+ }
1017
+ return this.rawRequest("POST", "/api/auth/verify-email", { token: token.trim() });
1018
+ }
1019
+ async resendVerification() {
1020
+ return this.apiPost("/api/auth/resend-verification");
1021
+ }
1022
+ async updatePassword(currentPassword, newPassword) {
1023
+ DominusNodeToolkit.validatePassword(currentPassword);
1024
+ DominusNodeToolkit.validatePassword(newPassword);
1025
+ return this.apiPost("/api/auth/change-password", {
1026
+ currentPassword,
1027
+ newPassword,
1028
+ });
1029
+ }
1030
+ // -- API Keys --
1031
+ async listKeys() {
1032
+ return this.apiGet("/api/keys");
1033
+ }
1034
+ async createKey(label) {
1035
+ if (!label || label.length === 0 || label.length > 100) {
1036
+ throw new Error("label is required and must be 1-100 characters.");
1037
+ }
1038
+ if (/[\x00-\x1f\x7f]/.test(label)) {
1039
+ throw new Error("label contains invalid control characters.");
1040
+ }
1041
+ return this.apiPost("/api/keys", { label });
1042
+ }
1043
+ async revokeKey(keyId) {
1044
+ validateUuid(keyId, "key_id");
1045
+ return this.apiDelete(`/api/keys/${encodeURIComponent(keyId)}`);
1046
+ }
1047
+ // -- Plans --
1048
+ async getPlan() {
1049
+ return this.apiGet("/api/plans/user/plan");
1050
+ }
1051
+ async listPlans() {
1052
+ return this.apiGet("/api/plans");
1053
+ }
1054
+ async changePlan(planId) {
1055
+ validateUuid(planId, "plan_id");
1056
+ return this.apiPut("/api/plans/user/plan", { planId });
1057
+ }
1058
+ // -- Teams (additional) --
1059
+ async teamDelete(teamId) {
1060
+ validateUuid(teamId, "team_id");
1061
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}`);
1062
+ }
1063
+ async teamRevokeKey(teamId, keyId) {
1064
+ validateUuid(teamId, "team_id");
1065
+ validateUuid(keyId, "key_id");
1066
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/keys/${encodeURIComponent(keyId)}`);
1067
+ }
1068
+ async teamListKeys(teamId) {
1069
+ validateUuid(teamId, "team_id");
1070
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/keys`);
1071
+ }
1072
+ async teamListMembers(teamId) {
1073
+ validateUuid(teamId, "team_id");
1074
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/members`);
1075
+ }
1076
+ async teamAddMember(teamId, userId, role = "member") {
1077
+ validateUuid(teamId, "team_id");
1078
+ validateUuid(userId, "user_id");
1079
+ if (role !== "member" && role !== "admin") {
1080
+ throw new Error("role must be 'member' or 'admin'.");
1081
+ }
1082
+ return this.apiPost(`/api/teams/${encodeURIComponent(teamId)}/members`, { userId, role });
1083
+ }
1084
+ async teamRemoveMember(teamId, userId) {
1085
+ validateUuid(teamId, "team_id");
1086
+ validateUuid(userId, "user_id");
1087
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(userId)}`);
1088
+ }
1089
+ async teamInviteMember(teamId, email, role = "member") {
1090
+ validateUuid(teamId, "team_id");
1091
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
1092
+ if (role !== "member" && role !== "admin") {
1093
+ throw new Error("role must be 'member' or 'admin'.");
1094
+ }
1095
+ return this.apiPost(`/api/teams/${encodeURIComponent(teamId)}/invites`, { email: safeEmail, role });
1096
+ }
1097
+ async teamListInvites(teamId) {
1098
+ validateUuid(teamId, "team_id");
1099
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/invites`);
1100
+ }
1101
+ async teamCancelInvite(teamId, inviteId) {
1102
+ validateUuid(teamId, "team_id");
1103
+ validateUuid(inviteId, "invite_id");
1104
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/invites/${encodeURIComponent(inviteId)}`);
1105
+ }
845
1106
  // -----------------------------------------------------------------------
846
- // getTools() -- returns Mastra createTool() instances for all 24 tools
1107
+ // getTools() -- returns Mastra createTool() instances for all 53 tools
847
1108
  // -----------------------------------------------------------------------
848
1109
  getTools() {
849
1110
  return [
@@ -1345,7 +1606,54 @@ class DominusNodeToolkit {
1345
1606
  }
1346
1607
  },
1347
1608
  }),
1348
- // 24. x402_info
1609
+ // 23. topup_stripe
1610
+ (0, tools_1.createTool)({
1611
+ id: "dominusnode_topup_stripe",
1612
+ description: "Top up your Dominus Node wallet balance via Stripe. Creates a Stripe checkout session and returns " +
1613
+ "a checkout URL to complete payment. Minimum $5 (500 cents), maximum $1,000 (100000 cents).",
1614
+ inputSchema: zod_1.z.object({
1615
+ amountCents: zod_1.z.number().int().min(500).max(100000)
1616
+ .describe("Amount in cents to top up (min 500 = $5, max 100000 = $1,000)"),
1617
+ }),
1618
+ outputSchema: zod_1.z.object({
1619
+ data: zod_1.z.unknown(),
1620
+ error: zod_1.z.string().optional(),
1621
+ }),
1622
+ execute: async ({ context }) => {
1623
+ try {
1624
+ return { data: await this.topupStripe(context.amountCents) };
1625
+ }
1626
+ catch (err) {
1627
+ return { data: null, error: safeError(err) };
1628
+ }
1629
+ },
1630
+ }),
1631
+ // 24. topup_crypto
1632
+ (0, tools_1.createTool)({
1633
+ id: "dominusnode_topup_crypto",
1634
+ description: "Top up your Dominus Node wallet balance via cryptocurrency. Creates a crypto payment invoice. " +
1635
+ "Supports BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, LINK. " +
1636
+ "Minimum $5, maximum $1,000.",
1637
+ inputSchema: zod_1.z.object({
1638
+ amountUsd: zod_1.z.number().min(5).max(1000)
1639
+ .describe("Amount in USD to top up (5-1000)"),
1640
+ currency: zod_1.z.enum(["btc", "eth", "ltc", "xmr", "zec", "usdc", "sol", "usdt", "dai", "bnb", "link"])
1641
+ .describe("Cryptocurrency to pay with"),
1642
+ }),
1643
+ outputSchema: zod_1.z.object({
1644
+ data: zod_1.z.unknown(),
1645
+ error: zod_1.z.string().optional(),
1646
+ }),
1647
+ execute: async ({ context }) => {
1648
+ try {
1649
+ return { data: await this.topupCrypto(context.amountUsd, context.currency) };
1650
+ }
1651
+ catch (err) {
1652
+ return { data: null, error: safeError(err) };
1653
+ }
1654
+ },
1655
+ }),
1656
+ // 26. x402_info
1349
1657
  (0, tools_1.createTool)({
1350
1658
  id: "dominusnode_x402_info",
1351
1659
  description: "Get x402 micropayment protocol information including supported " +
@@ -1364,6 +1672,556 @@ class DominusNodeToolkit {
1364
1672
  }
1365
1673
  },
1366
1674
  }),
1675
+ // 27. get_proxy_status
1676
+ (0, tools_1.createTool)({
1677
+ id: "dominusnode_get_proxy_status",
1678
+ description: "Get the current status of the proxy gateway including uptime, active connections, " +
1679
+ "and pool health.",
1680
+ inputSchema: zod_1.z.object({}),
1681
+ outputSchema: zod_1.z.object({
1682
+ data: zod_1.z.unknown(),
1683
+ error: zod_1.z.string().optional(),
1684
+ }),
1685
+ execute: async () => {
1686
+ try {
1687
+ return { data: await this.getProxyStatus() };
1688
+ }
1689
+ catch (err) {
1690
+ return { data: null, error: safeError(err) };
1691
+ }
1692
+ },
1693
+ }),
1694
+ // 28. get_transactions
1695
+ (0, tools_1.createTool)({
1696
+ id: "dominusnode_get_transactions",
1697
+ description: "Get wallet transaction history showing top-ups, charges, and refunds.",
1698
+ inputSchema: zod_1.z.object({
1699
+ limit: zod_1.z.number().int().min(1).max(100).default(20).describe("Number of transactions to return (1-100, default 20)"),
1700
+ }),
1701
+ outputSchema: zod_1.z.object({
1702
+ data: zod_1.z.unknown(),
1703
+ error: zod_1.z.string().optional(),
1704
+ }),
1705
+ execute: async ({ context }) => {
1706
+ try {
1707
+ return { data: await this.getTransactions(context.limit) };
1708
+ }
1709
+ catch (err) {
1710
+ return { data: null, error: safeError(err) };
1711
+ }
1712
+ },
1713
+ }),
1714
+ // 29. get_forecast
1715
+ (0, tools_1.createTool)({
1716
+ id: "dominusnode_get_forecast",
1717
+ description: "Get a spending forecast based on recent usage patterns. " +
1718
+ "Shows estimated days until balance runs out and projected monthly cost.",
1719
+ inputSchema: zod_1.z.object({}),
1720
+ outputSchema: zod_1.z.object({
1721
+ data: zod_1.z.unknown(),
1722
+ error: zod_1.z.string().optional(),
1723
+ }),
1724
+ execute: async () => {
1725
+ try {
1726
+ return { data: await this.getForecast() };
1727
+ }
1728
+ catch (err) {
1729
+ return { data: null, error: safeError(err) };
1730
+ }
1731
+ },
1732
+ }),
1733
+ // 30. check_payment
1734
+ (0, tools_1.createTool)({
1735
+ id: "dominusnode_check_payment",
1736
+ description: "Check the status of a crypto top-up payment by invoice ID. " +
1737
+ "Returns payment status (pending, confirming, completed, expired).",
1738
+ inputSchema: zod_1.z.object({
1739
+ invoiceId: zod_1.z.string().describe("Crypto invoice ID (UUID) returned from topup_crypto"),
1740
+ }),
1741
+ outputSchema: zod_1.z.object({
1742
+ data: zod_1.z.unknown(),
1743
+ error: zod_1.z.string().optional(),
1744
+ }),
1745
+ execute: async ({ context }) => {
1746
+ try {
1747
+ return { data: await this.checkPayment(context.invoiceId) };
1748
+ }
1749
+ catch (err) {
1750
+ return { data: null, error: safeError(err) };
1751
+ }
1752
+ },
1753
+ }),
1754
+ // 31. get_daily_usage
1755
+ (0, tools_1.createTool)({
1756
+ id: "dominusnode_get_daily_usage",
1757
+ description: "Get daily bandwidth usage breakdown for the specified number of days. " +
1758
+ "Returns per-day bytes transferred and cost.",
1759
+ inputSchema: zod_1.z.object({
1760
+ days: zod_1.z.number().int().min(1).max(365).default(7).describe("Number of days to look back (1-365, default 7)"),
1761
+ }),
1762
+ outputSchema: zod_1.z.object({
1763
+ data: zod_1.z.unknown(),
1764
+ error: zod_1.z.string().optional(),
1765
+ }),
1766
+ execute: async ({ context }) => {
1767
+ try {
1768
+ return { data: await this.getDailyUsage(context.days) };
1769
+ }
1770
+ catch (err) {
1771
+ return { data: null, error: safeError(err) };
1772
+ }
1773
+ },
1774
+ }),
1775
+ // 32. get_top_hosts
1776
+ (0, tools_1.createTool)({
1777
+ id: "dominusnode_get_top_hosts",
1778
+ description: "Get the top hosts by bandwidth usage. Shows which domains consume the most proxy traffic.",
1779
+ inputSchema: zod_1.z.object({
1780
+ limit: zod_1.z.number().int().min(1).max(100).default(10).describe("Number of top hosts to return (1-100, default 10)"),
1781
+ }),
1782
+ outputSchema: zod_1.z.object({
1783
+ data: zod_1.z.unknown(),
1784
+ error: zod_1.z.string().optional(),
1785
+ }),
1786
+ execute: async ({ context }) => {
1787
+ try {
1788
+ return { data: await this.getTopHosts(context.limit) };
1789
+ }
1790
+ catch (err) {
1791
+ return { data: null, error: safeError(err) };
1792
+ }
1793
+ },
1794
+ }),
1795
+ // 33. register
1796
+ (0, tools_1.createTool)({
1797
+ id: "dominusnode_register",
1798
+ description: "Register a new Dominus Node account. Does not require authentication. " +
1799
+ "Returns user info and initial API key.",
1800
+ inputSchema: zod_1.z.object({
1801
+ email: zod_1.z.string().describe("Email address for the new account"),
1802
+ password: zod_1.z.string().min(8).max(128).describe("Password (8-128 characters)"),
1803
+ }),
1804
+ outputSchema: zod_1.z.object({
1805
+ data: zod_1.z.unknown(),
1806
+ error: zod_1.z.string().optional(),
1807
+ }),
1808
+ execute: async ({ context }) => {
1809
+ try {
1810
+ return { data: await this.register(context.email, context.password) };
1811
+ }
1812
+ catch (err) {
1813
+ return { data: null, error: safeError(err) };
1814
+ }
1815
+ },
1816
+ }),
1817
+ // 34. login
1818
+ (0, tools_1.createTool)({
1819
+ id: "dominusnode_login",
1820
+ description: "Log in to an existing Dominus Node account. Does not require authentication. " +
1821
+ "Returns JWT access and refresh tokens.",
1822
+ inputSchema: zod_1.z.object({
1823
+ email: zod_1.z.string().describe("Account email address"),
1824
+ password: zod_1.z.string().min(8).max(128).describe("Account password"),
1825
+ }),
1826
+ outputSchema: zod_1.z.object({
1827
+ data: zod_1.z.unknown(),
1828
+ error: zod_1.z.string().optional(),
1829
+ }),
1830
+ execute: async ({ context }) => {
1831
+ try {
1832
+ return { data: await this.login(context.email, context.password) };
1833
+ }
1834
+ catch (err) {
1835
+ return { data: null, error: safeError(err) };
1836
+ }
1837
+ },
1838
+ }),
1839
+ // 35. get_account_info
1840
+ (0, tools_1.createTool)({
1841
+ id: "dominusnode_get_account_info",
1842
+ description: "Get your account profile information including email, plan, verification status, and creation date.",
1843
+ inputSchema: zod_1.z.object({}),
1844
+ outputSchema: zod_1.z.object({
1845
+ data: zod_1.z.unknown(),
1846
+ error: zod_1.z.string().optional(),
1847
+ }),
1848
+ execute: async () => {
1849
+ try {
1850
+ return { data: await this.getAccountInfo() };
1851
+ }
1852
+ catch (err) {
1853
+ return { data: null, error: safeError(err) };
1854
+ }
1855
+ },
1856
+ }),
1857
+ // 36. verify_email
1858
+ (0, tools_1.createTool)({
1859
+ id: "dominusnode_verify_email",
1860
+ description: "Verify an email address using the verification token sent to the user's email. " +
1861
+ "Does not require authentication.",
1862
+ inputSchema: zod_1.z.object({
1863
+ token: zod_1.z.string().describe("Email verification token from the verification email"),
1864
+ }),
1865
+ outputSchema: zod_1.z.object({
1866
+ data: zod_1.z.unknown(),
1867
+ error: zod_1.z.string().optional(),
1868
+ }),
1869
+ execute: async ({ context }) => {
1870
+ try {
1871
+ return { data: await this.verifyEmail(context.token) };
1872
+ }
1873
+ catch (err) {
1874
+ return { data: null, error: safeError(err) };
1875
+ }
1876
+ },
1877
+ }),
1878
+ // 37. resend_verification
1879
+ (0, tools_1.createTool)({
1880
+ id: "dominusnode_resend_verification",
1881
+ description: "Resend the email verification link. Requires authentication.",
1882
+ inputSchema: zod_1.z.object({}),
1883
+ outputSchema: zod_1.z.object({
1884
+ data: zod_1.z.unknown(),
1885
+ error: zod_1.z.string().optional(),
1886
+ }),
1887
+ execute: async () => {
1888
+ try {
1889
+ return { data: await this.resendVerification() };
1890
+ }
1891
+ catch (err) {
1892
+ return { data: null, error: safeError(err) };
1893
+ }
1894
+ },
1895
+ }),
1896
+ // 38. update_password
1897
+ (0, tools_1.createTool)({
1898
+ id: "dominusnode_update_password",
1899
+ description: "Change your account password. Requires current password for verification.",
1900
+ inputSchema: zod_1.z.object({
1901
+ currentPassword: zod_1.z.string().min(8).max(128).describe("Current account password"),
1902
+ newPassword: zod_1.z.string().min(8).max(128).describe("New password (8-128 characters)"),
1903
+ }),
1904
+ outputSchema: zod_1.z.object({
1905
+ data: zod_1.z.unknown(),
1906
+ error: zod_1.z.string().optional(),
1907
+ }),
1908
+ execute: async ({ context }) => {
1909
+ try {
1910
+ return { data: await this.updatePassword(context.currentPassword, context.newPassword) };
1911
+ }
1912
+ catch (err) {
1913
+ return { data: null, error: safeError(err) };
1914
+ }
1915
+ },
1916
+ }),
1917
+ // 39. list_keys
1918
+ (0, tools_1.createTool)({
1919
+ id: "dominusnode_list_keys",
1920
+ description: "List all your personal API keys with their labels, creation dates, and last-used timestamps.",
1921
+ inputSchema: zod_1.z.object({}),
1922
+ outputSchema: zod_1.z.object({
1923
+ data: zod_1.z.unknown(),
1924
+ error: zod_1.z.string().optional(),
1925
+ }),
1926
+ execute: async () => {
1927
+ try {
1928
+ return { data: await this.listKeys() };
1929
+ }
1930
+ catch (err) {
1931
+ return { data: null, error: safeError(err) };
1932
+ }
1933
+ },
1934
+ }),
1935
+ // 40. create_key
1936
+ (0, tools_1.createTool)({
1937
+ id: "dominusnode_create_key",
1938
+ description: "Create a new personal API key. The key is shown only once -- save it immediately. " +
1939
+ "Usage is billed against your personal wallet.",
1940
+ inputSchema: zod_1.z.object({
1941
+ label: zod_1.z.string().min(1).max(100).describe('Label for the API key (e.g., "production", "dev-testing")'),
1942
+ }),
1943
+ outputSchema: zod_1.z.object({
1944
+ data: zod_1.z.unknown(),
1945
+ error: zod_1.z.string().optional(),
1946
+ }),
1947
+ execute: async ({ context }) => {
1948
+ try {
1949
+ return { data: await this.createKey(context.label) };
1950
+ }
1951
+ catch (err) {
1952
+ return { data: null, error: safeError(err) };
1953
+ }
1954
+ },
1955
+ }),
1956
+ // 41. revoke_key
1957
+ (0, tools_1.createTool)({
1958
+ id: "dominusnode_revoke_key",
1959
+ description: "Revoke (delete) a personal API key. This action is irreversible -- " +
1960
+ "any applications using this key will lose access immediately.",
1961
+ inputSchema: zod_1.z.object({
1962
+ keyId: zod_1.z.string().describe("API key ID (UUID) to revoke"),
1963
+ }),
1964
+ outputSchema: zod_1.z.object({
1965
+ data: zod_1.z.unknown(),
1966
+ error: zod_1.z.string().optional(),
1967
+ }),
1968
+ execute: async ({ context }) => {
1969
+ try {
1970
+ return { data: await this.revokeKey(context.keyId) };
1971
+ }
1972
+ catch (err) {
1973
+ return { data: null, error: safeError(err) };
1974
+ }
1975
+ },
1976
+ }),
1977
+ // 42. get_plan
1978
+ (0, tools_1.createTool)({
1979
+ id: "dominusnode_get_plan",
1980
+ description: "Get your current subscription plan including tier, bandwidth limits, and pricing.",
1981
+ inputSchema: zod_1.z.object({}),
1982
+ outputSchema: zod_1.z.object({
1983
+ data: zod_1.z.unknown(),
1984
+ error: zod_1.z.string().optional(),
1985
+ }),
1986
+ execute: async () => {
1987
+ try {
1988
+ return { data: await this.getPlan() };
1989
+ }
1990
+ catch (err) {
1991
+ return { data: null, error: safeError(err) };
1992
+ }
1993
+ },
1994
+ }),
1995
+ // 43. list_plans
1996
+ (0, tools_1.createTool)({
1997
+ id: "dominusnode_list_plans",
1998
+ description: "List all available subscription plans with features, pricing, and bandwidth limits.",
1999
+ inputSchema: zod_1.z.object({}),
2000
+ outputSchema: zod_1.z.object({
2001
+ data: zod_1.z.unknown(),
2002
+ error: zod_1.z.string().optional(),
2003
+ }),
2004
+ execute: async () => {
2005
+ try {
2006
+ return { data: await this.listPlans() };
2007
+ }
2008
+ catch (err) {
2009
+ return { data: null, error: safeError(err) };
2010
+ }
2011
+ },
2012
+ }),
2013
+ // 44. change_plan
2014
+ (0, tools_1.createTool)({
2015
+ id: "dominusnode_change_plan",
2016
+ description: "Change your subscription plan. Takes effect immediately. " +
2017
+ "Use list_plans to see available options.",
2018
+ inputSchema: zod_1.z.object({
2019
+ planId: zod_1.z.string().describe("Plan ID (UUID) to switch to"),
2020
+ }),
2021
+ outputSchema: zod_1.z.object({
2022
+ data: zod_1.z.unknown(),
2023
+ error: zod_1.z.string().optional(),
2024
+ }),
2025
+ execute: async ({ context }) => {
2026
+ try {
2027
+ return { data: await this.changePlan(context.planId) };
2028
+ }
2029
+ catch (err) {
2030
+ return { data: null, error: safeError(err) };
2031
+ }
2032
+ },
2033
+ }),
2034
+ // 45. team_delete
2035
+ (0, tools_1.createTool)({
2036
+ id: "dominusnode_team_delete",
2037
+ description: "Delete a team. Only the team owner can delete. " +
2038
+ "All team keys are revoked and remaining balance is refunded.",
2039
+ inputSchema: zod_1.z.object({
2040
+ teamId: zod_1.z.string().describe("Team ID (UUID) to delete"),
2041
+ }),
2042
+ outputSchema: zod_1.z.object({
2043
+ data: zod_1.z.unknown(),
2044
+ error: zod_1.z.string().optional(),
2045
+ }),
2046
+ execute: async ({ context }) => {
2047
+ try {
2048
+ return { data: await this.teamDelete(context.teamId) };
2049
+ }
2050
+ catch (err) {
2051
+ return { data: null, error: safeError(err) };
2052
+ }
2053
+ },
2054
+ }),
2055
+ // 46. team_revoke_key
2056
+ (0, tools_1.createTool)({
2057
+ id: "dominusnode_team_revoke_key",
2058
+ description: "Revoke a team API key. Only owners and admins can revoke keys. " +
2059
+ "Applications using this key will lose access immediately.",
2060
+ inputSchema: zod_1.z.object({
2061
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2062
+ keyId: zod_1.z.string().describe("API key ID (UUID) to revoke"),
2063
+ }),
2064
+ outputSchema: zod_1.z.object({
2065
+ data: zod_1.z.unknown(),
2066
+ error: zod_1.z.string().optional(),
2067
+ }),
2068
+ execute: async ({ context }) => {
2069
+ try {
2070
+ return { data: await this.teamRevokeKey(context.teamId, context.keyId) };
2071
+ }
2072
+ catch (err) {
2073
+ return { data: null, error: safeError(err) };
2074
+ }
2075
+ },
2076
+ }),
2077
+ // 47. team_list_keys
2078
+ (0, tools_1.createTool)({
2079
+ id: "dominusnode_team_list_keys",
2080
+ description: "List all API keys for a team with labels, creation dates, and last-used timestamps.",
2081
+ inputSchema: zod_1.z.object({
2082
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2083
+ }),
2084
+ outputSchema: zod_1.z.object({
2085
+ data: zod_1.z.unknown(),
2086
+ error: zod_1.z.string().optional(),
2087
+ }),
2088
+ execute: async ({ context }) => {
2089
+ try {
2090
+ return { data: await this.teamListKeys(context.teamId) };
2091
+ }
2092
+ catch (err) {
2093
+ return { data: null, error: safeError(err) };
2094
+ }
2095
+ },
2096
+ }),
2097
+ // 48. team_list_members
2098
+ (0, tools_1.createTool)({
2099
+ id: "dominusnode_team_list_members",
2100
+ description: "List all members of a team with their roles and join dates.",
2101
+ inputSchema: zod_1.z.object({
2102
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2103
+ }),
2104
+ outputSchema: zod_1.z.object({
2105
+ data: zod_1.z.unknown(),
2106
+ error: zod_1.z.string().optional(),
2107
+ }),
2108
+ execute: async ({ context }) => {
2109
+ try {
2110
+ return { data: await this.teamListMembers(context.teamId) };
2111
+ }
2112
+ catch (err) {
2113
+ return { data: null, error: safeError(err) };
2114
+ }
2115
+ },
2116
+ }),
2117
+ // 49. team_add_member
2118
+ (0, tools_1.createTool)({
2119
+ id: "dominusnode_team_add_member",
2120
+ description: "Add a user directly to a team by user ID. " +
2121
+ "Only owners and admins can add members.",
2122
+ inputSchema: zod_1.z.object({
2123
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2124
+ userId: zod_1.z.string().describe("User ID (UUID) of the user to add"),
2125
+ role: zod_1.z.enum(["member", "admin"]).default("member").describe("Role for the new member"),
2126
+ }),
2127
+ outputSchema: zod_1.z.object({
2128
+ data: zod_1.z.unknown(),
2129
+ error: zod_1.z.string().optional(),
2130
+ }),
2131
+ execute: async ({ context }) => {
2132
+ try {
2133
+ return { data: await this.teamAddMember(context.teamId, context.userId, context.role) };
2134
+ }
2135
+ catch (err) {
2136
+ return { data: null, error: safeError(err) };
2137
+ }
2138
+ },
2139
+ }),
2140
+ // 50. team_remove_member
2141
+ (0, tools_1.createTool)({
2142
+ id: "dominusnode_team_remove_member",
2143
+ description: "Remove a member from a team. Only owners and admins can remove members.",
2144
+ inputSchema: zod_1.z.object({
2145
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2146
+ userId: zod_1.z.string().describe("User ID (UUID) of the member to remove"),
2147
+ }),
2148
+ outputSchema: zod_1.z.object({
2149
+ data: zod_1.z.unknown(),
2150
+ error: zod_1.z.string().optional(),
2151
+ }),
2152
+ execute: async ({ context }) => {
2153
+ try {
2154
+ return { data: await this.teamRemoveMember(context.teamId, context.userId) };
2155
+ }
2156
+ catch (err) {
2157
+ return { data: null, error: safeError(err) };
2158
+ }
2159
+ },
2160
+ }),
2161
+ // 51. team_invite_member
2162
+ (0, tools_1.createTool)({
2163
+ id: "dominusnode_team_invite_member",
2164
+ description: "Invite a user to join a team by email address. " +
2165
+ "The user will receive an invitation email.",
2166
+ inputSchema: zod_1.z.object({
2167
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2168
+ email: zod_1.z.string().describe("Email address of the user to invite"),
2169
+ role: zod_1.z.enum(["member", "admin"]).default("member").describe("Role for the invited member"),
2170
+ }),
2171
+ outputSchema: zod_1.z.object({
2172
+ data: zod_1.z.unknown(),
2173
+ error: zod_1.z.string().optional(),
2174
+ }),
2175
+ execute: async ({ context }) => {
2176
+ try {
2177
+ return { data: await this.teamInviteMember(context.teamId, context.email, context.role) };
2178
+ }
2179
+ catch (err) {
2180
+ return { data: null, error: safeError(err) };
2181
+ }
2182
+ },
2183
+ }),
2184
+ // 52. team_list_invites
2185
+ (0, tools_1.createTool)({
2186
+ id: "dominusnode_team_list_invites",
2187
+ description: "List all pending invitations for a team.",
2188
+ inputSchema: zod_1.z.object({
2189
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2190
+ }),
2191
+ outputSchema: zod_1.z.object({
2192
+ data: zod_1.z.unknown(),
2193
+ error: zod_1.z.string().optional(),
2194
+ }),
2195
+ execute: async ({ context }) => {
2196
+ try {
2197
+ return { data: await this.teamListInvites(context.teamId) };
2198
+ }
2199
+ catch (err) {
2200
+ return { data: null, error: safeError(err) };
2201
+ }
2202
+ },
2203
+ }),
2204
+ // 53. team_cancel_invite
2205
+ (0, tools_1.createTool)({
2206
+ id: "dominusnode_team_cancel_invite",
2207
+ description: "Cancel a pending team invitation. Only owners and admins can cancel invites.",
2208
+ inputSchema: zod_1.z.object({
2209
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2210
+ inviteId: zod_1.z.string().describe("Invite ID (UUID) to cancel"),
2211
+ }),
2212
+ outputSchema: zod_1.z.object({
2213
+ data: zod_1.z.unknown(),
2214
+ error: zod_1.z.string().optional(),
2215
+ }),
2216
+ execute: async ({ context }) => {
2217
+ try {
2218
+ return { data: await this.teamCancelInvite(context.teamId, context.inviteId) };
2219
+ }
2220
+ catch (err) {
2221
+ return { data: null, error: safeError(err) };
2222
+ }
2223
+ },
2224
+ }),
1367
2225
  ];
1368
2226
  }
1369
2227
  }