bsv-mcp 0.2.8 → 0.2.10

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.
@@ -1,168 +1,87 @@
1
- import { PrivateKey } from "@bsv/sdk";
2
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
- import type {
5
- ChangeResult,
6
- CreateOrdinalsCollectionItemMetadata,
7
- CreateOrdinalsCollectionMetadata,
8
- CreateOrdinalsConfig,
9
- Destination,
10
- Inscription,
11
- LocalSigner,
12
- PreMAP,
13
- } from "js-1sat-ord";
14
- import { createOrdinals } from "js-1sat-ord";
15
- import { z } from "zod";
16
- import { V5Broadcaster } from "../../utils/broadcaster";
17
- import type { Wallet } from "./wallet";
1
+ import type { OneSatContext } from '@1sat/actions'
2
+ import { inscribe } from '@1sat/actions'
3
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
4
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
5
+ import { z } from 'zod'
18
6
 
19
- /**
20
- * Schema for the createOrdinals tool arguments.
21
- * This is a simplified interface compared to the full CreateOrdinalsConfig
22
- * in js-1sat-ord. The wallet will provide UTXOs, private key, etc.
23
- */
24
7
  export const createOrdinalsArgsSchema = z.object({
25
- // Base64-encoded data to inscribe
26
- dataB64: z.string().describe("Base64-encoded content to inscribe"),
27
- // Content type (e.g., "image/jpeg", "text/plain", etc.)
28
- contentType: z.string().describe("MIME type of the content"),
29
- // Optional destination address (if not provided, uses the wallet's address)
8
+ dataB64: z.string().describe('Base64-encoded content to inscribe'),
9
+ contentType: z.string().describe('MIME type of the content'),
30
10
  destinationAddress: z
31
11
  .string()
32
12
  .optional()
33
- .describe("Optional destination address for the ordinal"),
34
- // Optional metadata for the inscription
13
+ .describe('Optional destination address for the ordinal'),
35
14
  metadata: z
36
- .any()
15
+ .record(z.string(), z.string())
37
16
  .optional()
38
- .describe("Optional MAP metadata for the inscription"),
39
- });
17
+ .describe('Optional MAP metadata for the inscription'),
18
+ signWithBAP: z
19
+ .boolean()
20
+ .optional()
21
+ .describe('Sign with BAP identity (Sigma protocol). Uses anchor+inscription two-step flow.'),
22
+ })
40
23
 
41
- export type CreateOrdinalsArgs = z.infer<typeof createOrdinalsArgsSchema>;
24
+ export type CreateOrdinalsArgs = z.infer<typeof createOrdinalsArgsSchema>
42
25
 
43
- /**
44
- * Registers the wallet_createOrdinals tool for minting ordinals/inscriptions
45
- */
46
- export function registerCreateOrdinalsTool(server: McpServer, wallet: Wallet) {
26
+ export function registerCreateOrdinalsTool(
27
+ server: McpServer,
28
+ ctx: OneSatContext | undefined,
29
+ ) {
47
30
  server.tool(
48
- "wallet_createOrdinals",
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.",
31
+ 'wallet_createOrdinals',
32
+ '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.',
50
33
  { ...createOrdinalsArgsSchema.shape },
51
- async ({ dataB64, contentType, destinationAddress, metadata }): Promise<CallToolResult> => {
52
- try {
53
- // Load optional identity key for sigma signing
54
- const identityKeyWif = process.env.IDENTITY_KEY_WIF;
55
- let identityPk: PrivateKey | undefined;
56
- if (identityKeyWif) {
57
- try {
58
- identityPk = PrivateKey.fromWif(identityKeyWif);
59
- } catch (e) {
60
- console.warn(
61
- "Warning: Invalid IDENTITY_KEY_WIF environment variable; sigma signing disabled",
62
- e,
63
- );
64
- }
65
- }
66
-
67
- // 1. Get private key from wallet
68
- const paymentPk = wallet.getPrivateKey();
69
- if (!paymentPk) {
70
- throw new Error("No private key available in wallet");
71
- }
72
-
73
- // 2. Get payment UTXOs from wallet
74
- const { paymentUtxos } = await wallet.getUtxos();
75
- if (!paymentUtxos || paymentUtxos.length === 0) {
76
- throw new Error(
77
- "No payment UTXOs available to fund this inscription",
78
- );
79
- }
80
-
81
- // 3. Get the wallet address for change/destination if not provided
82
- const walletAddress = paymentPk.toAddress().toString();
83
-
84
- // 4. Create the inscription object
85
- const inscription: Inscription = {
86
- dataB64: dataB64,
87
- contentType: contentType,
88
- };
89
-
90
- // 5. Create the destination
91
- const destinations: Destination[] = [
92
- {
93
- address: destinationAddress || walletAddress,
94
- inscription,
95
- },
96
- ];
97
-
98
- const createOrdinalsConfig: CreateOrdinalsConfig = {
99
- utxos: paymentUtxos,
100
- destinations,
101
- paymentPk,
102
- changeAddress: walletAddress,
103
- metaData: metadata as
104
- | PreMAP
105
- | CreateOrdinalsCollectionMetadata
106
- | CreateOrdinalsCollectionItemMetadata,
107
- };
108
-
109
- if (identityPk) {
110
- createOrdinalsConfig.signer = {
111
- idKey: identityPk,
112
- } as LocalSigner;
34
+ async ({ dataB64, contentType, destinationAddress, metadata, signWithBAP }): Promise<CallToolResult> => {
35
+ if (!ctx) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: 'text',
40
+ text: 'Wallet not initialized. Please configure a wallet before creating ordinals.',
41
+ },
42
+ ],
43
+ isError: true,
113
44
  }
45
+ }
114
46
 
115
- // 6. Create and broadcast the transaction
116
- const result = await createOrdinals(createOrdinalsConfig);
117
-
118
- const changeResult = result as ChangeResult;
119
-
120
- // 7. Optionally sign with identity key and broadcast the transaction
121
-
122
- const disableBroadcasting = process.env.DISABLE_BROADCASTING === "true";
123
- if (!disableBroadcasting) {
124
- const broadcaster = new V5Broadcaster();
125
- await changeResult.tx.broadcast(broadcaster);
126
-
127
- // 8. Refresh the wallet's UTXOs after spending
128
- try {
129
- await wallet.refreshUtxos();
130
- } catch (refreshError) {
131
- console.warn(
132
- "Failed to refresh UTXOs after transaction:",
133
- refreshError,
134
- );
135
- }
136
-
137
- // 9. Return transaction details
47
+ try {
48
+ const result = await inscribe.execute(ctx, {
49
+ base64Content: dataB64,
50
+ contentType,
51
+ map: metadata,
52
+ signWithBAP,
53
+ })
54
+
55
+ if (result.error) {
138
56
  return {
139
- content: [
140
- {
141
- type: "text",
142
- text: JSON.stringify({
143
- txid: changeResult.tx.id("hex"),
144
- spentOutpoints: changeResult.spentOutpoints,
145
- payChange: changeResult.payChange,
146
- inscriptionAddress: destinationAddress || walletAddress,
147
- contentType: contentType,
148
- }),
149
- },
150
- ],
151
- };
57
+ content: [{ type: 'text', text: result.error }],
58
+ isError: true,
59
+ }
152
60
  }
153
61
 
154
62
  return {
155
63
  content: [
156
64
  {
157
- type: "text",
158
- text: changeResult.tx.toHex(),
65
+ type: 'text',
66
+ text: JSON.stringify({
67
+ txid: result.txid,
68
+ rawtx: result.rawtx,
69
+ contentType,
70
+ }),
159
71
  },
160
72
  ],
161
- };
73
+ }
162
74
  } catch (err: unknown) {
163
- const msg = err instanceof Error ? err.message : String(err);
164
- return { content: [{ type: "text", text: msg }], isError: true };
75
+ return {
76
+ content: [
77
+ {
78
+ type: 'text',
79
+ text: err instanceof Error ? err.message : String(err),
80
+ },
81
+ ],
82
+ isError: true,
83
+ }
165
84
  }
166
85
  },
167
- );
86
+ )
168
87
  }
@@ -1,54 +1,58 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { toBitcoin } from "satoshi-token"; // For converting satoshis to BSV string
3
- import type { Wallet } from "./wallet";
1
+ import type { OneSatContext } from '@1sat/actions'
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
3
+ import { toBitcoin } from 'satoshi-token'
4
4
 
5
- /**
6
- * Registers the wallet_getBalance tool
7
- */
8
5
  export function registerWalletGetBalanceTool(
9
6
  server: McpServer,
10
- wallet: Wallet,
7
+ ctx: OneSatContext | undefined,
11
8
  ) {
12
9
  server.tool(
13
- "wallet_getBalance",
14
- "Retrieves the current BSV balance for the wallet based on its UTXOs.",
10
+ 'wallet_getBalance',
11
+ 'Retrieves the current BSV balance for the wallet.',
15
12
  {},
16
13
  async () => {
17
- try {
18
- const { paymentUtxos } = await wallet.getUtxos();
19
-
20
- let totalSatoshis = 0;
21
- if (paymentUtxos && paymentUtxos.length > 0) {
22
- for (const utxo of paymentUtxos) {
23
- totalSatoshis += utxo.satoshis || 0;
24
- }
14
+ if (!ctx) {
15
+ return {
16
+ content: [
17
+ {
18
+ type: 'text',
19
+ text: 'Wallet not initialized. Please configure a wallet before checking balance.',
20
+ },
21
+ ],
22
+ isError: true,
25
23
  }
24
+ }
26
25
 
27
- const bsvAmount = toBitcoin(totalSatoshis); // Convert to BSV string
26
+ try {
27
+ const result = await ctx.wallet.listOutputs({ basket: 'default' })
28
+ const totalSatoshis = result.outputs.reduce(
29
+ (sum, output) => sum + output.satoshis,
30
+ 0,
31
+ )
28
32
 
29
33
  return {
30
34
  content: [
31
35
  {
32
- type: "text",
36
+ type: 'text',
33
37
  text: JSON.stringify({
34
38
  satoshis: totalSatoshis,
35
- bsv: bsvAmount,
36
- utxoCount: paymentUtxos ? paymentUtxos.length : 0,
39
+ bsv: toBitcoin(totalSatoshis),
40
+ utxoCount: result.totalOutputs,
37
41
  }),
38
42
  },
39
43
  ],
40
- };
44
+ }
41
45
  } catch (error) {
42
46
  return {
43
47
  content: [
44
48
  {
45
- type: "text",
49
+ type: 'text',
46
50
  text: error instanceof Error ? error.message : String(error),
47
51
  },
48
52
  ],
49
53
  isError: true,
50
- };
54
+ }
51
55
  }
52
56
  },
53
- );
57
+ )
54
58
  }