@lanonasis/cli 3.0.13 → 3.2.14
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/__tests__/auth-persistence.test.d.ts +1 -0
- package/dist/__tests__/auth-persistence.test.js +243 -0
- package/dist/__tests__/cross-device-integration.test.d.ts +1 -0
- package/dist/__tests__/cross-device-integration.test.js +305 -0
- package/dist/__tests__/mcp-connection-reliability.test.d.ts +1 -0
- package/dist/__tests__/mcp-connection-reliability.test.js +489 -0
- package/dist/__tests__/setup.d.ts +1 -0
- package/dist/__tests__/setup.js +26 -0
- package/dist/commands/api-keys.js +12 -6
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +445 -19
- package/dist/commands/config.js +519 -1
- package/dist/commands/mcp.js +299 -0
- package/dist/index-simple.js +30 -0
- package/dist/index.js +35 -1
- package/dist/mcp/schemas/tool-schemas.d.ts +4 -4
- package/dist/mcp/server/lanonasis-server.d.ts +161 -6
- package/dist/mcp/server/lanonasis-server.js +813 -17
- package/dist/mcp/server/mcp/server/lanonasis-server.js +911 -0
- package/dist/mcp/server/utils/api.js +431 -0
- package/dist/mcp/server/utils/config.js +855 -0
- package/dist/utils/config.d.ts +57 -1
- package/dist/utils/config.js +530 -42
- package/dist/utils/mcp-client.d.ts +83 -2
- package/dist/utils/mcp-client.js +414 -15
- package/package.json +8 -4
package/dist/commands/mcp.js
CHANGED
|
@@ -355,4 +355,303 @@ export function mcpCommands(program) {
|
|
|
355
355
|
console.log(' --auto : Auto-detect based on authentication');
|
|
356
356
|
}
|
|
357
357
|
});
|
|
358
|
+
// Diagnose MCP connection issues
|
|
359
|
+
mcp.command('diagnose')
|
|
360
|
+
.description('Diagnose MCP connection issues')
|
|
361
|
+
.option('-v, --verbose', 'show detailed diagnostic information')
|
|
362
|
+
.action(async (options) => {
|
|
363
|
+
const config = new CLIConfig();
|
|
364
|
+
await config.init();
|
|
365
|
+
console.log(chalk.blue.bold('🔍 MCP Connection Diagnostic'));
|
|
366
|
+
console.log(chalk.cyan('━'.repeat(50)));
|
|
367
|
+
console.log();
|
|
368
|
+
const diagnostics = {
|
|
369
|
+
authenticationValid: false,
|
|
370
|
+
endpointsReachable: false,
|
|
371
|
+
transportTests: {
|
|
372
|
+
websocket: false,
|
|
373
|
+
http: false,
|
|
374
|
+
sse: false
|
|
375
|
+
},
|
|
376
|
+
connectionLatency: {},
|
|
377
|
+
currentConnection: null,
|
|
378
|
+
toolsAvailable: false,
|
|
379
|
+
healthCheckPassing: false
|
|
380
|
+
};
|
|
381
|
+
// Step 1: Check authentication status
|
|
382
|
+
console.log(chalk.cyan('1. Authentication Status'));
|
|
383
|
+
const token = config.getToken();
|
|
384
|
+
const vendorKey = config.getVendorKey();
|
|
385
|
+
if (!token && !vendorKey) {
|
|
386
|
+
console.log(chalk.red(' ✖ No authentication credentials found'));
|
|
387
|
+
console.log(chalk.gray(' → Run: lanonasis auth login'));
|
|
388
|
+
console.log(chalk.gray(' → MCP requires authentication for remote access'));
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
try {
|
|
392
|
+
const isValid = await config.validateStoredCredentials();
|
|
393
|
+
diagnostics.authenticationValid = isValid;
|
|
394
|
+
if (isValid) {
|
|
395
|
+
console.log(chalk.green(' ✓ Authentication credentials are valid'));
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
console.log(chalk.red(' ✖ Authentication credentials are invalid'));
|
|
399
|
+
console.log(chalk.gray(' → Run: lanonasis auth login'));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.log(chalk.yellow(' ⚠ Could not validate authentication'));
|
|
404
|
+
console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// Step 2: Test endpoint availability
|
|
408
|
+
console.log(chalk.cyan('\n2. Endpoint Availability'));
|
|
409
|
+
const spinner1 = ora('Testing MCP endpoints...').start();
|
|
410
|
+
try {
|
|
411
|
+
await config.discoverServices(options.verbose);
|
|
412
|
+
const services = config.get('discoveredServices');
|
|
413
|
+
if (services) {
|
|
414
|
+
spinner1.succeed('MCP endpoints discovered');
|
|
415
|
+
diagnostics.endpointsReachable = true;
|
|
416
|
+
console.log(chalk.green(' ✓ Service discovery successful'));
|
|
417
|
+
if (options.verbose) {
|
|
418
|
+
console.log(chalk.gray(` HTTP: ${services.mcp_base}`));
|
|
419
|
+
console.log(chalk.gray(` WebSocket: ${services.mcp_ws_base}`));
|
|
420
|
+
console.log(chalk.gray(` SSE: ${services.mcp_sse_base}`));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
spinner1.warn('Using fallback endpoints');
|
|
425
|
+
console.log(chalk.yellow(' ⚠ Service discovery failed, using fallbacks'));
|
|
426
|
+
diagnostics.endpointsReachable = true; // Fallbacks still work
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
spinner1.fail('Endpoint discovery failed');
|
|
431
|
+
console.log(chalk.red(' ✖ Cannot discover MCP endpoints'));
|
|
432
|
+
console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
433
|
+
}
|
|
434
|
+
// Step 3: Test transport protocols
|
|
435
|
+
console.log(chalk.cyan('\n3. Transport Protocol Tests'));
|
|
436
|
+
// Test HTTP/REST endpoint
|
|
437
|
+
if (diagnostics.authenticationValid) {
|
|
438
|
+
const httpSpinner = ora('Testing HTTP transport...').start();
|
|
439
|
+
try {
|
|
440
|
+
const startTime = Date.now();
|
|
441
|
+
const axios = (await import('axios')).default;
|
|
442
|
+
const httpUrl = config.getMCPRestUrl();
|
|
443
|
+
await axios.get(`${httpUrl}/health`, {
|
|
444
|
+
headers: {
|
|
445
|
+
'Authorization': `Bearer ${token}`,
|
|
446
|
+
'x-api-key': String(token || vendorKey)
|
|
447
|
+
},
|
|
448
|
+
timeout: 10000
|
|
449
|
+
});
|
|
450
|
+
const latency = Date.now() - startTime;
|
|
451
|
+
diagnostics.connectionLatency.http = latency;
|
|
452
|
+
diagnostics.transportTests.http = true;
|
|
453
|
+
httpSpinner.succeed(`HTTP transport working (${latency}ms)`);
|
|
454
|
+
console.log(chalk.green(` ✓ HTTP/REST endpoint reachable`));
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
httpSpinner.fail('HTTP transport failed');
|
|
458
|
+
console.log(chalk.red(' ✖ HTTP/REST endpoint failed'));
|
|
459
|
+
if (options.verbose) {
|
|
460
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
// Test WebSocket endpoint
|
|
464
|
+
const wsSpinner = ora('Testing WebSocket transport...').start();
|
|
465
|
+
try {
|
|
466
|
+
const startTime = Date.now();
|
|
467
|
+
const wsUrl = config.getMCPServerUrl();
|
|
468
|
+
// Create a test WebSocket connection
|
|
469
|
+
const WebSocket = (await import('ws'));
|
|
470
|
+
const ws = new WebSocket(wsUrl, [], {
|
|
471
|
+
headers: {
|
|
472
|
+
'Authorization': `Bearer ${token}`,
|
|
473
|
+
'X-API-Key': String(token || vendorKey)
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
await new Promise((resolve, reject) => {
|
|
477
|
+
const timeout = setTimeout(() => {
|
|
478
|
+
ws.close();
|
|
479
|
+
reject(new Error('WebSocket connection timeout'));
|
|
480
|
+
}, 10000);
|
|
481
|
+
ws.on('open', () => {
|
|
482
|
+
clearTimeout(timeout);
|
|
483
|
+
const latency = Date.now() - startTime;
|
|
484
|
+
diagnostics.connectionLatency.websocket = latency;
|
|
485
|
+
diagnostics.transportTests.websocket = true;
|
|
486
|
+
ws.close();
|
|
487
|
+
resolve(true);
|
|
488
|
+
});
|
|
489
|
+
ws.on('error', (error) => {
|
|
490
|
+
clearTimeout(timeout);
|
|
491
|
+
reject(error);
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
wsSpinner.succeed(`WebSocket transport working (${diagnostics.connectionLatency.websocket}ms)`);
|
|
495
|
+
console.log(chalk.green(' ✓ WebSocket endpoint reachable'));
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
wsSpinner.fail('WebSocket transport failed');
|
|
499
|
+
console.log(chalk.red(' ✖ WebSocket endpoint failed'));
|
|
500
|
+
if (options.verbose) {
|
|
501
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Test SSE endpoint
|
|
505
|
+
const sseSpinner = ora('Testing SSE transport...').start();
|
|
506
|
+
try {
|
|
507
|
+
const startTime = Date.now();
|
|
508
|
+
const sseUrl = config.getMCPSSEUrl();
|
|
509
|
+
// Test SSE endpoint with a quick connection test
|
|
510
|
+
const axios = (await import('axios')).default;
|
|
511
|
+
await axios.get(sseUrl.replace('/events', '/health'), {
|
|
512
|
+
headers: {
|
|
513
|
+
'Authorization': `Bearer ${token}`,
|
|
514
|
+
'x-api-key': String(token || vendorKey)
|
|
515
|
+
},
|
|
516
|
+
timeout: 10000
|
|
517
|
+
});
|
|
518
|
+
const latency = Date.now() - startTime;
|
|
519
|
+
diagnostics.connectionLatency.sse = latency;
|
|
520
|
+
diagnostics.transportTests.sse = true;
|
|
521
|
+
sseSpinner.succeed(`SSE transport working (${latency}ms)`);
|
|
522
|
+
console.log(chalk.green(' ✓ SSE endpoint reachable'));
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
sseSpinner.fail('SSE transport failed');
|
|
526
|
+
console.log(chalk.red(' ✖ SSE endpoint failed'));
|
|
527
|
+
if (options.verbose) {
|
|
528
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
console.log(chalk.gray(' - Skipped transport tests (authentication required)'));
|
|
534
|
+
}
|
|
535
|
+
// Step 4: Test current MCP connection
|
|
536
|
+
console.log(chalk.cyan('\n4. Current MCP Connection'));
|
|
537
|
+
const client = getMCPClient();
|
|
538
|
+
diagnostics.currentConnection = client.getConnectionStatus();
|
|
539
|
+
if (diagnostics.currentConnection.connected) {
|
|
540
|
+
console.log(chalk.green(' ✓ MCP client is connected'));
|
|
541
|
+
console.log(chalk.gray(` Mode: ${diagnostics.currentConnection.mode}`));
|
|
542
|
+
console.log(chalk.gray(` Server: ${diagnostics.currentConnection.server}`));
|
|
543
|
+
if (diagnostics.currentConnection.connectionUptime) {
|
|
544
|
+
const uptimeSeconds = Math.floor(diagnostics.currentConnection.connectionUptime / 1000);
|
|
545
|
+
console.log(chalk.gray(` Uptime: ${uptimeSeconds}s`));
|
|
546
|
+
}
|
|
547
|
+
if (diagnostics.currentConnection.lastHealthCheck) {
|
|
548
|
+
const healthCheckAge = Date.now() - diagnostics.currentConnection.lastHealthCheck.getTime();
|
|
549
|
+
console.log(chalk.gray(` Last health check: ${Math.floor(healthCheckAge / 1000)}s ago`));
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
console.log(chalk.red(' ✖ MCP client is not connected'));
|
|
554
|
+
console.log(chalk.gray(' → Try: lanonasis mcp connect'));
|
|
555
|
+
}
|
|
556
|
+
// Step 5: Test tool availability
|
|
557
|
+
console.log(chalk.cyan('\n5. Tool Availability'));
|
|
558
|
+
if (diagnostics.currentConnection.connected) {
|
|
559
|
+
const toolSpinner = ora('Testing MCP tools...').start();
|
|
560
|
+
try {
|
|
561
|
+
const tools = await client.listTools();
|
|
562
|
+
diagnostics.toolsAvailable = tools.length > 0;
|
|
563
|
+
toolSpinner.succeed(`Found ${tools.length} available tools`);
|
|
564
|
+
console.log(chalk.green(` ✓ ${tools.length} MCP tools available`));
|
|
565
|
+
if (options.verbose && tools.length > 0) {
|
|
566
|
+
console.log(chalk.gray(' Available tools:'));
|
|
567
|
+
tools.slice(0, 5).forEach(tool => {
|
|
568
|
+
console.log(chalk.gray(` • ${tool.name}`));
|
|
569
|
+
});
|
|
570
|
+
if (tools.length > 5) {
|
|
571
|
+
console.log(chalk.gray(` ... and ${tools.length - 5} more`));
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
catch (error) {
|
|
576
|
+
toolSpinner.fail('Tool listing failed');
|
|
577
|
+
console.log(chalk.red(' ✖ Cannot list MCP tools'));
|
|
578
|
+
if (options.verbose) {
|
|
579
|
+
console.log(chalk.gray(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
console.log(chalk.gray(' - Skipped (not connected to MCP server)'));
|
|
585
|
+
}
|
|
586
|
+
// Step 6: Connection quality measurement
|
|
587
|
+
console.log(chalk.cyan('\n6. Connection Quality'));
|
|
588
|
+
if (Object.keys(diagnostics.connectionLatency).length > 0) {
|
|
589
|
+
console.log(chalk.green(' ✓ Latency measurements:'));
|
|
590
|
+
Object.entries(diagnostics.connectionLatency).forEach(([transport, latency]) => {
|
|
591
|
+
const quality = latency < 100 ? 'Excellent' : latency < 300 ? 'Good' : latency < 1000 ? 'Fair' : 'Poor';
|
|
592
|
+
const color = latency < 100 ? chalk.green : latency < 300 ? chalk.yellow : chalk.red;
|
|
593
|
+
console.log(color(` ${transport.toUpperCase()}: ${latency}ms (${quality})`));
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
console.log(chalk.gray(' - No latency measurements available'));
|
|
598
|
+
}
|
|
599
|
+
// Summary and recommendations
|
|
600
|
+
console.log(chalk.blue.bold('\n📋 MCP Diagnostic Summary'));
|
|
601
|
+
console.log(chalk.cyan('━'.repeat(50)));
|
|
602
|
+
const issues = [];
|
|
603
|
+
const recommendations = [];
|
|
604
|
+
if (!diagnostics.authenticationValid) {
|
|
605
|
+
issues.push('Authentication credentials are invalid or missing');
|
|
606
|
+
recommendations.push('Run: lanonasis auth login');
|
|
607
|
+
}
|
|
608
|
+
if (!diagnostics.endpointsReachable) {
|
|
609
|
+
issues.push('MCP endpoints are not reachable');
|
|
610
|
+
recommendations.push('Check internet connection and firewall settings');
|
|
611
|
+
}
|
|
612
|
+
const workingTransports = Object.values(diagnostics.transportTests).filter(Boolean).length;
|
|
613
|
+
if (workingTransports === 0 && diagnostics.authenticationValid) {
|
|
614
|
+
issues.push('No transport protocols are working');
|
|
615
|
+
recommendations.push('Check network connectivity to mcp.lanonasis.com');
|
|
616
|
+
}
|
|
617
|
+
else if (workingTransports < 3 && diagnostics.authenticationValid) {
|
|
618
|
+
issues.push(`Only ${workingTransports}/3 transport protocols working`);
|
|
619
|
+
recommendations.push('Some MCP features may be limited');
|
|
620
|
+
}
|
|
621
|
+
if (!diagnostics.currentConnection.connected) {
|
|
622
|
+
issues.push('MCP client is not connected');
|
|
623
|
+
recommendations.push('Run: lanonasis mcp connect');
|
|
624
|
+
}
|
|
625
|
+
if (!diagnostics.toolsAvailable && diagnostics.currentConnection.connected) {
|
|
626
|
+
issues.push('No MCP tools are available');
|
|
627
|
+
recommendations.push('Check MCP server configuration');
|
|
628
|
+
}
|
|
629
|
+
// Show results
|
|
630
|
+
if (issues.length === 0) {
|
|
631
|
+
console.log(chalk.green('✅ All MCP connection checks passed!'));
|
|
632
|
+
console.log(chalk.cyan(' Your MCP connection is working correctly.'));
|
|
633
|
+
if (Object.keys(diagnostics.connectionLatency).length > 0) {
|
|
634
|
+
const avgLatency = Object.values(diagnostics.connectionLatency).reduce((a, b) => a + b, 0) / Object.values(diagnostics.connectionLatency).length;
|
|
635
|
+
console.log(chalk.cyan(` Average latency: ${Math.round(avgLatency)}ms`));
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
console.log(chalk.red(`❌ Found ${issues.length} issue(s):`));
|
|
640
|
+
issues.forEach(issue => {
|
|
641
|
+
console.log(chalk.red(` • ${issue}`));
|
|
642
|
+
});
|
|
643
|
+
console.log(chalk.yellow('\n💡 Recommended actions:'));
|
|
644
|
+
recommendations.forEach(rec => {
|
|
645
|
+
console.log(chalk.cyan(` • ${rec}`));
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
// Additional troubleshooting info
|
|
649
|
+
if (issues.length > 0) {
|
|
650
|
+
console.log(chalk.gray('\n🔧 Additional troubleshooting:'));
|
|
651
|
+
console.log(chalk.gray(' • Try different connection modes: --mode websocket|remote|local'));
|
|
652
|
+
console.log(chalk.gray(' • Check firewall settings for ports 80, 443, and WebSocket'));
|
|
653
|
+
console.log(chalk.gray(' • Verify your network allows outbound HTTPS connections'));
|
|
654
|
+
console.log(chalk.gray(' • Contact support if issues persist'));
|
|
655
|
+
}
|
|
656
|
+
});
|
|
358
657
|
}
|
package/dist/index-simple.js
CHANGED
|
@@ -247,16 +247,46 @@ authCmd
|
|
|
247
247
|
.action(async () => {
|
|
248
248
|
const isAuth = await cliConfig.isAuthenticated();
|
|
249
249
|
const user = await cliConfig.getCurrentUser();
|
|
250
|
+
const failureCount = cliConfig.getFailureCount();
|
|
251
|
+
const lastFailure = cliConfig.getLastAuthFailure();
|
|
252
|
+
const authMethod = cliConfig.get('authMethod');
|
|
253
|
+
const lastValidated = cliConfig.get('lastValidated');
|
|
254
|
+
console.log(chalk.blue.bold('🔐 Authentication Status'));
|
|
255
|
+
console.log('━'.repeat(40));
|
|
250
256
|
if (isAuth && user) {
|
|
251
257
|
console.log(chalk.green('✓ Authenticated'));
|
|
252
258
|
console.log(`Email: ${user.email}`);
|
|
253
259
|
console.log(`Organization: ${user.organization_id}`);
|
|
254
260
|
console.log(`Plan: ${user.plan}`);
|
|
261
|
+
if (authMethod) {
|
|
262
|
+
console.log(`Method: ${authMethod}`);
|
|
263
|
+
}
|
|
264
|
+
if (lastValidated) {
|
|
265
|
+
const validatedDate = new Date(lastValidated);
|
|
266
|
+
console.log(`Last validated: ${validatedDate.toLocaleString()}`);
|
|
267
|
+
}
|
|
255
268
|
}
|
|
256
269
|
else {
|
|
257
270
|
console.log(chalk.red('✖ Not authenticated'));
|
|
258
271
|
console.log(chalk.yellow('Run:'), chalk.white('memory login'));
|
|
259
272
|
}
|
|
273
|
+
// Show failure tracking information
|
|
274
|
+
if (failureCount > 0) {
|
|
275
|
+
console.log();
|
|
276
|
+
console.log(chalk.yellow('⚠️ Authentication Issues:'));
|
|
277
|
+
console.log(`Failed attempts: ${failureCount}`);
|
|
278
|
+
if (lastFailure) {
|
|
279
|
+
const failureDate = new Date(lastFailure);
|
|
280
|
+
console.log(`Last failure: ${failureDate.toLocaleString()}`);
|
|
281
|
+
}
|
|
282
|
+
if (cliConfig.shouldDelayAuth()) {
|
|
283
|
+
const delayMs = cliConfig.getAuthDelayMs();
|
|
284
|
+
console.log(chalk.yellow(`Next retry delay: ${Math.round(delayMs / 1000)} seconds`));
|
|
285
|
+
}
|
|
286
|
+
console.log();
|
|
287
|
+
console.log(chalk.cyan('💡 To reset failure count:'));
|
|
288
|
+
console.log(chalk.white(' lanonasis auth logout && lanonasis auth login'));
|
|
289
|
+
}
|
|
260
290
|
});
|
|
261
291
|
// MCP Commands (primary interface)
|
|
262
292
|
mcpCommands(program);
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from 'commander';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { config } from 'dotenv';
|
|
5
5
|
import { initCommand } from './commands/init.js';
|
|
6
|
-
import { loginCommand } from './commands/auth.js';
|
|
6
|
+
import { loginCommand, diagnoseCommand } from './commands/auth.js';
|
|
7
7
|
import { memoryCommands } from './commands/memory.js';
|
|
8
8
|
import { topicCommands } from './commands/topics.js';
|
|
9
9
|
import { configCommands } from './commands/config.js';
|
|
@@ -211,17 +211,51 @@ authCmd
|
|
|
211
211
|
.action(async () => {
|
|
212
212
|
const isAuth = await cliConfig.isAuthenticated();
|
|
213
213
|
const user = await cliConfig.getCurrentUser();
|
|
214
|
+
const failureCount = cliConfig.getFailureCount();
|
|
215
|
+
const lastFailure = cliConfig.getLastAuthFailure();
|
|
216
|
+
const authMethod = cliConfig.get('authMethod');
|
|
217
|
+
const lastValidated = cliConfig.get('lastValidated');
|
|
218
|
+
console.log(chalk.blue.bold('🔐 Authentication Status'));
|
|
219
|
+
console.log('━'.repeat(40));
|
|
214
220
|
if (isAuth && user) {
|
|
215
221
|
console.log(chalk.green('✓ Authenticated'));
|
|
216
222
|
console.log(`Email: ${user.email}`);
|
|
217
223
|
console.log(`Organization: ${user.organization_id}`);
|
|
218
224
|
console.log(`Plan: ${user.plan}`);
|
|
225
|
+
if (authMethod) {
|
|
226
|
+
console.log(`Method: ${authMethod}`);
|
|
227
|
+
}
|
|
228
|
+
if (lastValidated) {
|
|
229
|
+
const validatedDate = new Date(lastValidated);
|
|
230
|
+
console.log(`Last validated: ${validatedDate.toLocaleString()}`);
|
|
231
|
+
}
|
|
219
232
|
}
|
|
220
233
|
else {
|
|
221
234
|
console.log(chalk.red('✖ Not authenticated'));
|
|
222
235
|
console.log(chalk.yellow('Run:'), chalk.white('memory login'));
|
|
223
236
|
}
|
|
237
|
+
// Show failure tracking information
|
|
238
|
+
if (failureCount > 0) {
|
|
239
|
+
console.log();
|
|
240
|
+
console.log(chalk.yellow('⚠️ Authentication Issues:'));
|
|
241
|
+
console.log(`Failed attempts: ${failureCount}`);
|
|
242
|
+
if (lastFailure) {
|
|
243
|
+
const failureDate = new Date(lastFailure);
|
|
244
|
+
console.log(`Last failure: ${failureDate.toLocaleString()}`);
|
|
245
|
+
}
|
|
246
|
+
if (cliConfig.shouldDelayAuth()) {
|
|
247
|
+
const delayMs = cliConfig.getAuthDelayMs();
|
|
248
|
+
console.log(chalk.yellow(`Next retry delay: ${Math.round(delayMs / 1000)} seconds`));
|
|
249
|
+
}
|
|
250
|
+
console.log();
|
|
251
|
+
console.log(chalk.cyan('💡 To reset failure count:'));
|
|
252
|
+
console.log(chalk.white(' lanonasis auth logout && lanonasis auth login'));
|
|
253
|
+
}
|
|
224
254
|
});
|
|
255
|
+
authCmd
|
|
256
|
+
.command('diagnose')
|
|
257
|
+
.description('Diagnose authentication issues')
|
|
258
|
+
.action(diagnoseCommand);
|
|
225
259
|
// MCP Commands (primary interface)
|
|
226
260
|
mcpCommands(program);
|
|
227
261
|
// Memory commands (require auth) - now MCP-powered by default
|
|
@@ -201,12 +201,12 @@ export declare const SystemConfigSchema: z.ZodObject<{
|
|
|
201
201
|
scope: z.ZodDefault<z.ZodEnum<["user", "global"]>>;
|
|
202
202
|
}, "strip", z.ZodTypeAny, {
|
|
203
203
|
value?: any;
|
|
204
|
-
action?: "get" | "
|
|
204
|
+
action?: "get" | "set" | "reset";
|
|
205
205
|
key?: string;
|
|
206
206
|
scope?: "user" | "global";
|
|
207
207
|
}, {
|
|
208
208
|
value?: any;
|
|
209
|
-
action?: "get" | "
|
|
209
|
+
action?: "get" | "set" | "reset";
|
|
210
210
|
key?: string;
|
|
211
211
|
scope?: "user" | "global";
|
|
212
212
|
}>;
|
|
@@ -579,12 +579,12 @@ export declare const MCPSchemas: {
|
|
|
579
579
|
scope: z.ZodDefault<z.ZodEnum<["user", "global"]>>;
|
|
580
580
|
}, "strip", z.ZodTypeAny, {
|
|
581
581
|
value?: any;
|
|
582
|
-
action?: "get" | "
|
|
582
|
+
action?: "get" | "set" | "reset";
|
|
583
583
|
key?: string;
|
|
584
584
|
scope?: "user" | "global";
|
|
585
585
|
}, {
|
|
586
586
|
value?: any;
|
|
587
|
-
action?: "get" | "
|
|
587
|
+
action?: "get" | "set" | "reset";
|
|
588
588
|
key?: string;
|
|
589
589
|
scope?: "user" | "global";
|
|
590
590
|
}>;
|
|
@@ -9,6 +9,25 @@ export interface LanonasisServerOptions {
|
|
|
9
9
|
verbose?: boolean;
|
|
10
10
|
apiUrl?: string;
|
|
11
11
|
token?: string;
|
|
12
|
+
preferredTransport?: 'stdio' | 'websocket' | 'http';
|
|
13
|
+
enableTransportFallback?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ConnectionHealth {
|
|
16
|
+
clientId: string;
|
|
17
|
+
connectedAt: Date;
|
|
18
|
+
lastActivity: Date;
|
|
19
|
+
transport: 'stdio' | 'websocket' | 'http';
|
|
20
|
+
authenticated: boolean;
|
|
21
|
+
clientInfo?: {
|
|
22
|
+
name?: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ConnectionPoolStats {
|
|
27
|
+
totalConnections: number;
|
|
28
|
+
activeConnections: number;
|
|
29
|
+
authenticatedConnections: number;
|
|
30
|
+
connectionsByTransport: Record<string, number>;
|
|
12
31
|
}
|
|
13
32
|
export declare class LanonasisMCPServer {
|
|
14
33
|
private server;
|
|
@@ -16,6 +35,12 @@ export declare class LanonasisMCPServer {
|
|
|
16
35
|
private apiClient;
|
|
17
36
|
private transport;
|
|
18
37
|
private options;
|
|
38
|
+
private connectionPool;
|
|
39
|
+
private maxConnections;
|
|
40
|
+
private connectionCleanupInterval;
|
|
41
|
+
private supportedTransports;
|
|
42
|
+
private transportFailures;
|
|
43
|
+
private enableFallback;
|
|
19
44
|
constructor(options?: LanonasisServerOptions);
|
|
20
45
|
/**
|
|
21
46
|
* Initialize the server
|
|
@@ -26,15 +51,15 @@ export declare class LanonasisMCPServer {
|
|
|
26
51
|
*/
|
|
27
52
|
private registerTools;
|
|
28
53
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
54
|
+
* Register MCP resources
|
|
55
|
+
*/
|
|
31
56
|
private registerResources;
|
|
32
57
|
/**
|
|
33
58
|
* Register MCP prompts
|
|
34
59
|
*/
|
|
35
|
-
private registerPrompts;
|
|
36
|
-
|
|
37
|
-
|
|
60
|
+
private registerPrompts; /**
|
|
61
|
+
|
|
62
|
+
* Handle tool calls
|
|
38
63
|
*/
|
|
39
64
|
private handleToolCall;
|
|
40
65
|
/**
|
|
@@ -48,7 +73,133 @@ export declare class LanonasisMCPServer {
|
|
|
48
73
|
/**
|
|
49
74
|
* Handle system configuration
|
|
50
75
|
*/
|
|
51
|
-
private handleSystemConfig;
|
|
76
|
+
private handleSystemConfig; /**
|
|
77
|
+
|
|
78
|
+
* Connection pool management methods
|
|
79
|
+
*/
|
|
80
|
+
/**
|
|
81
|
+
* Add a new connection to the pool
|
|
82
|
+
*/
|
|
83
|
+
private addConnection;
|
|
84
|
+
/**
|
|
85
|
+
* Remove a connection from the pool
|
|
86
|
+
*/
|
|
87
|
+
private removeConnection;
|
|
88
|
+
/**
|
|
89
|
+
* Update connection activity timestamp
|
|
90
|
+
*/
|
|
91
|
+
private updateConnectionActivity;
|
|
92
|
+
/**
|
|
93
|
+
* Mark connection as authenticated
|
|
94
|
+
*/
|
|
95
|
+
private authenticateConnection;
|
|
96
|
+
/**
|
|
97
|
+
* Get connection pool statistics
|
|
98
|
+
*/
|
|
99
|
+
private getConnectionPoolStats;
|
|
100
|
+
/**
|
|
101
|
+
* Start connection cleanup monitoring
|
|
102
|
+
*/
|
|
103
|
+
private startConnectionCleanup;
|
|
104
|
+
/**
|
|
105
|
+
* Stop connection cleanup monitoring
|
|
106
|
+
*/
|
|
107
|
+
private stopConnectionCleanup;
|
|
108
|
+
/**
|
|
109
|
+
* Clean up stale connections (no activity for 10 minutes)
|
|
110
|
+
*/
|
|
111
|
+
private cleanupStaleConnections;
|
|
112
|
+
/**
|
|
113
|
+
* Generate unique client ID for new connections
|
|
114
|
+
*/
|
|
115
|
+
private generateClientId;
|
|
116
|
+
/**
|
|
117
|
+
* Extract client ID from request headers or metadata
|
|
118
|
+
*/
|
|
119
|
+
private extractClientId;
|
|
120
|
+
/**
|
|
121
|
+
* Authenticate incoming MCP request
|
|
122
|
+
*/
|
|
123
|
+
private authenticateRequest;
|
|
124
|
+
/**
|
|
125
|
+
* Extract authentication information from request
|
|
126
|
+
*/
|
|
127
|
+
private extractAuthInfo;
|
|
128
|
+
/**
|
|
129
|
+
* Check if this is a stdio connection
|
|
130
|
+
*/
|
|
131
|
+
private isStdioConnection;
|
|
132
|
+
/**
|
|
133
|
+
* Determine transport type from request
|
|
134
|
+
*/
|
|
135
|
+
private determineTransport;
|
|
136
|
+
/**
|
|
137
|
+
* Ensure connection exists in pool
|
|
138
|
+
*/
|
|
139
|
+
private ensureConnectionExists;
|
|
140
|
+
/**
|
|
141
|
+
* Validate stored CLI credentials
|
|
142
|
+
*/
|
|
143
|
+
private validateStoredCredentials;
|
|
144
|
+
/**
|
|
145
|
+
* Validate provided credentials against the API
|
|
146
|
+
*/
|
|
147
|
+
private validateCredentials;
|
|
148
|
+
/**
|
|
149
|
+
* Validate connection authentication status
|
|
150
|
+
*/
|
|
151
|
+
private validateConnectionAuth;
|
|
152
|
+
/**
|
|
153
|
+
* Get authentication status for all connections
|
|
154
|
+
*/
|
|
155
|
+
private getAuthenticationStatus;
|
|
156
|
+
/**
|
|
157
|
+
* Transport protocol management methods
|
|
158
|
+
*/
|
|
159
|
+
/**
|
|
160
|
+
* Check if a transport is available and working
|
|
161
|
+
*/
|
|
162
|
+
private checkTransportAvailability;
|
|
163
|
+
/**
|
|
164
|
+
* Test WebSocket transport availability
|
|
165
|
+
*/
|
|
166
|
+
private testWebSocketAvailability;
|
|
167
|
+
/**
|
|
168
|
+
* Test HTTP transport availability
|
|
169
|
+
*/
|
|
170
|
+
private testHttpAvailability;
|
|
171
|
+
/**
|
|
172
|
+
* Record a transport failure
|
|
173
|
+
*/
|
|
174
|
+
private recordTransportFailure;
|
|
175
|
+
/**
|
|
176
|
+
* Get the best available transport
|
|
177
|
+
*/
|
|
178
|
+
private getBestAvailableTransport;
|
|
179
|
+
/**
|
|
180
|
+
* Handle transport-specific errors with clear messages
|
|
181
|
+
*/
|
|
182
|
+
private handleTransportError;
|
|
183
|
+
/**
|
|
184
|
+
* Attempt to start server with transport fallback
|
|
185
|
+
*/
|
|
186
|
+
private startWithTransportFallback;
|
|
187
|
+
/**
|
|
188
|
+
* Start a specific transport
|
|
189
|
+
*/
|
|
190
|
+
private startTransport;
|
|
191
|
+
/**
|
|
192
|
+
* Get transport status and statistics
|
|
193
|
+
*/
|
|
194
|
+
private getTransportStatus;
|
|
195
|
+
/**
|
|
196
|
+
* Check if connection limit allows new connections
|
|
197
|
+
*/
|
|
198
|
+
private canAcceptNewConnection;
|
|
199
|
+
/**
|
|
200
|
+
* Get connection by client ID
|
|
201
|
+
*/
|
|
202
|
+
private getConnection;
|
|
52
203
|
/**
|
|
53
204
|
* Setup error handling
|
|
54
205
|
*/
|
|
@@ -65,4 +216,8 @@ export declare class LanonasisMCPServer {
|
|
|
65
216
|
* Get server instance (for testing)
|
|
66
217
|
*/
|
|
67
218
|
getServer(): Server;
|
|
219
|
+
/**
|
|
220
|
+
* Get connection pool for testing/monitoring
|
|
221
|
+
*/
|
|
222
|
+
getConnectionPool(): Map<string, ConnectionHealth>;
|
|
68
223
|
}
|