@lanonasis/cli 1.0.0 → 1.1.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.
@@ -80,7 +80,8 @@ export function memoryCommands(program) {
80
80
  }
81
81
  }
82
82
  catch (error) {
83
- console.error(chalk.red('✖ Failed to create memory:'), error.message);
83
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
84
+ console.error(chalk.red('✖ Failed to create memory:'), errorMessage);
84
85
  process.exit(1);
85
86
  }
86
87
  });
@@ -100,10 +101,10 @@ export function memoryCommands(program) {
100
101
  try {
101
102
  const spinner = ora('Fetching memories...').start();
102
103
  const params = {
103
- page: parseInt(options.page),
104
- limit: parseInt(options.limit),
105
- sort: options.sort,
106
- order: options.order
104
+ page: parseInt(options.page || '1'),
105
+ limit: parseInt(options.limit || '20'),
106
+ sort: options.sort || 'created_at',
107
+ order: options.order || 'desc'
107
108
  };
108
109
  if (options.type)
109
110
  params.memory_type = options.type;
@@ -155,7 +156,8 @@ export function memoryCommands(program) {
155
156
  }
156
157
  }
157
158
  catch (error) {
158
- console.error(chalk.red('✖ Failed to list memories:'), error.message);
159
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
160
+ console.error(chalk.red('✖ Failed to list memories:'), errorMessage);
159
161
  process.exit(1);
160
162
  }
161
163
  });
@@ -172,8 +174,8 @@ export function memoryCommands(program) {
172
174
  try {
173
175
  const spinner = ora(`Searching for "${query}"...`).start();
174
176
  const searchOptions = {
175
- limit: parseInt(options.limit),
176
- threshold: parseFloat(options.threshold)
177
+ limit: parseInt(options.limit || '20'),
178
+ threshold: parseFloat(options.threshold || '0.7')
177
179
  };
178
180
  if (options.type) {
179
181
  searchOptions.memory_types = options.type.split(',').map((t) => t.trim());
@@ -202,7 +204,8 @@ export function memoryCommands(program) {
202
204
  });
203
205
  }
204
206
  catch (error) {
205
- console.error(chalk.red('✖ Search failed:'), error.message);
207
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
208
+ console.error(chalk.red('✖ Search failed:'), errorMessage);
206
209
  process.exit(1);
207
210
  }
208
211
  });
@@ -244,7 +247,8 @@ export function memoryCommands(program) {
244
247
  }
245
248
  }
246
249
  catch (error) {
247
- console.error(chalk.red('✖ Failed to get memory:'), error.message);
250
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
251
+ console.error(chalk.red('✖ Failed to get memory:'), errorMessage);
248
252
  process.exit(1);
249
253
  }
250
254
  });
@@ -324,7 +328,8 @@ export function memoryCommands(program) {
324
328
  console.log(` Title: ${memory.title}`);
325
329
  }
326
330
  catch (error) {
327
- console.error(chalk.red('✖ Failed to update memory:'), error.message);
331
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
332
+ console.error(chalk.red('✖ Failed to update memory:'), errorMessage);
328
333
  process.exit(1);
329
334
  }
330
335
  });
@@ -357,7 +362,8 @@ export function memoryCommands(program) {
357
362
  spinner.succeed('Memory deleted successfully');
358
363
  }
359
364
  catch (error) {
360
- console.error(chalk.red('✖ Failed to delete memory:'), error.message);
365
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
366
+ console.error(chalk.red('✖ Failed to delete memory:'), errorMessage);
361
367
  process.exit(1);
362
368
  }
363
369
  });
@@ -394,7 +400,8 @@ export function memoryCommands(program) {
394
400
  }
395
401
  }
396
402
  catch (error) {
397
- console.error(chalk.red('✖ Failed to get statistics:'), error.message);
403
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
404
+ console.error(chalk.red('✖ Failed to get statistics:'), errorMessage);
398
405
  process.exit(1);
399
406
  }
400
407
  });
@@ -82,7 +82,8 @@ export function topicCommands(program) {
82
82
  }
83
83
  }
84
84
  catch (error) {
85
- console.error(chalk.red('✖ Failed to create topic:'), error.message);
85
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
86
+ console.error(chalk.red('✖ Failed to create topic:'), errorMessage);
86
87
  process.exit(1);
87
88
  }
88
89
  });
@@ -133,7 +134,8 @@ export function topicCommands(program) {
133
134
  }
134
135
  }
135
136
  catch (error) {
136
- console.error(chalk.red('✖ Failed to list topics:'), error.message);
137
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
138
+ console.error(chalk.red('✖ Failed to list topics:'), errorMessage);
137
139
  process.exit(1);
138
140
  }
139
141
  });
@@ -174,7 +176,8 @@ export function topicCommands(program) {
174
176
  }
175
177
  }
176
178
  catch (error) {
177
- console.error(chalk.red('✖ Failed to get topic:'), error.message);
179
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
180
+ console.error(chalk.red('✖ Failed to get topic:'), errorMessage);
178
181
  process.exit(1);
179
182
  }
180
183
  });
@@ -257,7 +260,8 @@ export function topicCommands(program) {
257
260
  console.log(` Name: ${topic.name}`);
258
261
  }
259
262
  catch (error) {
260
- console.error(chalk.red('✖ Failed to update topic:'), error.message);
263
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
264
+ console.error(chalk.red('✖ Failed to update topic:'), errorMessage);
261
265
  process.exit(1);
262
266
  }
263
267
  });
@@ -290,7 +294,8 @@ export function topicCommands(program) {
290
294
  spinner.succeed('Topic deleted successfully');
291
295
  }
292
296
  catch (error) {
293
- console.error(chalk.red('✖ Failed to delete topic:'), error.message);
297
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
298
+ console.error(chalk.red('✖ Failed to delete topic:'), errorMessage);
294
299
  process.exit(1);
295
300
  }
296
301
  });
@@ -11,7 +11,7 @@ const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
11
11
  const program = new Command();
12
12
  program
13
13
  .name('lanonasis')
14
- .description('Lanonasis Enterprise CLI - Memory as a Service and Infrastructure Management')
14
+ .description('Lanonasis Enterprise CLI - Memory as a Service with MCP Integration')
15
15
  .version(packageJson.version);
16
16
  program
17
17
  .command('init')
package/dist/index.js CHANGED
@@ -8,7 +8,9 @@ import { memoryCommands } from './commands/memory.js';
8
8
  import { topicCommands } from './commands/topics.js';
9
9
  import { configCommands } from './commands/config.js';
10
10
  import { orgCommands } from './commands/organization.js';
11
+ import { mcpCommands } from './commands/mcp.js';
11
12
  import { CLIConfig } from './utils/config.js';
13
+ import { getMCPClient } from './utils/mcp-client.js';
12
14
  // Load environment variables
13
15
  config();
14
16
  const program = new Command();
@@ -17,12 +19,13 @@ const cliConfig = new CLIConfig();
17
19
  program
18
20
  .name('memory')
19
21
  .alias('maas')
20
- .description('Enterprise Memory as a Service (MaaS) CLI')
22
+ .description('Enterprise Memory as a Service (MaaS) CLI with MCP Integration')
21
23
  .version('1.0.0')
22
24
  .option('-v, --verbose', 'enable verbose logging')
23
25
  .option('--api-url <url>', 'override API URL')
24
26
  .option('--output <format>', 'output format (json, table, yaml)', 'table')
25
- .hook('preAction', (thisCommand, actionCommand) => {
27
+ .option('--no-mcp', 'disable MCP and use direct API')
28
+ .hook('preAction', async (thisCommand, actionCommand) => {
26
29
  const opts = thisCommand.opts();
27
30
  if (opts.verbose) {
28
31
  process.env.CLI_VERBOSE = 'true';
@@ -31,6 +34,24 @@ program
31
34
  process.env.MEMORY_API_URL = opts.apiUrl;
32
35
  }
33
36
  process.env.CLI_OUTPUT_FORMAT = opts.output;
37
+ // Auto-initialize MCP unless disabled
38
+ if (opts.mcp !== false && !['init', 'auth', 'login', 'mcp'].includes(actionCommand.name())) {
39
+ try {
40
+ const client = getMCPClient();
41
+ if (!client.isConnectedToServer()) {
42
+ const useRemote = await cliConfig.isAuthenticated();
43
+ await client.connect({ useRemote });
44
+ if (process.env.CLI_VERBOSE === 'true') {
45
+ console.log(chalk.gray(`MCP connected (${useRemote ? 'remote' : 'local'})`));
46
+ }
47
+ }
48
+ }
49
+ catch (error) {
50
+ if (process.env.CLI_VERBOSE === 'true') {
51
+ console.log(chalk.yellow('MCP auto-connect failed, using direct API'));
52
+ }
53
+ }
54
+ }
34
55
  });
35
56
  // Global error handler
36
57
  process.on('uncaughtException', (error) => {
@@ -110,13 +131,16 @@ authCmd
110
131
  console.log(chalk.yellow('Run:'), chalk.white('memory login'));
111
132
  }
112
133
  });
113
- // Memory commands (require auth)
134
+ // MCP Commands (primary interface)
135
+ mcpCommands(program);
136
+ // Memory commands (require auth) - now MCP-powered by default
114
137
  const memoryCmd = program
115
138
  .command('memory')
116
139
  .alias('mem')
117
140
  .description('Memory management commands');
118
141
  requireAuth(memoryCmd);
119
142
  memoryCommands(memoryCmd);
143
+ // Note: Memory commands are now MCP-powered when available
120
144
  // Topic commands (require auth)
121
145
  const topicCmd = program
122
146
  .command('topic')
@@ -1,24 +1,164 @@
1
1
  import { AxiosRequestConfig } from 'axios';
2
+ export interface AuthResponse {
3
+ user: {
4
+ id: string;
5
+ email: string;
6
+ organization_id: string;
7
+ role: 'admin' | 'user' | 'viewer';
8
+ plan: 'free' | 'pro' | 'enterprise';
9
+ created_at: string;
10
+ updated_at: string;
11
+ };
12
+ token: string;
13
+ expires_at: string;
14
+ }
15
+ export interface RegisterRequest {
16
+ email: string;
17
+ password: string;
18
+ organization_name?: string;
19
+ }
20
+ export interface LoginRequest {
21
+ email: string;
22
+ password: string;
23
+ }
24
+ export type MemoryType = 'context' | 'project' | 'knowledge' | 'reference' | 'personal' | 'workflow';
25
+ export interface MemoryEntry {
26
+ id: string;
27
+ title: string;
28
+ content: string;
29
+ memory_type: MemoryType;
30
+ tags: string[];
31
+ topic_id?: string | null;
32
+ user_id: string;
33
+ organization_id: string;
34
+ metadata?: Record<string, unknown>;
35
+ created_at: string;
36
+ updated_at: string;
37
+ last_accessed?: string;
38
+ access_count: number;
39
+ }
40
+ export interface CreateMemoryRequest {
41
+ title: string;
42
+ content: string;
43
+ memory_type?: MemoryType;
44
+ tags?: string[];
45
+ topic_id?: string;
46
+ metadata?: Record<string, unknown>;
47
+ }
48
+ export interface UpdateMemoryRequest {
49
+ title?: string;
50
+ content?: string;
51
+ memory_type?: MemoryType;
52
+ tags?: string[];
53
+ topic_id?: string | null;
54
+ metadata?: Record<string, unknown>;
55
+ }
56
+ export interface GetMemoriesParams {
57
+ limit?: number;
58
+ offset?: number;
59
+ memory_type?: MemoryType;
60
+ tags?: string[];
61
+ topic_id?: string;
62
+ sort_by?: 'created_at' | 'updated_at' | 'last_accessed' | 'access_count';
63
+ sort_order?: 'asc' | 'desc';
64
+ }
65
+ export interface SearchMemoryRequest {
66
+ query: string;
67
+ memory_types?: MemoryType[];
68
+ tags?: string[];
69
+ topic_id?: string;
70
+ limit?: number;
71
+ threshold?: number;
72
+ }
73
+ export interface MemorySearchResult extends MemoryEntry {
74
+ relevance_score: number;
75
+ }
76
+ export interface MemoryStats {
77
+ total_memories: number;
78
+ memories_by_type: Record<MemoryType, number>;
79
+ total_size_bytes: number;
80
+ avg_access_count: number;
81
+ most_accessed_memory?: MemoryEntry;
82
+ recent_memories: MemoryEntry[];
83
+ }
84
+ export interface BulkDeleteRequest {
85
+ memory_ids: string[];
86
+ }
87
+ export interface BulkDeleteResponse {
88
+ deleted_count: number;
89
+ failed_deletes?: string[];
90
+ }
91
+ export interface MemoryTopic {
92
+ id: string;
93
+ name: string;
94
+ description?: string;
95
+ color?: string;
96
+ icon?: string;
97
+ user_id: string;
98
+ parent_topic_id?: string;
99
+ is_system: boolean;
100
+ metadata?: Record<string, unknown>;
101
+ created_at: string;
102
+ updated_at: string;
103
+ }
104
+ export interface CreateTopicRequest {
105
+ name: string;
106
+ description?: string;
107
+ color?: string;
108
+ icon?: string;
109
+ parent_topic_id?: string;
110
+ }
111
+ export interface UpdateTopicRequest {
112
+ name?: string;
113
+ description?: string;
114
+ color?: string;
115
+ icon?: string;
116
+ parent_topic_id?: string;
117
+ }
118
+ export interface HealthStatus {
119
+ status: 'healthy' | 'unhealthy';
120
+ version: string;
121
+ timestamp: string;
122
+ dependencies: Record<string, {
123
+ status: string;
124
+ latency_ms?: number;
125
+ }>;
126
+ }
127
+ export interface PaginatedResponse<T> {
128
+ data: T[];
129
+ pagination: {
130
+ total: number;
131
+ limit: number;
132
+ offset: number;
133
+ has_more: boolean;
134
+ };
135
+ }
136
+ export interface ApiErrorResponse {
137
+ error: string;
138
+ message: string;
139
+ status_code: number;
140
+ details?: Record<string, unknown>;
141
+ }
2
142
  export declare class APIClient {
3
143
  private client;
4
144
  private config;
5
145
  constructor();
6
- login(email: string, password: string): Promise<any>;
7
- register(email: string, password: string, organizationName?: string): Promise<any>;
8
- createMemory(data: any): Promise<any>;
9
- getMemories(params?: any): Promise<any>;
10
- getMemory(id: string): Promise<any>;
11
- updateMemory(id: string, data: any): Promise<any>;
146
+ login(email: string, password: string): Promise<AuthResponse>;
147
+ register(email: string, password: string, organizationName?: string): Promise<AuthResponse>;
148
+ createMemory(data: CreateMemoryRequest): Promise<MemoryEntry>;
149
+ getMemories(params?: GetMemoriesParams): Promise<PaginatedResponse<MemoryEntry>>;
150
+ getMemory(id: string): Promise<MemoryEntry>;
151
+ updateMemory(id: string, data: UpdateMemoryRequest): Promise<MemoryEntry>;
12
152
  deleteMemory(id: string): Promise<void>;
13
- searchMemories(query: string, options?: any): Promise<any>;
14
- getMemoryStats(): Promise<any>;
15
- bulkDeleteMemories(memoryIds: string[]): Promise<any>;
16
- createTopic(data: any): Promise<any>;
17
- getTopics(): Promise<any>;
18
- getTopic(id: string): Promise<any>;
19
- updateTopic(id: string, data: any): Promise<any>;
153
+ searchMemories(query: string, options?: Omit<SearchMemoryRequest, 'query'>): Promise<PaginatedResponse<MemorySearchResult>>;
154
+ getMemoryStats(): Promise<MemoryStats>;
155
+ bulkDeleteMemories(memoryIds: string[]): Promise<BulkDeleteResponse>;
156
+ createTopic(data: CreateTopicRequest): Promise<MemoryTopic>;
157
+ getTopics(): Promise<MemoryTopic[]>;
158
+ getTopic(id: string): Promise<MemoryTopic>;
159
+ updateTopic(id: string, data: UpdateTopicRequest): Promise<MemoryTopic>;
20
160
  deleteTopic(id: string): Promise<void>;
21
- getHealth(): Promise<any>;
22
- request<T = any>(config: AxiosRequestConfig): Promise<T>;
161
+ getHealth(): Promise<HealthStatus>;
162
+ request<T = Record<string, unknown>>(config: AxiosRequestConfig): Promise<T>;
23
163
  }
24
164
  export declare const apiClient: APIClient;
@@ -22,5 +22,11 @@ export declare class CLIConfig {
22
22
  clear(): Promise<void>;
23
23
  getConfigPath(): string;
24
24
  exists(): Promise<boolean>;
25
+ get(key: string): any;
26
+ set(key: string, value: any): void;
27
+ setAndSave(key: string, value: any): Promise<void>;
28
+ getMCPServerPath(): string;
29
+ getMCPServerUrl(): string;
30
+ shouldUseRemoteMCP(): boolean;
25
31
  }
26
32
  export {};
@@ -1,7 +1,10 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import os from 'os';
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
4
  import { jwtDecode } from 'jwt-decode';
5
+ import { fileURLToPath } from 'url';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
5
8
  export class CLIConfig {
6
9
  configDir;
7
10
  configPath;
@@ -15,7 +18,7 @@ export class CLIConfig {
15
18
  await fs.mkdir(this.configDir, { recursive: true });
16
19
  await this.load();
17
20
  }
18
- catch (error) {
21
+ catch {
19
22
  // Config doesn't exist yet, that's ok
20
23
  }
21
24
  }
@@ -24,7 +27,7 @@ export class CLIConfig {
24
27
  const data = await fs.readFile(this.configPath, 'utf-8');
25
28
  this.config = JSON.parse(data);
26
29
  }
27
- catch (error) {
30
+ catch {
28
31
  this.config = {};
29
32
  }
30
33
  }
@@ -50,13 +53,13 @@ export class CLIConfig {
50
53
  // We'll need to fetch full user details from the API
51
54
  // For now, store what we can decode
52
55
  this.config.user = {
53
- email: decoded.email || '',
54
- organization_id: decoded.organizationId || '',
55
- role: decoded.role || '',
56
- plan: decoded.plan || ''
56
+ email: String(decoded.email || ''),
57
+ organization_id: String(decoded.organizationId || ''),
58
+ role: String(decoded.role || ''),
59
+ plan: String(decoded.plan || '')
57
60
  };
58
61
  }
59
- catch (error) {
62
+ catch {
60
63
  // Invalid token, don't store user info
61
64
  }
62
65
  await this.save();
@@ -74,9 +77,9 @@ export class CLIConfig {
74
77
  try {
75
78
  const decoded = jwtDecode(token);
76
79
  const now = Date.now() / 1000;
77
- return decoded.exp > now;
80
+ return typeof decoded.exp === 'number' && decoded.exp > now;
78
81
  }
79
- catch (error) {
82
+ catch {
80
83
  return false;
81
84
  }
82
85
  }
@@ -101,4 +104,35 @@ export class CLIConfig {
101
104
  return false;
102
105
  }
103
106
  }
107
+ // Generic get/set methods for MCP and other dynamic config
108
+ get(key) {
109
+ return this.config[key];
110
+ }
111
+ set(key, value) {
112
+ this.config[key] = value;
113
+ }
114
+ async setAndSave(key, value) {
115
+ this.set(key, value);
116
+ await this.save();
117
+ }
118
+ // MCP-specific helpers
119
+ getMCPServerPath() {
120
+ return this.config.mcpServerPath || path.join(__dirname, '../../../../onasis-gateway/mcp-server/server.js');
121
+ }
122
+ getMCPServerUrl() {
123
+ return this.config.mcpServerUrl || 'https://api.lanonasis.com';
124
+ }
125
+ shouldUseRemoteMCP() {
126
+ const preference = this.config.mcpPreference || 'auto';
127
+ switch (preference) {
128
+ case 'remote':
129
+ return true;
130
+ case 'local':
131
+ return false;
132
+ case 'auto':
133
+ default:
134
+ // Use remote if authenticated, otherwise local
135
+ return !!this.config.token;
136
+ }
137
+ }
104
138
  }
@@ -1,4 +1,4 @@
1
- export declare function formatOutput(data: any, format?: string): void;
1
+ export declare function formatOutput(data: unknown, format?: string): void;
2
2
  export declare function formatBytes(bytes: number): string;
3
3
  export declare function truncateText(text: string, maxLength: number): string;
4
4
  export declare function formatDuration(ms: number): string;
@@ -0,0 +1,53 @@
1
+ interface MCPConnectionOptions {
2
+ serverPath?: string;
3
+ serverUrl?: string;
4
+ useRemote?: boolean;
5
+ }
6
+ export declare class MCPClient {
7
+ private client;
8
+ private config;
9
+ private isConnected;
10
+ private sseConnection;
11
+ constructor();
12
+ /**
13
+ * Connect to MCP server (local or remote)
14
+ */
15
+ connect(options?: MCPConnectionOptions): Promise<boolean>;
16
+ /**
17
+ * Initialize SSE connection for real-time updates
18
+ */
19
+ private initializeSSE;
20
+ /**
21
+ * Disconnect from MCP server
22
+ */
23
+ disconnect(): Promise<void>;
24
+ /**
25
+ * Call an MCP tool
26
+ */
27
+ callTool(toolName: string, args: any): Promise<any>;
28
+ /**
29
+ * Call remote tool via REST API with MCP interface
30
+ */
31
+ private callRemoteTool;
32
+ /**
33
+ * List available tools
34
+ */
35
+ listTools(): Promise<Array<{
36
+ name: string;
37
+ description: string;
38
+ }>>;
39
+ /**
40
+ * Check if connected to MCP server
41
+ */
42
+ isConnectedToServer(): boolean;
43
+ /**
44
+ * Get connection status details
45
+ */
46
+ getConnectionStatus(): {
47
+ connected: boolean;
48
+ mode: string;
49
+ server?: string;
50
+ };
51
+ }
52
+ export declare function getMCPClient(): MCPClient;
53
+ export {};