bsv-mcp 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "bsv-mcp",
3
3
  "module": "index.ts",
4
4
  "type": "module",
5
- "version": "0.0.4",
5
+ "version": "0.0.6",
6
6
  "bin": {
7
7
  "bsv-mcp": "./index.ts"
8
8
  },
@@ -118,6 +118,7 @@ function isTxid(str: string): boolean {
118
118
  export function registerDecodeTransactionTool(server: McpServer): void {
119
119
  server.tool(
120
120
  "bsv_decodeTransaction",
121
+ "Decodes and analyzes Bitcoin SV transactions to provide detailed insights. This powerful tool accepts either a transaction ID or raw transaction data and returns comprehensive information including inputs, outputs, fee calculations, script details, and blockchain context. Supports both hex and base64 encoded transactions and automatically fetches additional on-chain data when available.",
121
122
  {
122
123
  args: decodeTransactionArgsSchema,
123
124
  },
@@ -8,8 +8,9 @@ import { z } from "zod";
8
8
  export function registerGetPriceTool(server: McpServer): void {
9
9
  server.tool(
10
10
  "bsv_getPrice",
11
+ "Retrieves the current price of Bitcoin SV (BSV) in USD from a reliable exchange API. This tool provides real-time market data that can be used for calculating transaction values, monitoring market conditions, or converting between BSV and fiat currencies.",
11
12
  {
12
- args: z.object({}).optional(),
13
+ args: z.object({}).optional().describe("No parameters required - simply returns the current BSV price in USD"),
13
14
  },
14
15
  async () => {
15
16
  try {
@@ -40,6 +40,7 @@ interface InscriptionResponse {
40
40
  export function registerGetInscriptionTool(server: McpServer): void {
41
41
  server.tool(
42
42
  "ordinals_getInscription",
43
+ "Retrieves detailed information about a specific ordinal inscription by its outpoint. Returns complete inscription data including content type, file information, inscription origin, and current status. Useful for verifying NFT authenticity or retrieving metadata about digital artifacts.",
43
44
  {
44
45
  args: getInscriptionArgsSchema,
45
46
  },
@@ -0,0 +1,109 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
+ import { z } from "zod";
4
+
5
+ // Schema for get token by ID or ticker arguments
6
+ export const getTokenByIdOrTickerArgsSchema = z.object({
7
+ id: z.string().optional().describe("BSV20 token ID in outpoint format (txid_vout)"),
8
+ tick: z.string().optional().describe("BSV20 token ticker symbol"),
9
+ }).refine(data => data.id || data.tick, {
10
+ message: "Either id or tick must be provided",
11
+ });
12
+
13
+ export type GetTokenByIdOrTickerArgs = z.infer<typeof getTokenByIdOrTickerArgsSchema>;
14
+
15
+ // BSV20 token response type
16
+ interface TokenResponse {
17
+ id: string;
18
+ tick?: string;
19
+ sym?: string;
20
+ max?: string;
21
+ lim?: string;
22
+ dec?: number;
23
+ supply?: string;
24
+ amt?: string;
25
+ status?: number;
26
+ icon?: string;
27
+ height?: number;
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ /**
32
+ * Register the BSV20 token lookup tool
33
+ */
34
+ export function registerGetTokenByIdOrTickerTool(server: McpServer): void {
35
+ server.tool(
36
+ "ordinals_getTokenByIdOrTicker",
37
+ "Retrieves detailed information about a specific BSV-20 token by its ID or ticker symbol. Returns complete token data including ticker symbol, supply information, decimals, and current status. This tool is useful for verifying token authenticity or checking supply metrics.",
38
+ {
39
+ args: getTokenByIdOrTickerArgsSchema,
40
+ },
41
+ async (
42
+ { args }: { args: GetTokenByIdOrTickerArgs },
43
+ extra: RequestHandlerExtra,
44
+ ) => {
45
+ try {
46
+ const { id, tick } = args;
47
+
48
+ // Validate that at least one of id or tick is provided
49
+ if (!id && !tick) {
50
+ throw new Error("Either token ID or ticker symbol must be provided");
51
+ }
52
+
53
+ // Validate ID format if provided
54
+ if (id && !/^[0-9a-f]{64}_\d+$/i.test(id)) {
55
+ throw new Error("Invalid BSV20 ID format. Expected 'txid_vout'");
56
+ }
57
+
58
+ // Determine which endpoint to use based on provided parameters
59
+ let endpoint: string;
60
+ if (id) {
61
+ endpoint = `https://ordinals.gorillapool.io/api/bsv20/id/${id}`;
62
+ } else {
63
+ endpoint = `https://ordinals.gorillapool.io/api/bsv20/tick/${tick}`;
64
+ }
65
+
66
+ // Fetch BSV20 token data from GorillaPool API
67
+ const response = await fetch(endpoint);
68
+
69
+ if (response.status === 404) {
70
+ return {
71
+ content: [
72
+ {
73
+ type: "text",
74
+ text: JSON.stringify({ error: "BSV20 token not found" }),
75
+ },
76
+ ],
77
+ };
78
+ }
79
+
80
+ if (!response.ok) {
81
+ throw new Error(
82
+ `API error: ${response.status} ${response.statusText}`,
83
+ );
84
+ }
85
+
86
+ const data = (await response.json()) as TokenResponse;
87
+
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: JSON.stringify(data, null, 2),
93
+ },
94
+ ],
95
+ };
96
+ } catch (error) {
97
+ return {
98
+ content: [
99
+ {
100
+ type: "text",
101
+ text: error instanceof Error ? error.message : String(error),
102
+ },
103
+ ],
104
+ isError: true,
105
+ };
106
+ }
107
+ },
108
+ );
109
+ }
@@ -1,6 +1,6 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { registerGetBsv20ByIdTool } from "./getBsv20ById";
3
2
  import { registerGetInscriptionTool } from "./getInscription";
3
+ import { registerGetTokenByIdOrTickerTool } from "./getTokenByIdOrTicker";
4
4
  import { registerMarketListingsTool } from "./marketListings";
5
5
  import { registerMarketSalesTool } from "./marketSales";
6
6
  import { registerSearchInscriptionsTool } from "./searchInscriptions";
@@ -15,5 +15,5 @@ export function registerOrdinalsTools(server: McpServer): void {
15
15
  registerSearchInscriptionsTool(server);
16
16
  registerMarketListingsTool(server);
17
17
  registerMarketSalesTool(server);
18
- registerGetBsv20ByIdTool(server);
18
+ registerGetTokenByIdOrTickerTool(server);
19
19
  }
@@ -89,6 +89,7 @@ interface MarketListingResponse {
89
89
  export function registerMarketListingsTool(server: McpServer): void {
90
90
  server.tool(
91
91
  "ordinals_marketListings",
92
+ "Retrieves current marketplace listings for Bitcoin SV ordinals with flexible filtering. Supports multiple asset types (NFTs, BSV-20 tokens, BSV-21 tokens) through a unified interface. Results include listing prices, details about the assets, and seller information.",
92
93
  {
93
94
  args: marketListingsArgsSchema,
94
95
  },
@@ -130,7 +131,6 @@ export function registerMarketListingsTool(server: McpServer): void {
130
131
  url.searchParams.append("limit", limit.toString());
131
132
  url.searchParams.append("offset", offset.toString());
132
133
  url.searchParams.append("dir", dir);
133
- url.searchParams.append("script", "true");
134
134
 
135
135
  // Add sort parameter based on token type
136
136
  if (useTokenParams) {
@@ -67,6 +67,7 @@ interface MarketSaleResponse {
67
67
  export function registerMarketSalesTool(server: McpServer): void {
68
68
  server.tool(
69
69
  "ordinals_marketSales",
70
+ "Retrieves recent sales data for BSV-20 and BSV-21 tokens on the ordinals marketplace. This tool provides insights into market activity, including sale prices, transaction details, and token information. Supports filtering by token ID, ticker symbol, or seller address to help analyze market trends and track specific token sales.",
70
71
  {
71
72
  args: marketSalesArgsSchema,
72
73
  },
@@ -97,7 +98,6 @@ export function registerMarketSalesTool(server: McpServer): void {
97
98
  url.searchParams.append("limit", limit.toString());
98
99
  url.searchParams.append("offset", offset.toString());
99
100
  url.searchParams.append("dir", dir);
100
- url.searchParams.append("script", "true");
101
101
 
102
102
  // Add type parameter for bsv21 if needed
103
103
  if (tokenType === "bsv21") {
@@ -57,6 +57,7 @@ interface InscriptionSearchResponse {
57
57
  export function registerSearchInscriptionsTool(server: McpServer): void {
58
58
  server.tool(
59
59
  "ordinals_searchInscriptions",
60
+ "Searches for Bitcoin SV ordinal inscriptions using flexible criteria. This powerful search tool supports filtering by address, inscription content, MIME type, MAP fields, and other parameters. Results include detailed information about each matched inscription. Ideal for discovering NFTs and exploring the ordinals ecosystem.",
60
61
  {
61
62
  args: searchInscriptionsArgsSchema,
62
63
  },
@@ -11,11 +11,12 @@ const encodingSchema = z.enum(["utf8", "hex", "base64", "binary"]);
11
11
  export function registerUtilsTools(server: McpServer): void {
12
12
  server.tool(
13
13
  "utils_convertData",
14
+ "Converts data between different encodings (utf8, hex, base64, binary). Useful for transforming data formats when working with blockchain data, encryption, or file processing.",
14
15
  {
15
16
  args: z.object({
16
- data: z.string(),
17
- from: encodingSchema,
18
- to: encodingSchema,
17
+ data: z.string().describe("The data string to be converted"),
18
+ from: encodingSchema.describe("Source encoding format (utf8, hex, base64, or binary)"),
19
+ to: encodingSchema.describe("Target encoding format to convert to (utf8, hex, base64, or binary)"),
19
20
  }),
20
21
  },
21
22
  async ({ args }) => {
@@ -37,6 +37,7 @@ export type CreateOrdinalsArgs = z.infer<typeof createOrdinalsArgsSchema>;
37
37
  export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
38
38
  server.tool(
39
39
  "wallet_createOrdinals",
40
+ "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.",
40
41
  { args: createOrdinalsArgsSchema },
41
42
  async (
42
43
  { args }: { args: CreateOrdinalsArgs },
@@ -9,8 +9,9 @@ import { z } from "zod";
9
9
  export function registerGetAddressTool(server: McpServer): void {
10
10
  server.tool(
11
11
  "wallet_getAddress",
12
+ "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.",
12
13
  {
13
- args: z.object({}).optional(),
14
+ args: z.object({}).optional().describe("No parameters required - simply returns the current wallet address"),
14
15
  },
15
16
  async () => {
16
17
  try {
@@ -6,6 +6,7 @@ import {
6
6
  type ChangeResult,
7
7
  type ExistingListing,
8
8
  type Payment,
9
+ type Royalty,
9
10
  type TokenUtxo,
10
11
  type Utxo,
11
12
  TokenType,
@@ -23,11 +24,27 @@ import { purchaseListingArgsSchema } from "./schemas";
23
24
  import type { Wallet } from "./wallet";
24
25
 
25
26
  // Define types for 1Sat API response
26
- interface ListingResponse {
27
+ interface OrdUtxo {
27
28
  txid: string;
28
29
  vout: number;
29
30
  satoshis: number;
30
31
  script: string;
32
+ origin?: {
33
+ outpoint: string;
34
+ data?: {
35
+ map?: {
36
+ royalties?: string;
37
+ [key: string]: string | number | boolean | null | undefined;
38
+ };
39
+ insc?: {
40
+ text?: string;
41
+ file?: {
42
+ type?: string;
43
+ size?: number;
44
+ };
45
+ };
46
+ };
47
+ };
31
48
  data?: {
32
49
  list?: {
33
50
  price: number;
@@ -44,13 +61,17 @@ interface ListingResponse {
44
61
  /**
45
62
  * Register the purchaseListing tool
46
63
  *
47
- * This tool:
64
+ * This tool enables purchasing listed ordinals (NFTs or tokens) from the marketplace:
48
65
  * 1. Parses the listing outpoint to get the txid and vout
49
66
  * 2. Fetches the listing UTXO from the ordinals API
50
67
  * 3. Gets the wallet's payment UTXOs (using the wallet's internal UTXO management)
51
68
  * 4. Uses purchaseOrdListing or purchaseOrdTokenListing based on the listing type
52
- * 5. Broadcasts the transaction
53
- * 6. Returns the transaction details
69
+ * 5. For NFTs, automatically detects and processes royalty payments to original creators
70
+ * 6. Broadcasts the transaction
71
+ * 7. Returns the transaction details including success status and txid
72
+ *
73
+ * The tool supports both NFT and token listings with appropriate type-specific handling.
74
+ * Royalty payments are supported for NFT purchases only (based on creator-defined metadata).
54
75
  */
55
76
  export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
56
77
  // Store a reference to check if wallet is persistent
@@ -58,6 +79,7 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
58
79
 
59
80
  server.tool(
60
81
  "wallet_purchaseListing",
82
+ "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.",
61
83
  { args: purchaseListingArgsSchema },
62
84
  async (
63
85
  { args }: { args: z.infer<typeof purchaseListingArgsSchema> },
@@ -79,7 +101,7 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
79
101
  );
80
102
  }
81
103
 
82
- const listingData = (await response.json()) as ListingResponse;
104
+ const listingData = (await response.json()) as OrdUtxo;
83
105
 
84
106
  // Check if the listing is valid and has a price
85
107
  if (!listingData.data?.list?.price) {
@@ -183,7 +205,7 @@ Please fund this wallet address with enough BSV to cover the purchase price
183
205
  satoshis: 1, // TokenUtxo's satoshis must be exactly 1
184
206
  amt: listingData.data.bsv20.amt,
185
207
  id: args.tokenID,
186
- payout: listingData.data.list.payout,
208
+ payout: listingData.data.list.payout,
187
209
  };
188
210
 
189
211
  transaction = await purchaseOrdTokenListing({
@@ -211,6 +233,19 @@ Please fund this wallet address with enough BSV to cover the purchase price
211
233
  listingUtxo,
212
234
  };
213
235
 
236
+ // Check for royalties in the NFT origin data
237
+ // Royalties are only supported for NFTs, not for tokens
238
+ // The royalties are defined by the original creator as a JSON string
239
+ // in the NFT's metadata and parsed into a Royalty[] array
240
+ let royalties: Royalty[] = [];
241
+ if (listingData.origin?.data?.map?.royalties) {
242
+ try {
243
+ royalties = JSON.parse(listingData.origin.data.map.royalties);
244
+ } catch (error) {
245
+ console.warn("Failed to parse royalties:", error);
246
+ }
247
+ }
248
+
214
249
  transaction = await purchaseOrdListing({
215
250
  utxos: paymentUtxos,
216
251
  paymentPk,
@@ -218,6 +253,7 @@ Please fund this wallet address with enough BSV to cover the purchase price
218
253
  listing,
219
254
  additionalPayments,
220
255
  metaData,
256
+ royalties,
221
257
  });
222
258
  }
223
259
 
@@ -264,6 +300,8 @@ Please fund this wallet address with enough BSV to cover the purchase price
264
300
  price: listingData.data.list.price,
265
301
  marketFee,
266
302
  marketFeeAddress: MARKET_WALLET_ADDRESS,
303
+ royaltiesPaid: args.listingType === "nft" && listingData.origin?.data?.map?.royalties ?
304
+ JSON.parse(listingData.origin.data.map.royalties) : undefined,
267
305
  }),
268
306
  },
269
307
  ],
@@ -291,7 +291,7 @@ export const purchaseListingArgsSchema = z.object({
291
291
  .string()
292
292
  .optional()
293
293
  .describe("Optional description for the transaction"),
294
- });
294
+ }).describe("Schema for the wallet_purchaseListing tool arguments (purchase NFTs or tokens), with detailed field descriptions.");
295
295
 
296
296
  // Export types
297
297
  export type SendToAddressArgs = z.infer<typeof sendToAddressArgsSchema>;
@@ -26,6 +26,7 @@ export type SendOrdinalsArgs = z.infer<typeof sendOrdinalsArgsSchema>;
26
26
  export function registerSendOrdinalsTool(server: McpServer, wallet: Wallet) {
27
27
  server.tool(
28
28
  "wallet_sendOrdinals",
29
+ "Transfers ordinals (NFTs) from your wallet to another address on the Bitcoin SV blockchain. This tool enables sending inscriptions you own to any valid BSV address. The transaction is created, signed, and broadcast automatically, with appropriate fee calculation and change handling.",
29
30
  { args: sendOrdinalsArgsSchema },
30
31
  async (
31
32
  { args }: { args: SendOrdinalsArgs },
@@ -42,6 +42,7 @@ export type SendToAddressArgs = z.infer<typeof sendToAddressArgsSchema>;
42
42
  export function registerSendToAddressTool(server: McpServer, wallet: Wallet) {
43
43
  server.tool(
44
44
  "wallet_sendToAddress",
45
+ "Sends Bitcoin SV (BSV) to a specified address. This tool supports payments in both BSV and USD amounts (with automatic conversion using current exchange rates). Transaction fees are automatically calculated and a confirmation with transaction ID is returned upon success.",
45
46
  {
46
47
  args: sendToAddressArgsSchema,
47
48
  },
@@ -1,94 +0,0 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import { z } from "zod";
4
-
5
- // Schema for get BSV20 by ID arguments
6
- export const getBsv20ByIdArgsSchema = z.object({
7
- id: z.string().describe("BSV20 token ID in outpoint format (txid_vout)"),
8
- });
9
-
10
- export type GetBsv20ByIdArgs = z.infer<typeof getBsv20ByIdArgsSchema>;
11
-
12
- // BSV20 token response type
13
- interface Bsv20TokenResponse {
14
- id: string;
15
- tick?: string;
16
- sym?: string;
17
- max?: string;
18
- lim?: string;
19
- dec?: number;
20
- supply?: string;
21
- amt?: string;
22
- status?: number;
23
- icon?: string;
24
- height?: number;
25
- [key: string]: unknown;
26
- }
27
-
28
- /**
29
- * Register the BSV20 token lookup tool
30
- */
31
- export function registerGetBsv20ByIdTool(server: McpServer): void {
32
- server.tool(
33
- "ordinals_getBsv20ById",
34
- {
35
- args: getBsv20ByIdArgsSchema,
36
- },
37
- async (
38
- { args }: { args: GetBsv20ByIdArgs },
39
- extra: RequestHandlerExtra,
40
- ) => {
41
- try {
42
- const { id } = args;
43
-
44
- // Validate ID format (should be in outpoint format)
45
- if (!/^[0-9a-f]{64}_\d+$/i.test(id)) {
46
- throw new Error("Invalid BSV20 ID format. Expected 'txid_vout'");
47
- }
48
-
49
- // Fetch BSV20 token data from GorillaPool API
50
- const response = await fetch(
51
- `https://ordinals.gorillapool.io/api/bsv20/id/${id}`,
52
- );
53
-
54
- if (response.status === 404) {
55
- return {
56
- content: [
57
- {
58
- type: "text",
59
- text: JSON.stringify({ error: "BSV20 token not found" }),
60
- },
61
- ],
62
- };
63
- }
64
-
65
- if (!response.ok) {
66
- throw new Error(
67
- `API error: ${response.status} ${response.statusText}`,
68
- );
69
- }
70
-
71
- const data = (await response.json()) as Bsv20TokenResponse;
72
-
73
- return {
74
- content: [
75
- {
76
- type: "text",
77
- text: JSON.stringify(data, null, 2),
78
- },
79
- ],
80
- };
81
- } catch (error) {
82
- return {
83
- content: [
84
- {
85
- type: "text",
86
- text: error instanceof Error ? error.message : String(error),
87
- },
88
- ],
89
- isError: true,
90
- };
91
- }
92
- },
93
- );
94
- }