bsv-mcp 0.2.0 → 0.2.7

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 (52) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/index.js +87272 -70728
  3. package/index.ts +409 -22
  4. package/package.json +28 -24
  5. package/tools/a2b/discover.ts +13 -13
  6. package/tools/bap/friend.ts +2 -3
  7. package/tools/bap/generate.ts +7 -9
  8. package/tools/bap/getCurrentAddress.ts +1 -8
  9. package/tools/bap/getId.ts +3 -3
  10. package/tools/bsocial/bmapFollow.ts +3 -7
  11. package/tools/bsocial/bmapLikes.ts +3 -3
  12. package/tools/bsocial/bmapReadPosts.ts +3 -3
  13. package/tools/bsocial/createPost.ts +3 -3
  14. package/tools/bsocial/readPosts.ts +3 -3
  15. package/tools/bsv/decodeTransaction.ts +2 -5
  16. package/tools/bsv/explore.ts +2 -3
  17. package/tools/bsv/getPrice.ts +1 -9
  18. package/tools/bsv/token.ts +14 -26
  19. package/tools/index.ts +0 -13
  20. package/tools/mnee/getBalance.ts +2 -4
  21. package/tools/mnee/parseTx.ts +3 -3
  22. package/tools/mnee/sendMnee.ts +5 -5
  23. package/tools/ordinals/getInscription.ts +2 -3
  24. package/tools/ordinals/getTokenByIdOrTicker.ts +6 -3
  25. package/tools/ordinals/marketListings.ts +2 -18
  26. package/tools/ordinals/marketSales.ts +2 -4
  27. package/tools/ordinals/searchInscriptions.ts +2 -4
  28. package/tools/utils/index.ts +14 -16
  29. package/tools/wallet/a2bPublishAgent.ts +18 -27
  30. package/tools/wallet/a2bPublishMcp.ts +17 -22
  31. package/tools/wallet/createOrdinals.ts +11 -20
  32. package/tools/wallet/fetchPaymentUtxos.ts +9 -1
  33. package/tools/wallet/gatherCollectionInfo.ts +9 -13
  34. package/tools/wallet/getAddress.ts +1 -9
  35. package/tools/wallet/getBalance.ts +2 -14
  36. package/tools/wallet/getBalanceDroplet.ts +2 -13
  37. package/tools/wallet/getPublicKey.ts +3 -16
  38. package/tools/wallet/mintCollection.ts +17 -22
  39. package/tools/wallet/purchaseListing.ts +19 -29
  40. package/tools/wallet/refreshUtxos.ts +2 -14
  41. package/tools/wallet/sendOrdinals.ts +11 -20
  42. package/tools/wallet/sendToAddress.ts +2 -22
  43. package/tools/wallet/setupDroplet.ts +7 -18
  44. package/tools/wallet/tools.ts +10 -80
  45. package/tools/wallet/transferOrdToken.ts +12 -20
  46. package/vite.config.ts +15 -0
  47. package/tools/bigblocks/components.ts +0 -304
  48. package/tools/bigblocks/docs.ts +0 -488
  49. package/tools/bigblocks/examples.ts +0 -527
  50. package/tools/bigblocks/generator.ts +0 -485
  51. package/tools/bigblocks/index.ts +0 -23
  52. package/tools/bsocial/bigblocksApiClient.ts +0 -189
@@ -1,9 +1,8 @@
1
- import type { PrivateKey, WalletInterface } from "@bsv/sdk";
1
+ import type { PrivateKey } from "@bsv/sdk";
2
2
  import { Utils } from "@bsv/sdk";
3
3
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
4
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
5
5
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
7
6
  import type {
8
7
  ClientNotification,
9
8
  ClientRequest,
@@ -19,10 +18,9 @@ import type {
19
18
  PreMAP,
20
19
  } from "js-1sat-ord";
21
20
  import { createOrdinals } from "js-1sat-ord";
22
- import { Sigma } from "sigma-protocol";
23
21
  import { z } from "zod";
24
22
  import packageJson from "../../package.json";
25
- import { BsocialBroadcaster, V5Broadcaster } from "../../utils/broadcaster";
23
+ import { V5Broadcaster } from "../../utils/broadcaster";
26
24
  import type { Wallet } from "./wallet";
27
25
 
28
26
  const { toArray, toBase64 } = Utils;
@@ -196,11 +194,8 @@ export function registerA2bPublishMcpTool(
196
194
  server.tool(
197
195
  "wallet_a2bPublishMcp",
198
196
  "Publish an MCP tool configuration record on-chain via Ordinal inscription. This creates a permanent, immutable, and discoverable tool definition that can be accessed by other MCP servers. The tool is published as a JSON inscription with metadata and optional digital signatures for authenticity verification.",
199
- { args: a2bPublishMcpArgsSchema },
200
- async (
201
- { args }: { args: A2bPublishMcpArgs },
202
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
203
- ) => {
197
+ { ...a2bPublishMcpArgsSchema.shape },
198
+ async ({ toolName, command, args, keywords, env, description, destinationAddress }) => {
204
199
  try {
205
200
  if (!identityPk) {
206
201
  console.warn(
@@ -218,20 +213,20 @@ export function registerA2bPublishMcpTool(
218
213
  const walletAddress = paymentPk.toAddress().toString();
219
214
 
220
215
  // Fetch MCP metadata (tools, prompts, resources)
221
- const metadata = await fetchMcpMetadata(args.command, args.args);
216
+ const metadata = await fetchMcpMetadata(command, args);
222
217
  // console.log(`Discovered ${metadata.tools.length} tools, ${metadata.prompts.length} prompts, and ${metadata.resources.length} resources`);
223
218
 
224
219
  // Assemble tool configuration
225
220
  const toolConfig: McpConfig = {
226
- command: args.command,
227
- args: args.args,
221
+ command,
222
+ args,
228
223
  tools: metadata.tools,
229
224
  prompts: metadata.prompts,
230
225
  resources: metadata.resources,
231
- env: args.env
232
- ? args.env.reduce(
233
- (acc, { key, description }) => {
234
- acc[key] = description;
226
+ env: env
227
+ ? env.reduce(
228
+ (acc, { key, description: desc }) => {
229
+ acc[key] = desc;
235
230
  return acc;
236
231
  },
237
232
  {} as Record<string, string>,
@@ -245,9 +240,9 @@ export function registerA2bPublishMcpTool(
245
240
  // Prepare the full configuration with metadata
246
241
  const fullConfig = {
247
242
  mcpServers: {
248
- [args.toolName]: {
249
- description: args.description || "",
250
- keywords: args.keywords || [],
243
+ [toolName]: {
244
+ description: description || "",
245
+ keywords: keywords || [],
251
246
  tools: metadata.tools || [],
252
247
  prompts: metadata.prompts || [],
253
248
  resources: metadata.resources || [],
@@ -266,7 +261,7 @@ export function registerA2bPublishMcpTool(
266
261
  };
267
262
 
268
263
  // Destination for the ordinal
269
- const targetAddress = args.destinationAddress ?? walletAddress;
264
+ const targetAddress = destinationAddress ?? walletAddress;
270
265
  const destinations: Destination[] = [
271
266
  { address: targetAddress, inscription },
272
267
  ];
@@ -335,12 +330,12 @@ export function registerA2bPublishMcpTool(
335
330
  txid,
336
331
  outpoint,
337
332
  onchainUrl,
338
- toolName: args.toolName,
333
+ toolName,
339
334
  toolCount: metadata.tools.length,
340
335
  promptCount: metadata.prompts.length,
341
336
  resourceCount: metadata.resources.length,
342
337
  description:
343
- args.description || `MCP Tool: ${args.toolName}`,
338
+ description || `MCP Tool: ${toolName}`,
344
339
  address: targetAddress,
345
340
  },
346
341
  null,
@@ -1,11 +1,6 @@
1
1
  import { PrivateKey } from "@bsv/sdk";
2
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
- import type {
5
- CallToolResult,
6
- ServerNotification,
7
- ServerRequest,
8
- } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
9
4
  import type {
10
5
  ChangeResult,
11
6
  CreateOrdinalsCollectionItemMetadata,
@@ -16,10 +11,9 @@ import type {
16
11
  LocalSigner,
17
12
  PreMAP,
18
13
  } from "js-1sat-ord";
19
- import { createOrdinals, OneSatBroadcaster } from "js-1sat-ord";
20
- import { Sigma } from "sigma-protocol";
14
+ import { createOrdinals } from "js-1sat-ord";
21
15
  import { z } from "zod";
22
- import { BsocialBroadcaster, V5Broadcaster } from "../../utils/broadcaster";
16
+ import { V5Broadcaster } from "../../utils/broadcaster";
23
17
  import type { Wallet } from "./wallet";
24
18
 
25
19
  /**
@@ -53,11 +47,8 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
53
47
  server.tool(
54
48
  "wallet_createOrdinals",
55
49
  "Creates and inscribes ordinals (NFTs) on the Bitcoin SV blockchain. This tool lets you mint new digital artifacts by encoding data directly into the blockchain. Supports various content types including images, text, JSON, and HTML. The tool handles transaction creation, fee calculation, and broadcasting.",
56
- { args: createOrdinalsArgsSchema },
57
- async (
58
- { args }: { args: CreateOrdinalsArgs },
59
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
60
- ): Promise<CallToolResult> => {
50
+ { ...createOrdinalsArgsSchema.shape },
51
+ async ({ dataB64, contentType, destinationAddress, metadata }): Promise<CallToolResult> => {
61
52
  try {
62
53
  // Load optional identity key for sigma signing
63
54
  const identityKeyWif = process.env.IDENTITY_KEY_WIF;
@@ -92,14 +83,14 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
92
83
 
93
84
  // 4. Create the inscription object
94
85
  const inscription: Inscription = {
95
- dataB64: args.dataB64,
96
- contentType: args.contentType,
86
+ dataB64: dataB64,
87
+ contentType: contentType,
97
88
  };
98
89
 
99
90
  // 5. Create the destination
100
91
  const destinations: Destination[] = [
101
92
  {
102
- address: args.destinationAddress || walletAddress,
93
+ address: destinationAddress || walletAddress,
103
94
  inscription,
104
95
  },
105
96
  ];
@@ -109,7 +100,7 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
109
100
  destinations,
110
101
  paymentPk,
111
102
  changeAddress: walletAddress,
112
- metaData: args.metadata as
103
+ metaData: metadata as
113
104
  | PreMAP
114
105
  | CreateOrdinalsCollectionMetadata
115
106
  | CreateOrdinalsCollectionItemMetadata,
@@ -152,8 +143,8 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
152
143
  txid: changeResult.tx.id("hex"),
153
144
  spentOutpoints: changeResult.spentOutpoints,
154
145
  payChange: changeResult.payChange,
155
- inscriptionAddress: args.destinationAddress || walletAddress,
156
- contentType: args.contentType,
146
+ inscriptionAddress: destinationAddress || walletAddress,
147
+ contentType: contentType,
157
148
  }),
158
149
  },
159
150
  ],
@@ -104,7 +104,15 @@ export async function fetchPaymentUtxosFromV5(
104
104
  const url = `${V5_API_URL}/own/${address}/utxos?refresh=true&txo=true&script=true&limit=250&tags=p2pkh`;
105
105
  console.error(`Fetching UTXOs from V5: ${url}`);
106
106
  const response = await fetch(url);
107
- const data = (await response.json()) as V5Utxo[];
107
+ if (!response.ok) {
108
+ console.error(`V5 UTXO fetch failed: ${response.status} ${response.statusText}`);
109
+ return undefined;
110
+ }
111
+ const data = (await response.json()) as V5Utxo[] | null;
112
+ if (!Array.isArray(data)) {
113
+ console.error(`V5 UTXO response was not an array: ${typeof data}`);
114
+ return undefined;
115
+ }
108
116
  const utxos: Utxo[] = [];
109
117
  for (const utxo of data) {
110
118
  if (!utxo.data.p2pkh) {
@@ -133,15 +133,11 @@ export function registerGatherCollectionInfoTool(
133
133
  server.tool(
134
134
  "wallet_gatherCollectionInfo",
135
135
  "Analyzes a folder of images and gathers all necessary information for minting an ordinals collection. This includes validating images, checking wallet balance, estimating costs, and suggesting metadata. Use this before minting to ensure everything is ready.",
136
- { args: gatherCollectionInfoArgsSchema },
137
- async ({
138
- args,
139
- }: {
140
- args: GatherCollectionInfoArgs;
141
- }): Promise<CallToolResult> => {
136
+ { ...gatherCollectionInfoArgsSchema.shape },
137
+ async ({ folderPath }): Promise<CallToolResult> => {
142
138
  try {
143
139
  const analysis: CollectionAnalysis = {
144
- folderPath: args.folderPath,
140
+ folderPath,
145
141
  totalImages: 0,
146
142
  validImages: 0,
147
143
  invalidImages: 0,
@@ -172,13 +168,13 @@ export function registerGatherCollectionInfoTool(
172
168
 
173
169
  // Check if folder exists
174
170
  try {
175
- const folderStat = await fs.stat(args.folderPath);
171
+ const folderStat = await fs.stat(folderPath);
176
172
  if (!folderStat.isDirectory()) {
177
- throw new Error(`Path is not a directory: ${args.folderPath}`);
173
+ throw new Error(`Path is not a directory: ${folderPath}`);
178
174
  }
179
175
  } catch (error) {
180
176
  analysis.errors.push(
181
- `Folder not found or inaccessible: ${args.folderPath}`,
177
+ `Folder not found or inaccessible: ${folderPath}`,
182
178
  );
183
179
  return {
184
180
  content: [
@@ -222,7 +218,7 @@ export function registerGatherCollectionInfoTool(
222
218
  }
223
219
 
224
220
  // Scan folder for images
225
- const files = await fs.readdir(args.folderPath);
221
+ const files = await fs.readdir(folderPath);
226
222
  const imageExtensions = [
227
223
  ".jpg",
228
224
  ".jpeg",
@@ -233,7 +229,7 @@ export function registerGatherCollectionInfoTool(
233
229
  ];
234
230
 
235
231
  for (const file of files) {
236
- const filePath = path.join(args.folderPath, file);
232
+ const filePath = path.join(folderPath, file);
237
233
  const stat = await fs.stat(filePath);
238
234
 
239
235
  if (stat.isFile()) {
@@ -280,7 +276,7 @@ export function registerGatherCollectionInfoTool(
280
276
  }
281
277
 
282
278
  // Suggest metadata based on folder name
283
- const folderName = path.basename(args.folderPath);
279
+ const folderName = path.basename(folderPath);
284
280
  analysis.suggestedMetadata = {
285
281
  collectionName: folderName
286
282
  .replace(/[-_]/g, " ")
@@ -1,5 +1,4 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { z } from "zod";
3
2
  import type { Wallet } from "./wallet";
4
3
 
5
4
  /**
@@ -14,14 +13,7 @@ export function registerGetAddressTool(
14
13
  server.tool(
15
14
  "wallet_getAddress",
16
15
  "Retrieves the current wallet's Bitcoin SV address. This address can be used to receive BSV, ordinals, or tokens, and is derived from the wallet's private key.",
17
- {
18
- args: z
19
- .object({})
20
- .optional()
21
- .describe(
22
- "No parameters required - simply returns the current wallet address",
23
- ),
24
- },
16
+ {},
25
17
  async () => {
26
18
  try {
27
19
  const address = wallet.getAddress();
@@ -1,16 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type {
4
- ServerNotification,
5
- ServerRequest,
6
- } from "@modelcontextprotocol/sdk/types.js";
7
2
  import { toBitcoin } from "satoshi-token"; // For converting satoshis to BSV string
8
- import { z } from "zod";
9
3
  import type { Wallet } from "./wallet";
10
4
 
11
- export const walletGetBalanceArgsSchema = z.object({}).optional();
12
- export type WalletGetBalanceArgs = z.infer<typeof walletGetBalanceArgsSchema>;
13
-
14
5
  /**
15
6
  * Registers the wallet_getBalance tool
16
7
  */
@@ -21,11 +12,8 @@ export function registerWalletGetBalanceTool(
21
12
  server.tool(
22
13
  "wallet_getBalance",
23
14
  "Retrieves the current BSV balance for the wallet based on its UTXOs.",
24
- { args: walletGetBalanceArgsSchema },
25
- async (
26
- args: WalletGetBalanceArgs, // Args are empty but present for schema consistency
27
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
28
- ) => {
15
+ {},
16
+ async () => {
29
17
  try {
30
18
  const { paymentUtxos } = await wallet.getUtxos();
31
19
 
@@ -1,11 +1,5 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type {
4
- ServerNotification,
5
- ServerRequest,
6
- } from "@modelcontextprotocol/sdk/types.js";
7
2
  import type { DropletClient } from "../../utils/droplet";
8
- import { emptyArgsSchema } from "./schemas";
9
3
 
10
4
  /**
11
5
  * Register the getBalance tool for Droplet API mode
@@ -17,13 +11,8 @@ export function registerWalletGetBalanceDropletTool(
17
11
  server.tool(
18
12
  "wallet_getBalance",
19
13
  "Gets the current balance of the wallet (Droplet mode)",
20
- {
21
- args: emptyArgsSchema,
22
- },
23
- async (
24
- { args }: { args: unknown },
25
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
26
- ) => {
14
+ {},
15
+ async () => {
27
16
  try {
28
17
  const status = await dropletClient.getFaucetStatus();
29
18
 
@@ -1,16 +1,6 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type {
4
- ServerNotification,
5
- ServerRequest,
6
- } from "@modelcontextprotocol/sdk/types.js";
7
- import type { z } from "zod";
8
- import { getPublicKeyArgsSchema } from "./schemas";
9
2
  import type { Wallet } from "./wallet";
10
3
 
11
- // Use the schema imported from schemas.ts
12
- export type GetPublicKeyArgs = z.infer<typeof getPublicKeyArgsSchema>;
13
-
14
4
  /**
15
5
  * Register the getPublicKey tool
16
6
  */
@@ -18,13 +8,10 @@ export function registerGetPublicKeyTool(server: McpServer, wallet: Wallet) {
18
8
  server.tool(
19
9
  "wallet_getPublicKey",
20
10
  "Retrieves the current wallet's public key. This public key can be used for cryptographic operations like signature verification or encryption.",
21
- { args: getPublicKeyArgsSchema },
22
- async (
23
- { args }: { args: GetPublicKeyArgs },
24
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
25
- ) => {
11
+ {},
12
+ async () => {
26
13
  try {
27
- const result = await wallet.getPublicKey(args);
14
+ const result = await wallet.getPublicKey({});
28
15
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
29
16
  } catch (err: unknown) {
30
17
  const msg = err instanceof Error ? err.message : String(err);
@@ -2,12 +2,7 @@ import { promises as fs } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { Utils } from "@bsv/sdk";
4
4
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
6
- import type {
7
- CallToolResult,
8
- ServerNotification,
9
- ServerRequest,
10
- } from "@modelcontextprotocol/sdk/types.js";
5
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
11
6
  import type {
12
7
  ChangeResult,
13
8
  CollectionItemSubTypeData,
@@ -125,8 +120,8 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
125
120
  server.tool(
126
121
  "wallet_mintCollection",
127
122
  "Mint a collection of ordinals from a folder of images with proper metadata. This tool creates a collection inscription first, then mints each image as a collection item with the appropriate metadata linking it to the collection.",
128
- { args: mintCollectionArgsSchema },
129
- async ({ args }: { args: MintCollectionArgs }): Promise<CallToolResult> => {
123
+ { ...mintCollectionArgsSchema.shape },
124
+ async ({ folderPath, collectionName, description, rarityLabels, traits, skipBroadcast }): Promise<CallToolResult> => {
130
125
  try {
131
126
  // Get keys from wallet
132
127
  const paymentPk = wallet.getPaymentKey();
@@ -136,7 +131,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
136
131
  const identityPk = wallet.getIdentityKey();
137
132
 
138
133
  // Get image files
139
- const imageFiles = await getImageFiles(args.folderPath);
134
+ const imageFiles = await getImageFiles(folderPath);
140
135
  if (imageFiles.length === 0) {
141
136
  throw new Error("No image files found in the specified folder");
142
137
  }
@@ -145,14 +140,14 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
145
140
 
146
141
  // Prepare collection metadata
147
142
  const collectionSubTypeData: CollectionSubTypeData = {
148
- description: args.description,
143
+ description: description,
149
144
  quantity: imageFiles.length,
150
145
  // Transform rarity labels to correct format
151
146
  rarityLabels:
152
- args.rarityLabels?.map((r) => ({ label: r.label })) || [],
147
+ rarityLabels?.map((r) => ({ label: r.label })) || [],
153
148
  // Transform traits - need to match the CollectionTraits type
154
- traits: args.traits
155
- ? Object.entries(args.traits).reduce((acc, [key, values]) => {
149
+ traits: traits
150
+ ? Object.entries(traits).reduce((acc, [key, values]) => {
156
151
  acc[key] = {
157
152
  values,
158
153
  occurancePercentages: values.map(() =>
@@ -168,14 +163,14 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
168
163
  app: "ord",
169
164
  type: "ord",
170
165
  subType: "collection",
171
- name: args.collectionName,
166
+ name: collectionName,
172
167
  subTypeData: collectionSubTypeData,
173
168
  };
174
169
 
175
170
  // Create collection icon
176
171
  const svgString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
177
172
  <rect width="100" height="100" fill="#f0f0f0"/>
178
- <text x="50" y="55" text-anchor="middle" font-family="Arial" font-size="16">${args.collectionName}</text>
173
+ <text x="50" y="55" text-anchor="middle" font-family="Arial" font-size="16">${collectionName}</text>
179
174
  </svg>`;
180
175
  const collectionIconData = Utils.toBase64(
181
176
  Utils.toArray(svgString, "utf8"),
@@ -217,7 +212,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
217
212
 
218
213
  let collectionTxid = "";
219
214
  const disableBroadcasting =
220
- args.skipBroadcast || process.env.DISABLE_BROADCASTING === "true";
215
+ skipBroadcast || process.env.DISABLE_BROADCASTING === "true";
221
216
 
222
217
  if (!disableBroadcasting) {
223
218
  const broadcaster = new V5Broadcaster();
@@ -251,7 +246,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
251
246
  );
252
247
 
253
248
  try {
254
- const itemTraits = generateItemTraits(i, args.traits);
249
+ const itemTraits = generateItemTraits(i, traits);
255
250
 
256
251
  const itemSubTypeData: CollectionItemSubTypeData = {
257
252
  collectionId: collectionTxid,
@@ -260,13 +255,13 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
260
255
  };
261
256
 
262
257
  // Assign rarity if labels provided
263
- if (args.rarityLabels && args.rarityLabels.length > 0) {
258
+ if (rarityLabels && rarityLabels.length > 0) {
264
259
  const rarityIndex = Math.floor(
265
- (i / imageFiles.length) * args.rarityLabels.length,
260
+ (i / imageFiles.length) * rarityLabels.length,
266
261
  );
267
262
  const rarityItem =
268
- args.rarityLabels[
269
- Math.min(rarityIndex, args.rarityLabels.length - 1)
263
+ rarityLabels[
264
+ Math.min(rarityIndex, rarityLabels.length - 1)
270
265
  ];
271
266
  if (rarityItem) {
272
267
  itemSubTypeData.rarityLabel = [
@@ -352,7 +347,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
352
347
  totalItems: imageFiles.length,
353
348
  errors: results.errors,
354
349
  totalCost: results.totalCost,
355
- summary: `Collection "${args.collectionName}" created with ${results.itemTxids.length}/${imageFiles.length} items successfully minted.${results.errors.length > 0 ? ` ${results.errors.length} items failed.` : ""}`,
350
+ summary: `Collection "${collectionName}" created with ${results.itemTxids.length}/${imageFiles.length} items successfully minted.${results.errors.length > 0 ? ` ${results.errors.length} items failed.` : ""}`,
356
351
  },
357
352
  null,
358
353
  2,
@@ -1,11 +1,6 @@
1
1
  import { PrivateKey } from "@bsv/sdk";
2
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
- import type {
5
- CallToolResult,
6
- ServerNotification,
7
- ServerRequest,
8
- } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
9
4
  import {
10
5
  type ChangeResult,
11
6
  type ExistingListing,
@@ -20,8 +15,6 @@ import {
20
15
  type TokenUtxo,
21
16
  type Utxo,
22
17
  } from "js-1sat-ord";
23
- import { Sigma } from "sigma-protocol";
24
- import type { z } from "zod";
25
18
  import {
26
19
  MARKET_FEE_PERCENTAGE,
27
20
  MARKET_WALLET_ADDRESS,
@@ -86,11 +79,8 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
86
79
  server.tool(
87
80
  "wallet_purchaseListing",
88
81
  "Purchases a listing from the Bitcoin SV ordinals marketplace. Supports both NFT purchases (with royalty payments to original creators) and BSV-20/BSV-21 token purchases. The tool handles all aspects of the transaction - from fetching listing details, calculating fees, creating and broadcasting the transaction.",
89
- { args: purchaseListingArgsSchema },
90
- async (
91
- { args }: { args: z.infer<typeof purchaseListingArgsSchema> },
92
- extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
93
- ): Promise<CallToolResult> => {
82
+ { ...purchaseListingArgsSchema.shape },
83
+ async ({ listingOutpoint, ordAddress, listingType, tokenProtocol, tokenID, description }): Promise<CallToolResult> => {
94
84
  try {
95
85
  // Load optional identity key for sigma signing
96
86
  const identityKeyWif = process.env.IDENTITY_KEY_WIF;
@@ -108,7 +98,7 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
108
98
 
109
99
  // Fetch the listing info directly from the API
110
100
  const response = await fetch(
111
- `https://ordinals.gorillapool.io/api/txos/${args.listingOutpoint}?script=true`,
101
+ `https://ordinals.gorillapool.io/api/txos/${listingOutpoint}?script=true`,
112
102
  );
113
103
  if (!response.ok) {
114
104
  throw new Error(
@@ -138,7 +128,7 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
138
128
  }
139
129
 
140
130
  // Parse the listing outpoint to get txid and vout
141
- const [txid, voutStr] = args.listingOutpoint.split("_");
131
+ const [txid, voutStr] = listingOutpoint.split("_");
142
132
  if (!txid) {
143
133
  throw new Error("Invalid outpoint format. Expected txid_vout");
144
134
  }
@@ -182,12 +172,12 @@ Please fund this wallet address with enough BSV to cover the purchase price
182
172
  // Create the purchase transaction based on listing type
183
173
  let transaction: ChangeResult;
184
174
 
185
- if (args.listingType === "token") {
186
- if (!args.tokenProtocol) {
175
+ if (listingType === "token") {
176
+ if (!tokenProtocol) {
187
177
  throw new Error("tokenProtocol is required for token listings");
188
178
  }
189
179
 
190
- if (!args.tokenID) {
180
+ if (!tokenID) {
191
181
  throw new Error("tokenID is required for token listings");
192
182
  }
193
183
 
@@ -203,7 +193,7 @@ Please fund this wallet address with enough BSV to cover the purchase price
203
193
 
204
194
  // Convert the token protocol to the enum type expected by js-1sat-ord
205
195
  const protocol =
206
- args.tokenProtocol === "bsv-20" ? TokenType.BSV20 : TokenType.BSV21;
196
+ tokenProtocol === "bsv-20" ? TokenType.BSV20 : TokenType.BSV21;
207
197
 
208
198
  // Create a TokenUtxo with the required fields
209
199
  const listingUtxo: TokenUtxo = {
@@ -212,17 +202,17 @@ Please fund this wallet address with enough BSV to cover the purchase price
212
202
  script: listingData.script,
213
203
  satoshis: 1, // TokenUtxo's satoshis must be exactly 1
214
204
  amt: listingData.data.bsv20.amt,
215
- id: args.tokenID,
205
+ id: tokenID,
216
206
  payout: listingData.data.list.payout,
217
207
  };
218
208
 
219
209
  transaction = await purchaseOrdTokenListing({
220
210
  protocol,
221
- tokenID: args.tokenID,
211
+ tokenID: tokenID,
222
212
  utxos: paymentUtxos,
223
213
  paymentPk,
224
214
  listingUtxo,
225
- ordAddress: args.ordAddress,
215
+ ordAddress: ordAddress,
226
216
  additionalPayments,
227
217
  metaData,
228
218
  });
@@ -257,7 +247,7 @@ Please fund this wallet address with enough BSV to cover the purchase price
257
247
  const purchaseOrdListingConfig: PurchaseOrdListingConfig = {
258
248
  utxos: paymentUtxos,
259
249
  paymentPk,
260
- ordAddress: args.ordAddress,
250
+ ordAddress: ordAddress,
261
251
  listing,
262
252
  additionalPayments,
263
253
  metaData,
@@ -301,16 +291,16 @@ Please fund this wallet address with enough BSV to cover the purchase price
301
291
  status: resultStatus,
302
292
  message: resultMessage,
303
293
  txid: transaction.tx.id("hex"),
304
- listingOutpoint: args.listingOutpoint,
305
- destinationAddress: args.ordAddress,
306
- listingType: args.listingType,
307
- tokenProtocol: args.tokenID ? args.tokenProtocol : undefined,
308
- tokenID: args.tokenID,
294
+ listingOutpoint: listingOutpoint,
295
+ destinationAddress: ordAddress,
296
+ listingType: listingType,
297
+ tokenProtocol: tokenID ? tokenProtocol : undefined,
298
+ tokenID: tokenID,
309
299
  price: listingData.data.list.price,
310
300
  marketFee,
311
301
  marketFeeAddress: MARKET_WALLET_ADDRESS,
312
302
  royaltiesPaid:
313
- args.listingType === "nft" &&
303
+ listingType === "nft" &&
314
304
  listingData.origin?.data?.map?.royalties
315
305
  ? JSON.parse(listingData.origin.data.map.royalties)
316
306
  : undefined,
@@ -1,16 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type {
4
- ServerNotification,
5
- ServerRequest,
6
- } from "@modelcontextprotocol/sdk/types.js";
7
2
  import { toBitcoin } from "satoshi-token";
8
- import { z } from "zod";
9
3
  import type { Wallet } from "./wallet";
10
4
 
11
- const refreshUtxosArgsSchema = z.object({});
12
- type RefreshUtxosArgs = z.infer<typeof refreshUtxosArgsSchema>;
13
-
14
5
  /**
15
6
  * Registers the wallet_refreshUtxos tool that refreshes and returns the UTXOs for the wallet
16
7
  */
@@ -18,11 +9,8 @@ export function registerRefreshUtxosTool(server: McpServer, wallet: Wallet) {
18
9
  server.tool(
19
10
  "wallet_refreshUtxos",
20
11
  "Refreshes and returns the wallet's UTXOs. This is useful for debugging UTXO issues, ensuring the wallet has the latest transaction outputs, and for verifying available funds before making transactions.",
21
- { args: refreshUtxosArgsSchema },
22
- async (
23
- { args }: { args: RefreshUtxosArgs },
24
- _extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
25
- ) => {
12
+ {},
13
+ async () => {
26
14
  try {
27
15
  // Force refresh the UTXOs
28
16
  await wallet.refreshUtxos();