bsv-mcp 0.0.32 → 0.0.33

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # BSV MCP Server Changelog
2
2
 
3
+ ## v0.0.33 - Identity Key Sigma Signing
4
+
5
+ ### Features
6
+ - Added optional `IDENTITY_KEY_WIF` environment variable for sigma-protocol signing.
7
+ - `wallet_a2bPublishMcp`, `wallet_createOrdinals`, and `wallet_purchaseListing` tools now support signing with an identity key.
8
+ - Updated `README.md` to document `IDENTITY_KEY_WIF` usage and JSON configuration examples.
9
+
3
10
  ## v0.0.32 - Reliability Improvements
4
11
 
5
12
  ### Bug Fixes
package/README.md CHANGED
@@ -18,8 +18,7 @@ This project is built using [Bun](https://bun.sh/), a fast JavaScript runtime an
18
18
 
19
19
  **macOS (using Homebrew):**
20
20
  ```bash
21
- brew tap oven-sh/bun
22
- brew install bun
21
+ brew install oven-sh/bun/bun
23
22
  ```
24
23
 
25
24
  **macOS/Linux/WSL (using installer script):**
@@ -38,7 +37,7 @@ This server implements the [Model Context Protocol](https://modelcontextprotocol
38
37
 
39
38
  ![MCP Configuration Example](docs/images/mcp-config-example.png)
40
39
 
41
- > **Note:** The PRIVATE_KEY_WIF environment variable is now optional. Without it, the server runs in limited mode with educational resources and non-wallet tools available. Wallet and MNEE token operations require a valid private key.
40
+ > **Note:** The `PRIVATE_KEY_WIF` environment variable is now optional. Without it, the server runs in limited mode with educational resources and non-wallet tools available. Wallet and MNEE token operations require a valid private key. You can also set the `IDENTITY_KEY_WIF` environment variable to enable sigma-protocol signing of ordinals inscriptions for authentication, curation, and web-of-trust.
42
41
 
43
42
  ### Cursor
44
43
 
@@ -58,14 +57,15 @@ To use the BSV MCP server with [Cursor](https://cursor.sh/):
58
57
  "bsv-mcp@latest"
59
58
  ],
60
59
  "env": {
61
- "PRIVATE_KEY_WIF": "<your_private_key_wif>"
60
+ "PRIVATE_KEY_WIF": "<your_private_key_wif>",
61
+ "IDENTITY_KEY_WIF": "<your_identity_key_wif>"
62
62
  }
63
63
  }
64
64
  }
65
65
  }
66
66
  ```
67
67
 
68
- 5. Replace `<your_private_key_wif>` with your actual private key WIF (keep this secure!) If you dont have one you can leave this off for now but you wont be able to use tools that require a wallet.
68
+ 5. Replace `<your_private_key_wif>` with your actual private key WIF (keep this secure!) If you dont have one you can leave this off for now but you wont be able to use tools that require a wallet. `<your_identity_key_wif>` is also optional. It will sign 1Sat Ordinals with Sigma protocol using the provided identity key.
69
69
 
70
70
  6. Click "Save"
71
71
 
@@ -84,7 +84,8 @@ If you prefer to use npm instead of Bun:
84
84
  "bsv-mcp@latest"
85
85
  ],
86
86
  "env": {
87
- "PRIVATE_KEY_WIF": "<your_private_key_wif>"
87
+ "PRIVATE_KEY_WIF": "<your_private_key_wif>",
88
+ "IDENTITY_KEY_WIF": "<your_identity_key_wif>"
88
89
  }
89
90
  }
90
91
  }
@@ -118,7 +119,8 @@ Open the Claude configuration json file in your favorite text editor. If you pre
118
119
  "run", "bsv-mcp@latest"
119
120
  ],
120
121
  "env": {
121
- "PRIVATE_KEY_WIF": "<your_private_key_wif>"
122
+ "PRIVATE_KEY_WIF": "<your_private_key_wif>",
123
+ "IDENTITY_KEY_WIF": "<your_identity_key_wif>"
122
124
  }
123
125
  }
124
126
  }
@@ -362,6 +364,7 @@ The BSV MCP server can be customized using environment variables to enable or di
362
364
  | `DISABLE_BSV_TOOLS` | `false` | Set to `true` to disable BSV blockchain tools |
363
365
  | `DISABLE_ORDINALS_TOOLS` | `false` | Set to `true` to disable Ordinals/NFT tools |
364
366
  | `DISABLE_UTILS_TOOLS` | `false` | Set to `true` to disable utility tools |
367
+ | `IDENTITY_KEY_WIF` | `not set` | Optional WIF for identity key; if set, ordinals inscriptions will be signed with sigma-protocol for authentication, curation, and web-of-trust. |
365
368
 
366
369
  ### Examples
367
370
 
package/index.ts CHANGED
@@ -70,7 +70,7 @@ function initializePrivateKey(): PrivateKey | undefined {
70
70
  const privKey = initializePrivateKey();
71
71
 
72
72
  const server = new McpServer(
73
- { name: "Bitcoin SV", version: "0.0.32" },
73
+ { name: "Bitcoin SV", version: "0.0.33" },
74
74
  // {
75
75
  // // Advertise only what you actually implement
76
76
  // capabilities: {
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.32",
5
+ "version": "0.0.33",
6
6
  "license": "MIT",
7
7
  "author": "satchmo",
8
8
  "description": "A collection of Bitcoin SV (BSV) tools for the Model Context Protocol (MCP) framework",
@@ -52,6 +52,7 @@
52
52
  "js-1sat-ord": "^0.1.81",
53
53
  "mnee": "^2.0.0",
54
54
  "satoshi-token": "^0.0.4",
55
+ "sigma-protocol": "^0.1.6",
55
56
  "zod": "^3.24.3"
56
57
  },
57
58
  "scripts": {
package/smithery.yaml CHANGED
@@ -5,17 +5,74 @@ startCommand:
5
5
  type: stdio
6
6
  configSchema:
7
7
  type: object
8
- required:
9
- - privateKeyWif
10
8
  properties:
11
9
  privateKeyWif:
12
10
  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."
11
+ title: "Private Key (WIF)"
12
+ description: "The private key WIF (Wallet Import Format) for Bitcoin SV transactions. Optional but required for wallet operations. Without this, the server runs in limited mode with only educational resources and non-wallet tools."
13
+ disablePrompts:
14
+ type: boolean
15
+ title: "Disable Prompts"
16
+ description: "Set to true to disable all educational prompts"
17
+ default: false
18
+ disableResources:
19
+ type: boolean
20
+ title: "Disable Resources"
21
+ description: "Set to true to disable all resources (BRCs, changelog)"
22
+ default: false
23
+ disableTools:
24
+ type: boolean
25
+ title: "Disable All Tools"
26
+ description: "Set to true to disable all tools"
27
+ default: false
28
+ disableWalletTools:
29
+ type: boolean
30
+ title: "Disable Wallet Tools"
31
+ description: "Set to true to disable Bitcoin wallet tools"
32
+ default: false
33
+ disableMneeTools:
34
+ type: boolean
35
+ title: "Disable MNEE Tools"
36
+ description: "Set to true to disable MNEE token tools"
37
+ default: false
38
+ disableBsvTools:
39
+ type: boolean
40
+ title: "Disable BSV Blockchain Tools"
41
+ description: "Set to true to disable BSV blockchain tools"
42
+ default: false
43
+ disableOrdinalsTools:
44
+ type: boolean
45
+ title: "Disable Ordinals Tools"
46
+ description: "Set to true to disable Ordinals/NFT tools"
47
+ default: false
48
+ disableUtilsTools:
49
+ type: boolean
50
+ title: "Disable Utility Tools"
51
+ description: "Set to true to disable utility tools"
52
+ default: false
53
+ additionalProperties: false
14
54
  commandFunction: |
15
- (config) => ({
16
- command: 'bun',
17
- args: ['run', 'index.ts'],
18
- env: {
19
- PRIVATE_KEY_WIF: config.privateKeyWif
20
- }
21
- })
55
+ (config) => {
56
+ const env = {};
57
+
58
+ // Add private key if provided
59
+ if (config.privateKeyWif) {
60
+ env.PRIVATE_KEY_WIF = config.privateKeyWif;
61
+ }
62
+
63
+ // Map boolean config options to environment variables
64
+ if (config.disablePrompts) env.DISABLE_PROMPTS = 'true';
65
+ if (config.disableResources) env.DISABLE_RESOURCES = 'true';
66
+ if (config.disableTools) env.DISABLE_TOOLS = 'true';
67
+ if (config.disableWalletTools) env.DISABLE_WALLET_TOOLS = 'true';
68
+ if (config.disableMneeTools) env.DISABLE_MNEE_TOOLS = 'true';
69
+ if (config.disableBsvTools) env.DISABLE_BSV_TOOLS = 'true';
70
+ if (config.disableOrdinalsTools) env.DISABLE_ORDINALS_TOOLS = 'true';
71
+ if (config.disableUtilsTools) env.DISABLE_UTILS_TOOLS = 'true';
72
+
73
+ return {
74
+ command: 'bun',
75
+ args: ['run', 'index.ts'],
76
+ env
77
+ };
78
+ }
@@ -1,4 +1,4 @@
1
- import { Utils } from "@bsv/sdk";
1
+ import { PrivateKey, 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
4
  import type {
@@ -12,6 +12,7 @@ import type {
12
12
  Inscription,
13
13
  PreMAP,
14
14
  } from "js-1sat-ord";
15
+ import { Sigma } from "sigma-protocol";
15
16
  import { z } from "zod";
16
17
  import type { Wallet } from "./wallet";
17
18
  const { toArray, toBase64 } = Utils;
@@ -56,6 +57,20 @@ export function registerA2bPublishMcpTool(server: McpServer, wallet: Wallet) {
56
57
  extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
57
58
  ) => {
58
59
  try {
60
+ // Load optional identity key for sigma signing
61
+ const identityKeyWif = process.env.IDENTITY_KEY_WIF;
62
+ let identityPk: PrivateKey | undefined;
63
+ if (identityKeyWif) {
64
+ try {
65
+ identityPk = PrivateKey.fromWif(identityKeyWif);
66
+ } catch (e) {
67
+ console.warn(
68
+ "Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
69
+ e,
70
+ );
71
+ }
72
+ }
73
+
59
74
  const paymentPk = wallet.getPrivateKey();
60
75
  if (!paymentPk) throw new Error("No private key available");
61
76
 
@@ -77,10 +92,13 @@ export function registerA2bPublishMcpTool(server: McpServer, wallet: Wallet) {
77
92
 
78
93
  // Prepare the full configuration with metadata
79
94
  const fullConfig = {
80
- name: args.toolName,
81
- description: args.description || `MCP Tool: ${args.toolName}`,
82
- config: toolConfig,
83
- type: "mcp-tool",
95
+ mcpServers: {
96
+ [args.toolName]: {
97
+ description: args.description || `MCP Tool: ${args.toolName}`,
98
+ type: "mcp-tool",
99
+ ...toolConfig,
100
+ },
101
+ },
84
102
  };
85
103
 
86
104
  const fileContent = JSON.stringify(fullConfig, null, 2);
@@ -112,8 +130,14 @@ export function registerA2bPublishMcpTool(server: McpServer, wallet: Wallet) {
112
130
 
113
131
  const changeResult = result as ChangeResult;
114
132
 
133
+ let finalTx = changeResult.tx;
134
+ if (identityPk) {
135
+ const sigma = new Sigma(result.tx);
136
+ const signResponse = sigma.sign(identityPk);
137
+ finalTx = signResponse.signedTx;
138
+ }
115
139
  // Broadcast the transaction
116
- await changeResult.tx.broadcast();
140
+ await finalTx.broadcast();
117
141
 
118
142
  // Refresh UTXOs after spending
119
143
  try {
@@ -1,6 +1,11 @@
1
+ import { PrivateKey } from "@bsv/sdk";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
3
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
+ import type {
5
+ CallToolResult,
6
+ ServerNotification,
7
+ ServerRequest,
8
+ } from "@modelcontextprotocol/sdk/types.js";
4
9
  import { createOrdinals } from "js-1sat-ord";
5
10
  import type {
6
11
  ChangeResult,
@@ -10,6 +15,7 @@ import type {
10
15
  Inscription,
11
16
  PreMAP,
12
17
  } from "js-1sat-ord";
18
+ import { Sigma } from "sigma-protocol";
13
19
  import { z } from "zod";
14
20
  import type { Wallet } from "./wallet";
15
21
 
@@ -47,9 +53,23 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
47
53
  { args: createOrdinalsArgsSchema },
48
54
  async (
49
55
  { args }: { args: CreateOrdinalsArgs },
50
- extra: RequestHandlerExtra,
56
+ extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
51
57
  ): Promise<CallToolResult> => {
52
58
  try {
59
+ // Load optional identity key for sigma signing
60
+ const identityKeyWif = process.env.IDENTITY_KEY_WIF;
61
+ let identityPk: PrivateKey | undefined;
62
+ if (identityKeyWif) {
63
+ try {
64
+ identityPk = PrivateKey.fromWif(identityKeyWif);
65
+ } catch (e) {
66
+ console.warn(
67
+ "Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
68
+ e,
69
+ );
70
+ }
71
+ }
72
+
53
73
  // 1. Get private key from wallet
54
74
  const paymentPk = wallet.getPrivateKey();
55
75
  if (!paymentPk) {
@@ -95,8 +115,14 @@ export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
95
115
 
96
116
  const changeResult = result as ChangeResult;
97
117
 
98
- // 7. Broadcast the transaction
99
- await changeResult.tx.broadcast();
118
+ // 7. Optionally sign with identity key and broadcast the transaction
119
+ let finalTx = changeResult.tx;
120
+ if (identityPk) {
121
+ const sigma = new Sigma(changeResult.tx);
122
+ const signResponse = sigma.sign(identityPk);
123
+ finalTx = signResponse.signedTx;
124
+ }
125
+ await finalTx.broadcast();
100
126
 
101
127
  // 8. Refresh the wallet's UTXOs after spending
102
128
  try {
@@ -1,6 +1,10 @@
1
- // import { PrivateKey } from "@bsv/sdk"; // not used here
1
+ import { PrivateKey } 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 type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
9
  import {
6
10
  type ChangeResult,
@@ -14,6 +18,7 @@ import {
14
18
  purchaseOrdListing,
15
19
  purchaseOrdTokenListing,
16
20
  } from "js-1sat-ord";
21
+ import { Sigma } from "sigma-protocol";
17
22
  import type { z } from "zod";
18
23
  import {
19
24
  MARKET_FEE_PERCENTAGE,
@@ -82,9 +87,23 @@ export function registerPurchaseListingTool(server: McpServer, wallet: Wallet) {
82
87
  { args: purchaseListingArgsSchema },
83
88
  async (
84
89
  { args }: { args: z.infer<typeof purchaseListingArgsSchema> },
85
- extra: RequestHandlerExtra,
90
+ extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
86
91
  ): Promise<CallToolResult> => {
87
92
  try {
93
+ // Load optional identity key for sigma signing
94
+ const identityKeyWif = process.env.IDENTITY_KEY_WIF;
95
+ let identityPk: PrivateKey | undefined;
96
+ if (identityKeyWif) {
97
+ try {
98
+ identityPk = PrivateKey.fromWif(identityKeyWif);
99
+ } catch (e) {
100
+ console.warn(
101
+ "Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
102
+ e,
103
+ );
104
+ }
105
+ }
106
+
88
107
  // Fetch the listing info directly from the API
89
108
  const response = await fetch(
90
109
  `https://ordinals.gorillapool.io/api/txos/${args.listingOutpoint}?script=true`,
@@ -252,10 +271,14 @@ Please fund this wallet address with enough BSV to cover the purchase price
252
271
  // Remove console.warn
253
272
  }
254
273
 
255
- // Broadcast the transaction
256
- const broadcastResult = await transaction.tx.broadcast(
257
- oneSatBroadcaster(),
258
- );
274
+ // Optionally sign with identity key then broadcast the transaction
275
+ let finalTx = transaction.tx;
276
+ if (identityPk) {
277
+ const sigma = new Sigma(finalTx);
278
+ const signResponse = sigma.sign(identityPk);
279
+ finalTx = signResponse.signedTx;
280
+ }
281
+ const broadcastResult = await finalTx.broadcast(oneSatBroadcaster());
259
282
 
260
283
  // Handle broadcast response
261
284
  const resultStatus =
@@ -1,6 +1,11 @@
1
+ import { PrivateKey } from "@bsv/sdk";
1
2
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
3
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
3
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
+ import type {
5
+ CallToolResult,
6
+ ServerNotification,
7
+ ServerRequest,
8
+ } from "@modelcontextprotocol/sdk/types.js";
4
9
  import { sendOrdinals } from "js-1sat-ord";
5
10
  import type { ChangeResult, SendOrdinalsConfig } from "js-1sat-ord";
6
11
  import { z } from "zod";
@@ -37,7 +42,7 @@ export function registerSendOrdinalsTool(server: McpServer, wallet: Wallet) {
37
42
  { args: sendOrdinalsArgsSchema },
38
43
  async (
39
44
  { args }: { args: SendOrdinalsArgs },
40
- extra: RequestHandlerExtra,
45
+ extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
41
46
  ): Promise<CallToolResult> => {
42
47
  try {
43
48
  // 1. Get private key from wallet
@@ -86,6 +91,18 @@ export function registerSendOrdinalsTool(server: McpServer, wallet: Wallet) {
86
91
  changeAddress: walletAddress,
87
92
  };
88
93
 
94
+ const identityKeyWif = process.env.IDENTITY_KEY_WIF;
95
+ let identityPk: PrivateKey | undefined;
96
+ if (identityKeyWif) {
97
+ try {
98
+ identityPk = PrivateKey.fromWif(identityKeyWif);
99
+ } catch (e) {
100
+ console.warn(
101
+ "Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
102
+ e,
103
+ );
104
+ }
105
+ }
89
106
  // Add metadata if provided
90
107
  if (args.metadata) {
91
108
  sendOrdinalsConfig.metaData = args.metadata;
@@ -133,7 +133,7 @@ export function registerWalletTools(
133
133
  // registerA2bPublishAgentTool(server, wallet);
134
134
 
135
135
  // Register the wallet_a2bPublishMcp tool
136
- // registerA2bPublishMcpTool(server, wallet);
136
+ registerA2bPublishMcpTool(server, wallet);
137
137
 
138
138
  // Register only the minimal public-facing tools
139
139
  // wallet_createAction, wallet_signAction and wallet_getHeight have been removed