@lanonasis/cli 3.7.7 → 3.8.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.
@@ -370,7 +370,7 @@ export async function diagnoseCommand() {
370
370
  // Step 2: Check stored credentials
371
371
  console.log(chalk.cyan('\n2. Stored Credentials'));
372
372
  const token = config.getToken();
373
- const vendorKey = config.getVendorKey();
373
+ const vendorKey = await config.getVendorKeyAsync();
374
374
  const authMethod = config.get('authMethod');
375
375
  if (vendorKey) {
376
376
  diagnostics.hasCredentials = true;
@@ -825,10 +825,8 @@ async function handleCredentialsFlow(options, config) {
825
825
  if (response.user.role) {
826
826
  console.log(`Role: ${response.user.role}`);
827
827
  }
828
- console.log(chalk.gray('✓ API access configured'));
829
- console.log();
830
- console.log(chalk.dim('Note: MCP WebSocket commands require a vendor key.'));
831
- console.log(chalk.dim('Run'), chalk.white('onasis auth vendor-key <key>'), chalk.dim('to configure MCP access.'));
828
+ console.log(chalk.gray('✓ API and MCP access configured'));
829
+ console.log(chalk.dim('Your JWT token works with all services: API, MCP, CLI.'));
832
830
  }
833
831
  catch (error) {
834
832
  spinner.fail('Login failed');
@@ -382,7 +382,7 @@ export function configCommands(program) {
382
382
  // Step 2: Validate authentication configuration
383
383
  console.log(chalk.cyan('\n2. Authentication Configuration'));
384
384
  const token = config.getToken();
385
- const vendorKey = config.getVendorKey();
385
+ const vendorKey = await config.getVendorKeyAsync();
386
386
  const authMethod = config.get('authMethod');
387
387
  if (!token && !vendorKey) {
388
388
  console.log(chalk.yellow(' ⚠ No authentication credentials configured'));
@@ -190,7 +190,7 @@ export function mcpCommands(program) {
190
190
  const rootBase = restUrl.replace(/\/api\/v1$/, '');
191
191
  const healthUrl = `${rootBase}/health`;
192
192
  const token = config.getToken();
193
- const vendorKey = config.getVendorKey();
193
+ const vendorKey = await config.getVendorKeyAsync();
194
194
  const headers = {};
195
195
  if (vendorKey) {
196
196
  headers['X-API-Key'] = vendorKey;
@@ -457,6 +457,41 @@ export function mcpCommands(program) {
457
457
  console.log(' --auto : Auto-detect based on configuration (default)');
458
458
  }
459
459
  });
460
+ // Start MCP server for external clients
461
+ mcp.command('start')
462
+ .description('Start MCP server for external clients (Claude Desktop, Cursor, etc.)')
463
+ .option('--transport <type>', 'Transport: stdio (default), ws, http, sse', 'stdio')
464
+ .option('--port <number>', 'Port for ws/http/sse', '3009')
465
+ .option('--host <address>', 'Host address', '127.0.0.1')
466
+ .action(async (options) => {
467
+ const apiKey = process.env.LANONASIS_API_KEY;
468
+ if (!apiKey) {
469
+ console.error('Error: LANONASIS_API_KEY environment variable required');
470
+ process.exit(1);
471
+ }
472
+ try {
473
+ const { LanonasisMCPServer } = await import('../mcp/server/lanonasis-server.js');
474
+ const server = new LanonasisMCPServer({
475
+ apiKey,
476
+ transport: options.transport,
477
+ port: parseInt(options.port, 10),
478
+ host: options.host
479
+ });
480
+ if (options.transport === 'stdio') {
481
+ // Log to stderr since stdout is for MCP protocol
482
+ console.error(`Starting MCP server in stdio mode...`);
483
+ await server.startStdio();
484
+ }
485
+ else {
486
+ console.error(`Starting MCP server on ${options.host}:${options.port} (${options.transport})...`);
487
+ await server.start();
488
+ }
489
+ }
490
+ catch (error) {
491
+ console.error(`Failed to start MCP server: ${error instanceof Error ? error.message : 'Unknown error'}`);
492
+ process.exit(1);
493
+ }
494
+ });
460
495
  // Diagnose MCP connection issues
461
496
  mcp.command('diagnose')
462
497
  .description('Diagnose MCP connection issues')
@@ -483,7 +518,7 @@ export function mcpCommands(program) {
483
518
  // Step 1: Check authentication status
484
519
  console.log(chalk.cyan('1. Authentication Status'));
485
520
  const token = config.getToken();
486
- const vendorKey = config.getVendorKey();
521
+ const vendorKey = await config.getVendorKeyAsync();
487
522
  if (!token && !vendorKey) {
488
523
  console.log(chalk.red(' ✖ No authentication credentials found'));
489
524
  console.log(chalk.gray(' → Run: lanonasis auth login'));
@@ -15,15 +15,15 @@ export declare const MemoryCreateSchema: z.ZodObject<{
15
15
  content?: string;
16
16
  tags?: string[];
17
17
  topic_id?: string;
18
- memory_type?: "context" | "reference" | "note";
19
18
  metadata?: Record<string, any>;
19
+ memory_type?: "context" | "reference" | "note";
20
20
  }, {
21
21
  title?: string;
22
22
  content?: string;
23
23
  tags?: string[];
24
24
  topic_id?: string;
25
- memory_type?: "context" | "reference" | "note";
26
25
  metadata?: Record<string, any>;
26
+ memory_type?: "context" | "reference" | "note";
27
27
  }>;
28
28
  export declare const MemorySearchSchema: z.ZodObject<{
29
29
  query: z.ZodString;
@@ -59,15 +59,15 @@ export declare const MemoryUpdateSchema: z.ZodObject<{
59
59
  content?: string;
60
60
  tags?: string[];
61
61
  memory_id?: string;
62
- memory_type?: "context" | "reference" | "note";
63
62
  metadata?: Record<string, any>;
63
+ memory_type?: "context" | "reference" | "note";
64
64
  }, {
65
65
  title?: string;
66
66
  content?: string;
67
67
  tags?: string[];
68
68
  memory_id?: string;
69
- memory_type?: "context" | "reference" | "note";
70
69
  metadata?: Record<string, any>;
70
+ memory_type?: "context" | "reference" | "note";
71
71
  }>;
72
72
  export declare const MemoryDeleteSchema: z.ZodObject<{
73
73
  memory_id: z.ZodString;
@@ -217,13 +217,13 @@ export declare const BulkOperationSchema: z.ZodObject<{
217
217
  transaction: z.ZodDefault<z.ZodBoolean>;
218
218
  }, "strip", z.ZodTypeAny, {
219
219
  operation?: "create" | "delete" | "update";
220
- entity_type?: "topic" | "memory" | "apikey";
221
220
  items?: Record<string, any>[];
221
+ entity_type?: "topic" | "memory" | "apikey";
222
222
  transaction?: boolean;
223
223
  }, {
224
224
  operation?: "create" | "delete" | "update";
225
- entity_type?: "topic" | "memory" | "apikey";
226
225
  items?: Record<string, any>[];
226
+ entity_type?: "topic" | "memory" | "apikey";
227
227
  transaction?: boolean;
228
228
  }>;
229
229
  export declare const ImportExportSchema: z.ZodObject<{
@@ -387,15 +387,15 @@ export declare const MCPSchemas: {
387
387
  content?: string;
388
388
  tags?: string[];
389
389
  topic_id?: string;
390
- memory_type?: "context" | "reference" | "note";
391
390
  metadata?: Record<string, any>;
391
+ memory_type?: "context" | "reference" | "note";
392
392
  }, {
393
393
  title?: string;
394
394
  content?: string;
395
395
  tags?: string[];
396
396
  topic_id?: string;
397
- memory_type?: "context" | "reference" | "note";
398
397
  metadata?: Record<string, any>;
398
+ memory_type?: "context" | "reference" | "note";
399
399
  }>;
400
400
  search: z.ZodObject<{
401
401
  query: z.ZodString;
@@ -431,15 +431,15 @@ export declare const MCPSchemas: {
431
431
  content?: string;
432
432
  tags?: string[];
433
433
  memory_id?: string;
434
- memory_type?: "context" | "reference" | "note";
435
434
  metadata?: Record<string, any>;
435
+ memory_type?: "context" | "reference" | "note";
436
436
  }, {
437
437
  title?: string;
438
438
  content?: string;
439
439
  tags?: string[];
440
440
  memory_id?: string;
441
- memory_type?: "context" | "reference" | "note";
442
441
  metadata?: Record<string, any>;
442
+ memory_type?: "context" | "reference" | "note";
443
443
  }>;
444
444
  delete: z.ZodObject<{
445
445
  memory_id: z.ZodString;
@@ -597,13 +597,13 @@ export declare const MCPSchemas: {
597
597
  transaction: z.ZodDefault<z.ZodBoolean>;
598
598
  }, "strip", z.ZodTypeAny, {
599
599
  operation?: "create" | "delete" | "update";
600
- entity_type?: "topic" | "memory" | "apikey";
601
600
  items?: Record<string, any>[];
601
+ entity_type?: "topic" | "memory" | "apikey";
602
602
  transaction?: boolean;
603
603
  }, {
604
604
  operation?: "create" | "delete" | "update";
605
- entity_type?: "topic" | "memory" | "apikey";
606
605
  items?: Record<string, any>[];
606
+ entity_type?: "topic" | "memory" | "apikey";
607
607
  transaction?: boolean;
608
608
  }>;
609
609
  importExport: z.ZodObject<{
@@ -9,6 +9,10 @@ export interface LanonasisServerOptions {
9
9
  verbose?: boolean;
10
10
  apiUrl?: string;
11
11
  token?: string;
12
+ apiKey?: string;
13
+ transport?: 'stdio' | 'ws' | 'http' | 'sse';
14
+ port?: number;
15
+ host?: string;
12
16
  preferredTransport?: 'stdio' | 'websocket' | 'http';
13
17
  enableTransportFallback?: boolean;
14
18
  }
@@ -209,6 +213,11 @@ export declare class LanonasisMCPServer {
209
213
  * Start the server
210
214
  */
211
215
  start(): Promise<void>;
216
+ /**
217
+ * Start the server in stdio mode for external MCP clients (Claude Desktop, Cursor, etc.)
218
+ * This is the primary entry point for `lanonasis mcp start`
219
+ */
220
+ startStdio(): Promise<void>;
212
221
  /**
213
222
  * Stop the server
214
223
  */
@@ -1473,6 +1473,35 @@ Please choose an option (1-4):`
1473
1473
  throw error;
1474
1474
  }
1475
1475
  }
1476
+ /**
1477
+ * Start the server in stdio mode for external MCP clients (Claude Desktop, Cursor, etc.)
1478
+ * This is the primary entry point for `lanonasis mcp start`
1479
+ */
1480
+ async startStdio() {
1481
+ await this.initialize();
1482
+ try {
1483
+ // Use API key from options if provided (from LANONASIS_API_KEY env var)
1484
+ if (this.options.apiKey) {
1485
+ // Set the API key for authentication
1486
+ await this.config.setVendorKey(this.options.apiKey);
1487
+ }
1488
+ // Create stdio transport
1489
+ this.transport = new StdioServerTransport();
1490
+ await this.server.connect(this.transport);
1491
+ // Log to stderr since stdout is for MCP protocol
1492
+ console.error(chalk.cyan('🚀 Lanonasis MCP Server started (stdio mode)'));
1493
+ console.error(chalk.gray(`Backend: ${this.config.getApiUrl()}`));
1494
+ console.error(chalk.gray(`Tools: 18+ available`));
1495
+ console.error(chalk.gray('Ready for MCP client connections...'));
1496
+ // Keep the process alive
1497
+ process.stdin.resume();
1498
+ }
1499
+ catch (error) {
1500
+ console.error(chalk.red('❌ Failed to start MCP Server:'));
1501
+ console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));
1502
+ throw error;
1503
+ }
1504
+ }
1476
1505
  /**
1477
1506
  * Stop the server
1478
1507
  */
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Lanonasis MCP Server Entry Point
4
+ *
5
+ * Direct entry point for external MCP clients (Claude Desktop, Cursor, Windsurf, etc.)
6
+ * This allows simple configuration like:
7
+ *
8
+ * claude mcp add lanonasis -- lanonasis-mcp
9
+ *
10
+ * Or in claude_desktop_config.json:
11
+ * {
12
+ * "mcpServers": {
13
+ * "lanonasis": {
14
+ * "command": "lanonasis-mcp",
15
+ * "env": { "LANONASIS_API_KEY": "lano_xxx" }
16
+ * }
17
+ * }
18
+ * }
19
+ */
20
+ export {};
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Lanonasis MCP Server Entry Point
4
+ *
5
+ * Direct entry point for external MCP clients (Claude Desktop, Cursor, Windsurf, etc.)
6
+ * This allows simple configuration like:
7
+ *
8
+ * claude mcp add lanonasis -- lanonasis-mcp
9
+ *
10
+ * Or in claude_desktop_config.json:
11
+ * {
12
+ * "mcpServers": {
13
+ * "lanonasis": {
14
+ * "command": "lanonasis-mcp",
15
+ * "env": { "LANONASIS_API_KEY": "lano_xxx" }
16
+ * }
17
+ * }
18
+ * }
19
+ */
20
+ import { LanonasisMCPServer } from './mcp/server/lanonasis-server.js';
21
+ async function main() {
22
+ // Get API key from environment
23
+ const apiKey = process.env.LANONASIS_API_KEY;
24
+ if (!apiKey) {
25
+ console.error('Error: LANONASIS_API_KEY environment variable is required');
26
+ console.error('');
27
+ console.error('Usage:');
28
+ console.error(' LANONASIS_API_KEY=lano_xxx lanonasis-mcp');
29
+ console.error('');
30
+ console.error('Or configure in Claude Desktop/Cursor:');
31
+ console.error(' {');
32
+ console.error(' "mcpServers": {');
33
+ console.error(' "lanonasis": {');
34
+ console.error(' "command": "lanonasis-mcp",');
35
+ console.error(' "env": { "LANONASIS_API_KEY": "your_api_key" }');
36
+ console.error(' }');
37
+ console.error(' }');
38
+ console.error(' }');
39
+ process.exit(1);
40
+ }
41
+ try {
42
+ const server = new LanonasisMCPServer({
43
+ apiKey,
44
+ verbose: process.env.LOG_LEVEL === 'debug'
45
+ });
46
+ // Start in stdio mode (standard for MCP clients)
47
+ await server.startStdio();
48
+ }
49
+ catch (error) {
50
+ console.error(`Failed to start MCP server: ${error instanceof Error ? error.message : 'Unknown error'}`);
51
+ process.exit(1);
52
+ }
53
+ }
54
+ main();
@@ -77,12 +77,13 @@ export class CLIMCPServer {
77
77
  console.error(`Auth: ${this.config.hasVendorKey() ? 'Vendor Key' : 'JWT Token'}`);
78
78
  }
79
79
  const resolvedPort = typeof port === 'number' && !Number.isNaN(port) ? port : 3001;
80
+ const vendorKey = await this.config.getVendorKeyAsync();
80
81
  // Set environment variables from CLI config
81
82
  const env = {
82
83
  ...process.env,
83
84
  PORT: resolvedPort.toString(),
84
85
  MEMORY_API_URL: this.config.getApiUrl(),
85
- LANONASIS_VENDOR_KEY: this.config.getVendorKey(),
86
+ LANONASIS_VENDOR_KEY: vendorKey,
86
87
  LANONASIS_TOKEN: this.config.getToken(),
87
88
  MCP_VERBOSE: verbose ? 'true' : 'false',
88
89
  CLI_ALIGNED: 'true'
package/dist/utils/api.js CHANGED
@@ -27,7 +27,7 @@ export class APIClient {
27
27
  }
28
28
  // Enhanced Authentication Support
29
29
  const token = this.config.getToken();
30
- const vendorKey = this.config.getVendorKey();
30
+ const vendorKey = await this.config.getVendorKeyAsync();
31
31
  if (vendorKey) {
32
32
  // Vendor key authentication (validated server-side)
33
33
  // Send raw key - server handles hashing for comparison
@@ -43,6 +43,7 @@ export declare class CLIConfig {
43
43
  private authCheckCache;
44
44
  private readonly AUTH_CACHE_TTL;
45
45
  private apiKeyStorage;
46
+ private vendorKeyCache?;
46
47
  constructor();
47
48
  /**
48
49
  * Overrides the configuration storage directory. Primarily used for tests.
@@ -14,6 +14,7 @@ export class CLIConfig {
14
14
  authCheckCache = null;
15
15
  AUTH_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
16
16
  apiKeyStorage;
17
+ vendorKeyCache;
17
18
  constructor() {
18
19
  this.configDir = path.join(os.homedir(), '.maas');
19
20
  this.configPath = path.join(this.configDir, 'config.json');
@@ -28,6 +29,7 @@ export class CLIConfig {
28
29
  this.configDir = configDir;
29
30
  this.configPath = path.join(configDir, 'config.json');
30
31
  this.lockFile = path.join(configDir, 'config.lock');
32
+ this.vendorKeyCache = undefined;
31
33
  }
32
34
  /**
33
35
  * Exposes the current config path for tests and diagnostics.
@@ -45,6 +47,8 @@ export class CLIConfig {
45
47
  }
46
48
  }
47
49
  async load() {
50
+ // Reset in-memory cache; disk state may have changed
51
+ this.vendorKeyCache = undefined;
48
52
  try {
49
53
  const data = await fs.readFile(this.configPath, 'utf-8');
50
54
  this.config = JSON.parse(data);
@@ -170,7 +174,7 @@ export class CLIConfig {
170
174
  getApiUrl() {
171
175
  const baseUrl = process.env.MEMORY_API_URL ||
172
176
  this.config.apiUrl ||
173
- 'https://mcp.lanonasis.com';
177
+ 'https://api.lanonasis.com'; // Primary REST API endpoint
174
178
  // Ensure we don't double-append /api/v1 - strip it if present since APIClient adds it
175
179
  return baseUrl.replace(/\/api\/v1\/?$/, '');
176
180
  }
@@ -192,8 +196,8 @@ export class CLIConfig {
192
196
  if (!this.config.discoveredServices) {
193
197
  this.config.discoveredServices = {
194
198
  auth_base: 'https://auth.lanonasis.com',
195
- memory_base: 'https://mcp.lanonasis.com', // Base URL without /api/v1
196
- mcp_base: 'https://mcp.lanonasis.com/api/v1', // Full MCP REST path
199
+ memory_base: 'https://api.lanonasis.com', // Primary REST API (Supabase Edge Functions)
200
+ mcp_base: 'https://mcp.lanonasis.com/api/v1', // MCP protocol REST path
197
201
  mcp_ws_base: 'wss://mcp.lanonasis.com/ws',
198
202
  mcp_sse_base: 'https://mcp.lanonasis.com/api/v1/events',
199
203
  project_scope: 'lanonasis-maas'
@@ -245,10 +249,10 @@ export class CLIConfig {
245
249
  if (authBase.includes('localhost') || authBase.includes('127.0.0.1')) {
246
250
  authBase = 'https://auth.lanonasis.com';
247
251
  }
248
- // Memory base should be the MCP base URL without /api/v1 suffix
252
+ // Memory base should be the REST API URL without /api/v1 suffix
249
253
  // The API client will append the path as needed
250
- const rawMemoryBase = discovered.endpoints?.http || 'https://mcp.lanonasis.com/api/v1';
251
- const memoryBase = rawMemoryBase.replace(/\/api\/v1\/?$/, '') || 'https://mcp.lanonasis.com';
254
+ const rawMemoryBase = discovered.endpoints?.http || 'https://api.lanonasis.com/api/v1';
255
+ const memoryBase = rawMemoryBase.replace(/\/api\/v1\/?$/, '') || 'https://api.lanonasis.com';
252
256
  this.config.discoveredServices = {
253
257
  auth_base: authBase || 'https://auth.lanonasis.com',
254
258
  memory_base: memoryBase,
@@ -371,8 +375,8 @@ export class CLIConfig {
371
375
  const nodeEnv = (process.env.NODE_ENV ?? '').toLowerCase();
372
376
  const isDevEnvironment = nodeEnv === 'development' || nodeEnv === 'test';
373
377
  const defaultAuthBase = isDevEnvironment ? 'http://localhost:4000' : 'https://auth.lanonasis.com';
374
- const defaultMemoryBase = isDevEnvironment ? 'http://localhost:4000' : 'https://mcp.lanonasis.com'; // Base URL without /api/v1
375
- const defaultMcpBase = isDevEnvironment ? 'http://localhost:4100/api/v1' : 'https://mcp.lanonasis.com/api/v1'; // Full MCP REST path
378
+ const defaultMemoryBase = isDevEnvironment ? 'http://localhost:4000' : 'https://api.lanonasis.com'; // Primary REST API (Supabase Edge Functions)
379
+ const defaultMcpBase = isDevEnvironment ? 'http://localhost:4100/api/v1' : 'https://mcp.lanonasis.com/api/v1'; // MCP protocol REST path
376
380
  const defaultMcpWsBase = isDevEnvironment ? 'ws://localhost:4100/ws' : 'wss://mcp.lanonasis.com/ws';
377
381
  const defaultMcpSseBase = isDevEnvironment ? 'http://localhost:4100/api/v1/events' : 'https://mcp.lanonasis.com/api/v1/events';
378
382
  const endpoints = {
@@ -438,8 +442,8 @@ export class CLIConfig {
438
442
  }
439
443
  const currentServices = this.config.discoveredServices ?? {
440
444
  auth_base: 'https://auth.lanonasis.com',
441
- memory_base: 'https://mcp.lanonasis.com', // Base URL without /api/v1
442
- mcp_base: 'https://mcp.lanonasis.com/api/v1', // Full MCP REST path
445
+ memory_base: 'https://api.lanonasis.com', // Primary REST API (Supabase Edge Functions)
446
+ mcp_base: 'https://mcp.lanonasis.com/api/v1', // MCP protocol REST path
443
447
  mcp_ws_base: 'wss://mcp.lanonasis.com/ws',
444
448
  mcp_sse_base: 'https://mcp.lanonasis.com/api/v1/events',
445
449
  project_scope: 'lanonasis-maas'
@@ -488,6 +492,8 @@ export class CLIConfig {
488
492
  environment: process.env.NODE_ENV || 'production',
489
493
  createdAt: new Date().toISOString()
490
494
  });
495
+ // Cache the vendor key for this process so synchronous callers can reuse it
496
+ this.vendorKeyCache = trimmedKey;
491
497
  if (process.env.CLI_VERBOSE === 'true') {
492
498
  console.log('🔐 Vendor key stored securely via @lanonasis/oauth-client');
493
499
  }
@@ -566,10 +572,16 @@ export class CLIConfig {
566
572
  }
567
573
  }
568
574
  getVendorKey() {
575
+ if (this.vendorKeyCache) {
576
+ return this.vendorKeyCache;
577
+ }
569
578
  try {
570
579
  // Retrieve from secure storage using ApiKeyStorage (synchronous wrapper)
571
580
  const stored = this.getVendorKeySync();
572
- return stored;
581
+ if (stored) {
582
+ this.vendorKeyCache = stored;
583
+ }
584
+ return this.vendorKeyCache;
573
585
  }
574
586
  catch (error) {
575
587
  if (process.env.CLI_VERBOSE === 'true') {
@@ -600,7 +612,8 @@ export class CLIConfig {
600
612
  await this.apiKeyStorage.initialize();
601
613
  const stored = await this.apiKeyStorage.retrieve();
602
614
  if (stored) {
603
- return stored.apiKey;
615
+ this.vendorKeyCache = stored.apiKey;
616
+ return this.vendorKeyCache;
604
617
  }
605
618
  }
606
619
  catch (error) {
@@ -613,13 +626,14 @@ export class CLIConfig {
613
626
  if (process.env.CLI_VERBOSE === 'true') {
614
627
  console.log('ℹ️ Found legacy plaintext vendor key, will migrate on next auth');
615
628
  }
616
- return this.config.vendorKey;
629
+ this.vendorKeyCache = this.config.vendorKey;
630
+ return this.vendorKeyCache;
617
631
  }
618
632
  return undefined;
619
633
  }
620
634
  hasVendorKey() {
621
635
  // Check for marker or legacy storage
622
- return !!this.config.vendorKey;
636
+ return !!(this.vendorKeyCache || this.config.vendorKey);
623
637
  }
624
638
  async setApiUrl(url) {
625
639
  this.config.apiUrl = url;
@@ -662,7 +676,8 @@ export class CLIConfig {
662
676
  async isAuthenticated() {
663
677
  // Check if using vendor key authentication
664
678
  if (this.config.authMethod === 'vendor_key') {
665
- const vendorKey = this.getVendorKey();
679
+ // Use async method to read from encrypted ApiKeyStorage
680
+ const vendorKey = await this.getVendorKeyAsync();
666
681
  if (!vendorKey)
667
682
  return false;
668
683
  // Check cache first
@@ -847,10 +862,25 @@ export class CLIConfig {
847
862
  async logout() {
848
863
  this.config.token = undefined;
849
864
  this.config.user = undefined;
865
+ this.vendorKeyCache = undefined;
866
+ this.config.vendorKey = undefined;
867
+ this.config.authMethod = undefined;
868
+ try {
869
+ await this.apiKeyStorage.initialize();
870
+ // ApiKeyStorage may implement clear() to remove encrypted secrets
871
+ const storage = this.apiKeyStorage;
872
+ if (typeof storage.clear === 'function') {
873
+ await storage.clear();
874
+ }
875
+ }
876
+ catch {
877
+ // Ignore storage cleanup errors during logout
878
+ }
850
879
  await this.save();
851
880
  }
852
881
  async clear() {
853
882
  this.config = {};
883
+ this.vendorKeyCache = undefined;
854
884
  await this.save();
855
885
  }
856
886
  async exists() {
@@ -865,7 +895,7 @@ export class CLIConfig {
865
895
  // Enhanced credential validation methods
866
896
  async validateStoredCredentials() {
867
897
  try {
868
- const vendorKey = this.getVendorKey();
898
+ const vendorKey = await this.getVendorKeyAsync();
869
899
  const token = this.getToken();
870
900
  if (!vendorKey && !token) {
871
901
  return false;
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import crypto from 'crypto';
10
10
  import { homedir, platform, hostname } from 'os';
11
- import { hashApiKey, isSha256Hash } from './hash-utils.js';
11
+ import { hashApiKey, isSha256Hash } from '@lanonasis/security-sdk/hash-utils';
12
12
  // Encryption algorithm configuration
13
13
  const ALGORITHM = 'aes-256-gcm';
14
14
  const KEY_LENGTH = 32; // 256 bits
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@lanonasis/cli",
3
- "version": "3.7.7",
3
+ "version": "3.8.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
8
8
  "onasis": "dist/index.js",
9
- "lanonasis": "dist/index.js"
9
+ "lanonasis": "dist/index.js",
10
+ "lanonasis-mcp": "dist/mcp-server-entry.js"
10
11
  },
11
12
  "exports": {
12
13
  ".": {
@@ -23,8 +24,8 @@
23
24
  ],
24
25
  "dependencies": {
25
26
  "@lanonasis/oauth-client": "1.2.5",
26
- "@lanonasis/security-sdk": "^1.0.1",
27
- "@modelcontextprotocol/sdk": "^1.1.1",
27
+ "@lanonasis/security-sdk": "1.0.5",
28
+ "@modelcontextprotocol/sdk": "^1.25.2",
28
29
  "axios": "^1.7.7",
29
30
  "chalk": "^5.3.0",
30
31
  "cli-progress": "^3.12.0",
@@ -61,4 +62,4 @@
61
62
  "test:watch": "npm test -- --watch",
62
63
  "test:coverage": "npm test -- --coverage"
63
64
  }
64
- }
65
+ }