@lanonasis/cli 3.6.5 ā 3.6.7
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/dist/commands/api-keys.d.ts +2 -1
- package/dist/commands/api-keys.js +73 -78
- package/dist/commands/auth.js +160 -167
- package/dist/commands/completion.js +31 -39
- package/dist/commands/config.js +162 -201
- package/dist/commands/enhanced-memory.js +11 -17
- package/dist/commands/guide.js +79 -88
- package/dist/commands/init.js +14 -20
- package/dist/commands/mcp.d.ts +10 -0
- package/dist/commands/mcp.js +167 -156
- package/dist/commands/memory.js +77 -83
- package/dist/commands/organization.js +15 -21
- package/dist/commands/topics.js +52 -58
- package/dist/core/achievements.js +19 -26
- package/dist/core/architecture.js +42 -59
- package/dist/core/dashboard.js +71 -81
- package/dist/core/error-handler.js +30 -39
- package/dist/core/power-mode.js +46 -53
- package/dist/core/progress.js +35 -44
- package/dist/core/welcome.js +56 -64
- package/dist/enhanced-cli.js +49 -58
- package/dist/index-simple.js +75 -113
- package/dist/index.js +64 -69
- package/dist/mcp/access-control.js +13 -17
- package/dist/mcp/client/enhanced-client.js +16 -23
- package/dist/mcp/enhanced-server.js +10 -14
- package/dist/mcp/logger.js +3 -7
- package/dist/mcp/memory-state.js +13 -17
- package/dist/mcp/schemas/tool-schemas.d.ts +16 -16
- package/dist/mcp/schemas/tool-schemas.js +122 -126
- package/dist/mcp/server/lanonasis-server.js +66 -57
- package/dist/mcp/transports/transport-manager.js +18 -25
- package/dist/mcp/vector-store.js +6 -10
- package/dist/mcp-server.js +23 -27
- package/dist/utils/api.js +19 -26
- package/dist/utils/config.d.ts +2 -1
- package/dist/utils/config.js +65 -78
- package/dist/utils/formatting.js +6 -14
- package/dist/utils/mcp-client.js +76 -117
- package/package.json +36 -5
package/dist/commands/mcp.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { table } from 'table';
|
|
4
|
+
import { getMCPClient } from '../utils/mcp-client.js';
|
|
5
|
+
import { EnhancedMCPClient } from '../mcp/client/enhanced-client.js';
|
|
6
|
+
import { CLIConfig } from '../utils/config.js';
|
|
7
|
+
import WebSocket from 'ws';
|
|
8
|
+
/**
|
|
9
|
+
* Register MCP-related CLI commands (mcp and mcp-server) on a Commander program.
|
|
10
|
+
*
|
|
11
|
+
* Adds commands and subcommands for MCP server initialization, connection management,
|
|
12
|
+
* status reporting, tool listing and invocation, memory create/search operations,
|
|
13
|
+
* preference configuration, and diagnostic routines, wiring each command to its
|
|
14
|
+
* corresponding action handlers.
|
|
15
|
+
*
|
|
16
|
+
* @param program - Commander program instance to extend with MCP commands
|
|
17
|
+
*/
|
|
18
|
+
export function mcpCommands(program) {
|
|
15
19
|
const mcp = program
|
|
16
20
|
.command('mcp')
|
|
17
21
|
.description('MCP (Model Context Protocol) server operations');
|
|
@@ -22,35 +26,35 @@ function mcpCommands(program) {
|
|
|
22
26
|
mcpServer.command('init')
|
|
23
27
|
.description('Initialize MCP server configuration')
|
|
24
28
|
.action(async () => {
|
|
25
|
-
console.log(
|
|
29
|
+
console.log(chalk.cyan('š Initializing MCP Server Configuration'));
|
|
26
30
|
console.log('');
|
|
27
|
-
const config = new
|
|
31
|
+
const config = new CLIConfig();
|
|
28
32
|
const isAuthenticated = !!config.get('token');
|
|
29
33
|
if (isAuthenticated) {
|
|
30
|
-
console.log(
|
|
34
|
+
console.log(chalk.green('ā Authenticated - Using remote MCP mode'));
|
|
31
35
|
console.log(' Your memory operations will use mcp.lanonasis.com');
|
|
32
36
|
console.log(' with real-time SSE updates enabled');
|
|
33
37
|
}
|
|
34
38
|
else {
|
|
35
|
-
console.log(
|
|
39
|
+
console.log(chalk.yellow('ā ļø Not authenticated - Using local MCP mode'));
|
|
36
40
|
console.log(' Run "lanonasis auth login" to enable remote mode');
|
|
37
41
|
}
|
|
38
42
|
console.log('');
|
|
39
|
-
console.log(
|
|
43
|
+
console.log(chalk.cyan('Available MCP Commands:'));
|
|
40
44
|
console.log(' lanonasis mcp connect # Auto-connect to best mode');
|
|
41
45
|
console.log(' lanonasis mcp connect -r # Force remote mode');
|
|
42
46
|
console.log(' lanonasis mcp connect -l # Force local mode');
|
|
43
47
|
console.log(' lanonasis mcp status # Check connection status');
|
|
44
48
|
console.log(' lanonasis mcp tools # List available tools');
|
|
45
49
|
console.log('');
|
|
46
|
-
console.log(
|
|
50
|
+
console.log(chalk.cyan('Memory operations are MCP-powered by default!'));
|
|
47
51
|
// Auto-connect to MCP
|
|
48
|
-
const spinner = (
|
|
52
|
+
const spinner = ora('Auto-connecting to MCP...').start();
|
|
49
53
|
try {
|
|
50
|
-
const client =
|
|
54
|
+
const client = getMCPClient();
|
|
51
55
|
const connected = await client.connect({ useRemote: isAuthenticated });
|
|
52
56
|
if (connected) {
|
|
53
|
-
spinner.succeed(
|
|
57
|
+
spinner.succeed(chalk.green(`Connected to ${isAuthenticated ? 'remote' : 'local'} MCP server`));
|
|
54
58
|
process.exit(0);
|
|
55
59
|
}
|
|
56
60
|
else {
|
|
@@ -73,8 +77,8 @@ function mcpCommands(program) {
|
|
|
73
77
|
.option('-u, --url <url>', 'Remote/WebSocket server URL')
|
|
74
78
|
.option('--local-args <args>', 'Extra args for local server (e.g., "--stdio --port 3001")')
|
|
75
79
|
.action(async (options) => {
|
|
76
|
-
const spinner = (
|
|
77
|
-
const config = new
|
|
80
|
+
const spinner = ora('Connecting to MCP server...').start();
|
|
81
|
+
const config = new CLIConfig();
|
|
78
82
|
try {
|
|
79
83
|
let connectionMode;
|
|
80
84
|
// Determine connection mode - WebSocket takes precedence over remote and local
|
|
@@ -88,8 +92,9 @@ function mcpCommands(program) {
|
|
|
88
92
|
connectionMode = 'local';
|
|
89
93
|
}
|
|
90
94
|
else {
|
|
91
|
-
// Default to
|
|
92
|
-
|
|
95
|
+
// Default to websocket (production mode) for all users
|
|
96
|
+
// Local mode should only be used explicitly for development
|
|
97
|
+
connectionMode = 'websocket';
|
|
93
98
|
}
|
|
94
99
|
// Save preferences
|
|
95
100
|
config.set('mcpConnectionMode', connectionMode);
|
|
@@ -106,7 +111,7 @@ function mcpCommands(program) {
|
|
|
106
111
|
}
|
|
107
112
|
let connected = false;
|
|
108
113
|
// Use Enhanced MCP Client for better connection handling
|
|
109
|
-
const enhancedClient = new
|
|
114
|
+
const enhancedClient = new EnhancedMCPClient();
|
|
110
115
|
if (options.url) {
|
|
111
116
|
// Connect to specific URL (WebSocket or remote)
|
|
112
117
|
const serverConfig = {
|
|
@@ -117,14 +122,14 @@ function mcpCommands(program) {
|
|
|
117
122
|
};
|
|
118
123
|
connected = await enhancedClient.connectSingle(serverConfig);
|
|
119
124
|
if (connected) {
|
|
120
|
-
spinner.succeed(
|
|
125
|
+
spinner.succeed(chalk.green(`Connected to MCP server at ${options.url}`));
|
|
121
126
|
process.exit(0);
|
|
122
127
|
return;
|
|
123
128
|
}
|
|
124
129
|
}
|
|
125
130
|
else {
|
|
126
131
|
// Fall back to old client for local connections
|
|
127
|
-
const client =
|
|
132
|
+
const client = getMCPClient();
|
|
128
133
|
const localArgs = typeof options.localArgs === 'string' && options.localArgs.trim().length > 0
|
|
129
134
|
? options.localArgs.split(' ').map((s) => s.trim()).filter(Boolean)
|
|
130
135
|
: undefined;
|
|
@@ -136,15 +141,15 @@ function mcpCommands(program) {
|
|
|
136
141
|
});
|
|
137
142
|
}
|
|
138
143
|
if (connected) {
|
|
139
|
-
spinner.succeed(
|
|
144
|
+
spinner.succeed(chalk.green(`Connected to MCP server in ${connectionMode} mode`));
|
|
140
145
|
process.exit(0);
|
|
141
146
|
if (connectionMode === 'remote') {
|
|
142
|
-
console.log(
|
|
143
|
-
console.log(
|
|
147
|
+
console.log(chalk.cyan('ā¹ļø Using remote MCP via mcp.lanonasis.com'));
|
|
148
|
+
console.log(chalk.cyan('š” SSE endpoint active for real-time updates'));
|
|
144
149
|
}
|
|
145
150
|
else if (connectionMode === 'websocket') {
|
|
146
|
-
console.log(
|
|
147
|
-
console.log(
|
|
151
|
+
console.log(chalk.cyan('ā¹ļø Using enterprise WebSocket MCP server'));
|
|
152
|
+
console.log(chalk.cyan('š” WebSocket connection active with auto-reconnect'));
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
155
|
else {
|
|
@@ -161,47 +166,47 @@ function mcpCommands(program) {
|
|
|
161
166
|
mcp.command('disconnect')
|
|
162
167
|
.description('Disconnect from MCP server')
|
|
163
168
|
.action(async () => {
|
|
164
|
-
const client =
|
|
169
|
+
const client = getMCPClient();
|
|
165
170
|
await client.disconnect();
|
|
166
|
-
console.log(
|
|
171
|
+
console.log(chalk.green('ā Disconnected from MCP server'));
|
|
167
172
|
});
|
|
168
173
|
// Status command
|
|
169
174
|
mcp.command('status')
|
|
170
175
|
.description('Show MCP connection status')
|
|
171
176
|
.action(async () => {
|
|
172
|
-
const client =
|
|
177
|
+
const client = getMCPClient();
|
|
173
178
|
// Reload config from disk to get latest preference
|
|
174
179
|
await client.init();
|
|
175
180
|
const status = client.getConnectionStatus();
|
|
176
|
-
console.log(
|
|
177
|
-
console.log(
|
|
178
|
-
console.log(`Status: ${status.connected ?
|
|
181
|
+
console.log(chalk.cyan('\nš MCP Connection Status'));
|
|
182
|
+
console.log(chalk.cyan('========================'));
|
|
183
|
+
console.log(`Status: ${status.connected ? chalk.green('Connected') : chalk.red('Disconnected')}`);
|
|
179
184
|
// Display mode with proper labels
|
|
180
185
|
let modeDisplay;
|
|
181
186
|
switch (status.mode) {
|
|
182
187
|
case 'websocket':
|
|
183
|
-
modeDisplay =
|
|
188
|
+
modeDisplay = chalk.blue('WebSocket');
|
|
184
189
|
break;
|
|
185
190
|
case 'remote':
|
|
186
|
-
modeDisplay =
|
|
191
|
+
modeDisplay = chalk.blue('Remote (HTTP/SSE)');
|
|
187
192
|
break;
|
|
188
193
|
case 'local':
|
|
189
|
-
modeDisplay =
|
|
194
|
+
modeDisplay = chalk.yellow('Local (stdio)');
|
|
190
195
|
break;
|
|
191
196
|
default:
|
|
192
|
-
modeDisplay =
|
|
197
|
+
modeDisplay = chalk.gray(status.mode);
|
|
193
198
|
}
|
|
194
199
|
console.log(`Mode: ${modeDisplay}`);
|
|
195
200
|
console.log(`Server: ${status.server}`);
|
|
196
201
|
if (status.connected) {
|
|
197
202
|
if (status.mode === 'remote') {
|
|
198
|
-
console.log(`\n${
|
|
203
|
+
console.log(`\n${chalk.cyan('Features:')}`);
|
|
199
204
|
console.log('⢠Real-time updates via SSE');
|
|
200
205
|
console.log('⢠Authenticated API access');
|
|
201
206
|
console.log('⢠MCP-compatible tool interface');
|
|
202
207
|
}
|
|
203
208
|
else if (status.mode === 'websocket') {
|
|
204
|
-
console.log(`\n${
|
|
209
|
+
console.log(`\n${chalk.cyan('Features:')}`);
|
|
205
210
|
console.log('⢠Bi-directional real-time communication');
|
|
206
211
|
console.log('⢠Authenticated WebSocket connection');
|
|
207
212
|
console.log('⢠Production-ready MCP server');
|
|
@@ -212,29 +217,29 @@ function mcpCommands(program) {
|
|
|
212
217
|
mcp.command('tools')
|
|
213
218
|
.description('List available MCP tools')
|
|
214
219
|
.action(async () => {
|
|
215
|
-
const spinner = (
|
|
220
|
+
const spinner = ora('Fetching available tools...').start();
|
|
216
221
|
try {
|
|
217
|
-
const client =
|
|
222
|
+
const client = getMCPClient();
|
|
218
223
|
if (!client.isConnectedToServer()) {
|
|
219
224
|
spinner.info('Not connected. Attempting auto-connect...');
|
|
220
|
-
const config = new
|
|
225
|
+
const config = new CLIConfig();
|
|
221
226
|
const useRemote = !!config.get('token');
|
|
222
227
|
await client.connect({ useRemote });
|
|
223
228
|
}
|
|
224
229
|
const tools = await client.listTools();
|
|
225
230
|
spinner.succeed('Tools fetched successfully');
|
|
226
|
-
console.log(
|
|
227
|
-
console.log(
|
|
231
|
+
console.log(chalk.cyan('\nš§ Available MCP Tools'));
|
|
232
|
+
console.log(chalk.cyan('====================='));
|
|
228
233
|
const tableData = [
|
|
229
|
-
[
|
|
234
|
+
[chalk.bold('Tool Name'), chalk.bold('Description')]
|
|
230
235
|
];
|
|
231
236
|
tools.forEach(tool => {
|
|
232
237
|
tableData.push([
|
|
233
|
-
|
|
238
|
+
chalk.green(tool.name),
|
|
234
239
|
tool.description
|
|
235
240
|
]);
|
|
236
241
|
});
|
|
237
|
-
console.log(
|
|
242
|
+
console.log(table(tableData, {
|
|
238
243
|
border: {
|
|
239
244
|
topBody: 'ā',
|
|
240
245
|
topJoin: 'ā¬',
|
|
@@ -265,12 +270,12 @@ function mcpCommands(program) {
|
|
|
265
270
|
.argument('<tool>', 'Tool name to call')
|
|
266
271
|
.option('-a, --args <json>', 'Tool arguments as JSON')
|
|
267
272
|
.action(async (toolName, options) => {
|
|
268
|
-
const spinner = (
|
|
273
|
+
const spinner = ora(`Calling tool: ${toolName}...`).start();
|
|
269
274
|
try {
|
|
270
|
-
const client =
|
|
275
|
+
const client = getMCPClient();
|
|
271
276
|
if (!client.isConnectedToServer()) {
|
|
272
277
|
spinner.info('Not connected. Attempting auto-connect...');
|
|
273
|
-
const config = new
|
|
278
|
+
const config = new CLIConfig();
|
|
274
279
|
const useRemote = !!config.get('token');
|
|
275
280
|
await client.connect({ useRemote });
|
|
276
281
|
}
|
|
@@ -286,7 +291,7 @@ function mcpCommands(program) {
|
|
|
286
291
|
}
|
|
287
292
|
const result = await client.callTool(toolName, args);
|
|
288
293
|
spinner.succeed(`Tool ${toolName} executed successfully`);
|
|
289
|
-
console.log(
|
|
294
|
+
console.log(chalk.cyan('\nš¤ Tool Result:'));
|
|
290
295
|
console.log(JSON.stringify(result, null, 2));
|
|
291
296
|
}
|
|
292
297
|
catch (error) {
|
|
@@ -304,12 +309,12 @@ function mcpCommands(program) {
|
|
|
304
309
|
.option('-T, --type <type>', 'Memory type', 'context')
|
|
305
310
|
.option('--tags <tags>', 'Comma-separated tags')
|
|
306
311
|
.action(async (options) => {
|
|
307
|
-
const spinner = (
|
|
312
|
+
const spinner = ora('Creating memory via MCP...').start();
|
|
308
313
|
try {
|
|
309
|
-
const client =
|
|
314
|
+
const client = getMCPClient();
|
|
310
315
|
if (!client.isConnectedToServer()) {
|
|
311
316
|
spinner.info('Not connected. Attempting auto-connect...');
|
|
312
|
-
const config = new
|
|
317
|
+
const config = new CLIConfig();
|
|
313
318
|
const useRemote = !!config.get('token');
|
|
314
319
|
await client.connect({ useRemote });
|
|
315
320
|
}
|
|
@@ -320,8 +325,8 @@ function mcpCommands(program) {
|
|
|
320
325
|
tags: options.tags ? options.tags.split(',').map((t) => t.trim()) : []
|
|
321
326
|
});
|
|
322
327
|
spinner.succeed('Memory created successfully');
|
|
323
|
-
console.log(
|
|
324
|
-
console.log(`ID: ${
|
|
328
|
+
console.log(chalk.green('\nā Memory created'));
|
|
329
|
+
console.log(`ID: ${chalk.cyan(result.id)}`);
|
|
325
330
|
console.log(`Title: ${result.title}`);
|
|
326
331
|
console.log(`Type: ${result.memory_type}`);
|
|
327
332
|
}
|
|
@@ -336,12 +341,12 @@ function mcpCommands(program) {
|
|
|
336
341
|
.option('-l, --limit <number>', 'Maximum results', '10')
|
|
337
342
|
.option('-t, --threshold <number>', 'Similarity threshold (0-1)', '0.7')
|
|
338
343
|
.action(async (query, options) => {
|
|
339
|
-
const spinner = (
|
|
344
|
+
const spinner = ora('Searching memories via MCP...').start();
|
|
340
345
|
try {
|
|
341
|
-
const client =
|
|
346
|
+
const client = getMCPClient();
|
|
342
347
|
if (!client.isConnectedToServer()) {
|
|
343
348
|
spinner.info('Not connected. Attempting auto-connect...');
|
|
344
|
-
const config = new
|
|
349
|
+
const config = new CLIConfig();
|
|
345
350
|
const useRemote = !!config.get('token');
|
|
346
351
|
await client.connect({ useRemote });
|
|
347
352
|
}
|
|
@@ -352,15 +357,15 @@ function mcpCommands(program) {
|
|
|
352
357
|
});
|
|
353
358
|
spinner.succeed(`Found ${results.length} memories`);
|
|
354
359
|
if (results.length === 0) {
|
|
355
|
-
console.log(
|
|
360
|
+
console.log(chalk.yellow('\nNo memories found matching your query'));
|
|
356
361
|
return;
|
|
357
362
|
}
|
|
358
|
-
console.log(
|
|
363
|
+
console.log(chalk.cyan('\nš Search Results:'));
|
|
359
364
|
results.forEach((memory, index) => {
|
|
360
|
-
console.log(`\n${
|
|
361
|
-
console.log(` ID: ${
|
|
362
|
-
console.log(` Type: ${
|
|
363
|
-
console.log(` Score: ${
|
|
365
|
+
console.log(`\n${chalk.bold(`${index + 1}. ${memory.title}`)}`);
|
|
366
|
+
console.log(` ID: ${chalk.gray(memory.id)}`);
|
|
367
|
+
console.log(` Type: ${chalk.blue(memory.memory_type)}`);
|
|
368
|
+
console.log(` Score: ${chalk.green((memory.relevance_score * 100).toFixed(1) + '%')}`);
|
|
364
369
|
console.log(` Content: ${memory.content.substring(0, 100)}...`);
|
|
365
370
|
});
|
|
366
371
|
}
|
|
@@ -372,30 +377,36 @@ function mcpCommands(program) {
|
|
|
372
377
|
// Configure MCP preferences
|
|
373
378
|
mcp.command('config')
|
|
374
379
|
.description('Configure MCP preferences')
|
|
375
|
-
.option('--prefer-
|
|
376
|
-
.option('--prefer-
|
|
380
|
+
.option('--prefer-websocket', 'Prefer WebSocket MCP connection (recommended for production)')
|
|
381
|
+
.option('--prefer-remote', 'Prefer remote MCP server (REST/SSE mode)')
|
|
382
|
+
.option('--prefer-local', 'Prefer local MCP server (development only)')
|
|
377
383
|
.option('--auto', 'Auto-detect best connection mode')
|
|
378
384
|
.action(async (options) => {
|
|
379
|
-
const config = new
|
|
380
|
-
if (options.
|
|
385
|
+
const config = new CLIConfig();
|
|
386
|
+
if (options.preferWebsocket) {
|
|
387
|
+
await config.setAndSave('mcpPreference', 'websocket');
|
|
388
|
+
console.log(chalk.green('ā Set MCP preference to WebSocket (production mode)'));
|
|
389
|
+
}
|
|
390
|
+
else if (options.preferRemote) {
|
|
381
391
|
await config.setAndSave('mcpPreference', 'remote');
|
|
382
|
-
console.log(
|
|
392
|
+
console.log(chalk.green('ā Set MCP preference to remote (REST/SSE mode)'));
|
|
383
393
|
}
|
|
384
394
|
else if (options.preferLocal) {
|
|
385
395
|
await config.setAndSave('mcpPreference', 'local');
|
|
386
|
-
console.log(
|
|
396
|
+
console.log(chalk.green('ā Set MCP preference to local (development only)'));
|
|
387
397
|
}
|
|
388
398
|
else if (options.auto) {
|
|
389
399
|
await config.setAndSave('mcpPreference', 'auto');
|
|
390
|
-
console.log(
|
|
400
|
+
console.log(chalk.green('ā Set MCP preference to auto-detect'));
|
|
391
401
|
}
|
|
392
402
|
else {
|
|
393
403
|
const current = config.get('mcpPreference') || 'auto';
|
|
394
|
-
console.log(`Current MCP preference: ${
|
|
404
|
+
console.log(`Current MCP preference: ${chalk.cyan(current)}`);
|
|
395
405
|
console.log('\nOptions:');
|
|
396
|
-
console.log(' --prefer-
|
|
397
|
-
console.log(' --prefer-
|
|
398
|
-
console.log(' --
|
|
406
|
+
console.log(' --prefer-websocket : Use WebSocket mode (recommended for production)');
|
|
407
|
+
console.log(' --prefer-remote : Use remote REST/SSE mode (alternative)');
|
|
408
|
+
console.log(' --prefer-local : Use local stdio mode (development only)');
|
|
409
|
+
console.log(' --auto : Auto-detect based on configuration (default)');
|
|
399
410
|
}
|
|
400
411
|
});
|
|
401
412
|
// Diagnose MCP connection issues
|
|
@@ -403,10 +414,10 @@ function mcpCommands(program) {
|
|
|
403
414
|
.description('Diagnose MCP connection issues')
|
|
404
415
|
.option('-v, --verbose', 'show detailed diagnostic information')
|
|
405
416
|
.action(async (options) => {
|
|
406
|
-
const config = new
|
|
417
|
+
const config = new CLIConfig();
|
|
407
418
|
await config.init();
|
|
408
|
-
console.log(
|
|
409
|
-
console.log(
|
|
419
|
+
console.log(chalk.blue.bold('š MCP Connection Diagnostic'));
|
|
420
|
+
console.log(chalk.cyan('ā'.repeat(50)));
|
|
410
421
|
console.log();
|
|
411
422
|
const diagnostics = {
|
|
412
423
|
authenticationValid: false,
|
|
@@ -422,64 +433,64 @@ function mcpCommands(program) {
|
|
|
422
433
|
healthCheckPassing: false
|
|
423
434
|
};
|
|
424
435
|
// Step 1: Check authentication status
|
|
425
|
-
console.log(
|
|
436
|
+
console.log(chalk.cyan('1. Authentication Status'));
|
|
426
437
|
const token = config.getToken();
|
|
427
438
|
const vendorKey = config.getVendorKey();
|
|
428
439
|
if (!token && !vendorKey) {
|
|
429
|
-
console.log(
|
|
430
|
-
console.log(
|
|
431
|
-
console.log(
|
|
440
|
+
console.log(chalk.red(' ā No authentication credentials found'));
|
|
441
|
+
console.log(chalk.gray(' ā Run: lanonasis auth login'));
|
|
442
|
+
console.log(chalk.gray(' ā MCP requires authentication for remote access'));
|
|
432
443
|
}
|
|
433
444
|
else {
|
|
434
445
|
try {
|
|
435
446
|
const isValid = await config.validateStoredCredentials();
|
|
436
447
|
diagnostics.authenticationValid = isValid;
|
|
437
448
|
if (isValid) {
|
|
438
|
-
console.log(
|
|
449
|
+
console.log(chalk.green(' ā Authentication credentials are valid'));
|
|
439
450
|
}
|
|
440
451
|
else {
|
|
441
|
-
console.log(
|
|
442
|
-
console.log(
|
|
452
|
+
console.log(chalk.red(' ā Authentication credentials are invalid'));
|
|
453
|
+
console.log(chalk.gray(' ā Run: lanonasis auth login'));
|
|
443
454
|
}
|
|
444
455
|
}
|
|
445
456
|
catch (error) {
|
|
446
|
-
console.log(
|
|
447
|
-
console.log(
|
|
457
|
+
console.log(chalk.yellow(' ā Could not validate authentication'));
|
|
458
|
+
console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
448
459
|
}
|
|
449
460
|
}
|
|
450
461
|
// Step 2: Test endpoint availability
|
|
451
|
-
console.log(
|
|
452
|
-
const spinner1 = (
|
|
462
|
+
console.log(chalk.cyan('\n2. Endpoint Availability'));
|
|
463
|
+
const spinner1 = ora('Testing MCP endpoints...').start();
|
|
453
464
|
try {
|
|
454
465
|
await config.discoverServices(options.verbose);
|
|
455
466
|
const services = config.get('discoveredServices');
|
|
456
467
|
if (services) {
|
|
457
468
|
spinner1.succeed('MCP endpoints discovered');
|
|
458
469
|
diagnostics.endpointsReachable = true;
|
|
459
|
-
console.log(
|
|
470
|
+
console.log(chalk.green(' ā Service discovery successful'));
|
|
460
471
|
if (options.verbose) {
|
|
461
472
|
const svc = services;
|
|
462
|
-
console.log(
|
|
463
|
-
console.log(
|
|
464
|
-
console.log(
|
|
473
|
+
console.log(chalk.gray(` HTTP: ${svc.mcp_base}`));
|
|
474
|
+
console.log(chalk.gray(` WebSocket: ${svc.mcp_ws_base}`));
|
|
475
|
+
console.log(chalk.gray(` SSE: ${svc.mcp_sse_base}`));
|
|
465
476
|
}
|
|
466
477
|
}
|
|
467
478
|
else {
|
|
468
479
|
spinner1.warn('Using fallback endpoints');
|
|
469
|
-
console.log(
|
|
480
|
+
console.log(chalk.yellow(' ā Service discovery failed, using fallbacks'));
|
|
470
481
|
diagnostics.endpointsReachable = true; // Fallbacks still work
|
|
471
482
|
}
|
|
472
483
|
}
|
|
473
484
|
catch (error) {
|
|
474
485
|
spinner1.fail('Endpoint discovery failed');
|
|
475
|
-
console.log(
|
|
476
|
-
console.log(
|
|
486
|
+
console.log(chalk.red(' ā Cannot discover MCP endpoints'));
|
|
487
|
+
console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
477
488
|
}
|
|
478
489
|
// Step 3: Test transport protocols
|
|
479
|
-
console.log(
|
|
490
|
+
console.log(chalk.cyan('\n3. Transport Protocol Tests'));
|
|
480
491
|
// Test HTTP/REST endpoint
|
|
481
492
|
if (diagnostics.authenticationValid) {
|
|
482
|
-
const httpSpinner = (
|
|
493
|
+
const httpSpinner = ora('Testing HTTP transport...').start();
|
|
483
494
|
try {
|
|
484
495
|
const startTime = Date.now();
|
|
485
496
|
const axios = (await import('axios')).default;
|
|
@@ -495,22 +506,22 @@ function mcpCommands(program) {
|
|
|
495
506
|
diagnostics.connectionLatency.http = latency;
|
|
496
507
|
diagnostics.transportTests.http = true;
|
|
497
508
|
httpSpinner.succeed(`HTTP transport working (${latency}ms)`);
|
|
498
|
-
console.log(
|
|
509
|
+
console.log(chalk.green(` ā HTTP/REST endpoint reachable`));
|
|
499
510
|
}
|
|
500
511
|
catch (error) {
|
|
501
512
|
httpSpinner.fail('HTTP transport failed');
|
|
502
|
-
console.log(
|
|
513
|
+
console.log(chalk.red(' ā HTTP/REST endpoint failed'));
|
|
503
514
|
if (options.verbose) {
|
|
504
|
-
console.log(
|
|
515
|
+
console.log(chalk.gray(` Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
505
516
|
}
|
|
506
517
|
}
|
|
507
518
|
// Test WebSocket endpoint
|
|
508
|
-
const wsSpinner = (
|
|
519
|
+
const wsSpinner = ora('Testing WebSocket transport...').start();
|
|
509
520
|
try {
|
|
510
521
|
const startTime = Date.now();
|
|
511
522
|
const wsUrl = config.getMCPServerUrl();
|
|
512
523
|
// Create a test WebSocket connection
|
|
513
|
-
const ws = new
|
|
524
|
+
const ws = new WebSocket(wsUrl, [], {
|
|
514
525
|
headers: {
|
|
515
526
|
'Authorization': `Bearer ${token}`,
|
|
516
527
|
'X-API-Key': String(token || vendorKey)
|
|
@@ -535,17 +546,17 @@ function mcpCommands(program) {
|
|
|
535
546
|
});
|
|
536
547
|
});
|
|
537
548
|
wsSpinner.succeed(`WebSocket transport working (${diagnostics.connectionLatency.websocket}ms)`);
|
|
538
|
-
console.log(
|
|
549
|
+
console.log(chalk.green(' ā WebSocket endpoint reachable'));
|
|
539
550
|
}
|
|
540
551
|
catch (error) {
|
|
541
552
|
wsSpinner.fail('WebSocket transport failed');
|
|
542
|
-
console.log(
|
|
553
|
+
console.log(chalk.red(' ā WebSocket endpoint failed'));
|
|
543
554
|
if (options.verbose) {
|
|
544
|
-
console.log(
|
|
555
|
+
console.log(chalk.gray(` Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
545
556
|
}
|
|
546
557
|
}
|
|
547
558
|
// Test SSE endpoint
|
|
548
|
-
const sseSpinner = (
|
|
559
|
+
const sseSpinner = ora('Testing SSE transport...').start();
|
|
549
560
|
try {
|
|
550
561
|
const startTime = Date.now();
|
|
551
562
|
const sseUrl = config.getMCPSSEUrl();
|
|
@@ -562,86 +573,86 @@ function mcpCommands(program) {
|
|
|
562
573
|
diagnostics.connectionLatency.sse = latency;
|
|
563
574
|
diagnostics.transportTests.sse = true;
|
|
564
575
|
sseSpinner.succeed(`SSE transport working (${latency}ms)`);
|
|
565
|
-
console.log(
|
|
576
|
+
console.log(chalk.green(' ā SSE endpoint reachable'));
|
|
566
577
|
}
|
|
567
578
|
catch (error) {
|
|
568
579
|
sseSpinner.fail('SSE transport failed');
|
|
569
|
-
console.log(
|
|
580
|
+
console.log(chalk.red(' ā SSE endpoint failed'));
|
|
570
581
|
if (options.verbose) {
|
|
571
|
-
console.log(
|
|
582
|
+
console.log(chalk.gray(` Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
572
583
|
}
|
|
573
584
|
}
|
|
574
585
|
}
|
|
575
586
|
else {
|
|
576
|
-
console.log(
|
|
587
|
+
console.log(chalk.gray(' - Skipped transport tests (authentication required)'));
|
|
577
588
|
}
|
|
578
589
|
// Step 4: Test current MCP connection
|
|
579
|
-
console.log(
|
|
580
|
-
const client =
|
|
590
|
+
console.log(chalk.cyan('\n4. Current MCP Connection'));
|
|
591
|
+
const client = getMCPClient();
|
|
581
592
|
diagnostics.currentConnection = client.getConnectionStatus();
|
|
582
593
|
if (diagnostics.currentConnection.connected) {
|
|
583
|
-
console.log(
|
|
584
|
-
console.log(
|
|
585
|
-
console.log(
|
|
594
|
+
console.log(chalk.green(' ā MCP client is connected'));
|
|
595
|
+
console.log(chalk.gray(` Mode: ${diagnostics.currentConnection.mode}`));
|
|
596
|
+
console.log(chalk.gray(` Server: ${diagnostics.currentConnection.server}`));
|
|
586
597
|
if (diagnostics.currentConnection.connectionUptime) {
|
|
587
598
|
const uptimeSeconds = Math.floor(diagnostics.currentConnection.connectionUptime / 1000);
|
|
588
|
-
console.log(
|
|
599
|
+
console.log(chalk.gray(` Uptime: ${uptimeSeconds}s`));
|
|
589
600
|
}
|
|
590
601
|
if (diagnostics.currentConnection.lastHealthCheck) {
|
|
591
602
|
const healthCheckAge = Date.now() - diagnostics.currentConnection.lastHealthCheck.getTime();
|
|
592
|
-
console.log(
|
|
603
|
+
console.log(chalk.gray(` Last health check: ${Math.floor(healthCheckAge / 1000)}s ago`));
|
|
593
604
|
}
|
|
594
605
|
}
|
|
595
606
|
else {
|
|
596
|
-
console.log(
|
|
597
|
-
console.log(
|
|
607
|
+
console.log(chalk.red(' ā MCP client is not connected'));
|
|
608
|
+
console.log(chalk.gray(' ā Try: lanonasis mcp connect'));
|
|
598
609
|
}
|
|
599
610
|
// Step 5: Test tool availability
|
|
600
|
-
console.log(
|
|
611
|
+
console.log(chalk.cyan('\n5. Tool Availability'));
|
|
601
612
|
if (diagnostics.currentConnection.connected) {
|
|
602
|
-
const toolSpinner = (
|
|
613
|
+
const toolSpinner = ora('Testing MCP tools...').start();
|
|
603
614
|
try {
|
|
604
615
|
const tools = await client.listTools();
|
|
605
616
|
diagnostics.toolsAvailable = tools.length > 0;
|
|
606
617
|
toolSpinner.succeed(`Found ${tools.length} available tools`);
|
|
607
|
-
console.log(
|
|
618
|
+
console.log(chalk.green(` ā ${tools.length} MCP tools available`));
|
|
608
619
|
if (options.verbose && tools.length > 0) {
|
|
609
|
-
console.log(
|
|
620
|
+
console.log(chalk.gray(' Available tools:'));
|
|
610
621
|
tools.slice(0, 5).forEach(tool => {
|
|
611
|
-
console.log(
|
|
622
|
+
console.log(chalk.gray(` ⢠${tool.name}`));
|
|
612
623
|
});
|
|
613
624
|
if (tools.length > 5) {
|
|
614
|
-
console.log(
|
|
625
|
+
console.log(chalk.gray(` ... and ${tools.length - 5} more`));
|
|
615
626
|
}
|
|
616
627
|
}
|
|
617
628
|
}
|
|
618
629
|
catch (error) {
|
|
619
630
|
toolSpinner.fail('Tool listing failed');
|
|
620
|
-
console.log(
|
|
631
|
+
console.log(chalk.red(' ā Cannot list MCP tools'));
|
|
621
632
|
if (options.verbose) {
|
|
622
|
-
console.log(
|
|
633
|
+
console.log(chalk.gray(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
623
634
|
}
|
|
624
635
|
}
|
|
625
636
|
}
|
|
626
637
|
else {
|
|
627
|
-
console.log(
|
|
638
|
+
console.log(chalk.gray(' - Skipped (not connected to MCP server)'));
|
|
628
639
|
}
|
|
629
640
|
// Step 6: Connection quality measurement
|
|
630
|
-
console.log(
|
|
641
|
+
console.log(chalk.cyan('\n6. Connection Quality'));
|
|
631
642
|
if (Object.keys(diagnostics.connectionLatency).length > 0) {
|
|
632
|
-
console.log(
|
|
643
|
+
console.log(chalk.green(' ā Latency measurements:'));
|
|
633
644
|
Object.entries(diagnostics.connectionLatency).forEach(([transport, latency]) => {
|
|
634
645
|
const quality = latency < 100 ? 'Excellent' : latency < 300 ? 'Good' : latency < 1000 ? 'Fair' : 'Poor';
|
|
635
|
-
const color = latency < 100 ?
|
|
646
|
+
const color = latency < 100 ? chalk.green : latency < 300 ? chalk.yellow : chalk.red;
|
|
636
647
|
console.log(color(` ${transport.toUpperCase()}: ${latency}ms (${quality})`));
|
|
637
648
|
});
|
|
638
649
|
}
|
|
639
650
|
else {
|
|
640
|
-
console.log(
|
|
651
|
+
console.log(chalk.gray(' - No latency measurements available'));
|
|
641
652
|
}
|
|
642
653
|
// Summary and recommendations
|
|
643
|
-
console.log(
|
|
644
|
-
console.log(
|
|
654
|
+
console.log(chalk.blue.bold('\nš MCP Diagnostic Summary'));
|
|
655
|
+
console.log(chalk.cyan('ā'.repeat(50)));
|
|
645
656
|
const issues = [];
|
|
646
657
|
const recommendations = [];
|
|
647
658
|
if (!diagnostics.authenticationValid) {
|
|
@@ -671,30 +682,30 @@ function mcpCommands(program) {
|
|
|
671
682
|
}
|
|
672
683
|
// Show results
|
|
673
684
|
if (issues.length === 0) {
|
|
674
|
-
console.log(
|
|
675
|
-
console.log(
|
|
685
|
+
console.log(chalk.green('ā
All MCP connection checks passed!'));
|
|
686
|
+
console.log(chalk.cyan(' Your MCP connection is working correctly.'));
|
|
676
687
|
if (Object.keys(diagnostics.connectionLatency).length > 0) {
|
|
677
688
|
const avgLatency = Object.values(diagnostics.connectionLatency).reduce((a, b) => a + b, 0) / Object.values(diagnostics.connectionLatency).length;
|
|
678
|
-
console.log(
|
|
689
|
+
console.log(chalk.cyan(` Average latency: ${Math.round(avgLatency)}ms`));
|
|
679
690
|
}
|
|
680
691
|
}
|
|
681
692
|
else {
|
|
682
|
-
console.log(
|
|
693
|
+
console.log(chalk.red(`ā Found ${issues.length} issue(s):`));
|
|
683
694
|
issues.forEach(issue => {
|
|
684
|
-
console.log(
|
|
695
|
+
console.log(chalk.red(` ⢠${issue}`));
|
|
685
696
|
});
|
|
686
|
-
console.log(
|
|
697
|
+
console.log(chalk.yellow('\nš” Recommended actions:'));
|
|
687
698
|
recommendations.forEach(rec => {
|
|
688
|
-
console.log(
|
|
699
|
+
console.log(chalk.cyan(` ⢠${rec}`));
|
|
689
700
|
});
|
|
690
701
|
}
|
|
691
702
|
// Additional troubleshooting info
|
|
692
703
|
if (issues.length > 0) {
|
|
693
|
-
console.log(
|
|
694
|
-
console.log(
|
|
695
|
-
console.log(
|
|
696
|
-
console.log(
|
|
697
|
-
console.log(
|
|
704
|
+
console.log(chalk.gray('\nš§ Additional troubleshooting:'));
|
|
705
|
+
console.log(chalk.gray(' ⢠Try different connection modes: --mode websocket|remote|local'));
|
|
706
|
+
console.log(chalk.gray(' ⢠Check firewall settings for ports 80, 443, and WebSocket'));
|
|
707
|
+
console.log(chalk.gray(' ⢠Verify your network allows outbound HTTPS connections'));
|
|
708
|
+
console.log(chalk.gray(' ⢠Contact support if issues persist'));
|
|
698
709
|
}
|
|
699
710
|
});
|
|
700
711
|
}
|