bsv-mcp 0.0.35 → 0.2.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.
- package/CHANGELOG.md +112 -1
- package/README.md +233 -4
- package/dist/index.js +111762 -0
- package/index.ts +804 -86
- package/next-env.d.ts +6 -0
- package/package.json +57 -15
- package/prompts/bsvSdk/index.ts +5 -5
- package/prompts/bsvSdk/transaction.ts +2 -2
- package/prompts/bsvSdk/wallet.ts +1 -1
- package/prompts/index.ts +1 -1
- package/resources/bitcom.ts +132 -0
- package/resources/resources.ts +7 -3
- package/smithery.yaml +3 -0
- package/test-mcp-server.ts +157 -0
- package/tools/bap/friend.ts +267 -0
- package/tools/bap/generate.test.ts +350 -0
- package/tools/bap/generate.ts +433 -0
- package/tools/bap/getCurrentAddress.ts +76 -0
- package/tools/bap/getId.test.ts +121 -0
- package/tools/bap/getId.ts +169 -0
- package/tools/bap/index.ts +111 -0
- package/tools/bap/types.ts +66 -0
- package/tools/bap/utils.ts +33 -0
- package/tools/bigblocks/components.ts +304 -0
- package/tools/bigblocks/docs.ts +488 -0
- package/tools/bigblocks/examples.ts +527 -0
- package/tools/bigblocks/generator.ts +485 -0
- package/tools/bigblocks/index.ts +23 -0
- package/tools/bsocial/bigblocksApiClient.ts +189 -0
- package/tools/bsocial/bmapFollow.ts +125 -0
- package/tools/bsocial/bmapLikes.ts +111 -0
- package/tools/bsocial/bmapReadPosts.ts +148 -0
- package/tools/bsocial/createPost.ts +136 -0
- package/tools/bsocial/index.ts +45 -0
- package/tools/bsocial/readPosts.ts +255 -0
- package/tools/bsv/decodeTransaction.ts +5 -1
- package/tools/constants.ts +21 -0
- package/tools/index.ts +103 -17
- package/tools/mnee/index.ts +8 -0
- package/tools/mnee/parseTx.ts +1 -1
- package/tools/mnee/sendMnee.ts +1 -1
- package/tools/utils/aip.ts +46 -0
- package/tools/utils/conversion.ts +1 -0
- package/tools/utils/errorHandler.ts +76 -0
- package/tools/utils/index.ts +45 -1
- package/tools/utils/installAgentMaster.ts +84 -0
- package/tools/utils/logger.ts +20 -0
- package/tools/utils/toolConfig.ts +80 -0
- package/tools/utils/toolRegistration.ts +66 -0
- package/tools/utils/transactionBuilder.ts +196 -0
- package/tools/wallet/a2bPublishAgent.ts +8 -4
- package/tools/wallet/a2bPublishMcp.ts +28 -24
- package/tools/wallet/createOrdinals.ts +4 -2
- package/tools/wallet/fetchPaymentUtxos.ts +44 -43
- package/tools/wallet/gatherCollectionInfo.ts +374 -0
- package/tools/wallet/getAddress.ts +13 -21
- package/tools/wallet/getBalance.ts +66 -0
- package/tools/wallet/getBalanceDroplet.ts +59 -0
- package/tools/wallet/integratedWallet.ts +120 -0
- package/tools/wallet/mintCollection.ts +378 -0
- package/tools/wallet/purchaseListing.ts +4 -4
- package/tools/wallet/schemas.ts +18 -249
- package/tools/wallet/sendOrdinals.ts +4 -2
- package/tools/wallet/sendToAddress.ts +5 -1
- package/tools/wallet/setupDroplet.ts +172 -0
- package/tools/wallet/tools.ts +71 -156
- package/tools/wallet/transactionHelper.ts +121 -0
- package/tools/wallet/transferOrdToken.ts +7 -4
- package/tools/wallet/utxo.ts +62 -0
- package/tools/wallet/wallet.ts +237 -234
- package/tools/a2b/call.ts +0 -32
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import type {
|
|
4
|
+
ApiResponse,
|
|
5
|
+
BapIdentity,
|
|
6
|
+
PostMeta,
|
|
7
|
+
PostResponse,
|
|
8
|
+
PostsResponse,
|
|
9
|
+
PostTransaction,
|
|
10
|
+
} from "bmap-api-types";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { BMAP_URL } from "../constants";
|
|
13
|
+
|
|
14
|
+
// Schema for reading posts
|
|
15
|
+
const readPostsArgsSchema = z.object({
|
|
16
|
+
bapId: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("BAP identity key to filter posts by author"),
|
|
20
|
+
txid: z.string().optional().describe("Specific transaction ID to fetch"),
|
|
21
|
+
limit: z
|
|
22
|
+
.number()
|
|
23
|
+
.min(1)
|
|
24
|
+
.max(100)
|
|
25
|
+
.default(20)
|
|
26
|
+
.describe("Maximum number of posts to return"),
|
|
27
|
+
page: z
|
|
28
|
+
.number()
|
|
29
|
+
.min(1)
|
|
30
|
+
.default(1)
|
|
31
|
+
.describe("Page number for pagination (1-based)"),
|
|
32
|
+
feed: z
|
|
33
|
+
.boolean()
|
|
34
|
+
.default(false)
|
|
35
|
+
.describe("Whether to fetch feed (posts from followed users)"),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
type ReadPostsArgs = z.infer<typeof readPostsArgsSchema>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Read social posts from the BMAP API using official types
|
|
42
|
+
*/
|
|
43
|
+
export async function readSocialPosts(args: ReadPostsArgs): Promise<{
|
|
44
|
+
success: boolean;
|
|
45
|
+
posts?: PostTransaction[];
|
|
46
|
+
signers?: BapIdentity[];
|
|
47
|
+
meta?: PostMeta[];
|
|
48
|
+
pagination?: {
|
|
49
|
+
page: number;
|
|
50
|
+
limit: number;
|
|
51
|
+
count: number;
|
|
52
|
+
};
|
|
53
|
+
error?: string;
|
|
54
|
+
}> {
|
|
55
|
+
try {
|
|
56
|
+
const { bapId, txid, limit, page, feed } = args;
|
|
57
|
+
|
|
58
|
+
// Handle single post request
|
|
59
|
+
if (txid) {
|
|
60
|
+
const response = await fetch(`${BMAP_URL}/post/${txid}`, {
|
|
61
|
+
method: "GET",
|
|
62
|
+
headers: {
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
const errorText = await response.text();
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: `BMAP API request failed: ${response.status} ${errorText}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const data = (await response.json()) as ApiResponse<PostResponse>;
|
|
76
|
+
|
|
77
|
+
if (data.status !== "success") {
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
error: data.error || "Unknown API error",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
posts: [data.result.post],
|
|
87
|
+
signers: data.result.signers,
|
|
88
|
+
meta: [data.result.meta],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle posts list request
|
|
93
|
+
const params = new URLSearchParams();
|
|
94
|
+
if (bapId) params.append("bapId", bapId);
|
|
95
|
+
params.append("limit", limit.toString());
|
|
96
|
+
params.append("page", page.toString());
|
|
97
|
+
if (feed) params.append("feed", "true");
|
|
98
|
+
|
|
99
|
+
const response = await fetch(`${BMAP_URL}/posts?${params}`, {
|
|
100
|
+
method: "GET",
|
|
101
|
+
headers: {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
const errorText = await response.text();
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
error: `BMAP API request failed: ${response.status} ${errorText}`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const data = (await response.json()) as ApiResponse<PostsResponse>;
|
|
115
|
+
|
|
116
|
+
if (data.status !== "success") {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: data.error || "Unknown API error",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
success: true,
|
|
125
|
+
posts: data.data.results,
|
|
126
|
+
signers: data.data.signers,
|
|
127
|
+
meta: data.data.meta,
|
|
128
|
+
pagination: {
|
|
129
|
+
page: data.data.page,
|
|
130
|
+
limit: data.data.limit,
|
|
131
|
+
count: data.data.count,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
} catch (error) {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
136
|
+
console.error("Error reading social posts:", errorMessage);
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
error: errorMessage,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Format a post transaction for display
|
|
146
|
+
*/
|
|
147
|
+
function formatPost(
|
|
148
|
+
post: PostTransaction,
|
|
149
|
+
index: number,
|
|
150
|
+
signer?: BapIdentity,
|
|
151
|
+
meta?: PostMeta,
|
|
152
|
+
): string {
|
|
153
|
+
const lines = [
|
|
154
|
+
`Post ${index + 1}:`,
|
|
155
|
+
` TX ID: ${post.tx.h}`,
|
|
156
|
+
` Content: ${post.B[0]?.content || "[No Content]"}`,
|
|
157
|
+
` Content Type: ${post.B[0]?.["content-type"] || "text/plain"}`,
|
|
158
|
+
` Timestamp: ${new Date(post.timestamp * 1000).toISOString()}`,
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
// Add signer information
|
|
162
|
+
if (signer) {
|
|
163
|
+
lines.push(` Author: ${signer.displayName || signer.idKey}`);
|
|
164
|
+
if (signer.paymail) {
|
|
165
|
+
lines.push(` Paymail: ${signer.paymail}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Add MAP data
|
|
170
|
+
const mapData = post.MAP.find((m) => m.type === "post");
|
|
171
|
+
if (mapData?.app) {
|
|
172
|
+
lines.push(` App: ${mapData.app}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Add metadata
|
|
176
|
+
if (meta) {
|
|
177
|
+
if (meta.likes > 0) {
|
|
178
|
+
lines.push(` Likes: ${meta.likes}`);
|
|
179
|
+
}
|
|
180
|
+
if (meta.replies > 0) {
|
|
181
|
+
lines.push(` Replies: ${meta.replies}`);
|
|
182
|
+
}
|
|
183
|
+
if (meta.reactions.length > 0) {
|
|
184
|
+
const reactions = meta.reactions
|
|
185
|
+
.map((r) => `${r.emoji}(${r.count})`)
|
|
186
|
+
.join(" ");
|
|
187
|
+
lines.push(` Reactions: ${reactions}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return lines.join("\n");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Register the read posts tool with the MCP server
|
|
196
|
+
*/
|
|
197
|
+
export function registerReadPostsTool(server: McpServer) {
|
|
198
|
+
server.tool(
|
|
199
|
+
"bsocial_readPosts",
|
|
200
|
+
"Read social posts from the BSV blockchain using BMAP API. Can fetch posts by author (BAP ID), specific post by transaction ID, or recent posts from all users. Supports pagination and feed functionality.",
|
|
201
|
+
{ args: readPostsArgsSchema },
|
|
202
|
+
async ({ args }: { args: ReadPostsArgs }): Promise<CallToolResult> => {
|
|
203
|
+
try {
|
|
204
|
+
const result = await readSocialPosts(args);
|
|
205
|
+
|
|
206
|
+
if (result.success && result.posts) {
|
|
207
|
+
// Format posts for display
|
|
208
|
+
const formattedPosts = result.posts
|
|
209
|
+
.map((post, index) => {
|
|
210
|
+
const signer = result.signers?.find(
|
|
211
|
+
(s) => s.currentAddress === post.AIP[0]?.address,
|
|
212
|
+
);
|
|
213
|
+
const meta = result.meta?.[index];
|
|
214
|
+
return formatPost(post, index, signer, meta);
|
|
215
|
+
})
|
|
216
|
+
.join("\n\n");
|
|
217
|
+
|
|
218
|
+
let output =
|
|
219
|
+
result.posts.length > 0 ? formattedPosts : "No posts found";
|
|
220
|
+
|
|
221
|
+
// Add pagination info
|
|
222
|
+
if (result.pagination) {
|
|
223
|
+
output += `\n\nPagination: Page ${result.pagination.page}, showing ${result.posts.length} of ${result.pagination.count} posts`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: "text",
|
|
230
|
+
text: output,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
isError: false,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
content: [
|
|
239
|
+
{
|
|
240
|
+
type: "text",
|
|
241
|
+
text: result.error || "Unknown error occurred",
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
isError: true,
|
|
245
|
+
};
|
|
246
|
+
} catch (error) {
|
|
247
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
248
|
+
return {
|
|
249
|
+
content: [{ type: "text", text: `Error: ${msg}` }],
|
|
250
|
+
isError: true,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
);
|
|
255
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Transaction, Utils } from "@bsv/sdk";
|
|
2
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
|
+
import type {
|
|
5
|
+
ServerNotification,
|
|
6
|
+
ServerRequest,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
4
8
|
import { z } from "zod";
|
|
5
9
|
|
|
6
10
|
// Schema for decode transaction arguments
|
|
@@ -124,7 +128,7 @@ export function registerDecodeTransactionTool(server: McpServer): void {
|
|
|
124
128
|
},
|
|
125
129
|
async (
|
|
126
130
|
{ args }: { args: DecodeTransactionArgs },
|
|
127
|
-
extra: RequestHandlerExtra,
|
|
131
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
128
132
|
) => {
|
|
129
133
|
try {
|
|
130
134
|
const { tx, encoding } = args;
|
package/tools/constants.ts
CHANGED
|
@@ -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,18 @@
|
|
|
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 { registerBigBlocksTools } from "./bigblocks"; // Disabled - Turbopack module resolution issues
|
|
6
|
+
import { registerBsocialTools } from "./bsocial";
|
|
4
7
|
import { registerBsvTools } from "./bsv";
|
|
8
|
+
import { registerMneeTools } from "./mnee";
|
|
5
9
|
import { registerOrdinalsTools } from "./ordinals";
|
|
6
10
|
import { registerUtilsTools } from "./utils";
|
|
11
|
+
import { registerWalletGetBalanceDropletTool } from "./wallet/getBalanceDroplet";
|
|
12
|
+
import type { IntegratedWallet } from "./wallet/integratedWallet";
|
|
13
|
+
import { registerSetupDropletTool } from "./wallet/setupDroplet";
|
|
14
|
+
import { registerWalletTools } from "./wallet/tools";
|
|
15
|
+
import type { Wallet } from "./wallet/wallet";
|
|
7
16
|
|
|
8
17
|
/**
|
|
9
18
|
* Configuration options for tools
|
|
@@ -12,13 +21,29 @@ import { registerUtilsTools } from "./utils";
|
|
|
12
21
|
* - enableBsvTools: controlled by DISABLE_BSV_TOOLS
|
|
13
22
|
* - enableOrdinalsTools: controlled by DISABLE_ORDINALS_TOOLS
|
|
14
23
|
* - enableUtilsTools: controlled by DISABLE_UTILS_TOOLS
|
|
15
|
-
* - enableA2bTools: controlled by
|
|
24
|
+
* - enableA2bTools: controlled by ENABLE_A2B_TOOLS (disabled by default)
|
|
25
|
+
* - enableBapTools: controlled by DISABLE_BAP_TOOLS
|
|
26
|
+
* - enableBsocialTools: controlled by DISABLE_BSOCIAL_TOOLS
|
|
27
|
+
* - enableWalletTools: controlled by DISABLE_WALLET_TOOLS
|
|
28
|
+
* - enableMneeTools: controlled by DISABLE_MNEE_TOOLS
|
|
29
|
+
* - enableBigBlocksTools: controlled by DISABLE_BIGBLOCKS_TOOLS
|
|
16
30
|
*/
|
|
17
31
|
export interface ToolsConfig {
|
|
18
32
|
enableBsvTools?: boolean;
|
|
19
33
|
enableOrdinalsTools?: boolean;
|
|
20
34
|
enableUtilsTools?: boolean;
|
|
21
35
|
enableA2bTools?: boolean;
|
|
36
|
+
enableBapTools?: boolean;
|
|
37
|
+
enableBsocialTools?: boolean;
|
|
38
|
+
enableWalletTools?: boolean;
|
|
39
|
+
enableMneeTools?: boolean;
|
|
40
|
+
enableBigBlocksTools?: boolean;
|
|
41
|
+
identityPk?: PrivateKey;
|
|
42
|
+
payPk?: PrivateKey;
|
|
43
|
+
xprv?: string;
|
|
44
|
+
wallet?: Wallet;
|
|
45
|
+
integratedWallet?: IntegratedWallet;
|
|
46
|
+
disableBroadcasting?: boolean; // For wallet tools
|
|
22
47
|
}
|
|
23
48
|
|
|
24
49
|
/**
|
|
@@ -28,19 +53,33 @@ export interface ToolsConfig {
|
|
|
28
53
|
*/
|
|
29
54
|
export function registerAllTools(
|
|
30
55
|
server: McpServer,
|
|
31
|
-
config: ToolsConfig = {
|
|
32
|
-
enableBsvTools: true,
|
|
33
|
-
enableOrdinalsTools: true,
|
|
34
|
-
enableUtilsTools: true,
|
|
35
|
-
enableA2bTools: false,
|
|
36
|
-
},
|
|
56
|
+
config: ToolsConfig = {},
|
|
37
57
|
): void {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
// Ensure defaults are true unless explicitly set to false via env vars or config
|
|
59
|
+
const enableBsvTools =
|
|
60
|
+
process.env.DISABLE_BSV_TOOLS !== "true" && config.enableBsvTools !== false;
|
|
61
|
+
const enableOrdinalsTools =
|
|
62
|
+
process.env.DISABLE_ORDINALS_TOOLS !== "true" &&
|
|
63
|
+
config.enableOrdinalsTools !== false;
|
|
64
|
+
const enableUtilsTools =
|
|
65
|
+
process.env.DISABLE_UTILS_TOOLS !== "true" &&
|
|
66
|
+
config.enableUtilsTools !== false; // Ensure Utils are enabled by default
|
|
67
|
+
const enableA2bTools =
|
|
68
|
+
process.env.ENABLE_A2B_TOOLS === "true" && config.enableA2bTools !== false;
|
|
69
|
+
const enableBapTools =
|
|
70
|
+
process.env.DISABLE_BAP_TOOLS !== "true" && config.enableBapTools !== false;
|
|
71
|
+
const enableWalletTools =
|
|
72
|
+
process.env.DISABLE_WALLET_TOOLS !== "true" &&
|
|
73
|
+
config.enableWalletTools !== false;
|
|
74
|
+
const enableMneeTools =
|
|
75
|
+
process.env.DISABLE_MNEE_TOOLS !== "true" &&
|
|
76
|
+
config.enableMneeTools !== false;
|
|
77
|
+
const enableBsocialTools =
|
|
78
|
+
process.env.DISABLE_BSOCIAL_TOOLS !== "true" &&
|
|
79
|
+
config.enableBsocialTools !== false;
|
|
80
|
+
const enableBigBlocksTools =
|
|
81
|
+
process.env.DISABLE_BIGBLOCKS_TOOLS !== "true" &&
|
|
82
|
+
config.enableBigBlocksTools !== false;
|
|
44
83
|
|
|
45
84
|
// Register BSV-related tools
|
|
46
85
|
if (enableBsvTools) {
|
|
@@ -59,11 +98,58 @@ export function registerAllTools(
|
|
|
59
98
|
|
|
60
99
|
// Register agent-to-blockchain tools
|
|
61
100
|
if (enableA2bTools) {
|
|
62
|
-
// Register agent-to-blockchain discovery tool
|
|
63
101
|
registerA2bDiscoverTool(server);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Register BAP tools
|
|
105
|
+
if (enableBapTools) {
|
|
106
|
+
const bapConfig: import("./bap").BapToolsConfig = {
|
|
107
|
+
disableBroadcasting: config.disableBroadcasting,
|
|
108
|
+
identityPk: config.identityPk,
|
|
109
|
+
masterXprv: config.xprv,
|
|
110
|
+
wallet: config.wallet,
|
|
111
|
+
};
|
|
112
|
+
registerBapTools(server, bapConfig);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Register BSocial tools
|
|
116
|
+
if (enableBsocialTools && config.wallet) {
|
|
117
|
+
registerBsocialTools(server, { wallet: config.wallet });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Register BigBlocks tools
|
|
121
|
+
// Disabled - Turbopack module resolution issues
|
|
122
|
+
// if (enableBigBlocksTools) {
|
|
123
|
+
// registerBigBlocksTools(server);
|
|
124
|
+
// }
|
|
125
|
+
|
|
126
|
+
// Register Wallet tools themselves
|
|
127
|
+
if (enableWalletTools) {
|
|
128
|
+
if (config.integratedWallet?.isDropletMode) {
|
|
129
|
+
// Register Droplet-mode wallet tools
|
|
130
|
+
const dropletClient = config.integratedWallet.getDropletClient();
|
|
131
|
+
if (dropletClient) {
|
|
132
|
+
// Register Droplet-specific tools
|
|
133
|
+
registerWalletGetBalanceDropletTool(server, dropletClient);
|
|
134
|
+
if (config.integratedWallet) {
|
|
135
|
+
registerSetupDropletTool(server, config.integratedWallet);
|
|
136
|
+
}
|
|
137
|
+
console.error("Registered Droplet mode wallet tools");
|
|
138
|
+
}
|
|
139
|
+
} else if (config.wallet) {
|
|
140
|
+
// Register normal wallet tools
|
|
141
|
+
const walletToolOptions = {
|
|
142
|
+
disableBroadcasting: config.disableBroadcasting === true, // Default to false if undefined
|
|
143
|
+
enableA2bTools: enableA2bTools, // Use the already determined enableA2bTools value
|
|
144
|
+
identityPk: config.identityPk,
|
|
145
|
+
};
|
|
146
|
+
registerWalletTools(server, config.wallet, walletToolOptions);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
64
149
|
|
|
65
|
-
|
|
66
|
-
|
|
150
|
+
// Register MNEE tools
|
|
151
|
+
if (enableMneeTools) {
|
|
152
|
+
registerMneeTools(server);
|
|
67
153
|
}
|
|
68
154
|
|
|
69
155
|
// Add more tool categories as needed
|
package/tools/mnee/index.ts
CHANGED
|
@@ -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
|
}
|
package/tools/mnee/parseTx.ts
CHANGED
|
@@ -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";
|
package/tools/mnee/sendMnee.ts
CHANGED
|
@@ -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";
|
|
@@ -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
|
+
}
|
|
@@ -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
|
+
}
|
package/tools/utils/index.ts
CHANGED
|
@@ -1,14 +1,50 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { convertData } from "./conversion";
|
|
4
|
+
import { installAgentMasterTool } from "./installAgentMaster";
|
|
4
5
|
|
|
5
6
|
const encodingSchema = z.enum(["utf8", "hex", "base64", "binary"]);
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Register
|
|
9
|
+
* Register utility tools with the MCP server
|
|
9
10
|
* @param server The MCP server instance
|
|
10
11
|
*/
|
|
11
12
|
export function registerUtilsTools(server: McpServer): void {
|
|
13
|
+
// Register install agent master tool
|
|
14
|
+
server.tool(
|
|
15
|
+
installAgentMasterTool.name,
|
|
16
|
+
installAgentMasterTool.description,
|
|
17
|
+
{ args: installAgentMasterTool.inputSchema },
|
|
18
|
+
async ({ args }) => {
|
|
19
|
+
try {
|
|
20
|
+
const result = await installAgentMasterTool.handler(args);
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
type: "text",
|
|
25
|
+
text:
|
|
26
|
+
typeof result === "string"
|
|
27
|
+
? result
|
|
28
|
+
: JSON.stringify(result, null, 2),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
} catch (err: unknown) {
|
|
33
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: `Error: ${msg}`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Register conversion tool
|
|
12
48
|
server.tool(
|
|
13
49
|
"utils_convertData",
|
|
14
50
|
"Converts data between different encodings (utf8, hex, base64, binary). Useful for transforming data formats when working with blockchain data, encryption, or file processing.\n\n" +
|
|
@@ -66,3 +102,11 @@ export function registerUtilsTools(server: McpServer): void {
|
|
|
66
102
|
},
|
|
67
103
|
);
|
|
68
104
|
}
|
|
105
|
+
|
|
106
|
+
export * from "./aip";
|
|
107
|
+
// Export all utilities for use by other tools
|
|
108
|
+
export * from "./errorHandler";
|
|
109
|
+
export * from "./logger";
|
|
110
|
+
export * from "./toolConfig";
|
|
111
|
+
export * from "./toolRegistration";
|
|
112
|
+
export * from "./transactionBuilder";
|