bsv-mcp 0.0.7 → 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 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
+ [![smithery badge](https://smithery.ai/badge/@b-open-io/bsv-mcp)](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.
@@ -141,8 +143,7 @@ Wallet tools provide core BSV wallet functionality:
141
143
  | `wallet_getPublicKey` | Retrieves a public key for a specified protocol and key ID |
142
144
  | `wallet_createSignature` | Creates a cryptographic signature for the provided data |
143
145
  | `wallet_verifySignature` | Verifies a cryptographic signature against the provided data |
144
- | `wallet_encrypt` | Encrypts data using a specified protocol and key |
145
- | `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) |
146
147
  | `wallet_getAddress` | Returns a BSV address for the current wallet or a derived path |
147
148
  | `wallet_sendToAddress` | Sends BSV to a specified address (supports BSV or USD amounts) |
148
149
  | `wallet_purchaseListing` | Purchases NFTs or BSV-20/BSV-21 tokens from marketplace listings |
@@ -185,6 +186,8 @@ Once connected, you can use natural language to interact with Bitcoin SV through
185
186
  - "Get my Bitcoin SV address"
186
187
  - "Send 0.01 BSV to 1ExampleBsvAddressXXXXXXXXXXXXXXXXX"
187
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"
188
191
  - "Purchase this NFT listing: txid_vout"
189
192
  - "Purchase this BSV-20 token listing: txid_vout"
190
193
 
@@ -230,6 +233,9 @@ For Cursor, check the Cursor MCP logs in Settings → Extensions → Model Conte
230
233
 
231
234
  ## Recent Updates
232
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
+
233
239
  ### Enhanced Marketplace Tools
234
240
  - **Unified Market Listings**: The `ordinals_marketListings` tool now supports NFTs, BSV-20, and BSV-21 tokens through a single interface with appropriate filtering.
235
241
  - **Improved Market Sales**: The `ordinals_marketSales` tool (renamed from `ordinals_bsv20MarketSales`) now supports both BSV-20 and BSV-21 token sales.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "bsv-mcp",
3
3
  "module": "index.ts",
4
4
  "type": "module",
5
- "version": "0.0.7",
5
+ "version": "0.0.8",
6
6
  "bin": {
7
7
  "bsv-mcp": "./index.ts"
8
8
  },
package/smithery.yaml CHANGED
@@ -1,3 +1,6 @@
1
+ build:
2
+ dockerBuildPath: ./
3
+
1
4
  startCommand:
2
5
  type: stdio
3
6
  configSchema:
@@ -7,15 +10,12 @@ startCommand:
7
10
  properties:
8
11
  privateKeyWif:
9
12
  type: string
10
- description: "Your private key WIF (Wallet Import Format) for Bitcoin SV transactions. This key is used to sign transactions and is required for wallet operations."
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."
11
14
  commandFunction: |
12
- (config) => ({
13
- "command": "bun",
14
- "args": [
15
- "run",
16
- "index.ts"
17
- ],
18
- "env": {
19
- "PRIVATE_KEY_WIF": config.privateKeyWif
20
- }
15
+ (config) => ({
16
+ command: 'bun',
17
+ args: ['run', 'index.ts'],
18
+ env: {
19
+ PRIVATE_KEY_WIF: config.privateKeyWif
20
+ }
21
21
  })
@@ -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>;
@@ -31,8 +31,7 @@ import {
31
31
  type purchaseListingArgsSchema,
32
32
  type sendToAddressArgsSchema,
33
33
  verifySignatureArgsSchema,
34
- walletDecryptArgsSchema,
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
- wallet_encrypt: typeof walletEncryptArgsSchema;
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 wallet_encrypt
173
+ // Register combined wallet_encryption tool
172
174
  registerTool(
173
- "wallet_encrypt",
174
- { args: walletEncryptArgsSchema },
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 walletEncryptArgsSchema> },
179
+ { args }: { args: z.infer<typeof walletEncryptionArgsSchema> },
177
180
  extra: RequestHandlerExtra,
178
181
  ) => {
179
182
  try {
180
- const result = await wallet.encrypt(args);
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 wallet_decrypt
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
  }
@@ -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
- return Promise.reject(new Error("Not implemented"));
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,