bsv-mcp 0.0.6 → 0.0.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/Dockerfile +20 -0
- package/README.md +27 -41
- package/package.json +1 -1
- package/smithery.yaml +21 -0
- package/tools/wallet/schemas.ts +14 -0
- package/tools/wallet/tools.ts +36 -31
- package/tools/wallet/wallet.ts +10 -1
package/Dockerfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Use the official Bun image
|
|
2
|
+
FROM oven/bun:1
|
|
3
|
+
|
|
4
|
+
# Set working directory
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Copy all application code first
|
|
8
|
+
COPY . .
|
|
9
|
+
|
|
10
|
+
# Install dependencies
|
|
11
|
+
RUN bun install --frozen-lockfile
|
|
12
|
+
|
|
13
|
+
# Set user for security
|
|
14
|
+
USER bun
|
|
15
|
+
|
|
16
|
+
# Expose port (if needed)
|
|
17
|
+
EXPOSE 3000
|
|
18
|
+
|
|
19
|
+
# Run the application
|
|
20
|
+
CMD ["bun", "run", "index.ts"]
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Bitcoin SV MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://smithery.ai/server/@b-open-io/bsv-mcp)
|
|
4
|
+
|
|
3
5
|
> **⚠️ NOTICE: Experimental Work in Progress**
|
|
4
6
|
> This project is in an early experimental stage. Features may change, and the API is not yet stable.
|
|
5
7
|
> Contributions, feedback, and bug reports are welcome! Feel free to open issues or submit pull requests.
|
|
@@ -14,16 +16,6 @@ To install dependencies:
|
|
|
14
16
|
bun install
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
For global installation (recommended for MCP client integration):
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
# Install globally with bun
|
|
21
|
-
bun install -g bsv-mcp
|
|
22
|
-
|
|
23
|
-
# Or with npm
|
|
24
|
-
npm install -g bsv-mcp
|
|
25
|
-
```
|
|
26
|
-
|
|
27
19
|
## External Dependencies
|
|
28
20
|
|
|
29
21
|
For full functionality of all tools, the following additional dependencies are installed:
|
|
@@ -38,11 +30,7 @@ js-1sat-ord
|
|
|
38
30
|
Start the MCP server:
|
|
39
31
|
|
|
40
32
|
```bash
|
|
41
|
-
# If installed locally
|
|
42
33
|
bun run index.ts
|
|
43
|
-
|
|
44
|
-
# If installed globally
|
|
45
|
-
bunx bsv-mcp
|
|
46
34
|
```
|
|
47
35
|
|
|
48
36
|
## Connecting to MCP Clients
|
|
@@ -54,7 +42,7 @@ This server implements the [Model Context Protocol](https://modelcontextprotocol
|
|
|
54
42
|
To use the BSV MCP server with [Cursor](https://cursor.sh/):
|
|
55
43
|
|
|
56
44
|
1. Install Cursor if you haven't already
|
|
57
|
-
2.
|
|
45
|
+
2. Clone this repository and run `bun install` in the project directory
|
|
58
46
|
3. Open Cursor and navigate to Settings → Extensions → Model Context Protocol
|
|
59
47
|
4. Click "Add a new global MCP server"
|
|
60
48
|
5. Enter the following configuration in JSON format:
|
|
@@ -65,15 +53,17 @@ To use the BSV MCP server with [Cursor](https://cursor.sh/):
|
|
|
65
53
|
"command": "env",
|
|
66
54
|
"args": [
|
|
67
55
|
"PRIVATE_KEY_WIF=<your_private_key_wif>",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
56
|
+
"bun",
|
|
57
|
+
"run",
|
|
58
|
+
"<path_to_project>/index.ts"
|
|
70
59
|
]
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
62
|
```
|
|
74
63
|
|
|
75
64
|
6. Replace `<your_private_key_wif>` with your actual private key WIF (keep this secure!)
|
|
76
|
-
7.
|
|
65
|
+
7. Replace `<path_to_project>` with the full path to where you cloned this repository
|
|
66
|
+
8. Click "Save"
|
|
77
67
|
|
|
78
68
|
The BSV tools will now be available to Cursor's AI assistant under the "Bitcoin SV" namespace.
|
|
79
69
|
|
|
@@ -82,7 +72,7 @@ The BSV tools will now be available to Cursor's AI assistant under the "Bitcoin
|
|
|
82
72
|
To connect this server to Claude for Desktop:
|
|
83
73
|
|
|
84
74
|
1. Ensure you have [Claude for Desktop](https://claude.ai/desktop) installed and updated to the latest version
|
|
85
|
-
2.
|
|
75
|
+
2. Clone this repository and run `bun install` in the project directory
|
|
86
76
|
3. Open your Claude for Desktop configuration file:
|
|
87
77
|
```bash
|
|
88
78
|
# macOS/Linux
|
|
@@ -99,16 +89,18 @@ To connect this server to Claude for Desktop:
|
|
|
99
89
|
"command": "env",
|
|
100
90
|
"args": [
|
|
101
91
|
"PRIVATE_KEY_WIF=<your_private_key_wif>",
|
|
102
|
-
"
|
|
103
|
-
"
|
|
92
|
+
"bun",
|
|
93
|
+
"run",
|
|
94
|
+
"<path_to_project>/index.ts"
|
|
104
95
|
]
|
|
105
96
|
}
|
|
106
97
|
}
|
|
107
98
|
}
|
|
108
99
|
```
|
|
109
100
|
5. Replace `<your_private_key_wif>` with your actual private key WIF
|
|
110
|
-
6.
|
|
111
|
-
7.
|
|
101
|
+
6. Replace `<path_to_project>` with the full path to where you cloned this repository
|
|
102
|
+
7. Save the file and restart Claude for Desktop
|
|
103
|
+
8. The BSV tools will appear when you click the tools icon (hammer) in Claude for Desktop
|
|
112
104
|
|
|
113
105
|
### Generic MCP Client Integration
|
|
114
106
|
|
|
@@ -120,8 +112,9 @@ For other MCP clients that support JSON configuration:
|
|
|
120
112
|
"command": "env",
|
|
121
113
|
"args": [
|
|
122
114
|
"PRIVATE_KEY_WIF=<your_private_key_wif>",
|
|
123
|
-
"
|
|
124
|
-
"
|
|
115
|
+
"bun",
|
|
116
|
+
"run",
|
|
117
|
+
"<path_to_project>/index.ts"
|
|
125
118
|
]
|
|
126
119
|
}
|
|
127
120
|
}
|
|
@@ -134,7 +127,7 @@ If running the server directly:
|
|
|
134
127
|
export PRIVATE_KEY_WIF=<your_private_key_wif>
|
|
135
128
|
|
|
136
129
|
# Then run the server
|
|
137
|
-
|
|
130
|
+
bun run index.ts
|
|
138
131
|
```
|
|
139
132
|
|
|
140
133
|
## Available Tools
|
|
@@ -150,8 +143,7 @@ Wallet tools provide core BSV wallet functionality:
|
|
|
150
143
|
| `wallet_getPublicKey` | Retrieves a public key for a specified protocol and key ID |
|
|
151
144
|
| `wallet_createSignature` | Creates a cryptographic signature for the provided data |
|
|
152
145
|
| `wallet_verifySignature` | Verifies a cryptographic signature against the provided data |
|
|
153
|
-
| `
|
|
154
|
-
| `wallet_decrypt` | Decrypts data using a specified protocol and key |
|
|
146
|
+
| `wallet_encryption` | Combined tool for encrypting and decrypting data using the wallet's cryptographic keys (replaces separate encrypt/decrypt tools) |
|
|
155
147
|
| `wallet_getAddress` | Returns a BSV address for the current wallet or a derived path |
|
|
156
148
|
| `wallet_sendToAddress` | Sends BSV to a specified address (supports BSV or USD amounts) |
|
|
157
149
|
| `wallet_purchaseListing` | Purchases NFTs or BSV-20/BSV-21 tokens from marketplace listings |
|
|
@@ -194,6 +186,8 @@ Once connected, you can use natural language to interact with Bitcoin SV through
|
|
|
194
186
|
- "Get my Bitcoin SV address"
|
|
195
187
|
- "Send 0.01 BSV to 1ExampleBsvAddressXXXXXXXXXXXXXXXXX"
|
|
196
188
|
- "Send $5 USD worth of BSV to 1ExampleBsvAddressXXXXXXXXXXXXXXXXX"
|
|
189
|
+
- "Encrypt this message using my wallet's keys"
|
|
190
|
+
- "Decrypt this data that was previously encrypted for me"
|
|
197
191
|
- "Purchase this NFT listing: txid_vout"
|
|
198
192
|
- "Purchase this BSV-20 token listing: txid_vout"
|
|
199
193
|
|
|
@@ -225,7 +219,7 @@ When you interact with an MCP-enabled AI assistant:
|
|
|
225
219
|
|
|
226
220
|
If you're having issues connecting to the server:
|
|
227
221
|
|
|
228
|
-
1. Ensure the package
|
|
222
|
+
1. Ensure the package dependencies are properly installed: `bun install`
|
|
229
223
|
2. Verify your WIF private key is correctly set in the environment
|
|
230
224
|
3. Check that your client supports MCP and is properly configured
|
|
231
225
|
4. Look for error messages in the client's console output
|
|
@@ -239,6 +233,9 @@ For Cursor, check the Cursor MCP logs in Settings → Extensions → Model Conte
|
|
|
239
233
|
|
|
240
234
|
## Recent Updates
|
|
241
235
|
|
|
236
|
+
### Unified Encryption Tool
|
|
237
|
+
- **Combined Wallet Encryption**: The `wallet_encrypt` and `wallet_decrypt` tools have been merged into a single `wallet_encryption` tool with a mode parameter to switch between encryption and decryption operations.
|
|
238
|
+
|
|
242
239
|
### Enhanced Marketplace Tools
|
|
243
240
|
- **Unified Market Listings**: The `ordinals_marketListings` tool now supports NFTs, BSV-20, and BSV-21 tokens through a single interface with appropriate filtering.
|
|
244
241
|
- **Improved Market Sales**: The `ordinals_marketSales` tool (renamed from `ordinals_bsv20MarketSales`) now supports both BSV-20 and BSV-21 token sales.
|
|
@@ -254,18 +251,7 @@ This project was created using `bun init` in bun v1.2.9. [Bun](https://bun.sh) i
|
|
|
254
251
|
|
|
255
252
|
### Package Configuration
|
|
256
253
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
```json
|
|
260
|
-
{
|
|
261
|
-
"name": "bsv-mcp",
|
|
262
|
-
"bin": {
|
|
263
|
-
"bsv-mcp": "./index.ts"
|
|
264
|
-
},
|
|
265
|
-
"type": "module"
|
|
266
|
-
// ...other configuration
|
|
267
|
-
}
|
|
268
|
-
```
|
|
254
|
+
The main entry point for this package is `index.ts`.
|
|
269
255
|
|
|
270
256
|
### Running Tests
|
|
271
257
|
|
package/package.json
CHANGED
package/smithery.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
build:
|
|
2
|
+
dockerBuildPath: ./
|
|
3
|
+
|
|
4
|
+
startCommand:
|
|
5
|
+
type: stdio
|
|
6
|
+
configSchema:
|
|
7
|
+
type: object
|
|
8
|
+
required:
|
|
9
|
+
- privateKeyWif
|
|
10
|
+
properties:
|
|
11
|
+
privateKeyWif:
|
|
12
|
+
type: string
|
|
13
|
+
description: "The private key WIF (Wallet Import Format) for Bitcoin SV transactions. This key is used to sign transactions and is required for wallet operations."
|
|
14
|
+
commandFunction: |
|
|
15
|
+
(config) => ({
|
|
16
|
+
command: 'bun',
|
|
17
|
+
args: ['run', 'index.ts'],
|
|
18
|
+
env: {
|
|
19
|
+
PRIVATE_KEY_WIF: config.privateKeyWif
|
|
20
|
+
}
|
|
21
|
+
})
|
package/tools/wallet/schemas.ts
CHANGED
|
@@ -72,6 +72,19 @@ export const walletDecryptArgsSchema = z.object({
|
|
|
72
72
|
privileged: z.boolean().optional(),
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
// Combined wallet encryption/decryption args
|
|
76
|
+
export const walletEncryptionArgsSchema = z.object({
|
|
77
|
+
mode: z.enum(["encrypt", "decrypt"]).describe("Operation mode: 'encrypt' to encrypt data or 'decrypt' to decrypt data"),
|
|
78
|
+
data: z.array(z.number()).describe("Data to process: plaintext for encryption or ciphertext for decryption"),
|
|
79
|
+
protocolID: walletProtocolSchema,
|
|
80
|
+
keyID: z.string(),
|
|
81
|
+
privilegedReason: z.string().optional(),
|
|
82
|
+
counterparty: z
|
|
83
|
+
.union([z.string(), z.literal("self"), z.literal("anyone")])
|
|
84
|
+
.optional(),
|
|
85
|
+
privileged: z.boolean().optional(),
|
|
86
|
+
}).describe("Combined schema for encryption and decryption operations, with a mode parameter to switch between functions");
|
|
87
|
+
|
|
75
88
|
// Create HMAC arguments
|
|
76
89
|
export const createHmacArgsSchema = z.object({
|
|
77
90
|
message: z.string(),
|
|
@@ -296,3 +309,4 @@ export const purchaseListingArgsSchema = z.object({
|
|
|
296
309
|
// Export types
|
|
297
310
|
export type SendToAddressArgs = z.infer<typeof sendToAddressArgsSchema>;
|
|
298
311
|
export type PurchaseListingArgs = z.infer<typeof purchaseListingArgsSchema>;
|
|
312
|
+
export type WalletEncryptionArgs = z.infer<typeof walletEncryptionArgsSchema>;
|
package/tools/wallet/tools.ts
CHANGED
|
@@ -31,8 +31,7 @@ import {
|
|
|
31
31
|
type purchaseListingArgsSchema,
|
|
32
32
|
type sendToAddressArgsSchema,
|
|
33
33
|
verifySignatureArgsSchema,
|
|
34
|
-
|
|
35
|
-
walletEncryptArgsSchema,
|
|
34
|
+
walletEncryptionArgsSchema,
|
|
36
35
|
} from "./schemas";
|
|
37
36
|
|
|
38
37
|
import { registerCreateOrdinalsTool } from "./createOrdinals";
|
|
@@ -46,8 +45,7 @@ type ToolArgSchemas = {
|
|
|
46
45
|
wallet_getPublicKey: typeof getPublicKeyArgsSchema;
|
|
47
46
|
wallet_createSignature: typeof createSignatureArgsSchema;
|
|
48
47
|
wallet_verifySignature: typeof verifySignatureArgsSchema;
|
|
49
|
-
|
|
50
|
-
wallet_decrypt: typeof walletDecryptArgsSchema;
|
|
48
|
+
wallet_encryption: typeof walletEncryptionArgsSchema;
|
|
51
49
|
wallet_listActions: typeof listActionsArgsSchema;
|
|
52
50
|
wallet_listOutputs: typeof listOutputsArgsSchema;
|
|
53
51
|
wallet_getNetwork: typeof emptyArgsSchema;
|
|
@@ -94,11 +92,12 @@ export function registerWalletTools(
|
|
|
94
92
|
// Handle tools registration with properly typed parameters
|
|
95
93
|
function registerTool<T extends z.ZodType>(
|
|
96
94
|
name: keyof ToolArgSchemas,
|
|
95
|
+
description: string,
|
|
97
96
|
schema: { args: T },
|
|
98
97
|
handler: ToolCallback<{ args: T }>,
|
|
99
98
|
): void {
|
|
100
99
|
// Register all tools normally
|
|
101
|
-
server.tool(name, schema, handler);
|
|
100
|
+
server.tool(name, description, schema, handler);
|
|
102
101
|
handlers[name] = handler as ToolHandler;
|
|
103
102
|
}
|
|
104
103
|
|
|
@@ -117,6 +116,7 @@ export function registerWalletTools(
|
|
|
117
116
|
// Register wallet_getPublicKey
|
|
118
117
|
registerTool(
|
|
119
118
|
"wallet_getPublicKey",
|
|
119
|
+
"Retrieves the current wallet's public key. This public key can be used for cryptographic operations like signature verification or encryption.",
|
|
120
120
|
{ args: getPublicKeyArgsSchema },
|
|
121
121
|
async (
|
|
122
122
|
{ args }: { args: z.infer<typeof getPublicKeyArgsSchema> },
|
|
@@ -135,6 +135,7 @@ export function registerWalletTools(
|
|
|
135
135
|
// Register wallet_createSignature
|
|
136
136
|
registerTool(
|
|
137
137
|
"wallet_createSignature",
|
|
138
|
+
"Creates a cryptographic signature using the wallet's private key. This tool enables secure message signing and transaction authorization, supporting various signature protocols.",
|
|
138
139
|
{ args: createSignatureArgsSchema },
|
|
139
140
|
async (
|
|
140
141
|
{ args }: { args: z.infer<typeof createSignatureArgsSchema> },
|
|
@@ -153,6 +154,7 @@ export function registerWalletTools(
|
|
|
153
154
|
// Register wallet_verifySignature
|
|
154
155
|
registerTool(
|
|
155
156
|
"wallet_verifySignature",
|
|
157
|
+
"Verifies a cryptographic signature against a message or data. This tool supports various verification protocols and can validate signatures from both the wallet's own keys and external public keys.",
|
|
156
158
|
{ args: verifySignatureArgsSchema },
|
|
157
159
|
async (
|
|
158
160
|
{ args }: { args: z.infer<typeof verifySignatureArgsSchema> },
|
|
@@ -168,16 +170,38 @@ export function registerWalletTools(
|
|
|
168
170
|
},
|
|
169
171
|
);
|
|
170
172
|
|
|
171
|
-
// Register
|
|
173
|
+
// Register combined wallet_encryption tool
|
|
172
174
|
registerTool(
|
|
173
|
-
"
|
|
174
|
-
|
|
175
|
+
"wallet_encryption",
|
|
176
|
+
"Combined tool for encrypting and decrypting data using the wallet's cryptographic keys. Supports both encryption of plaintext data and decryption of previously encrypted content. Use the 'mode' parameter to switch between operations.",
|
|
177
|
+
{ args: walletEncryptionArgsSchema },
|
|
175
178
|
async (
|
|
176
|
-
{ args }: { args: z.infer<typeof
|
|
179
|
+
{ args }: { args: z.infer<typeof walletEncryptionArgsSchema> },
|
|
177
180
|
extra: RequestHandlerExtra,
|
|
178
181
|
) => {
|
|
179
182
|
try {
|
|
180
|
-
|
|
183
|
+
let result: { ciphertext?: number[]; plaintext?: number[] };
|
|
184
|
+
if (args.mode === "encrypt") {
|
|
185
|
+
// For encryption, the data is treated as plaintext
|
|
186
|
+
result = await wallet.encrypt({
|
|
187
|
+
plaintext: args.data,
|
|
188
|
+
protocolID: args.protocolID,
|
|
189
|
+
keyID: args.keyID,
|
|
190
|
+
privilegedReason: args.privilegedReason,
|
|
191
|
+
counterparty: args.counterparty,
|
|
192
|
+
privileged: args.privileged,
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
// For decryption, the data is treated as ciphertext
|
|
196
|
+
result = await wallet.decrypt({
|
|
197
|
+
ciphertext: args.data,
|
|
198
|
+
protocolID: args.protocolID,
|
|
199
|
+
keyID: args.keyID,
|
|
200
|
+
privilegedReason: args.privilegedReason,
|
|
201
|
+
counterparty: args.counterparty,
|
|
202
|
+
privileged: args.privileged,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
181
205
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
182
206
|
} catch (err: unknown) {
|
|
183
207
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -186,27 +210,8 @@ export function registerWalletTools(
|
|
|
186
210
|
},
|
|
187
211
|
);
|
|
188
212
|
|
|
189
|
-
// Register
|
|
190
|
-
registerTool(
|
|
191
|
-
"wallet_decrypt",
|
|
192
|
-
{ args: walletDecryptArgsSchema },
|
|
193
|
-
async (
|
|
194
|
-
{ args }: { args: z.infer<typeof walletDecryptArgsSchema> },
|
|
195
|
-
extra: RequestHandlerExtra,
|
|
196
|
-
) => {
|
|
197
|
-
try {
|
|
198
|
-
const result = await wallet.decrypt(args);
|
|
199
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
200
|
-
} catch (err: unknown) {
|
|
201
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
202
|
-
return { content: [{ type: "text", text: msg }], isError: true };
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
// Register ordinals extension tools
|
|
208
|
-
// Register the wallet_createOrdinals tool
|
|
213
|
+
// Register createOrdinals tool
|
|
209
214
|
registerCreateOrdinalsTool(server, wallet);
|
|
210
|
-
|
|
215
|
+
|
|
211
216
|
return handlers;
|
|
212
217
|
}
|
package/tools/wallet/wallet.ts
CHANGED
|
@@ -38,6 +38,7 @@ import type {
|
|
|
38
38
|
ListOutputsResult,
|
|
39
39
|
ProveCertificateArgs,
|
|
40
40
|
ProveCertificateResult,
|
|
41
|
+
PubKeyHex,
|
|
41
42
|
RelinquishCertificateArgs,
|
|
42
43
|
RelinquishCertificateResult,
|
|
43
44
|
RelinquishOutputArgs,
|
|
@@ -127,7 +128,15 @@ export class Wallet extends ProtoWallet implements WalletInterface {
|
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
async getPublicKey(args: GetPublicKeyArgs): Promise<GetPublicKeyResult> {
|
|
130
|
-
|
|
131
|
+
const privateKey = this.getPrivateKey();
|
|
132
|
+
if (!privateKey) {
|
|
133
|
+
throw new Error("No private key available");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const publicKey = privateKey.toPublicKey();
|
|
137
|
+
return {
|
|
138
|
+
publicKey: publicKey.toDER("hex") as PubKeyHex,
|
|
139
|
+
};
|
|
131
140
|
}
|
|
132
141
|
async revealCounterpartyKeyLinkage(
|
|
133
142
|
args: RevealCounterpartyKeyLinkageArgs,
|