bsv-mcp 0.0.36 → 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 (78) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +233 -4
  3. package/dist/index.js +120082 -54669
  4. package/index.ts +1196 -88
  5. package/next-env.d.ts +6 -0
  6. package/package.json +58 -15
  7. package/prompts/bsvSdk/index.ts +5 -5
  8. package/prompts/bsvSdk/transaction.ts +2 -2
  9. package/prompts/bsvSdk/wallet.ts +1 -1
  10. package/prompts/index.ts +1 -1
  11. package/resources/bitcom.ts +132 -0
  12. package/resources/resources.ts +7 -3
  13. package/smithery.yaml +3 -0
  14. package/test-mcp-server.ts +157 -0
  15. package/tools/a2b/discover.ts +13 -13
  16. package/tools/bap/friend.ts +266 -0
  17. package/tools/bap/generate.test.ts +350 -0
  18. package/tools/bap/generate.ts +431 -0
  19. package/tools/bap/getCurrentAddress.ts +69 -0
  20. package/tools/bap/getId.test.ts +121 -0
  21. package/tools/bap/getId.ts +169 -0
  22. package/tools/bap/index.ts +111 -0
  23. package/tools/bap/types.ts +66 -0
  24. package/tools/bap/utils.ts +33 -0
  25. package/tools/bsocial/bmapFollow.ts +121 -0
  26. package/tools/bsocial/bmapLikes.ts +111 -0
  27. package/tools/bsocial/bmapReadPosts.ts +148 -0
  28. package/tools/bsocial/createPost.ts +136 -0
  29. package/tools/bsocial/index.ts +45 -0
  30. package/tools/bsocial/readPosts.ts +255 -0
  31. package/tools/bsv/decodeTransaction.ts +7 -6
  32. package/tools/bsv/explore.ts +2 -3
  33. package/tools/bsv/getPrice.ts +1 -9
  34. package/tools/bsv/token.ts +14 -26
  35. package/tools/constants.ts +21 -0
  36. package/tools/index.ts +91 -18
  37. package/tools/mnee/getBalance.ts +2 -4
  38. package/tools/mnee/index.ts +8 -0
  39. package/tools/mnee/parseTx.ts +4 -4
  40. package/tools/mnee/sendMnee.ts +6 -6
  41. package/tools/ordinals/getInscription.ts +2 -3
  42. package/tools/ordinals/getTokenByIdOrTicker.ts +6 -3
  43. package/tools/ordinals/marketListings.ts +2 -18
  44. package/tools/ordinals/marketSales.ts +2 -4
  45. package/tools/ordinals/searchInscriptions.ts +2 -4
  46. package/tools/utils/aip.ts +46 -0
  47. package/tools/utils/conversion.ts +1 -0
  48. package/tools/utils/errorHandler.ts +76 -0
  49. package/tools/utils/index.ts +56 -14
  50. package/tools/utils/installAgentMaster.ts +84 -0
  51. package/tools/utils/logger.ts +20 -0
  52. package/tools/utils/toolConfig.ts +80 -0
  53. package/tools/utils/toolRegistration.ts +66 -0
  54. package/tools/utils/transactionBuilder.ts +196 -0
  55. package/tools/wallet/a2bPublishAgent.ts +25 -30
  56. package/tools/wallet/a2bPublishMcp.ts +43 -44
  57. package/tools/wallet/createOrdinals.ts +13 -20
  58. package/tools/wallet/fetchPaymentUtxos.ts +48 -39
  59. package/tools/wallet/gatherCollectionInfo.ts +370 -0
  60. package/tools/wallet/getAddress.ts +14 -30
  61. package/tools/wallet/getBalance.ts +54 -0
  62. package/tools/wallet/getBalanceDroplet.ts +48 -0
  63. package/tools/wallet/getPublicKey.ts +3 -16
  64. package/tools/wallet/integratedWallet.ts +120 -0
  65. package/tools/wallet/mintCollection.ts +373 -0
  66. package/tools/wallet/purchaseListing.ts +21 -31
  67. package/tools/wallet/refreshUtxos.ts +2 -14
  68. package/tools/wallet/schemas.ts +18 -249
  69. package/tools/wallet/sendOrdinals.ts +14 -21
  70. package/tools/wallet/sendToAddress.ts +2 -18
  71. package/tools/wallet/setupDroplet.ts +161 -0
  72. package/tools/wallet/tools.ts +55 -210
  73. package/tools/wallet/transactionHelper.ts +121 -0
  74. package/tools/wallet/transferOrdToken.ts +19 -24
  75. package/tools/wallet/utxo.ts +62 -0
  76. package/tools/wallet/wallet.ts +237 -234
  77. package/vite.config.ts +15 -0
  78. package/tools/a2b/call.ts +0 -32
@@ -17,14 +17,11 @@ export function registerTokenTools(server: McpServer): void {
17
17
  server.tool(
18
18
  "bsv_toSatoshi",
19
19
  {
20
- args: z.object({
21
- bitcoin: z.union([z.number(), z.string()]),
22
- returnType: z.enum(["number", "string", "bigint"]).optional(),
23
- }),
20
+ bitcoin: z.union([z.number(), z.string()]),
21
+ returnType: z.enum(["number", "string", "bigint"]).optional(),
24
22
  },
25
- async ({ args }) => {
23
+ async ({ bitcoin, returnType }) => {
26
24
  try {
27
- const { bitcoin, returnType } = args;
28
25
  let result: number | string | bigint;
29
26
 
30
27
  switch (returnType) {
@@ -49,14 +46,11 @@ export function registerTokenTools(server: McpServer): void {
49
46
  server.tool(
50
47
  "bsv_toBitcoin",
51
48
  {
52
- args: z.object({
53
- satoshis: z.union([z.number(), z.string(), z.bigint()]),
54
- returnType: z.enum(["number", "string", "bigint"]).optional(),
55
- }),
49
+ satoshis: z.union([z.number(), z.string(), z.bigint()]),
50
+ returnType: z.enum(["number", "string", "bigint"]).optional(),
56
51
  },
57
- async ({ args }) => {
52
+ async ({ satoshis, returnType }) => {
58
53
  try {
59
- const { satoshis, returnType } = args;
60
54
  let result: number | string | bigint;
61
55
 
62
56
  switch (returnType) {
@@ -93,15 +87,12 @@ export function registerTokenTools(server: McpServer): void {
93
87
  server.tool(
94
88
  "bsv_toTokenSatoshi",
95
89
  {
96
- args: z.object({
97
- token: z.union([z.number(), z.string(), z.bigint()]),
98
- decimals: z.number().int().min(0),
99
- returnType: z.enum(["number", "string", "bigint"]).optional(),
100
- }),
90
+ token: z.union([z.number(), z.string(), z.bigint()]),
91
+ decimals: z.number().int().min(0),
92
+ returnType: z.enum(["number", "string", "bigint"]).optional(),
101
93
  },
102
- async ({ args }) => {
94
+ async ({ token, decimals, returnType }) => {
103
95
  try {
104
- const { token, decimals, returnType } = args;
105
96
  let result: number | string | bigint;
106
97
 
107
98
  switch (returnType) {
@@ -126,15 +117,12 @@ export function registerTokenTools(server: McpServer): void {
126
117
  server.tool(
127
118
  "bsv_toToken",
128
119
  {
129
- args: z.object({
130
- tokenSatoshi: z.union([z.number(), z.string(), z.bigint()]),
131
- decimals: z.number().int().min(0),
132
- returnType: z.enum(["number", "string", "bigint"]).optional(),
133
- }),
120
+ tokenSatoshi: z.union([z.number(), z.string(), z.bigint()]),
121
+ decimals: z.number().int().min(0),
122
+ returnType: z.enum(["number", "string", "bigint"]).optional(),
134
123
  },
135
- async ({ args }) => {
124
+ async ({ tokenSatoshi, decimals, returnType }) => {
136
125
  try {
137
- const { tokenSatoshi, decimals, returnType } = args;
138
126
  let result: number | string | bigint;
139
127
 
140
128
  switch (returnType) {
@@ -19,3 +19,24 @@ export const MARKET_WALLET_ADDRESS = "15q8YQSqUa9uTh6gh4AVixxq29xkpBBP9z";
19
19
  * Market fee will never be less than this amount
20
20
  */
21
21
  export const MINIMUM_MARKET_FEE_SATOSHIS = 10000; // 10000 satoshis = 0.0001 BSV
22
+
23
+ export const BAP_PREFIX = "1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT";
24
+ export const B_PREFIX = "19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut";
25
+ export const MAP_PREFIX = "1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5";
26
+ export const AIP_PREFIX = "1HPcP7a4kQjpJzyV4HWHKagon76KC3BsZA";
27
+ export const STORAGE_MNEMONIC_KEY = "id_mnemonic";
28
+ export const PUBLIC_URL = process.env.PUBLIC_URL || "";
29
+ export const BMAP_URL =
30
+ process.env.PUBLIC_BMAP_URL || "https://bmap-api-production.up.railway.app";
31
+
32
+ export const ORDFS_URL =
33
+ process.env.PUBLIC_ORDFS_URL || "https://ordfs.network";
34
+ export const YOURS_INSTALL_URL =
35
+ "https://chromewebstore.google.com/detail/yours-wallet/mlbnicldlpdimbjdcncnklfempedeipj";
36
+
37
+ // export const BSOCIAL_API_URL =
38
+ // process.env.PUBLIC_BSOCIAL_API_URL ||
39
+ // "https://bsocial-overlay-production.up.railway.app/api/v1";
40
+
41
+ export const BSOCIAL_API_URL = "https://api.sigmaidentity.com/v1";
42
+ export const V5_API_URL = "https://ordinals.1sat.app/v5";
package/tools/index.ts CHANGED
@@ -1,9 +1,17 @@
1
+ import type { PrivateKey } from "@bsv/sdk";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { registerA2aCallTool } from "./a2b/call";
3
3
  import { registerA2bDiscoverTool } from "./a2b/discover";
4
+ import { registerBapTools } from "./bap";
5
+ import { registerBsocialTools } from "./bsocial";
4
6
  import { registerBsvTools } from "./bsv";
7
+ import { registerMneeTools } from "./mnee";
5
8
  import { registerOrdinalsTools } from "./ordinals";
6
9
  import { registerUtilsTools } from "./utils";
10
+ import { registerWalletGetBalanceDropletTool } from "./wallet/getBalanceDroplet";
11
+ import type { IntegratedWallet } from "./wallet/integratedWallet";
12
+ import { registerSetupDropletTool } from "./wallet/setupDroplet";
13
+ import { registerWalletTools } from "./wallet/tools";
14
+ import type { Wallet } from "./wallet/wallet";
7
15
 
8
16
  /**
9
17
  * Configuration options for tools
@@ -12,13 +20,27 @@ import { registerUtilsTools } from "./utils";
12
20
  * - enableBsvTools: controlled by DISABLE_BSV_TOOLS
13
21
  * - enableOrdinalsTools: controlled by DISABLE_ORDINALS_TOOLS
14
22
  * - enableUtilsTools: controlled by DISABLE_UTILS_TOOLS
15
- * - enableA2bTools: controlled by DISABLE_A2B_TOOLS
23
+ * - enableA2bTools: controlled by ENABLE_A2B_TOOLS (disabled by default)
24
+ * - enableBapTools: controlled by DISABLE_BAP_TOOLS
25
+ * - enableBsocialTools: controlled by DISABLE_BSOCIAL_TOOLS
26
+ * - enableWalletTools: controlled by DISABLE_WALLET_TOOLS
27
+ * - enableMneeTools: controlled by DISABLE_MNEE_TOOLS
16
28
  */
17
29
  export interface ToolsConfig {
18
30
  enableBsvTools?: boolean;
19
31
  enableOrdinalsTools?: boolean;
20
32
  enableUtilsTools?: boolean;
21
33
  enableA2bTools?: boolean;
34
+ enableBapTools?: boolean;
35
+ enableBsocialTools?: boolean;
36
+ enableWalletTools?: boolean;
37
+ enableMneeTools?: boolean;
38
+ identityPk?: PrivateKey;
39
+ payPk?: PrivateKey;
40
+ xprv?: string;
41
+ wallet?: Wallet;
42
+ integratedWallet?: IntegratedWallet;
43
+ disableBroadcasting?: boolean; // For wallet tools
22
44
  }
23
45
 
24
46
  /**
@@ -28,20 +50,30 @@ export interface ToolsConfig {
28
50
  */
29
51
  export function registerAllTools(
30
52
  server: McpServer,
31
- config: ToolsConfig = {
32
- enableBsvTools: true,
33
- enableOrdinalsTools: true,
34
- enableUtilsTools: true,
35
- enableA2bTools: false,
36
- },
53
+ config: ToolsConfig = {},
37
54
  ): void {
38
- const {
39
- enableBsvTools = true,
40
- enableOrdinalsTools = true,
41
- enableUtilsTools = true,
42
- enableA2bTools = false,
43
- } = config;
44
-
55
+ // Ensure defaults are true unless explicitly set to false via env vars or config
56
+ const enableBsvTools =
57
+ process.env.DISABLE_BSV_TOOLS !== "true" && config.enableBsvTools !== false;
58
+ const enableOrdinalsTools =
59
+ process.env.DISABLE_ORDINALS_TOOLS !== "true" &&
60
+ config.enableOrdinalsTools !== false;
61
+ const enableUtilsTools =
62
+ process.env.DISABLE_UTILS_TOOLS !== "true" &&
63
+ config.enableUtilsTools !== false; // Ensure Utils are enabled by default
64
+ const enableA2bTools =
65
+ process.env.ENABLE_A2B_TOOLS === "true" && config.enableA2bTools !== false;
66
+ const enableBapTools =
67
+ process.env.DISABLE_BAP_TOOLS !== "true" && config.enableBapTools !== false;
68
+ const enableWalletTools =
69
+ process.env.DISABLE_WALLET_TOOLS !== "true" &&
70
+ config.enableWalletTools !== false;
71
+ const enableMneeTools =
72
+ process.env.DISABLE_MNEE_TOOLS !== "true" &&
73
+ config.enableMneeTools !== false;
74
+ const enableBsocialTools =
75
+ process.env.DISABLE_BSOCIAL_TOOLS !== "true" &&
76
+ config.enableBsocialTools !== false;
45
77
  // Register BSV-related tools
46
78
  if (enableBsvTools) {
47
79
  registerBsvTools(server);
@@ -59,11 +91,52 @@ export function registerAllTools(
59
91
 
60
92
  // Register agent-to-blockchain tools
61
93
  if (enableA2bTools) {
62
- // Register agent-to-blockchain discovery tool
63
94
  registerA2bDiscoverTool(server);
95
+ }
96
+
97
+ // Register BAP tools
98
+ if (enableBapTools) {
99
+ const bapConfig: import("./bap").BapToolsConfig = {
100
+ disableBroadcasting: config.disableBroadcasting,
101
+ identityPk: config.identityPk,
102
+ masterXprv: config.xprv,
103
+ wallet: config.wallet,
104
+ };
105
+ registerBapTools(server, bapConfig);
106
+ }
107
+
108
+ // Register BSocial tools
109
+ if (enableBsocialTools && config.wallet) {
110
+ registerBsocialTools(server, { wallet: config.wallet });
111
+ }
112
+
113
+ // Register Wallet tools themselves
114
+ if (enableWalletTools) {
115
+ if (config.integratedWallet?.isDropletMode) {
116
+ // Register Droplet-mode wallet tools
117
+ const dropletClient = config.integratedWallet.getDropletClient();
118
+ if (dropletClient) {
119
+ // Register Droplet-specific tools
120
+ registerWalletGetBalanceDropletTool(server, dropletClient);
121
+ if (config.integratedWallet) {
122
+ registerSetupDropletTool(server, config.integratedWallet);
123
+ }
124
+ console.error("Registered Droplet mode wallet tools");
125
+ }
126
+ } else if (config.wallet) {
127
+ // Register normal wallet tools
128
+ const walletToolOptions = {
129
+ disableBroadcasting: config.disableBroadcasting === true, // Default to false if undefined
130
+ enableA2bTools: enableA2bTools, // Use the already determined enableA2bTools value
131
+ identityPk: config.identityPk,
132
+ };
133
+ registerWalletTools(server, config.wallet, walletToolOptions);
134
+ }
135
+ }
64
136
 
65
- // Register agent-to-agent call tool
66
- // registerA2aCallTool(server);
137
+ // Register MNEE tools
138
+ if (enableMneeTools) {
139
+ registerMneeTools(server);
67
140
  }
68
141
 
69
142
  // Add more tool categories as needed
@@ -19,11 +19,9 @@ export function registerGetBalanceTool(
19
19
  server.tool(
20
20
  "mnee_getBalance",
21
21
  "Retrieves the current MNEE token balance for the wallet. Returns the balance in MNEE tokens.",
22
- {
23
- args: getBalanceArgsSchema,
24
- },
22
+ {},
25
23
  async (
26
- { args }: { args: GetBalanceArgs },
24
+ _params,
27
25
  extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
28
26
  ) => {
29
27
  try {
@@ -7,15 +7,23 @@ import { registerSendMneeTool } from "./sendMnee";
7
7
  const mnee = new Mnee({
8
8
  environment: "production",
9
9
  });
10
+
11
+ const mneeToolsRegistered = new WeakSet<McpServer>();
12
+
10
13
  /**
11
14
  * Register all MNEE tools with the MCP server
12
15
  * @param server The MCP server instance
13
16
  */
14
17
  export function registerMneeTools(server: McpServer): void {
18
+ if (mneeToolsRegistered.has(server)) {
19
+ // console.warn("WARN: MNEE tools already registered for this server instance. Skipping.");
20
+ return;
21
+ }
15
22
  // Register MNEE-related tools
16
23
  registerGetBalanceTool(server, mnee);
17
24
 
18
25
  registerSendMneeTool(server, mnee);
19
26
 
20
27
  registerParseTxTool(server, mnee);
28
+ mneeToolsRegistered.add(server);
21
29
  }
@@ -1,7 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
3
  import type {
4
+ CallToolResult,
5
5
  ServerNotification,
6
6
  ServerRequest,
7
7
  } from "@modelcontextprotocol/sdk/types.js";
@@ -24,13 +24,13 @@ export function registerParseTxTool(
24
24
  server.tool(
25
25
  "mnee_parseTx",
26
26
  "Parse an MNEE transaction to get detailed information about its operations and amounts. All amounts are in atomic units with 5 decimal precision (e.g. 1000 atomic units = 0.01 MNEE).",
27
- { args: parseTxArgsSchema },
27
+ { ...parseTxArgsSchema.shape },
28
28
  async (
29
- { args }: { args: ParseTxArgs },
29
+ { txid },
30
30
  extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
31
31
  ): Promise<CallToolResult> => {
32
32
  try {
33
- const result: ParseTxResponse = await mnee.parseTx(args.txid);
33
+ const result: ParseTxResponse = await mnee.parseTx(txid);
34
34
 
35
35
  return {
36
36
  content: [
@@ -1,7 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
3
  import type {
4
+ CallToolResult,
5
5
  ServerNotification,
6
6
  ServerRequest,
7
7
  } from "@modelcontextprotocol/sdk/types.js";
@@ -42,18 +42,18 @@ export function registerSendMneeTool(server: McpServer, mnee: Mnee): void {
42
42
  server.tool(
43
43
  "mnee_sendMnee",
44
44
  "Send MNEE tokens to a specified address",
45
- { args: sendMneeArgsSchema },
45
+ { ...sendMneeArgsSchema.shape },
46
46
  async (
47
- { args }: { args: SendMneeArgs },
47
+ { address, amount, currency },
48
48
  extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
49
49
  ): Promise<CallToolResult> => {
50
50
  try {
51
51
  // Since 1 MNEE = $1, the amount is the same in both currencies
52
- const mneeAmount = args.amount;
52
+ const mneeAmount = amount;
53
53
 
54
54
  const transferRequest: SendMNEE[] = [
55
55
  {
56
- address: args.address,
56
+ address,
57
57
  amount: mneeAmount,
58
58
  },
59
59
  ];
@@ -101,7 +101,7 @@ export function registerSendMneeTool(server: McpServer, mnee: Mnee): void {
101
101
  rawtx: result.rawtx,
102
102
  mneeAmount: mneeAmount,
103
103
  usdAmount: formatUSD(mneeAmount),
104
- recipient: args.address,
104
+ recipient: address,
105
105
  },
106
106
  null,
107
107
  2,
@@ -42,14 +42,13 @@ export function registerGetInscriptionTool(server: McpServer): void {
42
42
  "ordinals_getInscription",
43
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.",
44
44
  {
45
- args: getInscriptionArgsSchema,
45
+ ...getInscriptionArgsSchema.shape,
46
46
  },
47
47
  async (
48
- { args }: { args: GetInscriptionArgs },
48
+ { outpoint },
49
49
  extra: RequestHandlerExtra,
50
50
  ) => {
51
51
  try {
52
- const { outpoint } = args;
53
52
 
54
53
  // Validate outpoint format
55
54
  if (!/^[0-9a-f]{64}_\d+$/i.test(outpoint)) {
@@ -43,14 +43,17 @@ export function registerGetTokenByIdOrTickerTool(server: McpServer): void {
43
43
  "ordinals_getTokenByIdOrTicker",
44
44
  "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.",
45
45
  {
46
- args: getTokenByIdOrTickerArgsSchema,
46
+ id: z
47
+ .string()
48
+ .optional()
49
+ .describe("BSV20 token ID in outpoint format (txid_vout)"),
50
+ tick: z.string().optional().describe("BSV20 token ticker symbol"),
47
51
  },
48
52
  async (
49
- { args }: { args: GetTokenByIdOrTickerArgs },
53
+ { id, tick },
50
54
  extra: RequestHandlerExtra,
51
55
  ) => {
52
56
  try {
53
- const { id, tick } = args;
54
57
 
55
58
  // Validate that at least one of id or tick is provided
56
59
  if (!id && !tick) {
@@ -95,29 +95,13 @@ export function registerMarketListingsTool(server: McpServer): void {
95
95
  "ordinals_marketListings",
96
96
  "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.",
97
97
  {
98
- args: marketListingsArgsSchema,
98
+ ...marketListingsArgsSchema.shape,
99
99
  },
100
100
  async (
101
- { args }: { args: MarketListingsArgs },
101
+ { limit, offset, sort, dir, address, origin, mime, num, minPrice, maxPrice, tokenType, id, tick, pending },
102
102
  extra: RequestHandlerExtra,
103
103
  ) => {
104
104
  try {
105
- const {
106
- limit,
107
- offset,
108
- sort,
109
- dir,
110
- address,
111
- origin,
112
- mime,
113
- num,
114
- minPrice,
115
- maxPrice,
116
- tokenType,
117
- id,
118
- tick,
119
- pending,
120
- } = args;
121
105
 
122
106
  // Determine the API endpoint based on tokenType
123
107
  let baseUrl = "https://ordinals.gorillapool.io/api";
@@ -73,12 +73,10 @@ export function registerMarketSalesTool(server: McpServer): void {
73
73
  "ordinals_marketSales",
74
74
  "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.",
75
75
  {
76
- args: marketSalesArgsSchema,
76
+ ...marketSalesArgsSchema.shape,
77
77
  },
78
- async ({ args }: { args: MarketSalesArgs }, extra: RequestHandlerExtra) => {
78
+ async ({ limit, offset, dir, tokenType, id, tick, pending, address }, extra: RequestHandlerExtra) => {
79
79
  try {
80
- const { limit, offset, dir, tokenType, id, tick, pending, address } =
81
- args;
82
80
 
83
81
  // Determine the API endpoint based on tokenType
84
82
  let baseUrl = "https://ordinals.gorillapool.io/api";
@@ -59,15 +59,13 @@ export function registerSearchInscriptionsTool(server: McpServer): void {
59
59
  "ordinals_searchInscriptions",
60
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.",
61
61
  {
62
- args: searchInscriptionsArgsSchema,
62
+ ...searchInscriptionsArgsSchema.shape,
63
63
  },
64
64
  async (
65
- { args }: { args: SearchInscriptionsArgs },
65
+ { limit, offset, dir, num, origin, address, map, terms, mime },
66
66
  extra: RequestHandlerExtra,
67
67
  ) => {
68
68
  try {
69
- const { limit, offset, dir, num, origin, address, map, terms, mime } =
70
- args;
71
69
 
72
70
  // Build the URL with query parameters
73
71
  const url = new URL(
@@ -0,0 +1,46 @@
1
+ import { BSM, type PrivateKey, Utils } from "@bsv/sdk";
2
+ import { AIP_PREFIX } from "../constants";
3
+
4
+ const { toArray, toBase64, toUTF8 } = Utils;
5
+
6
+ /**
7
+ * Sign OP_RETURN data with AIP (Author Identity Protocol)
8
+ * @param dataArrays - Array of data arrays to sign
9
+ * @param signingKey - Private key to sign with
10
+ * @param signingAddress - Address associated with the signing key
11
+ * @returns Object containing signed data array
12
+ */
13
+ export async function signOpReturnWithAIP(
14
+ dataArrays: Uint8Array[],
15
+ signingKey: PrivateKey,
16
+ signingAddress: string,
17
+ ): Promise<{ signedData: Uint8Array[] }> {
18
+ // Concatenate all data arrays to create message to sign
19
+ let messageToSign = new Uint8Array();
20
+ for (const data of dataArrays) {
21
+ const temp = new Uint8Array(messageToSign.length + data.length);
22
+ temp.set(messageToSign);
23
+ temp.set(data, messageToSign.length);
24
+ messageToSign = temp;
25
+ }
26
+
27
+ // Create BSM signature
28
+ const signature = BSM.sign(messageToSign, signingKey);
29
+
30
+ // Convert signature to base64
31
+ const signatureBase64 = toBase64(signature.toCompact());
32
+
33
+ // Add AIP data to the arrays
34
+ const aipData: Uint8Array[] = [
35
+ toArray("|", "utf8"), // Separator
36
+ toArray(AIP_PREFIX, "utf8"),
37
+ toArray("BITCOIN_ECDSA", "utf8"),
38
+ toArray(signingAddress, "utf8"),
39
+ toArray(signatureBase64, "utf8"),
40
+ ];
41
+
42
+ // Return combined data
43
+ return {
44
+ signedData: [...dataArrays, ...aipData],
45
+ };
46
+ }
@@ -1,5 +1,6 @@
1
1
  import { Utils } from "@bsv/sdk";
2
2
  import { z } from "zod";
3
+
3
4
  const {
4
5
  toArray: bsvToArray,
5
6
  toBase64: bsvToBase64,
@@ -0,0 +1,76 @@
1
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
+
3
+ /**
4
+ * Format an error message consistently
5
+ */
6
+ export function formatError(error: unknown): string {
7
+ if (error instanceof Error) {
8
+ return error.message;
9
+ }
10
+ return String(error);
11
+ }
12
+
13
+ /**
14
+ * Create a standardized error response for MCP tools
15
+ */
16
+ export function createErrorResponse(error: unknown): CallToolResult {
17
+ return {
18
+ content: [
19
+ {
20
+ type: "text",
21
+ text: formatError(error),
22
+ },
23
+ ],
24
+ isError: true,
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Create a standardized success response for MCP tools
30
+ */
31
+ export function createSuccessResponse(data: unknown): CallToolResult {
32
+ const text = typeof data === "string" ? data : JSON.stringify(data, null, 2);
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text,
38
+ },
39
+ ],
40
+ isError: false,
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Create a response based on a result object with success field
46
+ */
47
+ export function createResponse(result: {
48
+ success: boolean;
49
+ [key: string]: unknown;
50
+ }): CallToolResult {
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text",
55
+ text: JSON.stringify(result, null, 2),
56
+ },
57
+ ],
58
+ isError: !result.success,
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Wrap an async function with standard error handling
64
+ */
65
+ export function withErrorHandler<
66
+ T extends (...args: unknown[]) => Promise<unknown>,
67
+ >(fn: T): (...args: Parameters<T>) => Promise<CallToolResult> {
68
+ return async (...args: Parameters<T>): Promise<CallToolResult> => {
69
+ try {
70
+ const result = await fn(...args);
71
+ return createSuccessResponse(result);
72
+ } catch (error) {
73
+ return createErrorResponse(error);
74
+ }
75
+ };
76
+ }