@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
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Tool profiles: which tools the server exposes.
3
+ *
4
+ * Every tool definition is sent to the client's model on each session, so
5
+ * `--install` writes `AIBTC_TOOLS=core`: a lean set covering wallet, balances,
6
+ * transfers, x402 and earning. Other groups are added with
7
+ * `AIBTC_TOOLS=core,defi,ordinals` (the core set is always included).
8
+ *
9
+ * An unset AIBTC_TOOLS loads every tool: configs written before profiles
10
+ * existed have no AIBTC_TOOLS, and their users keep the tools they had.
11
+ */
12
+ /** Tools exposed by default, whatever groups are enabled. */
13
+ export const CORE_TOOLS = new Set([
14
+ // Wallet
15
+ "get_wallet_info",
16
+ "wallet_status",
17
+ "wallet_create",
18
+ "wallet_import",
19
+ "wallet_unlock",
20
+ "wallet_lock",
21
+ "wallet_export",
22
+ "wallet_rotate_password",
23
+ // Balances
24
+ "get_stx_balance",
25
+ "get_btc_balance",
26
+ "sbtc_get_balance",
27
+ "get_token_balance",
28
+ // Move funds
29
+ "transfer_stx",
30
+ "transfer_btc",
31
+ "sbtc_transfer",
32
+ "get_transaction_status",
33
+ "get_btc_fees",
34
+ // x402
35
+ "list_x402_endpoints",
36
+ "probe_x402_endpoint",
37
+ "execute_x402_endpoint",
38
+ // Earn (bounty_submit requires a registered identity)
39
+ "earning_opportunities",
40
+ "bounty_list",
41
+ "bounty_get",
42
+ "bounty_submit",
43
+ "identity_register",
44
+ ]);
45
+ export const TOOL_GROUPS = {
46
+ wallet: "Wallet management extras, encrypted credential store",
47
+ stacks: "Stacks transactions, contracts, tokens, NFTs, chain queries, nonce tools",
48
+ sbtc: "sBTC deposit/withdraw, Styx BTC→sBTC",
49
+ bitcoin: "Bitcoin L1 UTXOs, mempool watch",
50
+ lightning: "Lightning (Spark) wallet and L402 payments",
51
+ stacking: "PoX stacking, dual stacking, StackSpot",
52
+ defi: "ALEX, Zest, Bitflow, Jingswap, yield hunter/dashboard, Tenero analytics",
53
+ pillar: "Pillar smart wallet",
54
+ ordinals: "Inscriptions, runes, PSBT, ordinals marketplace/P2P, taproot multisig",
55
+ bns: "BNS names",
56
+ identity: "ERC-8004 identity and reputation, message signing",
57
+ social: "Nostr, AIBTC inbox",
58
+ earn: "Bounty board (create, accept, pay, my views)",
59
+ legion: "AIBTC News Legion",
60
+ markets: "Stacks prediction market, At Stake",
61
+ dev: "Scaffolding, OpenRouter, settings, inference marketplace, arXiv",
62
+ };
63
+ export const ALL_TOOLS = { all: true };
64
+ export function isToolGroup(name) {
65
+ return Object.prototype.hasOwnProperty.call(TOOL_GROUPS, name);
66
+ }
67
+ export function isToolSelected(selection, name, group) {
68
+ return selection.all || CORE_TOOLS.has(name) || selection.groups.has(group);
69
+ }
70
+ /**
71
+ * Resolve the selection from `--profile <lean|full>` and `AIBTC_TOOLS`
72
+ * (`all`, or `core` and/or comma-separated group names; unset means `all`).
73
+ * Unknown values throw so a typo doesn't silently hide tools.
74
+ */
75
+ export function resolveToolSelection(argv = process.argv, env = process.env) {
76
+ const flag = argv.indexOf("--profile");
77
+ const profile = flag === -1 ? undefined : argv[flag + 1];
78
+ if (profile !== undefined && profile !== "lean" && profile !== "full") {
79
+ throw new Error(`Unknown --profile "${profile}". Use "lean" or "full".`);
80
+ }
81
+ if (profile === "full")
82
+ return ALL_TOOLS;
83
+ if (profile === "lean")
84
+ return { all: false, groups: new Set() };
85
+ const names = (env.AIBTC_TOOLS ?? "all")
86
+ .split(",")
87
+ .map((s) => s.trim().toLowerCase())
88
+ .filter((n) => n && n !== "core");
89
+ if (names.includes("all"))
90
+ return ALL_TOOLS;
91
+ const unknown = names.filter((n) => !isToolGroup(n));
92
+ if (unknown.length > 0) {
93
+ throw new Error(`Unknown AIBTC_TOOLS group(s): ${unknown.join(", ")}. ` +
94
+ `Valid: all, core, ${Object.keys(TOOL_GROUPS).join(", ")}.`);
95
+ }
96
+ return { all: false, groups: new Set(names) };
97
+ }
98
+ /** Server-instructions paragraph telling the agent what is off and how to turn it on. */
99
+ export function describeSelection(selection) {
100
+ if (selection.all)
101
+ return "All tool groups are enabled.";
102
+ const off = Object.keys(TOOL_GROUPS).filter((g) => !selection.groups.has(g));
103
+ const on = [...selection.groups];
104
+ return [
105
+ `Tool profile: lean core${on.length > 0 ? ` + ${on.join(", ")}` : ""}.`,
106
+ "These groups are not loaded; if the user needs one, tell them to set",
107
+ "AIBTC_TOOLS=core,<group,...> (or all) in this server's config and restart:",
108
+ ...off.map((g) => `- ${g}: ${TOOL_GROUPS[g]}`),
109
+ ].join("\n");
110
+ }
111
+ //# sourceMappingURL=profiles.js.map
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerPsbtTools(server: McpServer): void;
3
3
  //# sourceMappingURL=psbt.tools.d.ts.map
@@ -71,7 +71,7 @@ export function registerPsbtTools(server) {
71
71
  server.registerTool("psbt_create_ordinal_buy", {
72
72
  description: "Create a PSBT for buying an ordinal: buyer pays seller in BTC, seller's inscription UTXO is transferred to buyer. " +
73
73
  "This prepares the PSBT for both parties to sign.",
74
- inputSchema: {
74
+ inputSchema: z.object({
75
75
  inscriptionUtxo: z
76
76
  .string()
77
77
  .describe("Seller inscription outpoint in txid:vout format"),
@@ -89,7 +89,7 @@ export function registerPsbtTools(server) {
89
89
  .optional()
90
90
  .default("medium")
91
91
  .describe("Fee rate: 'fast' (~10 min), 'medium' (~30 min), 'slow' (~1 hr), or explicit sat/vB"),
92
- },
92
+ }),
93
93
  }, async ({ inscriptionUtxo, sellerAddress, priceSats, buyerReceiveAddress, feeRate }) => {
94
94
  try {
95
95
  const walletManager = getWalletManager();
@@ -214,7 +214,7 @@ export function registerPsbtTools(server) {
214
214
  });
215
215
  server.registerTool("psbt_sign", {
216
216
  description: "Sign one or more PSBT inputs with the active wallet. Supports buyer (P2WPKH) and taproot keys.",
217
- inputSchema: {
217
+ inputSchema: z.object({
218
218
  psbtBase64: z.string().describe("PSBT in base64 format"),
219
219
  signInputs: z
220
220
  .array(z.number().int().nonnegative())
@@ -225,7 +225,7 @@ export function registerPsbtTools(server) {
225
225
  .optional()
226
226
  .default(false)
227
227
  .describe("Finalize only the inputs signed in this call"),
228
- },
228
+ }),
229
229
  }, async ({ psbtBase64, signInputs, finalizeSignedInputs }) => {
230
230
  try {
231
231
  const walletManager = getWalletManager();
@@ -299,9 +299,9 @@ export function registerPsbtTools(server) {
299
299
  });
300
300
  server.registerTool("psbt_broadcast", {
301
301
  description: "Finalize a fully signed PSBT and broadcast it to the Bitcoin network via mempool.space.",
302
- inputSchema: {
302
+ inputSchema: z.object({
303
303
  psbtBase64: z.string().describe("Fully signed PSBT in base64 format"),
304
- },
304
+ }),
305
305
  }, async ({ psbtBase64 }) => {
306
306
  try {
307
307
  const tx = decodePsbtBase64(psbtBase64);
@@ -324,9 +324,9 @@ export function registerPsbtTools(server) {
324
324
  });
325
325
  server.registerTool("psbt_decode", {
326
326
  description: "Decode a PSBT to inspect inputs, outputs, signatures, and signing status before broadcast.",
327
- inputSchema: {
327
+ inputSchema: z.object({
328
328
  psbtBase64: z.string().describe("PSBT in base64 format"),
329
- },
329
+ }),
330
330
  }, async ({ psbtBase64 }) => {
331
331
  try {
332
332
  const tx = decodePsbtBase64(psbtBase64);
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerQueryTools(server: McpServer): void;
3
3
  //# sourceMappingURL=query.tools.d.ts.map
@@ -78,12 +78,12 @@ export function registerQueryTools(server) {
78
78
  // Get account info
79
79
  server.registerTool("get_account_info", {
80
80
  description: "Get detailed account information including nonce and balance.",
81
- inputSchema: {
81
+ inputSchema: z.object({
82
82
  address: z
83
83
  .string()
84
84
  .optional()
85
85
  .describe("Stacks address. Uses configured wallet if not provided."),
86
- },
86
+ }),
87
87
  }, async ({ address }) => {
88
88
  try {
89
89
  const hiro = getHiroApi(NETWORK);
@@ -104,14 +104,14 @@ export function registerQueryTools(server) {
104
104
  // Get account transactions
105
105
  server.registerTool("get_account_transactions", {
106
106
  description: "Get transaction history for an account.",
107
- inputSchema: {
107
+ inputSchema: z.object({
108
108
  address: z
109
109
  .string()
110
110
  .optional()
111
111
  .describe("Stacks address. Uses configured wallet if not provided."),
112
112
  limit: z.number().optional().default(20).describe("Maximum number of results"),
113
113
  offset: z.number().optional().default(0).describe("Offset for pagination"),
114
- },
114
+ }),
115
115
  }, async ({ address, limit, offset }) => {
116
116
  try {
117
117
  const hiro = getHiroApi(NETWORK);
@@ -140,9 +140,9 @@ export function registerQueryTools(server) {
140
140
  // Get block info
141
141
  server.registerTool("get_block_info", {
142
142
  description: "Get information about a specific block.",
143
- inputSchema: {
143
+ inputSchema: z.object({
144
144
  heightOrHash: z.string().describe("Block height (number) or block hash"),
145
- },
145
+ }),
146
146
  }, async ({ heightOrHash }) => {
147
147
  try {
148
148
  const hiro = getHiroApi(NETWORK);
@@ -167,11 +167,11 @@ export function registerQueryTools(server) {
167
167
  // Get mempool info
168
168
  server.registerTool("get_mempool_info", {
169
169
  description: "Get pending transactions in the mempool.",
170
- inputSchema: {
170
+ inputSchema: z.object({
171
171
  senderAddress: z.string().optional().describe("Filter by sender address"),
172
172
  limit: z.number().optional().default(20).describe("Maximum number of results"),
173
173
  offset: z.number().optional().default(0).describe("Offset for pagination"),
174
- },
174
+ }),
175
175
  }, async ({ senderAddress, limit, offset }) => {
176
176
  try {
177
177
  const hiro = getHiroApi(NETWORK);
@@ -200,9 +200,9 @@ export function registerQueryTools(server) {
200
200
  // Get contract info
201
201
  server.registerTool("get_contract_info", {
202
202
  description: "Get information about a smart contract including its ABI.",
203
- inputSchema: {
203
+ inputSchema: z.object({
204
204
  contractId: z.string().describe("Contract ID in format: address.contract-name"),
205
- },
205
+ }),
206
206
  }, async ({ contractId }) => {
207
207
  try {
208
208
  const hiro = getHiroApi(NETWORK);
@@ -232,11 +232,11 @@ export function registerQueryTools(server) {
232
232
  // Get contract events
233
233
  server.registerTool("get_contract_events", {
234
234
  description: "Get events emitted by a smart contract.",
235
- inputSchema: {
235
+ inputSchema: z.object({
236
236
  contractId: z.string().describe("Contract ID in format: address.contract-name"),
237
237
  limit: z.number().optional().default(20).describe("Maximum number of results"),
238
238
  offset: z.number().optional().default(0).describe("Offset for pagination"),
239
- },
239
+ }),
240
240
  }, async ({ contractId, limit, offset }) => {
241
241
  try {
242
242
  const hiro = getHiroApi(NETWORK);
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Tools for checking sponsor relay health and diagnosing nonce issues
5
5
  */
6
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { McpServer } from "@modelcontextprotocol/server";
7
7
  export declare function registerRelayDiagnosticTools(server: McpServer): void;
8
8
  //# sourceMappingURL=relay-diagnostic.tools.d.ts.map
@@ -23,7 +23,7 @@ Use this tool for operator diagnostics around relay-owned sponsor state. It will
23
23
 
24
24
  This tool does not redefine caller-facing x402 payment states. Use paymentId
25
25
  polling for payment lifecycle truth; use this output only as backup diagnostics.`,
26
- inputSchema: {},
26
+ inputSchema: z.object({}),
27
27
  }, async () => {
28
28
  try {
29
29
  const status = await checkRelayHealth(NETWORK);
@@ -57,7 +57,7 @@ Recovery modes:
57
57
  If the relay does not yet support relay endpoints it returns a 404 or 501 and this
58
58
  tool will respond with a clear message rather than throwing an error. In that case,
59
59
  share the txids and nonces from check_relay_health with the AIBTC team.`,
60
- inputSchema: {
60
+ inputSchema: z.object({
61
61
  action: z
62
62
  .enum(["rbf", "fill-gaps", "both", "resync-local-nonce"])
63
63
  .default("both")
@@ -70,7 +70,7 @@ share the txids and nonces from check_relay_health with the AIBTC team.`,
70
70
  .array(z.number().int().nonnegative())
71
71
  .optional()
72
72
  .describe("Specific missing nonces for gap-fill (omit to fill all detected gaps)"),
73
- },
73
+ }),
74
74
  }, async ({ action = "both", txids, nonces }) => {
75
75
  try {
76
76
  // Resolve API key from wallet (if unlocked) to align with sponsor-builder auth flow
@@ -19,6 +19,6 @@
19
19
  * - reputation_append_response - Append a response to received feedback
20
20
  * - reputation_approve_client - Approve a client with index limit
21
21
  */
22
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
+ import { McpServer } from "@modelcontextprotocol/server";
23
23
  export declare function registerReputationTools(server: McpServer): void;
24
24
  //# sourceMappingURL=reputation.tools.d.ts.map
@@ -42,9 +42,9 @@ export function registerReputationTools(server) {
42
42
  description: "Get aggregated reputation summary for an agent from the ERC-8004 reputation registry. " +
43
43
  "Returns average rating as a WAD string (18 decimals) and total feedback count. " +
44
44
  "No wallet required.",
45
- inputSchema: {
45
+ inputSchema: z.object({
46
46
  agentId: z.number().int().min(0).describe("Agent ID to get reputation summary for"),
47
- },
47
+ }),
48
48
  }, async ({ agentId }) => {
49
49
  try {
50
50
  const callerAddress = getCallerAddress();
@@ -78,10 +78,10 @@ export function registerReputationTools(server) {
78
78
  description: "Read a specific feedback entry for an agent by index from the ERC-8004 reputation registry. " +
79
79
  "Returns client address, value, decimals, tags, and timestamp. " +
80
80
  "No wallet required.",
81
- inputSchema: {
81
+ inputSchema: z.object({
82
82
  agentId: z.number().int().min(0).describe("Agent ID to read feedback for"),
83
83
  index: z.number().int().min(0).describe("Feedback index to read"),
84
- },
84
+ }),
85
85
  }, async ({ agentId, index }) => {
86
86
  try {
87
87
  const callerAddress = getCallerAddress();
@@ -120,7 +120,7 @@ export function registerReputationTools(server) {
120
120
  "WARNING: Uses one RPC call per entry (N+1 pattern) — avoid calling for agents with " +
121
121
  "large feedback sets without using cursor-based pagination. " +
122
122
  "No wallet required.",
123
- inputSchema: {
123
+ inputSchema: z.object({
124
124
  agentId: z.number().int().min(0).describe("Agent ID to read all feedback for"),
125
125
  tag1: z.string().optional().describe("Filter by tag1 (exact match). Optional."),
126
126
  tag2: z.string().optional().describe("Filter by tag2 (exact match). Optional."),
@@ -136,7 +136,7 @@ export function registerReputationTools(server) {
136
136
  .optional()
137
137
  .default(0)
138
138
  .describe("Pagination cursor (index to start from). Default 0."),
139
- },
139
+ }),
140
140
  }, async ({ agentId, tag1, tag2, includeRevoked, cursor }) => {
141
141
  try {
142
142
  const callerAddress = getCallerAddress();
@@ -160,7 +160,7 @@ export function registerReputationTools(server) {
160
160
  description: "Get a paginated list of clients who gave feedback to an agent. " +
161
161
  "Returns client addresses and a nextCursor for pagination. " +
162
162
  "No wallet required.",
163
- inputSchema: {
163
+ inputSchema: z.object({
164
164
  agentId: z.number().int().min(0).describe("Agent ID to get clients for"),
165
165
  cursor: z
166
166
  .number()
@@ -169,7 +169,7 @@ export function registerReputationTools(server) {
169
169
  .optional()
170
170
  .default(0)
171
171
  .describe("Pagination cursor. Default 0."),
172
- },
172
+ }),
173
173
  }, async ({ agentId, cursor }) => {
174
174
  try {
175
175
  const callerAddress = getCallerAddress();
@@ -192,9 +192,9 @@ export function registerReputationTools(server) {
192
192
  server.registerTool("reputation_get_feedback_count", {
193
193
  description: "Get the total number of feedback entries for an agent from the ERC-8004 reputation registry. " +
194
194
  "No wallet required.",
195
- inputSchema: {
195
+ inputSchema: z.object({
196
196
  agentId: z.number().int().min(0).describe("Agent ID to get feedback count for"),
197
- },
197
+ }),
198
198
  }, async ({ agentId }) => {
199
199
  try {
200
200
  const callerAddress = getCallerAddress();
@@ -215,10 +215,10 @@ export function registerReputationTools(server) {
215
215
  description: "Get the approved feedback index limit for a specific client of an agent. " +
216
216
  "Returns the maximum index up to which the client is approved to submit feedback. " +
217
217
  "No wallet required.",
218
- inputSchema: {
218
+ inputSchema: z.object({
219
219
  agentId: z.number().int().min(0).describe("Agent ID"),
220
220
  client: stacksAddressSchema,
221
- },
221
+ }),
222
222
  }, async ({ agentId, client }) => {
223
223
  try {
224
224
  const callerAddress = getCallerAddress();
@@ -240,10 +240,10 @@ export function registerReputationTools(server) {
240
240
  server.registerTool("reputation_get_last_index", {
241
241
  description: "Get the last feedback index submitted by a specific client for an agent. " +
242
242
  "No wallet required.",
243
- inputSchema: {
243
+ inputSchema: z.object({
244
244
  agentId: z.number().int().min(0).describe("Agent ID"),
245
245
  client: stacksAddressSchema,
246
- },
246
+ }),
247
247
  }, async ({ agentId, client }) => {
248
248
  try {
249
249
  const callerAddress = getCallerAddress();
@@ -269,7 +269,7 @@ export function registerReputationTools(server) {
269
269
  description: "Submit feedback for an agent using the ERC-8004 reputation registry. " +
270
270
  "Value is normalized to 18 decimals (WAD) internally for aggregation. " +
271
271
  "Requires an unlocked wallet.",
272
- inputSchema: {
272
+ inputSchema: z.object({
273
273
  agentId: z.number().int().min(0).describe("Agent ID to give feedback for"),
274
274
  value: z
275
275
  .number()
@@ -295,7 +295,7 @@ export function registerReputationTools(server) {
295
295
  .optional()
296
296
  .describe('Fee preset ("low", "medium", "high") or micro-STX amount. Optional.'),
297
297
  sponsored: sponsoredSchema,
298
- },
298
+ }),
299
299
  }, async ({ agentId, value, valueDecimals, tag1, tag2, endpoint, feedbackUri, feedbackHash, fee, sponsored }) => {
300
300
  try {
301
301
  const walletManager = getWalletManager();
@@ -328,7 +328,7 @@ export function registerReputationTools(server) {
328
328
  description: "Revoke a previously submitted feedback entry by index. " +
329
329
  "Only the original submitter can revoke their feedback. " +
330
330
  "Requires an unlocked wallet.",
331
- inputSchema: {
331
+ inputSchema: z.object({
332
332
  agentId: z.number().int().min(0).describe("Agent ID the feedback was given for"),
333
333
  index: z.number().int().min(0).describe("Feedback index to revoke"),
334
334
  fee: z
@@ -336,7 +336,7 @@ export function registerReputationTools(server) {
336
336
  .optional()
337
337
  .describe('Fee preset ("low", "medium", "high") or micro-STX amount. Optional.'),
338
338
  sponsored: sponsoredSchema,
339
- },
339
+ }),
340
340
  }, async ({ agentId, index, fee, sponsored }) => {
341
341
  try {
342
342
  const walletManager = getWalletManager();
@@ -365,7 +365,7 @@ export function registerReputationTools(server) {
365
365
  description: "Append a response to feedback received from a client. " +
366
366
  "Must be called by the agent that received the feedback. " +
367
367
  "Requires an unlocked wallet.",
368
- inputSchema: {
368
+ inputSchema: z.object({
369
369
  agentId: z.number().int().min(0).describe("Agent ID that received the feedback"),
370
370
  client: stacksAddressSchema,
371
371
  index: z.number().int().min(0).describe("Feedback index to respond to"),
@@ -376,7 +376,7 @@ export function registerReputationTools(server) {
376
376
  .optional()
377
377
  .describe('Fee preset ("low", "medium", "high") or micro-STX amount. Optional.'),
378
378
  sponsored: sponsoredSchema,
379
- },
379
+ }),
380
380
  }, async ({ agentId, client, index, responseUri, responseHash, fee, sponsored }) => {
381
381
  try {
382
382
  const walletManager = getWalletManager();
@@ -407,7 +407,7 @@ export function registerReputationTools(server) {
407
407
  description: "Approve a client to submit feedback up to a specified index limit. " +
408
408
  "Must be called by the agent owner. " +
409
409
  "Requires an unlocked wallet.",
410
- inputSchema: {
410
+ inputSchema: z.object({
411
411
  agentId: z.number().int().min(0).describe("Agent ID to approve a client for"),
412
412
  client: stacksAddressSchema,
413
413
  indexLimit: z
@@ -420,7 +420,7 @@ export function registerReputationTools(server) {
420
420
  .optional()
421
421
  .describe('Fee preset ("low", "medium", "high") or micro-STX amount. Optional.'),
422
422
  sponsored: sponsoredSchema,
423
- },
423
+ }),
424
424
  }, async ({ agentId, client, indexLimit, fee, sponsored }) => {
425
425
  try {
426
426
  const walletManager = getWalletManager();
@@ -20,6 +20,6 @@
20
20
  * Set HIRO_API_KEY to increase Hiro rate limits.
21
21
  * Set UNISAT_API_KEY for Unisat indexer access (5 req/s free tier).
22
22
  */
23
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
23
+ import { McpServer } from "@modelcontextprotocol/server";
24
24
  export declare function registerRunesTools(server: McpServer): void;
25
25
  //# sourceMappingURL=runes.tools.d.ts.map
@@ -71,7 +71,7 @@ export function registerRunesTools(server) {
71
71
  "Returns rune names, IDs, supply, divisibility, symbol, etching transaction, " +
72
72
  "and other metadata for each rune.\n\n" +
73
73
  "Use runes_get_etching to get full details on a specific rune.",
74
- inputSchema: {
74
+ inputSchema: z.object({
75
75
  limit: z
76
76
  .number()
77
77
  .int()
@@ -85,7 +85,7 @@ export function registerRunesTools(server) {
85
85
  .min(0)
86
86
  .optional()
87
87
  .describe("Number of results to skip for pagination (default: 0)"),
88
- },
88
+ }),
89
89
  }, async ({ limit = 20, offset = 0 }) => {
90
90
  try {
91
91
  const data = await runesApiFetch(`/runes/v1/etchings?limit=${limit}&offset=${offset}`);
@@ -103,11 +103,11 @@ export function registerRunesTools(server) {
103
103
  "Returns name, ID, supply info, divisibility, symbol, etching transaction, " +
104
104
  "cenotaph status, terms (mint conditions), and turbo flag.\n\n" +
105
105
  "Rune names use spacers (e.g., 'UNCOMMONGOODS' or 'UNCOMMON•GOODS').",
106
- inputSchema: {
106
+ inputSchema: z.object({
107
107
  rune: z
108
108
  .string()
109
109
  .describe("Rune name (e.g., 'UNCOMMONGOODS' or 'UNCOMMON•GOODS') or numeric rune ID"),
110
- },
110
+ }),
111
111
  }, async ({ rune }) => {
112
112
  try {
113
113
  const encoded = encodeURIComponent(rune);
@@ -125,7 +125,7 @@ export function registerRunesTools(server) {
125
125
  description: "Get the list of holders for a specific Bitcoin Rune.\n\n" +
126
126
  "Returns Bitcoin addresses and their rune balances, sorted by balance descending.\n\n" +
127
127
  "Supports pagination for runes with many holders.",
128
- inputSchema: {
128
+ inputSchema: z.object({
129
129
  rune: z
130
130
  .string()
131
131
  .describe("Rune name (e.g., 'UNCOMMONGOODS' or 'UNCOMMON•GOODS') or numeric rune ID"),
@@ -142,7 +142,7 @@ export function registerRunesTools(server) {
142
142
  .min(0)
143
143
  .optional()
144
144
  .describe("Number of results to skip for pagination (default: 0)"),
145
- },
145
+ }),
146
146
  }, async ({ rune, limit = 20, offset = 0 }) => {
147
147
  try {
148
148
  const encoded = encodeURIComponent(rune);
@@ -160,7 +160,7 @@ export function registerRunesTools(server) {
160
160
  description: "Get recent on-chain activity (mints, transfers, burns) for a specific Bitcoin Rune.\n\n" +
161
161
  "Returns transaction events with amounts, addresses, block heights, and timestamps.\n\n" +
162
162
  "Useful for monitoring rune distribution and trading activity.",
163
- inputSchema: {
163
+ inputSchema: z.object({
164
164
  rune: z
165
165
  .string()
166
166
  .describe("Rune name (e.g., 'UNCOMMONGOODS' or 'UNCOMMON•GOODS') or numeric rune ID"),
@@ -177,7 +177,7 @@ export function registerRunesTools(server) {
177
177
  .min(0)
178
178
  .optional()
179
179
  .describe("Number of results to skip for pagination (default: 0)"),
180
- },
180
+ }),
181
181
  }, async ({ rune, limit = 20, offset = 0 }) => {
182
182
  try {
183
183
  const encoded = encodeURIComponent(rune);
@@ -196,11 +196,11 @@ export function registerRunesTools(server) {
196
196
  "Returns each rune the address holds along with its balance, divisibility, " +
197
197
  "and symbol. Useful for checking which runes a wallet owns.\n\n" +
198
198
  "Address can be any Bitcoin address format (P2WPKH bc1q..., P2TR bc1p..., legacy 1..., etc.)",
199
- inputSchema: {
199
+ inputSchema: z.object({
200
200
  address: z
201
201
  .string()
202
202
  .describe("Bitcoin address to check rune balances for"),
203
- },
203
+ }),
204
204
  }, async ({ address }) => {
205
205
  try {
206
206
  const encoded = encodeURIComponent(address);
@@ -219,7 +219,7 @@ export function registerRunesTools(server) {
219
219
  "Returns mints received, transfers sent/received, and burns associated with " +
220
220
  "this address across all runes.\n\n" +
221
221
  "Address can be any Bitcoin address format (P2WPKH bc1q..., P2TR bc1p..., legacy 1..., etc.)",
222
- inputSchema: {
222
+ inputSchema: z.object({
223
223
  address: z
224
224
  .string()
225
225
  .describe("Bitcoin address to query rune activity for"),
@@ -236,7 +236,7 @@ export function registerRunesTools(server) {
236
236
  .min(0)
237
237
  .optional()
238
238
  .describe("Number of results to skip for pagination (default: 0)"),
239
- },
239
+ }),
240
240
  }, async ({ address, limit = 20, offset = 0 }) => {
241
241
  try {
242
242
  const encoded = encodeURIComponent(address);
@@ -255,12 +255,12 @@ export function registerRunesTools(server) {
255
255
  "Returns rune IDs, amounts, symbols, and divisibility for all runes at the address.\n\n" +
256
256
  "If no address is provided, uses the active wallet's Taproot address.\n" +
257
257
  "Set UNISAT_API_KEY for higher rate limits (5 req/s on free tier).",
258
- inputSchema: {
258
+ inputSchema: z.object({
259
259
  address: z
260
260
  .string()
261
261
  .optional()
262
262
  .describe("Bitcoin address to check (uses active wallet's Taproot address if omitted)"),
263
- },
263
+ }),
264
264
  }, async ({ address }) => {
265
265
  try {
266
266
  let resolvedAddress = address;
@@ -303,7 +303,7 @@ export function registerRunesTools(server) {
303
303
  description: "List UTXOs containing a specific rune at a Bitcoin address via the Unisat indexer.\n\n" +
304
304
  "Rune ID format: 'block:tx' (e.g., '840000:1' for UNCOMMONGOODS).\n\n" +
305
305
  "If no address is provided, uses the active wallet's Taproot address.",
306
- inputSchema: {
306
+ inputSchema: z.object({
307
307
  runeId: z
308
308
  .string()
309
309
  .describe("Rune ID in 'block:tx' format (e.g., '840000:1')"),
@@ -311,7 +311,7 @@ export function registerRunesTools(server) {
311
311
  .string()
312
312
  .optional()
313
313
  .describe("Bitcoin address to check (uses active wallet's Taproot address if omitted)"),
314
- },
314
+ }),
315
315
  }, async ({ runeId, address }) => {
316
316
  try {
317
317
  let resolvedAddress = address;
@@ -365,7 +365,7 @@ export function registerRunesTools(server) {
365
365
  "and returns remaining runes to the sender Taproot address.\n\n" +
366
366
  "Requires wallet to be unlocked. Amount is in smallest rune units (raw integer).\n" +
367
367
  "Uses Unisat indexer to fetch rune UTXOs (UNISAT_API_KEY recommended).",
368
- inputSchema: {
368
+ inputSchema: z.object({
369
369
  runeId: z
370
370
  .string()
371
371
  .describe("Rune ID in 'block:tx' format (e.g., '840000:1')"),
@@ -379,7 +379,7 @@ export function registerRunesTools(server) {
379
379
  .union([z.enum(["fast", "medium", "slow"]), z.number().positive()])
380
380
  .optional()
381
381
  .describe("Fee rate: 'fast' (~10 min), 'medium' (~30 min), 'slow' (~1 hr), or sat/vB number (default: medium)"),
382
- },
382
+ }),
383
383
  }, async ({ runeId, amount, toAddress, feeRate }) => {
384
384
  try {
385
385
  const walletManager = getWalletManager();
@@ -1,3 +1,3 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerSbtcTools(server: McpServer): void;
3
3
  //# sourceMappingURL=sbtc.tools.d.ts.map