bsv-mcp 0.2.0 → 0.2.8
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 +13 -0
- package/dist/index.js +87290 -70731
- package/index.ts +422 -22
- package/package.json +28 -24
- package/tools/a2b/discover.ts +13 -13
- package/tools/bap/friend.ts +2 -3
- package/tools/bap/generate.ts +7 -9
- package/tools/bap/getCurrentAddress.ts +1 -8
- package/tools/bap/getId.ts +3 -3
- package/tools/bsocial/bmapFollow.ts +3 -7
- package/tools/bsocial/bmapLikes.ts +3 -3
- package/tools/bsocial/bmapReadPosts.ts +3 -3
- package/tools/bsocial/createPost.ts +8 -7
- package/tools/bsocial/readPosts.ts +3 -3
- package/tools/bsv/decodeTransaction.ts +2 -5
- package/tools/bsv/explore.ts +2 -3
- package/tools/bsv/getPrice.ts +1 -9
- package/tools/bsv/token.ts +14 -26
- package/tools/index.ts +0 -13
- package/tools/mnee/getBalance.ts +2 -4
- package/tools/mnee/parseTx.ts +3 -3
- package/tools/mnee/sendMnee.ts +5 -5
- package/tools/ordinals/getInscription.ts +2 -3
- package/tools/ordinals/getTokenByIdOrTicker.ts +6 -3
- package/tools/ordinals/marketListings.ts +2 -18
- package/tools/ordinals/marketSales.ts +2 -4
- package/tools/ordinals/searchInscriptions.ts +2 -4
- package/tools/utils/index.ts +14 -16
- package/tools/wallet/a2bPublishAgent.ts +18 -27
- package/tools/wallet/a2bPublishMcp.ts +17 -22
- package/tools/wallet/createOrdinals.ts +11 -20
- package/tools/wallet/fetchPaymentUtxos.ts +9 -1
- package/tools/wallet/gatherCollectionInfo.ts +9 -13
- package/tools/wallet/getAddress.ts +1 -9
- package/tools/wallet/getBalance.ts +2 -14
- package/tools/wallet/getBalanceDroplet.ts +2 -13
- package/tools/wallet/getPublicKey.ts +3 -16
- package/tools/wallet/mintCollection.ts +21 -24
- package/tools/wallet/purchaseListing.ts +19 -29
- package/tools/wallet/refreshUtxos.ts +2 -14
- package/tools/wallet/sendOrdinals.ts +11 -20
- package/tools/wallet/sendToAddress.ts +2 -22
- package/tools/wallet/setupDroplet.ts +7 -18
- package/tools/wallet/tools.ts +10 -80
- package/tools/wallet/transferOrdToken.ts +12 -20
- package/vite.config.ts +15 -0
- package/tools/bigblocks/components.ts +0 -304
- package/tools/bigblocks/docs.ts +0 -488
- package/tools/bigblocks/examples.ts +0 -527
- package/tools/bigblocks/generator.ts +0 -485
- package/tools/bigblocks/index.ts +0 -23
- package/tools/bsocial/bigblocksApiClient.ts +0 -189
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { PrivateKey, Utils } 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
|
-
ServerNotification,
|
|
6
|
-
ServerRequest,
|
|
7
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
8
3
|
import type {
|
|
9
4
|
ChangeResult,
|
|
10
5
|
CreateOrdinalsConfig,
|
|
@@ -14,7 +9,6 @@ import type {
|
|
|
14
9
|
PreMAP,
|
|
15
10
|
} from "js-1sat-ord";
|
|
16
11
|
import { createOrdinals } from "js-1sat-ord";
|
|
17
|
-
import { Sigma } from "sigma-protocol";
|
|
18
12
|
import { z } from "zod";
|
|
19
13
|
import packageJson from "../../package.json";
|
|
20
14
|
import { V5Broadcaster } from "../../utils/broadcaster";
|
|
@@ -155,11 +149,8 @@ export function registerA2bPublishAgentTool(server: McpServer, wallet: Wallet) {
|
|
|
155
149
|
server.tool(
|
|
156
150
|
"wallet_a2bPublish",
|
|
157
151
|
"Publish an agent.json record on-chain via Ordinal inscription",
|
|
158
|
-
{
|
|
159
|
-
async (
|
|
160
|
-
{ args }: { args: A2bPublishArgs },
|
|
161
|
-
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
162
|
-
) => {
|
|
152
|
+
{ ...a2bPublishArgsSchema.shape },
|
|
153
|
+
async ({ agentUrl, agentName, description, providerOrganization, providerUrl, version, documentationUrl, streaming, pushNotifications, stateTransitionHistory, defaultInputModes, defaultOutputModes, skills, destinationAddress }) => {
|
|
163
154
|
try {
|
|
164
155
|
const paymentPk = wallet.getPaymentKey();
|
|
165
156
|
if (!paymentPk) throw new Error("No private key available");
|
|
@@ -167,7 +158,7 @@ export function registerA2bPublishAgentTool(server: McpServer, wallet: Wallet) {
|
|
|
167
158
|
if (!paymentUtxos?.length)
|
|
168
159
|
throw new Error("No payment UTXOs available to fund inscription");
|
|
169
160
|
|
|
170
|
-
// TODO: Get the skills from actually running the MCP instead of trusting the agent args for
|
|
161
|
+
// TODO: Get the skills from actually running the MCP instead of trusting the agent args for skills
|
|
171
162
|
const walletAddress = paymentPk.toAddress().toString();
|
|
172
163
|
|
|
173
164
|
// Create pricing plans using the new schema
|
|
@@ -212,27 +203,27 @@ export function registerA2bPublishAgentTool(server: McpServer, wallet: Wallet) {
|
|
|
212
203
|
|
|
213
204
|
// Assemble AgentCard with defaults and user overrides
|
|
214
205
|
const agentCard = {
|
|
215
|
-
name:
|
|
216
|
-
description:
|
|
217
|
-
url:
|
|
206
|
+
name: agentName,
|
|
207
|
+
description: description ?? null,
|
|
208
|
+
url: agentUrl,
|
|
218
209
|
provider:
|
|
219
|
-
|
|
210
|
+
providerOrganization && providerUrl
|
|
220
211
|
? {
|
|
221
|
-
organization:
|
|
222
|
-
url:
|
|
212
|
+
organization: providerOrganization,
|
|
213
|
+
url: providerUrl,
|
|
223
214
|
}
|
|
224
215
|
: null,
|
|
225
|
-
version:
|
|
226
|
-
documentationUrl:
|
|
216
|
+
version: version ?? packageJson.version,
|
|
217
|
+
documentationUrl: documentationUrl ?? null,
|
|
227
218
|
capabilities: {
|
|
228
|
-
streaming
|
|
229
|
-
pushNotifications
|
|
230
|
-
stateTransitionHistory
|
|
219
|
+
streaming,
|
|
220
|
+
pushNotifications,
|
|
221
|
+
stateTransitionHistory,
|
|
231
222
|
},
|
|
232
223
|
authentication: null,
|
|
233
|
-
defaultInputModes
|
|
234
|
-
defaultOutputModes
|
|
235
|
-
skills
|
|
224
|
+
defaultInputModes,
|
|
225
|
+
defaultOutputModes,
|
|
226
|
+
skills,
|
|
236
227
|
"x-payment-config": pricingConfig,
|
|
237
228
|
};
|
|
238
229
|
// Validate compliance
|
|
@@ -245,7 +236,7 @@ export function registerA2bPublishAgentTool(server: McpServer, wallet: Wallet) {
|
|
|
245
236
|
contentType: "application/json",
|
|
246
237
|
};
|
|
247
238
|
// Destination for the ordinal
|
|
248
|
-
const targetAddress =
|
|
239
|
+
const targetAddress = destinationAddress ?? walletAddress;
|
|
249
240
|
const destinations: Destination[] = [
|
|
250
241
|
{ address: targetAddress, inscription },
|
|
251
242
|
];
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { PrivateKey
|
|
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 {
|
|
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
|
-
{
|
|
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(
|
|
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
|
|
227
|
-
args
|
|
221
|
+
command,
|
|
222
|
+
args,
|
|
228
223
|
tools: metadata.tools,
|
|
229
224
|
prompts: metadata.prompts,
|
|
230
225
|
resources: metadata.resources,
|
|
231
|
-
env:
|
|
232
|
-
?
|
|
233
|
-
(acc, { key, description }) => {
|
|
234
|
-
acc[key] =
|
|
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
|
-
[
|
|
249
|
-
description:
|
|
250
|
-
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 =
|
|
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
|
|
333
|
+
toolName,
|
|
339
334
|
toolCount: metadata.tools.length,
|
|
340
335
|
promptCount: metadata.prompts.length,
|
|
341
336
|
resourceCount: metadata.resources.length,
|
|
342
337
|
description:
|
|
343
|
-
|
|
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 {
|
|
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
|
|
20
|
-
import { Sigma } from "sigma-protocol";
|
|
14
|
+
import { createOrdinals } from "js-1sat-ord";
|
|
21
15
|
import { z } from "zod";
|
|
22
|
-
import {
|
|
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
|
-
{
|
|
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:
|
|
96
|
-
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:
|
|
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:
|
|
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:
|
|
156
|
-
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
|
-
|
|
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
|
-
{
|
|
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
|
|
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(
|
|
171
|
+
const folderStat = await fs.stat(folderPath);
|
|
176
172
|
if (!folderStat.isDirectory()) {
|
|
177
|
-
throw new Error(`Path is not a directory: ${
|
|
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: ${
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
-
{
|
|
22
|
-
async (
|
|
23
|
-
{ args }: { args: GetPublicKeyArgs },
|
|
24
|
-
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
25
|
-
) => {
|
|
11
|
+
{},
|
|
12
|
+
async () => {
|
|
26
13
|
try {
|
|
27
|
-
const result = await wallet.getPublicKey(
|
|
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 {
|
|
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,
|
|
@@ -40,10 +35,10 @@ const mintCollectionArgsSchema = z.object({
|
|
|
40
35
|
.optional()
|
|
41
36
|
.describe("Rarity labels and their percentages"),
|
|
42
37
|
traits: z
|
|
43
|
-
.
|
|
38
|
+
.string()
|
|
44
39
|
.optional()
|
|
45
40
|
.describe(
|
|
46
|
-
|
|
41
|
+
'Collection traits as JSON string of key-value pairs where values are arrays, e.g. \'{"Background": ["Blue", "Red"], "Eyes": ["Big", "Small"]}\'',
|
|
47
42
|
),
|
|
48
43
|
skipBroadcast: z
|
|
49
44
|
.boolean()
|
|
@@ -125,9 +120,11 @@ 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
|
-
{
|
|
129
|
-
async ({
|
|
123
|
+
{ ...mintCollectionArgsSchema.shape },
|
|
124
|
+
async ({ folderPath, collectionName, description, rarityLabels, traits: traitsJson, skipBroadcast }): Promise<CallToolResult> => {
|
|
130
125
|
try {
|
|
126
|
+
// Parse traits JSON string if provided
|
|
127
|
+
const traits: Record<string, string[]> | undefined = traitsJson ? JSON.parse(traitsJson) : undefined;
|
|
131
128
|
// Get keys from wallet
|
|
132
129
|
const paymentPk = wallet.getPaymentKey();
|
|
133
130
|
if (!paymentPk) {
|
|
@@ -136,7 +133,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
136
133
|
const identityPk = wallet.getIdentityKey();
|
|
137
134
|
|
|
138
135
|
// Get image files
|
|
139
|
-
const imageFiles = await getImageFiles(
|
|
136
|
+
const imageFiles = await getImageFiles(folderPath);
|
|
140
137
|
if (imageFiles.length === 0) {
|
|
141
138
|
throw new Error("No image files found in the specified folder");
|
|
142
139
|
}
|
|
@@ -145,14 +142,14 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
145
142
|
|
|
146
143
|
// Prepare collection metadata
|
|
147
144
|
const collectionSubTypeData: CollectionSubTypeData = {
|
|
148
|
-
description:
|
|
145
|
+
description: description,
|
|
149
146
|
quantity: imageFiles.length,
|
|
150
147
|
// Transform rarity labels to correct format
|
|
151
148
|
rarityLabels:
|
|
152
|
-
|
|
149
|
+
rarityLabels?.map((r) => ({ label: r.label })) || [],
|
|
153
150
|
// Transform traits - need to match the CollectionTraits type
|
|
154
|
-
traits:
|
|
155
|
-
? Object.entries(
|
|
151
|
+
traits: traits
|
|
152
|
+
? Object.entries(traits).reduce((acc, [key, values]) => {
|
|
156
153
|
acc[key] = {
|
|
157
154
|
values,
|
|
158
155
|
occurancePercentages: values.map(() =>
|
|
@@ -168,14 +165,14 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
168
165
|
app: "ord",
|
|
169
166
|
type: "ord",
|
|
170
167
|
subType: "collection",
|
|
171
|
-
name:
|
|
168
|
+
name: collectionName,
|
|
172
169
|
subTypeData: collectionSubTypeData,
|
|
173
170
|
};
|
|
174
171
|
|
|
175
172
|
// Create collection icon
|
|
176
173
|
const svgString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
177
174
|
<rect width="100" height="100" fill="#f0f0f0"/>
|
|
178
|
-
<text x="50" y="55" text-anchor="middle" font-family="Arial" font-size="16">${
|
|
175
|
+
<text x="50" y="55" text-anchor="middle" font-family="Arial" font-size="16">${collectionName}</text>
|
|
179
176
|
</svg>`;
|
|
180
177
|
const collectionIconData = Utils.toBase64(
|
|
181
178
|
Utils.toArray(svgString, "utf8"),
|
|
@@ -217,7 +214,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
217
214
|
|
|
218
215
|
let collectionTxid = "";
|
|
219
216
|
const disableBroadcasting =
|
|
220
|
-
|
|
217
|
+
skipBroadcast || process.env.DISABLE_BROADCASTING === "true";
|
|
221
218
|
|
|
222
219
|
if (!disableBroadcasting) {
|
|
223
220
|
const broadcaster = new V5Broadcaster();
|
|
@@ -251,7 +248,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
251
248
|
);
|
|
252
249
|
|
|
253
250
|
try {
|
|
254
|
-
const itemTraits = generateItemTraits(i,
|
|
251
|
+
const itemTraits = generateItemTraits(i, traits);
|
|
255
252
|
|
|
256
253
|
const itemSubTypeData: CollectionItemSubTypeData = {
|
|
257
254
|
collectionId: collectionTxid,
|
|
@@ -260,13 +257,13 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
260
257
|
};
|
|
261
258
|
|
|
262
259
|
// Assign rarity if labels provided
|
|
263
|
-
if (
|
|
260
|
+
if (rarityLabels && rarityLabels.length > 0) {
|
|
264
261
|
const rarityIndex = Math.floor(
|
|
265
|
-
(i / imageFiles.length) *
|
|
262
|
+
(i / imageFiles.length) * rarityLabels.length,
|
|
266
263
|
);
|
|
267
264
|
const rarityItem =
|
|
268
|
-
|
|
269
|
-
Math.min(rarityIndex,
|
|
265
|
+
rarityLabels[
|
|
266
|
+
Math.min(rarityIndex, rarityLabels.length - 1)
|
|
270
267
|
];
|
|
271
268
|
if (rarityItem) {
|
|
272
269
|
itemSubTypeData.rarityLabel = [
|
|
@@ -352,7 +349,7 @@ export function registerMintCollectionTool(server: McpServer, wallet: Wallet) {
|
|
|
352
349
|
totalItems: imageFiles.length,
|
|
353
350
|
errors: results.errors,
|
|
354
351
|
totalCost: results.totalCost,
|
|
355
|
-
summary: `Collection "${
|
|
352
|
+
summary: `Collection "${collectionName}" created with ${results.itemTxids.length}/${imageFiles.length} items successfully minted.${results.errors.length > 0 ? ` ${results.errors.length} items failed.` : ""}`,
|
|
356
353
|
},
|
|
357
354
|
null,
|
|
358
355
|
2,
|