@proofofprotocol/inscribe-mcp 0.1.0 → 0.3.0
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/package.json +1 -1
- package/src/cli/commands/init.js +193 -30
- package/src/cli/commands/setup-mcp.js +205 -0
- package/src/cli/index.js +2 -0
package/package.json
CHANGED
package/src/cli/commands/init.js
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
import { createInterface } from 'readline';
|
|
9
|
+
import { PrivateKey } from '@hashgraph/sdk';
|
|
9
10
|
import { writeConfig, configExists, getConfigPath } from '../lib/config.js';
|
|
10
11
|
import { EXIT_CODES } from '../lib/exit-codes.js';
|
|
12
|
+
import { exec } from 'child_process';
|
|
13
|
+
import { platform } from 'os';
|
|
11
14
|
|
|
12
15
|
// Simple prompt helper (no external dependency)
|
|
13
16
|
function prompt(question) {
|
|
@@ -34,6 +37,57 @@ const colors = {
|
|
|
34
37
|
dim: (s) => `\x1b[2m${s}\x1b[0m`
|
|
35
38
|
};
|
|
36
39
|
|
|
40
|
+
// Open URL in browser
|
|
41
|
+
function openBrowser(url) {
|
|
42
|
+
const os = platform();
|
|
43
|
+
let cmd;
|
|
44
|
+
if (os === 'darwin') {
|
|
45
|
+
cmd = `open "${url}"`;
|
|
46
|
+
} else if (os === 'win32') {
|
|
47
|
+
cmd = `start "" "${url}"`;
|
|
48
|
+
} else {
|
|
49
|
+
cmd = `xdg-open "${url}"`;
|
|
50
|
+
}
|
|
51
|
+
exec(cmd, () => {});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Generate ECDSA key pair and EVM address
|
|
55
|
+
function generateKeyPair() {
|
|
56
|
+
const privateKey = PrivateKey.generateECDSA();
|
|
57
|
+
const publicKey = privateKey.publicKey;
|
|
58
|
+
|
|
59
|
+
// Get EVM address from public key
|
|
60
|
+
const evmAddress = publicKey.toEvmAddress();
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
privateKey: privateKey.toStringDer(),
|
|
64
|
+
privateKeyRaw: privateKey.toStringRaw(),
|
|
65
|
+
publicKey: publicKey.toStringDer(),
|
|
66
|
+
evmAddress: `0x${evmAddress}`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Fetch account ID from EVM address via Mirror Node
|
|
71
|
+
async function fetchAccountIdFromEvmAddress(evmAddress, network) {
|
|
72
|
+
const mirrorUrl = network === 'mainnet'
|
|
73
|
+
? 'https://mainnet.mirrornode.hedera.com'
|
|
74
|
+
: 'https://testnet.mirrornode.hedera.com';
|
|
75
|
+
|
|
76
|
+
// Remove 0x prefix if present
|
|
77
|
+
const address = evmAddress.startsWith('0x') ? evmAddress.slice(2) : evmAddress;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(`${mirrorUrl}/api/v1/accounts/${address}`);
|
|
81
|
+
if (response.ok) {
|
|
82
|
+
const data = await response.json();
|
|
83
|
+
return data.account;
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
// Ignore errors
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
37
91
|
export const initCommand = new Command('init')
|
|
38
92
|
.description('Initialize inscribe-mcp configuration')
|
|
39
93
|
.option('-f, --force', 'Overwrite existing configuration')
|
|
@@ -90,53 +144,162 @@ export const initCommand = new Command('init')
|
|
|
90
144
|
console.log(colors.bold('2. Hedera Account'));
|
|
91
145
|
console.log('');
|
|
92
146
|
|
|
147
|
+
let accountId;
|
|
148
|
+
let privateKey;
|
|
149
|
+
|
|
93
150
|
if (network === 'testnet') {
|
|
94
|
-
|
|
95
|
-
console.log('
|
|
151
|
+
// Testnet: offer new or existing account
|
|
152
|
+
console.log(' 1) ' + colors.cyan('Create new account') + colors.dim(' (generate key + faucet)'));
|
|
153
|
+
console.log(' 2) ' + colors.dim('Use existing account'));
|
|
96
154
|
console.log('');
|
|
97
|
-
|
|
155
|
+
|
|
156
|
+
let accountChoice;
|
|
157
|
+
while (!accountChoice) {
|
|
158
|
+
const choice = await prompt('Select (1 or 2): ');
|
|
159
|
+
if (choice === '1') accountChoice = 'new';
|
|
160
|
+
else if (choice === '2') accountChoice = 'existing';
|
|
161
|
+
else console.log(colors.red('Invalid selection. Enter 1 or 2.'));
|
|
162
|
+
}
|
|
98
163
|
console.log('');
|
|
164
|
+
|
|
165
|
+
if (accountChoice === 'new') {
|
|
166
|
+
// Generate new key pair
|
|
167
|
+
console.log(colors.bold('Generating ECDSA key pair...'));
|
|
168
|
+
const keyPair = generateKeyPair();
|
|
169
|
+
console.log('');
|
|
170
|
+
console.log(colors.green('✓') + ' Key pair generated');
|
|
171
|
+
console.log('');
|
|
172
|
+
console.log(colors.bold('Your EVM Address:'));
|
|
173
|
+
console.log(colors.cyan(` ${keyPair.evmAddress}`));
|
|
174
|
+
console.log('');
|
|
175
|
+
|
|
176
|
+
privateKey = keyPair.privateKey;
|
|
177
|
+
|
|
178
|
+
// Open faucet
|
|
179
|
+
console.log(colors.bold('3. Get Free HBAR'));
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log('Opening faucet in browser...');
|
|
182
|
+
console.log(colors.dim(' https://portal.hedera.com/faucet'));
|
|
183
|
+
console.log('');
|
|
184
|
+
openBrowser('https://portal.hedera.com/faucet');
|
|
185
|
+
|
|
186
|
+
console.log('Steps:');
|
|
187
|
+
console.log(' 1. Paste your EVM address above in the faucet');
|
|
188
|
+
console.log(' 2. Click "RECEIVE 100 TESTNET HBAR"');
|
|
189
|
+
console.log(' 3. Wait a few seconds for the account to be created');
|
|
190
|
+
console.log('');
|
|
191
|
+
|
|
192
|
+
await prompt('Press Enter when you have received HBAR...');
|
|
193
|
+
console.log('');
|
|
194
|
+
|
|
195
|
+
// Try to fetch account ID automatically
|
|
196
|
+
console.log('Looking up your Account ID...');
|
|
197
|
+
let retries = 3;
|
|
198
|
+
while (retries > 0 && !accountId) {
|
|
199
|
+
accountId = await fetchAccountIdFromEvmAddress(keyPair.evmAddress, network);
|
|
200
|
+
if (!accountId) {
|
|
201
|
+
retries--;
|
|
202
|
+
if (retries > 0) {
|
|
203
|
+
console.log(colors.dim(' Waiting for account creation...'));
|
|
204
|
+
await new Promise(r => setTimeout(r, 3000));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (accountId) {
|
|
210
|
+
console.log(colors.green('✓') + ` Account ID: ${accountId}`);
|
|
211
|
+
} else {
|
|
212
|
+
console.log(colors.yellow('Could not find Account ID automatically.'));
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log('Check HashScan:');
|
|
215
|
+
console.log(colors.cyan(` https://hashscan.io/testnet/account/${keyPair.evmAddress.slice(2)}`));
|
|
216
|
+
console.log('');
|
|
217
|
+
while (!accountId) {
|
|
218
|
+
const input = await prompt('Enter your Account ID (e.g., 0.0.123456): ');
|
|
219
|
+
if (/^0\.0\.\d+$/.test(input)) {
|
|
220
|
+
accountId = input;
|
|
221
|
+
} else {
|
|
222
|
+
console.log(colors.red('Invalid format. Use 0.0.XXXXXX'));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
console.log('');
|
|
227
|
+
|
|
228
|
+
} else {
|
|
229
|
+
// Existing account
|
|
230
|
+
console.log(colors.cyan('Enter your existing Hedera account details.'));
|
|
231
|
+
console.log('');
|
|
232
|
+
|
|
233
|
+
while (!accountId) {
|
|
234
|
+
const input = await prompt('Account ID (e.g., 0.0.123456): ');
|
|
235
|
+
if (/^0\.0\.\d+$/.test(input)) {
|
|
236
|
+
accountId = input;
|
|
237
|
+
} else {
|
|
238
|
+
console.log(colors.red('Invalid format. Use 0.0.XXXXXX'));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log(colors.green('✓') + ` Account ID: ${accountId}`);
|
|
243
|
+
console.log('');
|
|
244
|
+
|
|
245
|
+
// Private key input
|
|
246
|
+
console.log(colors.bold('3. Private Key'));
|
|
247
|
+
console.log('');
|
|
248
|
+
console.log(colors.dim('Your private key is stored locally and never transmitted.'));
|
|
249
|
+
console.log('');
|
|
250
|
+
|
|
251
|
+
while (!privateKey) {
|
|
252
|
+
const input = await prompt('Private Key (hex or DER format): ');
|
|
253
|
+
if (input.length >= 32) {
|
|
254
|
+
privateKey = input;
|
|
255
|
+
} else {
|
|
256
|
+
console.log(colors.red('Private key seems too short.'));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(colors.green('✓') + ' Private key received');
|
|
261
|
+
console.log('');
|
|
262
|
+
}
|
|
263
|
+
|
|
99
264
|
} else {
|
|
265
|
+
// Mainnet: always use existing account
|
|
100
266
|
console.log(colors.cyan('Create Mainnet Account:'));
|
|
101
267
|
console.log(' HashPack: https://www.hashpack.app/');
|
|
102
268
|
console.log(' Blade: https://www.bladewallet.io/');
|
|
103
269
|
console.log('');
|
|
104
270
|
console.log('Transfer a small amount of HBAR (1-5 HBAR recommended).');
|
|
105
271
|
console.log('');
|
|
106
|
-
}
|
|
107
272
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
console.log(colors.red('Invalid format. Use 0.0.XXXXXX'));
|
|
273
|
+
while (!accountId) {
|
|
274
|
+
const input = await prompt('Account ID (e.g., 0.0.123456): ');
|
|
275
|
+
if (/^0\.0\.\d+$/.test(input)) {
|
|
276
|
+
accountId = input;
|
|
277
|
+
} else {
|
|
278
|
+
console.log(colors.red('Invalid format. Use 0.0.XXXXXX'));
|
|
279
|
+
}
|
|
116
280
|
}
|
|
117
|
-
}
|
|
118
281
|
|
|
119
|
-
|
|
120
|
-
|
|
282
|
+
console.log(colors.green('✓') + ` Account ID: ${accountId}`);
|
|
283
|
+
console.log('');
|
|
121
284
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
285
|
+
// Private key input
|
|
286
|
+
console.log(colors.bold('3. Private Key'));
|
|
287
|
+
console.log('');
|
|
288
|
+
console.log(colors.dim('Your private key is stored locally and never transmitted.'));
|
|
289
|
+
console.log('');
|
|
127
290
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
291
|
+
while (!privateKey) {
|
|
292
|
+
const input = await prompt('Private Key (hex or DER format): ');
|
|
293
|
+
if (input.length >= 32) {
|
|
294
|
+
privateKey = input;
|
|
295
|
+
} else {
|
|
296
|
+
console.log(colors.red('Private key seems too short.'));
|
|
297
|
+
}
|
|
135
298
|
}
|
|
136
|
-
}
|
|
137
299
|
|
|
138
|
-
|
|
139
|
-
|
|
300
|
+
console.log(colors.green('✓') + ' Private key received');
|
|
301
|
+
console.log('');
|
|
302
|
+
}
|
|
140
303
|
|
|
141
304
|
// Topic ID (optional)
|
|
142
305
|
console.log(colors.bold('4. Topic ID (optional)'));
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup-mcp command
|
|
3
|
+
*
|
|
4
|
+
* Configure MCP client to use inscribe-mcp server.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { createInterface } from 'readline';
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'fs';
|
|
10
|
+
import { homedir, platform } from 'os';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
import { EXIT_CODES } from '../lib/exit-codes.js';
|
|
13
|
+
import { configExists } from '../lib/config.js';
|
|
14
|
+
|
|
15
|
+
// Simple prompt helper
|
|
16
|
+
function prompt(question) {
|
|
17
|
+
const rl = createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
rl.question(question, (answer) => {
|
|
24
|
+
rl.close();
|
|
25
|
+
resolve(answer.trim());
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ANSI colors
|
|
31
|
+
const colors = {
|
|
32
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
33
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
34
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
35
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
36
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
37
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Get Claude Desktop config path based on OS
|
|
41
|
+
function getClaudeDesktopConfigPath() {
|
|
42
|
+
const os = platform();
|
|
43
|
+
if (os === 'darwin') {
|
|
44
|
+
return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
45
|
+
} else if (os === 'win32') {
|
|
46
|
+
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
47
|
+
} else {
|
|
48
|
+
// Linux
|
|
49
|
+
return join(homedir(), '.config', 'Claude', 'claude_desktop_config.json');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// MCP server config for inscribe
|
|
54
|
+
const INSCRIBE_MCP_CONFIG = {
|
|
55
|
+
command: 'npx',
|
|
56
|
+
args: ['@proofofprotocol/inscribe-mcp-server']
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Generate JSON snippet for display
|
|
60
|
+
function generateJsonSnippet() {
|
|
61
|
+
return JSON.stringify({
|
|
62
|
+
mcpServers: {
|
|
63
|
+
inscribe: INSCRIBE_MCP_CONFIG
|
|
64
|
+
}
|
|
65
|
+
}, null, 2);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const setupMcpCommand = new Command('setup-mcp')
|
|
69
|
+
.description('Configure MCP client to use inscribe-mcp server')
|
|
70
|
+
.option('--claude-desktop', 'Configure Claude Desktop automatically')
|
|
71
|
+
.option('--show-json', 'Just show the JSON configuration')
|
|
72
|
+
.action(async (options) => {
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(colors.bold('inscribe-mcp MCP Setup'));
|
|
75
|
+
console.log('─'.repeat(40));
|
|
76
|
+
console.log('');
|
|
77
|
+
|
|
78
|
+
// Check if inscribe-mcp is configured
|
|
79
|
+
if (!configExists()) {
|
|
80
|
+
console.log(colors.yellow('⚠ inscribe-mcp is not configured yet.'));
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log('Run ' + colors.cyan('inscribe-mcp init') + ' first to set up your Hedera account.');
|
|
83
|
+
console.log('');
|
|
84
|
+
process.exit(EXIT_CODES.ERROR);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// If --show-json, just display and exit
|
|
88
|
+
if (options.showJson) {
|
|
89
|
+
console.log('Add this to your MCP client configuration:');
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(colors.cyan(generateJsonSnippet()));
|
|
92
|
+
console.log('');
|
|
93
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// If --claude-desktop, skip selection
|
|
97
|
+
let clientChoice = options.claudeDesktop ? 'claude' : null;
|
|
98
|
+
|
|
99
|
+
if (!clientChoice) {
|
|
100
|
+
console.log(colors.bold('Select MCP Client'));
|
|
101
|
+
console.log('');
|
|
102
|
+
console.log(' 1) ' + colors.cyan('Claude Desktop') + colors.dim(' (auto-configure)'));
|
|
103
|
+
console.log(' 2) ' + colors.dim('Other MCP client') + colors.dim(' (show JSON)'));
|
|
104
|
+
console.log('');
|
|
105
|
+
|
|
106
|
+
while (!clientChoice) {
|
|
107
|
+
const choice = await prompt('Select (1 or 2): ');
|
|
108
|
+
if (choice === '1') clientChoice = 'claude';
|
|
109
|
+
else if (choice === '2') clientChoice = 'other';
|
|
110
|
+
else console.log(colors.red('Invalid selection. Enter 1 or 2.'));
|
|
111
|
+
}
|
|
112
|
+
console.log('');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (clientChoice === 'other') {
|
|
116
|
+
// Just show JSON
|
|
117
|
+
console.log(colors.bold('MCP Configuration'));
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log('Add this to your MCP client configuration:');
|
|
120
|
+
console.log('');
|
|
121
|
+
console.log(colors.cyan(generateJsonSnippet()));
|
|
122
|
+
console.log('');
|
|
123
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Claude Desktop configuration
|
|
127
|
+
console.log(colors.bold('Claude Desktop Configuration'));
|
|
128
|
+
console.log('');
|
|
129
|
+
|
|
130
|
+
const configPath = getClaudeDesktopConfigPath();
|
|
131
|
+
console.log('Config file: ' + colors.dim(configPath));
|
|
132
|
+
console.log('');
|
|
133
|
+
|
|
134
|
+
// Check if config file exists
|
|
135
|
+
let existingConfig = { mcpServers: {} };
|
|
136
|
+
let configFileExists = false;
|
|
137
|
+
|
|
138
|
+
if (existsSync(configPath)) {
|
|
139
|
+
configFileExists = true;
|
|
140
|
+
try {
|
|
141
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
142
|
+
existingConfig = JSON.parse(content);
|
|
143
|
+
if (!existingConfig.mcpServers) {
|
|
144
|
+
existingConfig.mcpServers = {};
|
|
145
|
+
}
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.log(colors.yellow('⚠ Could not parse existing config, will create new one.'));
|
|
148
|
+
existingConfig = { mcpServers: {} };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check if inscribe is already configured
|
|
153
|
+
if (existingConfig.mcpServers.inscribe) {
|
|
154
|
+
console.log(colors.yellow('inscribe is already configured in Claude Desktop.'));
|
|
155
|
+
console.log('');
|
|
156
|
+
const confirm = await prompt('Overwrite? (yes/no): ');
|
|
157
|
+
if (confirm.toLowerCase() !== 'yes') {
|
|
158
|
+
console.log('Aborted.');
|
|
159
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
160
|
+
}
|
|
161
|
+
console.log('');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Backup existing config if it exists
|
|
165
|
+
if (configFileExists) {
|
|
166
|
+
const backupPath = configPath + '.backup.' + Date.now();
|
|
167
|
+
try {
|
|
168
|
+
copyFileSync(configPath, backupPath);
|
|
169
|
+
console.log(colors.green('✓') + ' Backup created: ' + colors.dim(backupPath));
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.log(colors.yellow('⚠ Could not create backup: ' + error.message));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Add inscribe config
|
|
176
|
+
existingConfig.mcpServers.inscribe = INSCRIBE_MCP_CONFIG;
|
|
177
|
+
|
|
178
|
+
// Write new config
|
|
179
|
+
try {
|
|
180
|
+
writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), 'utf-8');
|
|
181
|
+
console.log(colors.green('✓') + ' Configuration updated');
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.log(colors.red('✗ Failed to write config: ' + error.message));
|
|
184
|
+
console.log('');
|
|
185
|
+
console.log('You may need to create the config file manually:');
|
|
186
|
+
console.log(colors.cyan(configPath));
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log('With content:');
|
|
189
|
+
console.log(colors.cyan(generateJsonSnippet()));
|
|
190
|
+
console.log('');
|
|
191
|
+
process.exit(EXIT_CODES.ERROR);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log('');
|
|
195
|
+
console.log('─'.repeat(40));
|
|
196
|
+
console.log(colors.green(colors.bold('✓ Setup Complete!')));
|
|
197
|
+
console.log('');
|
|
198
|
+
console.log('Next steps:');
|
|
199
|
+
console.log(' 1. ' + colors.cyan('Restart Claude Desktop'));
|
|
200
|
+
console.log(' 2. Look for "inscribe" in the MCP tools menu');
|
|
201
|
+
console.log(' 3. Try: "このテキストを刻んで: Hello World"');
|
|
202
|
+
console.log('');
|
|
203
|
+
|
|
204
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
205
|
+
});
|
package/src/cli/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { configCommand } from './commands/config.js';
|
|
|
17
17
|
import { balanceCommand } from './commands/balance.js';
|
|
18
18
|
import { logCommand } from './commands/log.js';
|
|
19
19
|
import { showCommand } from './commands/show.js';
|
|
20
|
+
import { setupMcpCommand } from './commands/setup-mcp.js';
|
|
20
21
|
|
|
21
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
22
23
|
const __dirname = dirname(__filename);
|
|
@@ -35,6 +36,7 @@ program
|
|
|
35
36
|
|
|
36
37
|
// Register commands
|
|
37
38
|
program.addCommand(initCommand);
|
|
39
|
+
program.addCommand(setupMcpCommand);
|
|
38
40
|
program.addCommand(configCommand);
|
|
39
41
|
program.addCommand(balanceCommand);
|
|
40
42
|
program.addCommand(logCommand);
|