@lanonasis/cli 1.0.1 → 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.
package/README.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # Lanonasis CLI - Enterprise Infrastructure Management
2
2
 
3
- šŸš€ **Professional CLI for Lanonasis Platform Services**
3
+ šŸš€ **Professional CLI for Lanonasis Platform Services with MCP Integration**
4
4
 
5
- The Lanonasis CLI provides a powerful command-line interface for interacting with the entire Lanonasis ecosystem, including Memory as a Service (MaaS), infrastructure management, and multi-service orchestration. Manage your memories, search through knowledge bases, organize your thoughts, and control your infrastructure - all from the terminal.
5
+ The Lanonasis CLI provides a powerful command-line interface for interacting with the entire Lanonasis ecosystem, including Memory as a Service (MaaS), infrastructure management, and multi-service orchestration. Now with **Model Context Protocol (MCP)** integration for unified AI-agent communication. Manage your memories, search through knowledge bases, organize your thoughts, and control your infrastructure - all from the terminal.
6
+
7
+ ## šŸ†• New in v1.1.0
8
+ - **MCP Integration**: Full Model Context Protocol support for AI agents
9
+ - **Hybrid Mode**: Seamless switching between local MCP and remote API
10
+ - **Real-time Updates**: SSE streaming for live memory synchronization
11
+ - **Unified Interface**: Same commands work with local or cloud backends
6
12
 
7
13
  ## ⚔ Quick Start
8
14
 
@@ -135,6 +141,40 @@ memory search "my query" # Direct memory command
135
141
  maas list --type knowledge # MaaS command
136
142
  ```
137
143
 
144
+ ## šŸ¤– MCP Integration (Model Context Protocol)
145
+
146
+ The CLI now includes full MCP support for AI agent integration:
147
+
148
+ ```bash
149
+ # Connect to MCP server
150
+ lanonasis mcp connect # Auto-detect mode
151
+ lanonasis mcp connect --remote # Use cloud API
152
+ lanonasis mcp connect --local # Use local server
153
+
154
+ # Check MCP status
155
+ lanonasis mcp status
156
+
157
+ # List available tools
158
+ lanonasis mcp tools
159
+
160
+ # Memory operations via MCP
161
+ lanonasis mcp memory create -t "Title" -c "Content"
162
+ lanonasis mcp memory search "query"
163
+
164
+ # Stream real-time updates
165
+ lanonasis memory-mcp stream
166
+
167
+ # Configure MCP preferences
168
+ lanonasis mcp config --prefer-remote
169
+ ```
170
+
171
+ ### MCP Features:
172
+ - **Unified Interface**: Same commands for local/remote backends
173
+ - **Auto-Connect**: Automatically connects based on auth status
174
+ - **Tool Discovery**: Dynamic listing of available MCP tools
175
+ - **Real-time SSE**: Live updates when using remote mode
176
+ - **Hybrid Mode**: Seamless fallback between MCP and REST API
177
+
138
178
  ## 🌐 MaaS Service Integration
139
179
 
140
180
  This CLI is designed to work with Memory as a Service platforms that provide:
@@ -181,11 +221,43 @@ node dist/index-simple.js help
181
221
  - **Configuration** - Flexible service setup
182
222
  - **Help System** - Comprehensive documentation
183
223
 
224
+ ## šŸ“¦ SDK & Related Packages
225
+
226
+ ### Memory Client SDK
227
+ Install the TypeScript/JavaScript SDK for application integration:
228
+
229
+ ```bash
230
+ # Install SDK for your applications
231
+ npm install @lanonasis/memory-client
232
+
233
+ # Use in your code
234
+ import { createMemoryClient } from '@lanonasis/memory-client';
235
+
236
+ const client = createMemoryClient({
237
+ baseURL: 'https://api.lanonasis.com',
238
+ apiKey: 'your-api-key-here'
239
+ });
240
+ ```
241
+
242
+ ### Complete Installation for Developers
243
+ ```bash
244
+ # Install CLI globally for command-line usage
245
+ npm install -g @lanonasis/cli
246
+
247
+ # Install SDK locally for application development
248
+ npm install @lanonasis/memory-client
249
+
250
+ # Now you have both CLI and SDK available!
251
+ lanonasis --help # CLI commands
252
+ # SDK available for import in your code
253
+ ```
254
+
184
255
  ## šŸ”— Related Projects
185
256
 
186
- - **Memory Service Backend** - Full MaaS API server
187
- - **Memory SDK** - JavaScript/TypeScript SDK for developers
188
- - **Memory Visualizer** - Interactive memory exploration
257
+ - **Memory Service Backend** - Full MaaS API server ([GitHub](https://github.com/thefixer3x/vibe-memory))
258
+ - **Memory Client SDK** - JavaScript/TypeScript SDK (`@lanonasis/memory-client`)
259
+ - **Memory Visualizer** - Interactive memory exploration (included in backend)
260
+ - **VSCode Extension** - IDE integration (coming soon)
189
261
 
190
262
  ## šŸ“„ License
191
263
 
@@ -1 +1,6 @@
1
- export declare function loginCommand(options: any): Promise<void>;
1
+ interface LoginOptions {
2
+ email?: string;
3
+ password?: string;
4
+ }
5
+ export declare function loginCommand(options: LoginOptions): Promise<void>;
6
+ export {};
@@ -49,7 +49,9 @@ export async function loginCommand(options) {
49
49
  }
50
50
  catch (error) {
51
51
  spinner.fail('Login failed');
52
- if (error.response?.status === 401) {
52
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
53
+ const errorResponse = error && typeof error === 'object' && 'response' in error ? error.response : null;
54
+ if (errorResponse && typeof errorResponse === 'object' && 'status' in errorResponse && errorResponse.status === 401) {
53
55
  console.error(chalk.red('āœ– Invalid email or password'));
54
56
  // Ask if they want to register
55
57
  const answer = await inquirer.prompt([
@@ -65,7 +67,7 @@ export async function loginCommand(options) {
65
67
  }
66
68
  }
67
69
  else {
68
- console.error(chalk.red('āœ– Login failed:'), error.message);
70
+ console.error(chalk.red('āœ– Login failed:'), errorMessage);
69
71
  }
70
72
  process.exit(1);
71
73
  }
@@ -98,7 +100,7 @@ async function registerFlow(defaultEmail) {
98
100
  message: 'Confirm password:',
99
101
  mask: '*',
100
102
  validate: (input, answers) => {
101
- return input === answers.password || 'Passwords do not match';
103
+ return input === answers?.password || 'Passwords do not match';
102
104
  }
103
105
  },
104
106
  {
@@ -124,7 +126,8 @@ async function registerFlow(defaultEmail) {
124
126
  }
125
127
  catch (error) {
126
128
  spinner.fail('Registration failed');
127
- console.error(chalk.red('āœ– Registration failed:'), error.message);
129
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
130
+ console.error(chalk.red('āœ– Registration failed:'), errorMessage);
128
131
  process.exit(1);
129
132
  }
130
133
  }
@@ -3,6 +3,65 @@ import inquirer from 'inquirer';
3
3
  import { CLIConfig } from '../utils/config.js';
4
4
  import { apiClient } from '../utils/api.js';
5
5
  export function configCommands(program) {
6
+ // Generic config set command
7
+ program
8
+ .command('set <key> <value>')
9
+ .description('Set configuration value')
10
+ .action(async (key, value) => {
11
+ const config = new CLIConfig();
12
+ await config.init();
13
+ // Handle special cases
14
+ switch (key) {
15
+ case 'api-url':
16
+ await config.setApiUrl(value);
17
+ console.log(chalk.green('āœ“ API URL updated:'), value);
18
+ break;
19
+ case 'ai-integration':
20
+ if (value === 'claude-mcp') {
21
+ config.set('mcpEnabled', true);
22
+ config.set('aiIntegration', 'claude-mcp');
23
+ console.log(chalk.green('āœ“ AI integration set to Claude MCP'));
24
+ console.log(chalk.cyan(' MCP will be automatically initialized for memory operations'));
25
+ console.log(chalk.cyan(' Run "lanonasis mcp-server init" to test the connection'));
26
+ }
27
+ else {
28
+ console.log(chalk.yellow('āš ļø Unknown AI integration:'), value);
29
+ console.log(chalk.gray(' Currently supported: claude-mcp'));
30
+ }
31
+ break;
32
+ case 'mcp-use-remote':
33
+ config.set('mcpUseRemote', value === 'true');
34
+ console.log(chalk.green('āœ“ MCP remote mode:'), value === 'true' ? 'enabled' : 'disabled');
35
+ break;
36
+ case 'mcp-server-path':
37
+ config.set('mcpServerPath', value);
38
+ console.log(chalk.green('āœ“ MCP server path updated:'), value);
39
+ break;
40
+ case 'mcp-server-url':
41
+ config.set('mcpServerUrl', value);
42
+ console.log(chalk.green('āœ“ MCP server URL updated:'), value);
43
+ break;
44
+ default:
45
+ // Generic config set
46
+ config.set(key, value);
47
+ console.log(chalk.green(`āœ“ ${key} set to:`), value);
48
+ }
49
+ });
50
+ // Generic config get command
51
+ program
52
+ .command('get <key>')
53
+ .description('Get configuration value')
54
+ .action(async (key) => {
55
+ const config = new CLIConfig();
56
+ await config.init();
57
+ const value = config.get(key);
58
+ if (value !== undefined) {
59
+ console.log(chalk.green(`${key}:`), value);
60
+ }
61
+ else {
62
+ console.log(chalk.yellow(`āš ļø ${key} is not set`));
63
+ }
64
+ });
6
65
  // Show current configuration
7
66
  program
8
67
  .command('show')
@@ -26,6 +85,29 @@ export function configCommands(program) {
26
85
  }
27
86
  }
28
87
  });
88
+ // List all configuration options
89
+ program
90
+ .command('list')
91
+ .description('List all configuration options')
92
+ .action(async () => {
93
+ const config = new CLIConfig();
94
+ await config.init();
95
+ console.log(chalk.blue.bold('šŸ“‹ Configuration Options'));
96
+ console.log();
97
+ const configOptions = [
98
+ { key: 'api-url', description: 'API endpoint URL', current: config.getApiUrl() },
99
+ { key: 'ai-integration', description: 'AI integration mode', current: config.get('aiIntegration') || 'none' },
100
+ { key: 'mcp-use-remote', description: 'Use remote MCP server', current: config.get('mcpUseRemote') || false },
101
+ { key: 'mcp-server-path', description: 'Local MCP server path', current: config.get('mcpServerPath') || 'default' },
102
+ { key: 'mcp-server-url', description: 'Remote MCP server URL', current: config.get('mcpServerUrl') || 'https://api.lanonasis.com' },
103
+ { key: 'mcpEnabled', description: 'MCP integration enabled', current: config.get('mcpEnabled') || false }
104
+ ];
105
+ configOptions.forEach(opt => {
106
+ console.log(chalk.green(opt.key.padEnd(20)), chalk.gray(opt.description.padEnd(30)), chalk.yellow(String(opt.current)));
107
+ });
108
+ console.log();
109
+ console.log(chalk.gray('Use "lanonasis config set <key> <value>" to update any option'));
110
+ });
29
111
  // Set API URL
30
112
  program
31
113
  .command('set-url')
@@ -72,24 +154,26 @@ export function configCommands(program) {
72
154
  console.log(chalk.green('āœ“ Connection successful'));
73
155
  console.log(`Status: ${health.status}`);
74
156
  console.log(`Version: ${health.version}`);
75
- console.log(`Uptime: ${Math.round(health.uptime)}s`);
76
157
  if (health.dependencies) {
77
158
  console.log();
78
159
  console.log(chalk.yellow('Dependencies:'));
79
160
  Object.entries(health.dependencies).forEach(([name, info]) => {
80
161
  const status = info.status === 'healthy' ? chalk.green('āœ“') : chalk.red('āœ–');
81
- console.log(` ${status} ${name}: ${info.status} (${info.response_time}ms)`);
162
+ const responseTime = info.response_time || info.latency_ms || 0;
163
+ console.log(` ${status} ${name}: ${info.status} (${responseTime}ms)`);
82
164
  });
83
165
  }
84
166
  }
85
167
  catch (error) {
86
168
  console.log(chalk.red('āœ– Connection failed'));
87
- if (error.code === 'ECONNREFUSED') {
169
+ const errorCode = error && typeof error === 'object' && 'code' in error ? error.code : null;
170
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
171
+ if (errorCode === 'ECONNREFUSED') {
88
172
  console.error(chalk.red('Cannot connect to API server'));
89
173
  console.log(chalk.yellow('Make sure the API server is running'));
90
174
  }
91
175
  else {
92
- console.error(chalk.red('Error:'), error.message);
176
+ console.error(chalk.red('Error:'), errorMessage);
93
177
  }
94
178
  process.exit(1);
95
179
  }
@@ -1 +1,5 @@
1
- export declare function initCommand(options: any): Promise<void>;
1
+ interface InitOptions {
2
+ force?: boolean;
3
+ }
4
+ export declare function initCommand(options: InitOptions): Promise<void>;
5
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function mcpCommands(program: Command): void;
@@ -0,0 +1,318 @@
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 { CLIConfig } from '../utils/config.js';
6
+ export function mcpCommands(program) {
7
+ const mcp = program
8
+ .command('mcp')
9
+ .description('MCP (Model Context Protocol) server operations');
10
+ // Also register mcp-server command directly on program for convenience
11
+ const mcpServer = program
12
+ .command('mcp-server')
13
+ .description('MCP server initialization and management');
14
+ mcpServer.command('init')
15
+ .description('Initialize MCP server configuration')
16
+ .action(async () => {
17
+ console.log(chalk.cyan('šŸš€ Initializing MCP Server Configuration'));
18
+ console.log('');
19
+ const config = new CLIConfig();
20
+ const isAuthenticated = !!config.get('token');
21
+ if (isAuthenticated) {
22
+ console.log(chalk.green('āœ“ Authenticated - Using remote MCP mode'));
23
+ console.log(' Your memory operations will use api.lanonasis.com');
24
+ console.log(' with real-time SSE updates enabled');
25
+ }
26
+ else {
27
+ console.log(chalk.yellow('āš ļø Not authenticated - Using local MCP mode'));
28
+ console.log(' Run "lanonasis auth login" to enable remote mode');
29
+ }
30
+ console.log('');
31
+ console.log(chalk.cyan('Available MCP Commands:'));
32
+ console.log(' lanonasis mcp connect # Auto-connect to best mode');
33
+ console.log(' lanonasis mcp connect -r # Force remote mode');
34
+ console.log(' lanonasis mcp connect -l # Force local mode');
35
+ console.log(' lanonasis mcp status # Check connection status');
36
+ console.log(' lanonasis mcp tools # List available tools');
37
+ console.log('');
38
+ console.log(chalk.cyan('Memory operations are MCP-powered by default!'));
39
+ // Auto-connect to MCP
40
+ const spinner = ora('Auto-connecting to MCP...').start();
41
+ try {
42
+ const client = getMCPClient();
43
+ const connected = await client.connect({ useRemote: isAuthenticated });
44
+ if (connected) {
45
+ spinner.succeed(chalk.green(`Connected to ${isAuthenticated ? 'remote' : 'local'} MCP server`));
46
+ }
47
+ else {
48
+ spinner.fail('Failed to auto-connect to MCP');
49
+ }
50
+ }
51
+ catch (error) {
52
+ spinner.fail('MCP auto-connect failed');
53
+ }
54
+ });
55
+ // Connect command
56
+ mcp.command('connect')
57
+ .description('Connect to MCP server (local or remote)')
58
+ .option('-l, --local', 'Connect to local MCP server')
59
+ .option('-r, --remote', 'Connect to remote MCP server (api.lanonasis.com)')
60
+ .option('-s, --server <path>', 'Local MCP server path')
61
+ .option('-u, --url <url>', 'Remote MCP server URL')
62
+ .action(async (options) => {
63
+ const spinner = ora('Connecting to MCP server...').start();
64
+ const config = new CLIConfig();
65
+ try {
66
+ // Determine connection mode
67
+ let useRemote = options.remote;
68
+ if (!options.local && !options.remote) {
69
+ // Default to remote if authenticated, otherwise local
70
+ useRemote = !!config.get('token');
71
+ }
72
+ // Save preference
73
+ config.set('mcpUseRemote', useRemote);
74
+ if (options.server) {
75
+ config.set('mcpServerPath', options.server);
76
+ }
77
+ if (options.url) {
78
+ config.set('mcpServerUrl', options.url);
79
+ }
80
+ const client = getMCPClient();
81
+ const connected = await client.connect({
82
+ useRemote,
83
+ serverPath: options.server,
84
+ serverUrl: options.url
85
+ });
86
+ if (connected) {
87
+ spinner.succeed(chalk.green(`Connected to ${useRemote ? 'remote' : 'local'} MCP server`));
88
+ if (useRemote) {
89
+ console.log(chalk.cyan('ā„¹ļø Using remote MCP via api.lanonasis.com'));
90
+ console.log(chalk.cyan('šŸ“” SSE endpoint active for real-time updates'));
91
+ }
92
+ }
93
+ else {
94
+ spinner.fail('Failed to connect to MCP server');
95
+ }
96
+ }
97
+ catch (error) {
98
+ spinner.fail(`Connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
99
+ process.exit(1);
100
+ }
101
+ });
102
+ // Disconnect command
103
+ mcp.command('disconnect')
104
+ .description('Disconnect from MCP server')
105
+ .action(async () => {
106
+ const client = getMCPClient();
107
+ await client.disconnect();
108
+ console.log(chalk.green('āœ“ Disconnected from MCP server'));
109
+ });
110
+ // Status command
111
+ mcp.command('status')
112
+ .description('Show MCP connection status')
113
+ .action(async () => {
114
+ const client = getMCPClient();
115
+ const status = client.getConnectionStatus();
116
+ console.log(chalk.cyan('\nšŸ“Š MCP Connection Status'));
117
+ console.log(chalk.cyan('========================'));
118
+ console.log(`Status: ${status.connected ? chalk.green('Connected') : chalk.red('Disconnected')}`);
119
+ console.log(`Mode: ${status.mode === 'remote' ? chalk.blue('Remote (API)') : chalk.yellow('Local')}`);
120
+ console.log(`Server: ${status.server}`);
121
+ if (status.connected && status.mode === 'remote') {
122
+ console.log(`\n${chalk.cyan('Features:')}`);
123
+ console.log('• Real-time updates via SSE');
124
+ console.log('• Authenticated API access');
125
+ console.log('• MCP-compatible tool interface');
126
+ }
127
+ });
128
+ // List tools command
129
+ mcp.command('tools')
130
+ .description('List available MCP tools')
131
+ .action(async () => {
132
+ const spinner = ora('Fetching available tools...').start();
133
+ try {
134
+ const client = getMCPClient();
135
+ if (!client.isConnectedToServer()) {
136
+ spinner.info('Not connected. Attempting auto-connect...');
137
+ const config = new CLIConfig();
138
+ const useRemote = !!config.get('token');
139
+ await client.connect({ useRemote });
140
+ }
141
+ const tools = await client.listTools();
142
+ spinner.succeed('Tools fetched successfully');
143
+ console.log(chalk.cyan('\nšŸ”§ Available MCP Tools'));
144
+ console.log(chalk.cyan('====================='));
145
+ const tableData = [
146
+ [chalk.bold('Tool Name'), chalk.bold('Description')]
147
+ ];
148
+ tools.forEach(tool => {
149
+ tableData.push([
150
+ chalk.green(tool.name),
151
+ tool.description
152
+ ]);
153
+ });
154
+ console.log(table(tableData, {
155
+ border: {
156
+ topBody: '─',
157
+ topJoin: '┬',
158
+ topLeft: 'ā”Œ',
159
+ topRight: '┐',
160
+ bottomBody: '─',
161
+ bottomJoin: '┓',
162
+ bottomLeft: 'ā””',
163
+ bottomRight: 'ā”˜',
164
+ bodyLeft: '│',
165
+ bodyRight: '│',
166
+ bodyJoin: '│',
167
+ joinBody: '─',
168
+ joinLeft: 'ā”œ',
169
+ joinRight: '┤',
170
+ joinJoin: '┼'
171
+ }
172
+ }));
173
+ }
174
+ catch (error) {
175
+ spinner.fail(`Failed to fetch tools: ${error instanceof Error ? error.message : 'Unknown error'}`);
176
+ process.exit(1);
177
+ }
178
+ });
179
+ // Call tool command
180
+ mcp.command('call')
181
+ .description('Call an MCP tool directly')
182
+ .argument('<tool>', 'Tool name to call')
183
+ .option('-a, --args <json>', 'Tool arguments as JSON')
184
+ .action(async (toolName, options) => {
185
+ const spinner = ora(`Calling tool: ${toolName}...`).start();
186
+ try {
187
+ const client = getMCPClient();
188
+ if (!client.isConnectedToServer()) {
189
+ spinner.info('Not connected. Attempting auto-connect...');
190
+ const config = new CLIConfig();
191
+ const useRemote = !!config.get('token');
192
+ await client.connect({ useRemote });
193
+ }
194
+ let args = {};
195
+ if (options.args) {
196
+ try {
197
+ args = JSON.parse(options.args);
198
+ }
199
+ catch (error) {
200
+ spinner.fail('Invalid JSON arguments');
201
+ process.exit(1);
202
+ }
203
+ }
204
+ const result = await client.callTool(toolName, args);
205
+ spinner.succeed(`Tool ${toolName} executed successfully`);
206
+ console.log(chalk.cyan('\nšŸ“¤ Tool Result:'));
207
+ console.log(JSON.stringify(result, null, 2));
208
+ }
209
+ catch (error) {
210
+ spinner.fail(`Tool execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
211
+ process.exit(1);
212
+ }
213
+ });
214
+ // Memory-specific MCP commands
215
+ const memory = mcp.command('memory')
216
+ .description('Memory operations via MCP');
217
+ memory.command('create')
218
+ .description('Create memory via MCP')
219
+ .requiredOption('-t, --title <title>', 'Memory title')
220
+ .requiredOption('-c, --content <content>', 'Memory content')
221
+ .option('-T, --type <type>', 'Memory type', 'context')
222
+ .option('--tags <tags>', 'Comma-separated tags')
223
+ .action(async (options) => {
224
+ const spinner = ora('Creating memory via MCP...').start();
225
+ try {
226
+ const client = getMCPClient();
227
+ if (!client.isConnectedToServer()) {
228
+ spinner.info('Not connected. Attempting auto-connect...');
229
+ const config = new CLIConfig();
230
+ const useRemote = !!config.get('token');
231
+ await client.connect({ useRemote });
232
+ }
233
+ const result = await client.callTool('memory_create_memory', {
234
+ title: options.title,
235
+ content: options.content,
236
+ memory_type: options.type,
237
+ tags: options.tags ? options.tags.split(',').map((t) => t.trim()) : []
238
+ });
239
+ spinner.succeed('Memory created successfully');
240
+ console.log(chalk.green('\nāœ“ Memory created'));
241
+ console.log(`ID: ${chalk.cyan(result.id)}`);
242
+ console.log(`Title: ${result.title}`);
243
+ console.log(`Type: ${result.memory_type}`);
244
+ }
245
+ catch (error) {
246
+ spinner.fail(`Failed to create memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
247
+ process.exit(1);
248
+ }
249
+ });
250
+ memory.command('search')
251
+ .description('Search memories via MCP')
252
+ .argument('<query>', 'Search query')
253
+ .option('-l, --limit <number>', 'Maximum results', '10')
254
+ .option('-t, --threshold <number>', 'Similarity threshold (0-1)', '0.7')
255
+ .action(async (query, options) => {
256
+ const spinner = ora('Searching memories via MCP...').start();
257
+ try {
258
+ const client = getMCPClient();
259
+ if (!client.isConnectedToServer()) {
260
+ spinner.info('Not connected. Attempting auto-connect...');
261
+ const config = new CLIConfig();
262
+ const useRemote = !!config.get('token');
263
+ await client.connect({ useRemote });
264
+ }
265
+ const results = await client.callTool('memory_search_memories', {
266
+ query,
267
+ limit: parseInt(options.limit),
268
+ threshold: parseFloat(options.threshold)
269
+ });
270
+ spinner.succeed(`Found ${results.length} memories`);
271
+ if (results.length === 0) {
272
+ console.log(chalk.yellow('\nNo memories found matching your query'));
273
+ return;
274
+ }
275
+ console.log(chalk.cyan('\nšŸ” Search Results:'));
276
+ results.forEach((memory, index) => {
277
+ console.log(`\n${chalk.bold(`${index + 1}. ${memory.title}`)}`);
278
+ console.log(` ID: ${chalk.gray(memory.id)}`);
279
+ console.log(` Type: ${chalk.blue(memory.memory_type)}`);
280
+ console.log(` Score: ${chalk.green((memory.relevance_score * 100).toFixed(1) + '%')}`);
281
+ console.log(` Content: ${memory.content.substring(0, 100)}...`);
282
+ });
283
+ }
284
+ catch (error) {
285
+ spinner.fail(`Search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
286
+ process.exit(1);
287
+ }
288
+ });
289
+ // Configure MCP preferences
290
+ mcp.command('config')
291
+ .description('Configure MCP preferences')
292
+ .option('--prefer-remote', 'Prefer remote MCP server when available')
293
+ .option('--prefer-local', 'Prefer local MCP server')
294
+ .option('--auto', 'Auto-detect best connection mode')
295
+ .action(async (options) => {
296
+ const config = new CLIConfig();
297
+ if (options.preferRemote) {
298
+ config.set('mcpPreference', 'remote');
299
+ console.log(chalk.green('āœ“ Set MCP preference to remote'));
300
+ }
301
+ else if (options.preferLocal) {
302
+ config.set('mcpPreference', 'local');
303
+ console.log(chalk.green('āœ“ Set MCP preference to local'));
304
+ }
305
+ else if (options.auto) {
306
+ config.set('mcpPreference', 'auto');
307
+ console.log(chalk.green('āœ“ Set MCP preference to auto-detect'));
308
+ }
309
+ else {
310
+ const current = config.get('mcpPreference') || 'auto';
311
+ console.log(`Current MCP preference: ${chalk.cyan(current)}`);
312
+ console.log('\nOptions:');
313
+ console.log(' --prefer-remote : Use remote MCP server (api.lanonasis.com)');
314
+ console.log(' --prefer-local : Use local MCP server');
315
+ console.log(' --auto : Auto-detect based on authentication');
316
+ }
317
+ });
318
+ }