@aibtc/mcp-server 1.70.1 → 1.72.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.
Files changed (134) hide show
  1. package/README.md +45 -8
  2. package/dist/bridge/index.js +4 -4
  3. package/dist/config/contracts.d.ts +4 -4
  4. package/dist/config/contracts.js +2 -2
  5. package/dist/config/networks.js +4 -1
  6. package/dist/endpoints/registry.d.ts +8 -26
  7. package/dist/endpoints/registry.js +7 -932
  8. package/dist/index.js +118 -42
  9. package/dist/services/stacking.service.d.ts +144 -45
  10. package/dist/services/stacking.service.js +416 -123
  11. package/dist/services/x402-discovery.service.d.ts +81 -0
  12. package/dist/services/x402-discovery.service.js +170 -0
  13. package/dist/tools/arxiv-research.tools.d.ts +1 -1
  14. package/dist/tools/arxiv-research.tools.js +6 -6
  15. package/dist/tools/at-stake-legion.tools.d.ts +1 -1
  16. package/dist/tools/at-stake-legion.tools.js +14 -14
  17. package/dist/tools/at-stake.tools.d.ts +1 -1
  18. package/dist/tools/at-stake.tools.js +17 -17
  19. package/dist/tools/bitcoin.tools.d.ts +1 -1
  20. package/dist/tools/bitcoin.tools.js +12 -12
  21. package/dist/tools/bitflow.tools.d.ts +1 -1
  22. package/dist/tools/bitflow.tools.js +21 -21
  23. package/dist/tools/bns.tools.d.ts +1 -1
  24. package/dist/tools/bns.tools.js +18 -18
  25. package/dist/tools/bounty-hint.d.ts +1 -1
  26. package/dist/tools/bounty-scanner.tools.d.ts +1 -1
  27. package/dist/tools/bounty-scanner.tools.js +20 -20
  28. package/dist/tools/child-inscription.tools.d.ts +1 -1
  29. package/dist/tools/child-inscription.tools.js +6 -6
  30. package/dist/tools/competition.tools.d.ts +1 -1
  31. package/dist/tools/competition.tools.js +4 -4
  32. package/dist/tools/contract.tools.d.ts +1 -1
  33. package/dist/tools/contract.tools.js +8 -8
  34. package/dist/tools/credentials.tools.d.ts +1 -1
  35. package/dist/tools/credentials.tools.js +8 -8
  36. package/dist/tools/defi.tools.d.ts +1 -1
  37. package/dist/tools/defi.tools.js +21 -21
  38. package/dist/tools/dual-stacking.tools.d.ts +1 -1
  39. package/dist/tools/dual-stacking.tools.js +7 -7
  40. package/dist/tools/earning.tools.d.ts +1 -1
  41. package/dist/tools/earning.tools.js +5 -5
  42. package/dist/tools/endpoint.tools.d.ts +1 -1
  43. package/dist/tools/endpoint.tools.js +92 -49
  44. package/dist/tools/identity.tools.d.ts +1 -1
  45. package/dist/tools/identity.tools.js +19 -19
  46. package/dist/tools/inbox-x402.tools.d.ts +1 -1
  47. package/dist/tools/inbox-x402.tools.js +2 -2
  48. package/dist/tools/inbox.tools.d.ts +1 -1
  49. package/dist/tools/inbox.tools.js +2 -2
  50. package/dist/tools/index.d.ts +6 -3
  51. package/dist/tools/index.js +69 -58
  52. package/dist/tools/inference-marketplace.tools.d.ts +1 -1
  53. package/dist/tools/inference-marketplace.tools.js +10 -10
  54. package/dist/tools/jingswap.tools.d.ts +1 -1
  55. package/dist/tools/jingswap.tools.js +30 -30
  56. package/dist/tools/legion.tools.d.ts +1 -1
  57. package/dist/tools/legion.tools.js +20 -20
  58. package/dist/tools/lightning.tools.d.ts +1 -1
  59. package/dist/tools/lightning.tools.js +14 -14
  60. package/dist/tools/mempool.tools.d.ts +1 -1
  61. package/dist/tools/mempool.tools.js +5 -5
  62. package/dist/tools/news.tools.d.ts +1 -1
  63. package/dist/tools/news.tools.js +2 -1
  64. package/dist/tools/nft.tools.d.ts +1 -1
  65. package/dist/tools/nft.tools.js +12 -12
  66. package/dist/tools/nonce.tools.d.ts +1 -1
  67. package/dist/tools/nonce.tools.js +8 -8
  68. package/dist/tools/nostr.tools.d.ts +1 -1
  69. package/dist/tools/nostr.tools.js +12 -12
  70. package/dist/tools/openrouter.tools.d.ts +1 -1
  71. package/dist/tools/openrouter.tools.js +4 -4
  72. package/dist/tools/ordinals-marketplace.tools.d.ts +1 -1
  73. package/dist/tools/ordinals-marketplace.tools.js +10 -10
  74. package/dist/tools/ordinals-p2p.tools.d.ts +1 -1
  75. package/dist/tools/ordinals-p2p.tools.js +18 -18
  76. package/dist/tools/ordinals.tools.d.ts +1 -1
  77. package/dist/tools/ordinals.tools.js +8 -8
  78. package/dist/tools/pillar-direct.tools.d.ts +1 -1
  79. package/dist/tools/pillar-direct.tools.js +59 -38
  80. package/dist/tools/pillar.tools.d.ts +1 -1
  81. package/dist/tools/pillar.tools.js +28 -26
  82. package/dist/tools/profiles.d.ts +51 -0
  83. package/dist/tools/profiles.js +111 -0
  84. package/dist/tools/psbt.tools.d.ts +1 -1
  85. package/dist/tools/psbt.tools.js +8 -8
  86. package/dist/tools/query.tools.d.ts +1 -1
  87. package/dist/tools/query.tools.js +12 -12
  88. package/dist/tools/relay-diagnostic.tools.d.ts +1 -1
  89. package/dist/tools/relay-diagnostic.tools.js +3 -3
  90. package/dist/tools/reputation.tools.d.ts +1 -1
  91. package/dist/tools/reputation.tools.js +22 -22
  92. package/dist/tools/runes.tools.d.ts +1 -1
  93. package/dist/tools/runes.tools.js +18 -18
  94. package/dist/tools/sbtc.tools.d.ts +1 -1
  95. package/dist/tools/sbtc.tools.js +14 -33
  96. package/dist/tools/scaffold.tools.d.ts +1 -1
  97. package/dist/tools/scaffold.tools.js +4 -4
  98. package/dist/tools/settings.tools.d.ts +1 -1
  99. package/dist/tools/settings.tools.js +9 -9
  100. package/dist/tools/signing.tools.d.ts +1 -1
  101. package/dist/tools/signing.tools.js +20 -20
  102. package/dist/tools/skill-mappings.js +4 -0
  103. package/dist/tools/souldinals.tools.d.ts +1 -1
  104. package/dist/tools/souldinals.tools.js +10 -10
  105. package/dist/tools/stacking-lottery.tools.d.ts +1 -1
  106. package/dist/tools/stacking-lottery.tools.js +11 -11
  107. package/dist/tools/stacking.tools.d.ts +1 -1
  108. package/dist/tools/stacking.tools.js +358 -50
  109. package/dist/tools/stacks-market.tools.d.ts +1 -1
  110. package/dist/tools/stacks-market.tools.js +22 -22
  111. package/dist/tools/styx.tools.d.ts +1 -1
  112. package/dist/tools/styx.tools.js +11 -11
  113. package/dist/tools/taproot-multisig.tools.d.ts +1 -1
  114. package/dist/tools/taproot-multisig.tools.js +5 -5
  115. package/dist/tools/tenero.tools.d.ts +1 -1
  116. package/dist/tools/tenero.tools.js +22 -22
  117. package/dist/tools/tokens.tools.d.ts +1 -1
  118. package/dist/tools/tokens.tools.js +10 -10
  119. package/dist/tools/transfer.tools.d.ts +1 -1
  120. package/dist/tools/transfer.tools.js +4 -4
  121. package/dist/tools/wallet-management.tools.d.ts +1 -1
  122. package/dist/tools/wallet-management.tools.js +16 -16
  123. package/dist/tools/wallet.tools.d.ts +1 -1
  124. package/dist/tools/wallet.tools.js +2 -2
  125. package/dist/tools/yield-dashboard.tools.d.ts +1 -1
  126. package/dist/tools/yield-dashboard.tools.js +18 -27
  127. package/dist/tools/yield-hunter.tools.d.ts +1 -1
  128. package/dist/tools/yield-hunter.tools.js +6 -6
  129. package/dist/utils/bitcoin.d.ts +8 -0
  130. package/dist/utils/bitcoin.js +24 -0
  131. package/dist/utils/fee.js +1 -1
  132. package/package.json +8 -7
  133. package/skill/SKILL.md +1 -1
  134. package/skill/references/stacks-defi.md +1 -1
@@ -22,7 +22,7 @@ export function registerCredentialsTools(server) {
22
22
  */
23
23
  server.registerTool("credentials_list", {
24
24
  description: "List all stored credentials. Shows service names, key names, and last-updated timestamps. Does NOT reveal credential values.",
25
- inputSchema: {},
25
+ inputSchema: z.object({}),
26
26
  }, async () => {
27
27
  try {
28
28
  await ensureUnlocked();
@@ -42,10 +42,10 @@ export function registerCredentialsTools(server) {
42
42
  */
43
43
  server.registerTool("credentials_get", {
44
44
  description: "Retrieve a stored credential value by service and key. Returns the decrypted value. WARNING: The returned value is sensitive — do not log or display it unnecessarily.",
45
- inputSchema: {
45
+ inputSchema: z.object({
46
46
  service: z.string().min(1).describe("Service name (e.g. 'github', 'openrouter')"),
47
47
  key: z.string().min(1).describe("Key name within the service (e.g. 'api_key', 'token')"),
48
- },
48
+ }),
49
49
  }, async ({ service, key }) => {
50
50
  try {
51
51
  await ensureUnlocked();
@@ -74,14 +74,14 @@ export function registerCredentialsTools(server) {
74
74
  */
75
75
  server.registerTool("credentials_set", {
76
76
  description: "Store or update a credential. Encrypts the value with AES-256-GCM and saves to ~/.aibtc/credentials.enc. If the service/key pair already exists, it is updated.",
77
- inputSchema: {
77
+ inputSchema: z.object({
78
78
  service: z.string().min(1).describe("Service name (e.g. 'github', 'openrouter')"),
79
79
  key: z.string().min(1).describe("Key name within the service (e.g. 'api_key', 'token')"),
80
80
  value: z
81
81
  .string()
82
82
  .min(1)
83
83
  .describe("The credential value to store — WARNING: sensitive"),
84
- },
84
+ }),
85
85
  }, async ({ service, key, value }) => {
86
86
  try {
87
87
  await ensureUnlocked();
@@ -104,10 +104,10 @@ export function registerCredentialsTools(server) {
104
104
  */
105
105
  server.registerTool("credentials_delete", {
106
106
  description: "Remove a stored credential by service and key. The encrypted store file is rewritten without the deleted entry.",
107
- inputSchema: {
107
+ inputSchema: z.object({
108
108
  service: z.string().min(1).describe("Service name (e.g. 'github', 'openrouter')"),
109
109
  key: z.string().min(1).describe("Key name within the service (e.g. 'api_key', 'token')"),
110
- },
110
+ }),
111
111
  }, async ({ service, key }) => {
112
112
  try {
113
113
  await ensureUnlocked();
@@ -130,7 +130,7 @@ export function registerCredentialsTools(server) {
130
130
  */
131
131
  server.registerTool("credentials_unlock", {
132
132
  description: "Verify that the credential store password works and show store info. Uses ARC_CREDS_PASSWORD env var. Creates a new empty store if none exists.",
133
- inputSchema: {},
133
+ inputSchema: z.object({}),
134
134
  }, async () => {
135
135
  try {
136
136
  await credentials.unlock();
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerDefiTools(server: McpServer): void;
3
3
  //# sourceMappingURL=defi.tools.d.ts.map
@@ -15,11 +15,11 @@ Returns the expected output amount for swapping tokenX to tokenY.
15
15
  Use full contract IDs for tokens (e.g., 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-wstx-v2').
16
16
 
17
17
  Note: ALEX DEX is only available on mainnet.`,
18
- inputSchema: {
18
+ inputSchema: z.object({
19
19
  tokenX: z.string().describe("Input token contract ID"),
20
20
  tokenY: z.string().describe("Output token contract ID"),
21
21
  amountIn: z.string().describe("Amount of tokenX to swap (in smallest units)"),
22
- },
22
+ }),
23
23
  }, async ({ tokenX, tokenY, amountIn }) => {
24
24
  try {
25
25
  if (NETWORK !== "mainnet") {
@@ -54,7 +54,7 @@ Swaps tokenX for tokenY using the ALEX AMM.
54
54
  Use full contract IDs for tokens.
55
55
 
56
56
  Note: ALEX DEX is only available on mainnet.`,
57
- inputSchema: {
57
+ inputSchema: z.object({
58
58
  tokenX: z.string().describe("Input token contract ID"),
59
59
  tokenY: z.string().describe("Output token contract ID"),
60
60
  amountIn: z.string().describe("Amount of tokenX to swap (in smallest units)"),
@@ -63,7 +63,7 @@ Note: ALEX DEX is only available on mainnet.`,
63
63
  .optional()
64
64
  .default("0")
65
65
  .describe("Minimum acceptable output amount (slippage protection)"),
66
- },
66
+ }),
67
67
  }, async ({ tokenX, tokenY, amountIn, minAmountOut }) => {
68
68
  try {
69
69
  if (NETWORK !== "mainnet") {
@@ -99,10 +99,10 @@ Note: ALEX DEX is only available on mainnet.`,
99
99
  Returns reserve balances and pool details for a token pair.
100
100
 
101
101
  Note: ALEX DEX is only available on mainnet.`,
102
- inputSchema: {
102
+ inputSchema: z.object({
103
103
  tokenX: z.string().describe("First token contract ID"),
104
104
  tokenY: z.string().describe("Second token contract ID"),
105
- },
105
+ }),
106
106
  }, async ({ tokenX, tokenY }) => {
107
107
  try {
108
108
  if (NETWORK !== "mainnet") {
@@ -140,13 +140,13 @@ Returns pool ID, token pair, and factor (fee tier) for each pool.
140
140
  Use this to find which tokens can be swapped before calling alex_swap.
141
141
 
142
142
  Note: ALEX DEX is only available on mainnet.`,
143
- inputSchema: {
143
+ inputSchema: z.object({
144
144
  limit: z
145
145
  .number()
146
146
  .optional()
147
147
  .default(50)
148
148
  .describe("Maximum number of pools to return (default 50)"),
149
- },
149
+ }),
150
150
  }, async ({ limit }) => {
151
151
  try {
152
152
  if (NETWORK !== "mainnet") {
@@ -187,7 +187,7 @@ Each asset includes its symbol, name, and contract ID.
187
187
  Supported assets: wSTX, sBTC, stSTX, USDC, USDH, stSTXbtc.
188
188
 
189
189
  Note: Zest Protocol is only available on mainnet.`,
190
- inputSchema: {},
190
+ inputSchema: z.object({}),
191
191
  }, async () => {
192
192
  try {
193
193
  if (NETWORK !== "mainnet") {
@@ -223,13 +223,13 @@ Returns collateral, debt, health factor, and LTV data across all assets.
223
223
  The position query returns USD-denominated totals.
224
224
 
225
225
  Note: Zest Protocol is only available on mainnet.`,
226
- inputSchema: {
226
+ inputSchema: z.object({
227
227
  asset: z.string().default("sBTC").describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
228
228
  address: z
229
229
  .string()
230
230
  .optional()
231
231
  .describe("User address (uses wallet if not specified)"),
232
- },
232
+ }),
233
233
  }, async ({ asset, address }) => {
234
234
  try {
235
235
  if (NETWORK !== "mainnet") {
@@ -272,10 +272,10 @@ You can use the asset symbol (e.g., 'sBTC', 'USDC') or full contract ID.
272
272
  Supported assets: wSTX, sBTC, stSTX, USDC, USDH, stSTXbtc.
273
273
 
274
274
  Note: Zest Protocol is only available on mainnet.`,
275
- inputSchema: {
275
+ inputSchema: z.object({
276
276
  asset: z.string().describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
277
277
  amount: z.string().describe("Amount to supply (in smallest units)"),
278
- },
278
+ }),
279
279
  }, async ({ asset, amount }) => {
280
280
  try {
281
281
  if (NETWORK !== "mainnet") {
@@ -310,10 +310,10 @@ Removes collateral and redeems for underlying assets in one atomic operation.
310
310
  You can use the asset symbol (e.g., 'sBTC', 'USDC') or full contract ID.
311
311
 
312
312
  Note: Amount is in zToken shares. Zest Protocol is only available on mainnet.`,
313
- inputSchema: {
313
+ inputSchema: z.object({
314
314
  asset: z.string().describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
315
315
  amount: z.string().describe("Amount of zToken shares to withdraw"),
316
- },
316
+ }),
317
317
  }, async ({ asset, amount }) => {
318
318
  try {
319
319
  if (NETWORK !== "mainnet") {
@@ -351,10 +351,10 @@ You can use the asset symbol (e.g., 'USDC', 'sBTC') or full contract ID.
351
351
  Three LTV tiers: ~75% (borrow limit), ~85% (partial liquidation), ~95% (full liquidation).
352
352
 
353
353
  Note: Zest Protocol is only available on mainnet.`,
354
- inputSchema: {
354
+ inputSchema: z.object({
355
355
  asset: z.string().describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
356
356
  amount: z.string().describe("Amount to borrow (in smallest units)"),
357
- },
357
+ }),
358
358
  }, async ({ asset, amount }) => {
359
359
  try {
360
360
  if (NETWORK !== "mainnet") {
@@ -392,10 +392,10 @@ Note: zest_supply already handles this atomically via supply-collateral-add.
392
392
  This tool is only needed if you used vault deposit separately.
393
393
 
394
394
  Mainnet only.`,
395
- inputSchema: {
395
+ inputSchema: z.object({
396
396
  asset: z.string().describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
397
397
  amount: z.string().describe("Amount of zTokens to add as collateral (in smallest units)"),
398
- },
398
+ }),
399
399
  }, async ({ asset, amount }) => {
400
400
  try {
401
401
  if (NETWORK !== "mainnet") {
@@ -430,14 +430,14 @@ Repays borrowed assets plus accrued interest.
430
430
  You can use the asset symbol (e.g., 'USDC', 'sBTC') or full contract ID.
431
431
 
432
432
  Note: Zest Protocol is only available on mainnet.`,
433
- inputSchema: {
433
+ inputSchema: z.object({
434
434
  asset: z.string().describe("Asset symbol (e.g., 'sBTC', 'USDC') or full contract ID"),
435
435
  amount: z.string().describe("Amount to repay (in smallest units)"),
436
436
  onBehalfOf: z
437
437
  .string()
438
438
  .optional()
439
439
  .describe("Optional: repay on behalf of another address"),
440
- },
440
+ }),
441
441
  }, async ({ asset, amount, onBehalfOf }) => {
442
442
  try {
443
443
  if (NETWORK !== "mainnet") {
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerDualStackingTools(server: McpServer): void;
3
3
  //# sourceMappingURL=dual-stacking.tools.d.ts.map
@@ -103,12 +103,12 @@ Returns enrollment state for both the current and next cycle, the APR range
103
103
  (higher with more stacked STX), minimum enrollment amount, and current cycle data.
104
104
 
105
105
  Note: Dual Stacking is only available on mainnet.`,
106
- inputSchema: {
106
+ inputSchema: z.object({
107
107
  address: z
108
108
  .string()
109
109
  .optional()
110
110
  .describe("Address to check. Uses configured wallet if not provided."),
111
- },
111
+ }),
112
112
  }, async ({ address }) => {
113
113
  try {
114
114
  if (NETWORK !== "mainnet") {
@@ -231,7 +231,7 @@ The rollback parameter lets you look up rewards from a specific snapshot offset
231
231
  within the cycle (default 0 = most recent).
232
232
 
233
233
  Note: Dual Stacking is only available on mainnet.`,
234
- inputSchema: {
234
+ inputSchema: z.object({
235
235
  cycle: z.number().describe("Cycle number to query rewards for"),
236
236
  address: z
237
237
  .string()
@@ -242,7 +242,7 @@ Note: Dual Stacking is only available on mainnet.`,
242
242
  .optional()
243
243
  .default(0)
244
244
  .describe("Snapshot rollback offset within the cycle (default 0)"),
245
- },
245
+ }),
246
246
  }, async ({ cycle, address, rollback }) => {
247
247
  try {
248
248
  if (NETWORK !== "mainnet") {
@@ -290,12 +290,12 @@ address than the signing wallet. If omitted, rewards go to the signing wallet.
290
290
  Requires an unlocked wallet with sufficient sBTC balance.
291
291
 
292
292
  Note: Dual Stacking is only available on mainnet.`,
293
- inputSchema: {
293
+ inputSchema: z.object({
294
294
  rewardAddress: z
295
295
  .string()
296
296
  .optional()
297
297
  .describe("Optional Stacks address to receive sBTC rewards. Uses signing wallet address if not provided."),
298
- },
298
+ }),
299
299
  }, async ({ rewardAddress }) => {
300
300
  try {
301
301
  if (NETWORK !== "mainnet") {
@@ -337,7 +337,7 @@ the start of the next PoX cycle; you continue to earn rewards for the current cy
337
337
  Requires an unlocked wallet.
338
338
 
339
339
  Note: Dual Stacking is only available on mainnet.`,
340
- inputSchema: {},
340
+ inputSchema: z.object({}),
341
341
  }, async () => {
342
342
  try {
343
343
  if (NETWORK !== "mainnet") {
@@ -10,7 +10,7 @@
10
10
  * DeFi yields, bounties, deploy paid endpoints). News correspondent and the
11
11
  * trading competition are intentionally excluded from this menu.
12
12
  */
13
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
+ import { McpServer } from "@modelcontextprotocol/server";
14
14
  export interface EarningStrategy {
15
15
  /** Stable id for filtering. */
16
16
  id: string;
@@ -15,9 +15,9 @@ export const EARNING_STRATEGIES = [
15
15
  id: "stacking",
16
16
  name: "Bitcoin Stacking (PoX)",
17
17
  assets: ["STX"],
18
- returns: "BTC / sBTC rewards per PoX cycle",
19
- summary: "Lock STX to support Stacks consensus and earn Bitcoin rewards. Dual Stacking routes the yield as sBTC.",
20
- start_with: ["get_stacking_status", "stack_stx", "dual_stacking_enroll"],
18
+ returns: "sBTC rewards per PoX cycle",
19
+ summary: "Lock STX with a PoX-5 signer manager to support Stacks consensus and earn sBTC rewards (or BTC via the manager's payout address). Dual Stacking routes the yield as sBTC.",
20
+ start_with: ["list_stacking_signers", "stack_stx", "get_stacking_status", "dual_stacking_enroll"],
21
21
  },
22
22
  {
23
23
  id: "defi_yield",
@@ -71,12 +71,12 @@ Each entry: \`{ id, name, assets, returns, summary, start_with, reference? }\` w
71
71
  Optional \`asset\` filter (e.g. "STX", "sBTC") returns only strategies that put that asset to work — useful for "what can I do with the STX I hold?". Matching is case-insensitive substring over each strategy's \`assets\`.
72
72
 
73
73
  Aligned with aibtc.com. The trading competition and news correspondent are intentionally not part of this menu.`,
74
- inputSchema: {
74
+ inputSchema: z.object({
75
75
  asset: z
76
76
  .string()
77
77
  .optional()
78
78
  .describe('Optional asset filter (e.g. "STX", "sBTC"). Returns only strategies that use a matching asset.'),
79
- },
79
+ }),
80
80
  }, async ({ asset }) => {
81
81
  try {
82
82
  const filtered = asset
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerEndpointTools(server: McpServer): void;
3
3
  //# sourceMappingURL=endpoint.tools.d.ts.map
@@ -1,12 +1,12 @@
1
1
  import { z } from "zod";
2
2
  import { createApiClient, API_URL, probeEndpoint, formatPaymentAmount, checkSufficientBalance, generateDedupKey, checkDedupCache, recordTransaction, X402_DEDUP_TTL_MS, NETWORK } from "../services/x402.service.js";
3
- import { ALL_ENDPOINTS, searchEndpoints, formatEndpointsTable, getEndpointsBySource, getCategories, } from "../endpoints/registry.js";
3
+ import { STATIC_ENDPOINTS, formatEndpointsTable } from "../endpoints/registry.js";
4
+ import { discoverOpenApiEndpoints, fetchDirectoryEntries, } from "../services/x402-discovery.service.js";
4
5
  import { createJsonResponse, createErrorResponse } from "../utils/index.js";
5
6
  import { X402_HEADERS, decodePaymentResponse } from "../utils/x402-protocol.js";
6
7
  import { extractPaymentIdFromPaymentSignature, extractTxidFromPaymentSignature, pollTransactionConfirmation, } from "../utils/x402-recovery.js";
7
8
  import { formatCanonicalPaymentStatus } from "../utils/x402-payment-state.js";
8
9
  import { emitPaymentLog } from "../utils/x402-payment-logging.js";
9
- const ALL_SOURCES = "x402.biwas.xyz, x402.aibtc.com, stx402.com, aibtc.com";
10
10
  /**
11
11
  * Parse and validate endpoint URL from either a full URL or path+apiUrl combination.
12
12
  * Merges any query parameters from the URL into the provided params.
@@ -130,27 +130,26 @@ function formatProbeResponse(result, method, fullUrl, callWithOptions, messagePr
130
130
  export function registerEndpointTools(server) {
131
131
  // List x402 endpoints
132
132
  server.registerTool("list_x402_endpoints", {
133
- description: `List known x402 API endpoints from ${ALL_SOURCES}.
134
-
135
- The agent can:
136
- 1. Execute x402 endpoints from these sources (paid API calls with automatic payment handling)
137
- 2. Execute direct Stacks transactions (transfer STX, call contracts, deploy contracts)
133
+ description: `List x402 API endpoints. x402.aibtc.com and stx402.com are read live from their OpenAPI specs; the stx402.com directory lists x402 endpoints registered by third parties.
138
134
 
139
135
  Sources:
140
136
  - x402.biwas.xyz: DeFi analytics, market data, wallet analysis, Zest/ALEX protocols
141
- - x402.aibtc.com: AI inference, OpenRouter integration, Stacks utilities, hashing, storage
142
- - stx402.com: AI services, cryptography, storage, utilities, agent registry
143
- - aibtc.com: Inbox messaging system`,
144
- inputSchema: {
137
+ - x402.aibtc.com: AI inference, Stacks utilities, hashing, storage (live)
138
+ - stx402.com: x402 endpoint registry, agent registry (ERC-8004), links (live)
139
+ - aibtc.com: Inbox messaging
140
+ - directory: third-party endpoints registered at stx402.com (live, mainnet). Unverified entries are hidden unless includeUnverified is true — probe before paying.
141
+
142
+ Costs from live specs are tiers ("paid (standard)", "paid (dynamic)"); use probe_x402_endpoint for the exact price.`,
143
+ inputSchema: z.object({
145
144
  source: z
146
- .enum(["x402.biwas.xyz", "x402.aibtc.com", "stx402.com", "aibtc.com", "all"])
145
+ .enum(["x402.biwas.xyz", "x402.aibtc.com", "stx402.com", "aibtc.com", "directory", "all"])
147
146
  .optional()
148
147
  .default("all")
149
148
  .describe("Filter by API source"),
150
149
  category: z
151
150
  .string()
152
151
  .optional()
153
- .describe("Filter by category (use without value to see available categories)"),
152
+ .describe("Filter by category (case-insensitive)"),
154
153
  search: z
155
154
  .string()
156
155
  .optional()
@@ -163,12 +162,42 @@ Sources:
163
162
  .boolean()
164
163
  .optional()
165
164
  .describe("Only show paid endpoints (require x402 payment)"),
166
- },
167
- }, async ({ source, category, search, showFreeOnly, showPaidOnly }) => {
165
+ includeUnverified: z
166
+ .boolean()
167
+ .optional()
168
+ .default(false)
169
+ .describe("Include unverified third-party entries from the stx402.com directory"),
170
+ }),
171
+ }, async ({ source, category, search, showFreeOnly, showPaidOnly, includeUnverified }) => {
168
172
  try {
169
- let endpoints = ALL_ENDPOINTS;
170
- if (source && source !== "all") {
171
- endpoints = getEndpointsBySource(source);
173
+ const wanted = source ?? "all";
174
+ const unavailable = [];
175
+ let endpoints = STATIC_ENDPOINTS.filter((ep) => wanted === "all" || ep.source === wanted);
176
+ if (wanted === "all" || wanted === "x402.aibtc.com" || wanted === "stx402.com") {
177
+ const live = await discoverOpenApiEndpoints();
178
+ endpoints.push(...live.endpoints.filter((ep) => wanted === "all" || ep.source === wanted));
179
+ unavailable.push(...live.unavailable.filter((u) => wanted === "all" || u.source === wanted));
180
+ }
181
+ let directory = [];
182
+ // Directory entries carry no method or price, so they only answer
183
+ // unfiltered or keyword/category browsing, not free/paid filters.
184
+ if ((wanted === "all" || wanted === "directory") && !showFreeOnly && !showPaidOnly) {
185
+ if (NETWORK !== "mainnet") {
186
+ if (wanted === "directory") {
187
+ unavailable.push({ source: "directory", error: "the stx402.com directory lists mainnet endpoints only" });
188
+ }
189
+ }
190
+ else {
191
+ try {
192
+ directory = (await fetchDirectoryEntries()).filter((e) => includeUnverified || e.status === "verified");
193
+ }
194
+ catch (error) {
195
+ unavailable.push({
196
+ source: "directory",
197
+ error: error instanceof Error ? error.message : String(error),
198
+ });
199
+ }
200
+ }
172
201
  }
173
202
  if (showFreeOnly) {
174
203
  endpoints = endpoints.filter((ep) => ep.cost === "FREE");
@@ -177,38 +206,52 @@ Sources:
177
206
  endpoints = endpoints.filter((ep) => ep.cost !== "FREE");
178
207
  }
179
208
  if (category) {
180
- endpoints = endpoints.filter((ep) => ep.category.toLowerCase() === category.toLowerCase());
209
+ const c = category.toLowerCase();
210
+ endpoints = endpoints.filter((ep) => ep.category.toLowerCase() === c);
211
+ directory = directory.filter((e) => e.category.toLowerCase() === c);
181
212
  }
182
213
  if (search) {
183
- const searchResults = searchEndpoints(search);
184
- endpoints = endpoints.filter((ep) => searchResults.includes(ep));
214
+ const q = search.toLowerCase();
215
+ endpoints = endpoints.filter((ep) => ep.path.toLowerCase().includes(q) ||
216
+ ep.description.toLowerCase().includes(q) ||
217
+ ep.category.toLowerCase().includes(q));
218
+ directory = directory.filter((e) => e.name.toLowerCase().includes(q) ||
219
+ e.url.toLowerCase().includes(q) ||
220
+ e.category.toLowerCase().includes(q));
185
221
  }
186
- if (endpoints.length === 0) {
187
- const categories = getCategories();
222
+ const unavailableText = unavailable.length > 0
223
+ ? `\n\n## Unavailable sources\n${unavailable.map((u) => `- ${u.source}: ${u.error}`).join("\n")}`
224
+ : "";
225
+ if (endpoints.length === 0 && directory.length === 0) {
188
226
  return {
189
227
  content: [
190
228
  {
191
229
  type: "text",
192
- text: `No endpoints found matching your criteria.
193
-
194
- Available categories: ${categories.join(", ")}
195
-
196
- Sources: ${ALL_SOURCES}
197
-
198
- If you're looking to perform a direct blockchain action (transfer STX, call a contract), those are available via separate tools.`,
230
+ text: `No endpoints found matching your criteria (source: ${wanted}).` +
231
+ unavailableText +
232
+ `\n\nIf you're looking to perform a direct blockchain action (transfer STX, call a contract), those are available via separate tools.`,
199
233
  },
200
234
  ],
201
235
  };
202
236
  }
203
- const formatted = formatEndpointsTable(endpoints);
204
- const sourceInfo = source === "all"
205
- ? `Sources: ${ALL_SOURCES}`
206
- : `Source: ${source}`;
237
+ const directoryText = directory.length > 0
238
+ ? `\n\n## Directory (stx402.com, third-party)\n` +
239
+ directory
240
+ .map((e) => `- ${e.name} [${e.category}, ${e.status}]\n ${e.url}`)
241
+ .join("\n")
242
+ : "";
207
243
  return {
208
244
  content: [
209
245
  {
210
246
  type: "text",
211
- text: `# Available x402 Endpoints (${endpoints.length} total)\n\n${sourceInfo}\nDefault API: ${API_URL}\n${formatted}\n\n---\nUse execute_x402_endpoint to call any of these endpoints.`,
247
+ text: `# Available x402 Endpoints (${endpoints.length + directory.length} total)\n\n` +
248
+ `Source: ${wanted}\nDefault API: ${API_URL}\n` +
249
+ (endpoints.length > 0 ? `\n${formatEndpointsTable(endpoints)}` : "") +
250
+ directoryText +
251
+ unavailableText +
252
+ `\n\n---\nUse execute_x402_endpoint to call an endpoint: pass apiUrl="https://<source>" with the path ` +
253
+ `(the source is in each heading; a bare path goes to ${API_URL}), or the full url for directory entries. ` +
254
+ `Use probe_x402_endpoint first to see the exact price.`,
212
255
  },
213
256
  ],
214
257
  };
@@ -222,16 +265,16 @@ If you're looking to perform a direct blockchain action (transfer STX, call a co
222
265
  description: `Execute an x402 API endpoint. Payment is handled automatically.
223
266
 
224
267
  Supported sources:
225
- - x402.biwas.xyz (default): Use path like "/api/pools/trending"
226
- - x402.aibtc.com (mainnet) / x402.aibtc.dev (testnet): Use apiUrl="https://x402.aibtc.com" with path like "/inference/openrouter/chat"
227
- - stx402.com: Use apiUrl="https://stx402.com" with path like "/ai/dad-joke"
268
+ - x402.aibtc.com (mainnet) / x402.aibtc.dev (testnet), the default: Use path like "/inference/openrouter/chat"
269
+ - x402.biwas.xyz: Use apiUrl="https://x402.biwas.xyz" with path like "/api/pools/trending"
270
+ - stx402.com: Use apiUrl="https://stx402.com" with path like "/registry/list"
228
271
  - aibtc.com (mainnet) / aibtc.dev (testnet): Use apiUrl="https://aibtc.com" with path like "/api/inbox/{address}"
229
272
  - Any x402-compatible URL: Use url parameter with full endpoint URL
230
273
 
231
274
  Use list_x402_endpoints to discover available endpoints.
232
275
 
233
276
  For aibtc.com inbox messages, use send_inbox_message_direct instead — it signs a standard sBTC transfer and settles directly through the x402 facilitator.`,
234
- inputSchema: {
277
+ inputSchema: z.object({
235
278
  method: z
236
279
  .enum(["GET", "POST", "PUT", "DELETE"])
237
280
  .default("GET")
@@ -240,7 +283,7 @@ For aibtc.com inbox messages, use send_inbox_message_direct instead — it signs
240
283
  .string()
241
284
  .url()
242
285
  .optional()
243
- .describe("Full endpoint URL (e.g., 'https://stx402.com/ai/dad-joke'). Takes precedence over path+apiUrl."),
286
+ .describe("Full endpoint URL (e.g., 'https://x402.aibtc.com/hashing/sha256'). Takes precedence over path+apiUrl."),
244
287
  path: z
245
288
  .string()
246
289
  .optional()
@@ -249,7 +292,7 @@ For aibtc.com inbox messages, use send_inbox_message_direct instead — it signs
249
292
  .string()
250
293
  .url()
251
294
  .optional()
252
- .describe("API base URL. Known sources: x402.biwas.xyz, x402.aibtc.com, stx402.com, aibtc.com. Defaults to configured API_URL."),
295
+ .describe("API base URL: https:// plus the source host from list_x402_endpoints (x402.aibtc.com, x402.biwas.xyz, stx402.com, aibtc.com). Defaults to x402.aibtc.com (testnet x402.aibtc.dev)."),
253
296
  params: z
254
297
  .record(z.string(), z.string())
255
298
  .optional()
@@ -267,7 +310,7 @@ For aibtc.com inbox messages, use send_inbox_message_direct instead — it signs
267
310
  .string()
268
311
  .optional()
269
312
  .describe("Which asset to pay with when the endpoint accepts several. Accepts a symbol (\"sBTC\", \"STX\") or a full contract identifier. Defaults to the first asset this client can pay. Only STX and sBTC can be signed; requesting any other asset returns an error listing what is accepted."),
270
- },
313
+ }),
271
314
  }, async ({ method, url, path, apiUrl, params, data, autoApprove, asset }) => {
272
315
  let fullUrl = "";
273
316
  // Hoisted so the catch can record a broadcast payment for dedup — a
@@ -462,12 +505,12 @@ For paid endpoints, returns payment details (amount, asset, recipient) without e
462
505
  After probing a paid endpoint, use execute_x402_endpoint to actually execute and pay.
463
506
 
464
507
  Supported sources:
465
- - x402.biwas.xyz (default): Use path like "/api/pools/trending"
466
- - x402.aibtc.com (mainnet) / x402.aibtc.dev (testnet): Use apiUrl="https://x402.aibtc.com" with path like "/inference/openrouter/chat"
467
- - stx402.com: Use apiUrl="https://stx402.com" with path like "/ai/dad-joke"
508
+ - x402.aibtc.com (mainnet) / x402.aibtc.dev (testnet), the default: Use path like "/inference/openrouter/chat"
509
+ - x402.biwas.xyz: Use apiUrl="https://x402.biwas.xyz" with path like "/api/pools/trending"
510
+ - stx402.com: Use apiUrl="https://stx402.com" with path like "/registry/list"
468
511
  - aibtc.com (mainnet) / aibtc.dev (testnet): Use apiUrl="https://aibtc.com" with path like "/api/inbox/{address}"
469
512
  - Any x402-compatible URL: Use url parameter with full endpoint URL`,
470
- inputSchema: {
513
+ inputSchema: z.object({
471
514
  method: z
472
515
  .enum(["GET", "POST", "PUT", "DELETE"])
473
516
  .default("GET")
@@ -476,7 +519,7 @@ Supported sources:
476
519
  .string()
477
520
  .url()
478
521
  .optional()
479
- .describe("Full endpoint URL (e.g., 'https://stx402.com/ai/dad-joke'). Takes precedence over path+apiUrl."),
522
+ .describe("Full endpoint URL (e.g., 'https://x402.aibtc.com/hashing/sha256'). Takes precedence over path+apiUrl."),
480
523
  path: z
481
524
  .string()
482
525
  .optional()
@@ -485,7 +528,7 @@ Supported sources:
485
528
  .string()
486
529
  .url()
487
530
  .optional()
488
- .describe("API base URL. Known sources: x402.biwas.xyz, x402.aibtc.com, stx402.com, aibtc.com. Defaults to configured API_URL."),
531
+ .describe("API base URL: https:// plus the source host from list_x402_endpoints (x402.aibtc.com, x402.biwas.xyz, stx402.com, aibtc.com). Defaults to x402.aibtc.com (testnet x402.aibtc.dev)."),
489
532
  params: z
490
533
  .record(z.string(), z.string())
491
534
  .optional()
@@ -498,7 +541,7 @@ Supported sources:
498
541
  .string()
499
542
  .optional()
500
543
  .describe("Quote the cost in this asset when the endpoint accepts several. Accepts a symbol (\"sBTC\", \"STX\") or a full contract identifier. Defaults to the first asset this client can pay; the full accepts[] list is always returned."),
501
- },
544
+ }),
502
545
  }, async ({ method, url, path, apiUrl, params, data, asset }) => {
503
546
  let fullUrl = "";
504
547
  try {
@@ -17,6 +17,6 @@
17
17
  * - identity_unset_wallet - Remove agent wallet association
18
18
  * - identity_transfer - Transfer identity NFT to new owner
19
19
  */
20
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
20
+ import { McpServer } from "@modelcontextprotocol/server";
21
21
  export declare function registerIdentityTools(server: McpServer): void;
22
22
  //# sourceMappingURL=identity.tools.d.ts.map