@mcp-use/cli 1.0.0 → 1.0.1

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.
Files changed (54) hide show
  1. package/dist/InputPrompt.d.ts +13 -0
  2. package/dist/InputPrompt.js +188 -0
  3. package/dist/MultilineInput.d.ts +13 -0
  4. package/dist/MultilineInput.js +154 -0
  5. package/dist/MultilineTextInput.d.ts +11 -0
  6. package/dist/MultilineTextInput.js +97 -0
  7. package/dist/PasteAwareInput.d.ts +13 -0
  8. package/dist/PasteAwareInput.js +183 -0
  9. package/dist/SimpleMultilineInput.d.ts +11 -0
  10. package/dist/SimpleMultilineInput.js +125 -0
  11. package/dist/app.d.ts +1 -5
  12. package/dist/app.js +291 -186
  13. package/dist/cli.js +2 -5
  14. package/dist/commands.d.ts +15 -30
  15. package/dist/commands.js +308 -568
  16. package/dist/components/AsciiLogo.d.ts +2 -0
  17. package/dist/components/AsciiLogo.js +7 -0
  18. package/dist/components/Footer.d.ts +5 -0
  19. package/dist/components/Footer.js +19 -0
  20. package/dist/components/InputPrompt.d.ts +13 -0
  21. package/dist/components/InputPrompt.js +188 -0
  22. package/dist/components/Messages.d.ts +21 -0
  23. package/dist/components/Messages.js +80 -0
  24. package/dist/components/ServerStatus.d.ts +7 -0
  25. package/dist/components/ServerStatus.js +36 -0
  26. package/dist/components/Spinner.d.ts +16 -0
  27. package/dist/components/Spinner.js +63 -0
  28. package/dist/components/ToolStatus.d.ts +8 -0
  29. package/dist/components/ToolStatus.js +33 -0
  30. package/dist/components/textInput.d.ts +1 -0
  31. package/dist/components/textInput.js +1 -0
  32. package/dist/logger.d.ts +10 -0
  33. package/dist/logger.js +48 -0
  34. package/dist/mcp-service.d.ts +5 -4
  35. package/dist/mcp-service.js +98 -207
  36. package/dist/services/agent-service.d.ts +56 -0
  37. package/dist/services/agent-service.js +203 -0
  38. package/dist/services/cli-service.d.ts +132 -0
  39. package/dist/services/cli-service.js +591 -0
  40. package/dist/services/index.d.ts +4 -0
  41. package/dist/services/index.js +4 -0
  42. package/dist/services/llm-service.d.ts +174 -0
  43. package/dist/services/llm-service.js +567 -0
  44. package/dist/services/mcp-config-service.d.ts +69 -0
  45. package/dist/services/mcp-config-service.js +426 -0
  46. package/dist/services/mcp-service.d.ts +1 -0
  47. package/dist/services/mcp-service.js +1 -0
  48. package/dist/services/utility-service.d.ts +47 -0
  49. package/dist/services/utility-service.js +208 -0
  50. package/dist/storage.js +4 -4
  51. package/dist/types.d.ts +30 -0
  52. package/dist/types.js +1 -0
  53. package/package.json +22 -8
  54. package/readme.md +68 -39
@@ -0,0 +1,591 @@
1
+ import { config } from 'dotenv';
2
+ import { Logger } from '../logger.js';
3
+ import { AgentService } from './agent-service.js';
4
+ import { LLMService } from './llm-service.js';
5
+ import { MCPConfigService } from './mcp-config-service.js';
6
+ import { UtilityService } from './utility-service.js';
7
+ // Load environment variables
8
+ config();
9
+ export class CLIService {
10
+ /**
11
+ * Initializes the CLIService and its dependencies. This acts as the
12
+ * composition root for the application's services.
13
+ */
14
+ constructor() {
15
+ Object.defineProperty(this, "isInitialized", {
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true,
19
+ value: false
20
+ });
21
+ Object.defineProperty(this, "agentService", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: void 0
26
+ });
27
+ Object.defineProperty(this, "llmService", {
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true,
31
+ value: void 0
32
+ });
33
+ Object.defineProperty(this, "mcpConfigService", {
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true,
37
+ value: void 0
38
+ });
39
+ Object.defineProperty(this, "utilityService", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: void 0
44
+ });
45
+ Object.defineProperty(this, "commandRegistry", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+ // Initialize services
52
+ this.llmService = new LLMService();
53
+ this.mcpConfigService = new MCPConfigService();
54
+ this.agentService = new AgentService({
55
+ llmService: this.llmService,
56
+ });
57
+ this.utilityService = new UtilityService({
58
+ llmService: this.llmService,
59
+ mcpConfigService: this.mcpConfigService,
60
+ });
61
+ // Initialize command registry
62
+ this.commandRegistry = new Map();
63
+ this.registerCommands();
64
+ }
65
+ /**
66
+ * Registers all available commands in the command registry.
67
+ * This creates a centralized mapping of command names to their handlers.
68
+ */
69
+ registerCommands() {
70
+ // LLM-related commands
71
+ this.commandRegistry.set('/model', {
72
+ handler: args => this.llmService.handleModelCommand(args),
73
+ description: 'Choose your LLM provider and model',
74
+ });
75
+ this.commandRegistry.set('/models', {
76
+ handler: args => this.llmService.handleListModelsCommand(args),
77
+ description: 'List available models',
78
+ });
79
+ this.commandRegistry.set('/setkey', {
80
+ handler: args => this.llmService.handleSetKeyCommand(args),
81
+ description: 'Set API key manually',
82
+ });
83
+ this.commandRegistry.set('/clearkeys', {
84
+ handler: () => this.llmService.handleClearKeysCommand(),
85
+ description: 'Clear all stored API keys',
86
+ });
87
+ this.commandRegistry.set('/config', {
88
+ handler: args => this.llmService.handleConfigCommand(args),
89
+ description: 'Configure temperature and max tokens',
90
+ });
91
+ // MCP server commands with subcommands
92
+ this.commandRegistry.set('/server', {
93
+ handler: args => this.handleServerCommand(args),
94
+ description: 'Manage MCP servers',
95
+ });
96
+ this.commandRegistry.set('/server add', {
97
+ handler: () => this.handleServerAddCommand(),
98
+ description: 'Configure a new server',
99
+ });
100
+ this.commandRegistry.set('/server connect', {
101
+ handler: async (args) => this.handleServerConnectCommand(args),
102
+ description: 'Connect to a configured server',
103
+ });
104
+ this.commandRegistry.set('/server disconnect', {
105
+ handler: async (args) => this.handleServerDisconnectCommand(args),
106
+ description: 'Disconnect from a server',
107
+ });
108
+ this.commandRegistry.set('/servers', {
109
+ handler: () => this.handleListServersCommand(),
110
+ description: 'List configured servers',
111
+ });
112
+ this.commandRegistry.set('/test-server', {
113
+ handler: args => this.mcpConfigService.handleTestServerCommand(args),
114
+ description: 'Test server configuration',
115
+ });
116
+ this.commandRegistry.set('/tools', {
117
+ handler: () => this.agentService.handleListToolsCommand(),
118
+ description: 'Show available MCP tools',
119
+ });
120
+ // Utility commands
121
+ this.commandRegistry.set('/help', {
122
+ handler: () => this.utilityService.handleHelpCommand(),
123
+ description: 'Show this help',
124
+ });
125
+ this.commandRegistry.set('/status', {
126
+ handler: () => this.utilityService.handleStatusCommand(),
127
+ description: 'Show current configuration',
128
+ });
129
+ this.commandRegistry.set('/logs', {
130
+ handler: args => this.utilityService.handleLogsCommand(args),
131
+ description: 'View debug logs',
132
+ });
133
+ this.commandRegistry.set('/clearlogs', {
134
+ handler: () => this.utilityService.handleClearLogsCommand(),
135
+ description: 'Clear debug logs',
136
+ });
137
+ this.commandRegistry.set('/history', {
138
+ handler: () => this.utilityService.handleHistoryCommand(),
139
+ description: 'Info about input history navigation',
140
+ });
141
+ }
142
+ /**
143
+ * Initializes the CLI service, ensuring the agent is ready.
144
+ * This method is idempotent and will only run once.
145
+ */
146
+ async initialize() {
147
+ if (this.isInitialized) {
148
+ return;
149
+ }
150
+ await this.initializeAgent();
151
+ this.isInitialized = true;
152
+ }
153
+ /**
154
+ * Initializes the underlying MCP agent via the AgentService.
155
+ * If initialization fails, an error is logged, but the CLI can continue
156
+ * to operate for command-line tasks.
157
+ */
158
+ async initializeAgent() {
159
+ try {
160
+ Logger.info('Agent service initialized successfully.');
161
+ }
162
+ catch (error) {
163
+ Logger.error('Agent service initialization failed.', {
164
+ error: error instanceof Error ? error.message : String(error),
165
+ });
166
+ }
167
+ }
168
+ /**
169
+ * Re-initializes the agent. This is useful when the configuration
170
+ * (e.g., model or servers) has changed.
171
+ */
172
+ async refreshAgent() {
173
+ await this.initializeAgent();
174
+ }
175
+ /**
176
+ * Checks if the input is a slash command.
177
+ * @param input - The user input to check
178
+ * @returns True if the input starts with /
179
+ */
180
+ isCommand(input) {
181
+ return input.trim().startsWith('/');
182
+ }
183
+ /**
184
+ * Handles command execution by routing to the appropriate service.
185
+ * @param input - The full command input including the slash
186
+ * @returns A promise that resolves to the command result
187
+ */
188
+ async handleCommand(input) {
189
+ const parts = input.trim().split(/\s+/);
190
+ const command = parts[0];
191
+ let args = parts.slice(1);
192
+ // Try to match with subcommand first
193
+ let commandEntry = null;
194
+ if (args.length > 0) {
195
+ // Try matching with one subcommand (e.g., "/server add")
196
+ const withSubcommand = `${command} ${args[0]}`;
197
+ commandEntry = this.commandRegistry.get(withSubcommand);
198
+ if (commandEntry) {
199
+ // Remove the subcommand from args since it's part of the command
200
+ args = args.slice(1);
201
+ }
202
+ }
203
+ // If no subcommand match, try the base command
204
+ if (!commandEntry) {
205
+ commandEntry = this.commandRegistry.get(command);
206
+ }
207
+ if (!commandEntry) {
208
+ return {
209
+ type: 'error',
210
+ message: `Unknown command: ${command}. Type /help for available commands.`,
211
+ };
212
+ }
213
+ // Execute the command handler
214
+ try {
215
+ return await commandEntry.handler(args);
216
+ }
217
+ catch (error) {
218
+ Logger.error(`Error executing command ${command}`, {
219
+ error: error instanceof Error ? error.message : String(error),
220
+ stack: error instanceof Error ? error.stack : undefined,
221
+ });
222
+ return {
223
+ type: 'error',
224
+ message: `Command failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
225
+ };
226
+ }
227
+ }
228
+ /**
229
+ * Processes a user's message. It determines if the message is a command
230
+ * or a prompt for the agent and routes it accordingly. It also handles
231
+ * special input modes like API key entry or server configuration.
232
+ * @param message The raw input string from the user.
233
+ * @param isApiKeyInput True if the input is an API key.
234
+ * @param pendingProvider The provider for which the API key is being entered.
235
+ * @param pendingModel The model for which the API key is being entered.
236
+ * @param isServerConfigInput True if the input is part of the server config flow.
237
+ * @param serverConfigStep The current step in the server configuration flow.
238
+ * @param serverConfig The server configuration object being built.
239
+ * @returns A promise that resolves to the result of the message processing.
240
+ */
241
+ async *sendMessage(message, isApiKeyInput, pendingProvider, pendingModel, isServerConfigInput, serverConfigStep, serverConfig) {
242
+ // Handle server configuration input (non-streaming)
243
+ if (isServerConfigInput && serverConfigStep) {
244
+ const commandResult = this.mcpConfigService.handleServerConfigInput(message.trim(), serverConfigStep, serverConfig);
245
+ yield {
246
+ response: commandResult.message,
247
+ toolCalls: [],
248
+ isCommand: true,
249
+ commandResult,
250
+ done: true,
251
+ };
252
+ return;
253
+ }
254
+ // Handle API key input (non-streaming)
255
+ if (isApiKeyInput && pendingProvider && pendingModel) {
256
+ const commandResult = this.llmService.handleApiKeyInput(message.trim(), pendingProvider, pendingModel);
257
+ // If successful, reinitialize the agent
258
+ if (commandResult.data?.llmConfig) {
259
+ await this.initializeAgent();
260
+ }
261
+ yield {
262
+ response: commandResult.message,
263
+ toolCalls: [],
264
+ isCommand: true,
265
+ commandResult,
266
+ done: true,
267
+ };
268
+ return;
269
+ }
270
+ // Check if it's a slash command (non-streaming)
271
+ if (this.isCommand(message)) {
272
+ try {
273
+ const commandResult = await this.handleCommand(message);
274
+ // Handle special commands that need coordination
275
+ if (commandResult.data?.checkTools) {
276
+ const toolsResult = await this.agentService.getAvailableTools();
277
+ yield {
278
+ response: 'Available MCP Tools',
279
+ toolCalls: [],
280
+ isCommand: true,
281
+ commandResult: {
282
+ type: 'list_tools',
283
+ message: 'Available MCP Tools',
284
+ data: toolsResult,
285
+ },
286
+ done: true,
287
+ };
288
+ return;
289
+ }
290
+ // If the command changed the LLM config, added servers, or needs agent reinitialization
291
+ if (commandResult.data?.llmConfig ||
292
+ commandResult.data?.serversAdded ||
293
+ commandResult.data?.reinitializeAgent) {
294
+ await this.initializeAgent();
295
+ }
296
+ yield {
297
+ response: commandResult.message,
298
+ toolCalls: [],
299
+ isCommand: true,
300
+ commandResult,
301
+ done: true,
302
+ };
303
+ return;
304
+ }
305
+ catch (error) {
306
+ yield {
307
+ response: `Command error: ${error instanceof Error ? error.message : 'Unknown error'}`,
308
+ toolCalls: [],
309
+ isCommand: true,
310
+ commandResult: { type: 'error', message: 'Command failed' },
311
+ done: true,
312
+ };
313
+ return;
314
+ }
315
+ }
316
+ if (!this.agentService.isReady()) {
317
+ const availableProviders = this.llmService.getAvailableProviders();
318
+ if (availableProviders.length === 0) {
319
+ yield {
320
+ response: `🤖 Choose a model to get started!\n\nTry one of these popular options:\n• /model openai gpt-4o-mini\n• /model anthropic claude-3-5-sonnet-20241022\n• /model google gemini-1.5-pro\n\nThe CLI will help you set up the API key when needed.\nUse /models to see all available models.`,
321
+ toolCalls: [],
322
+ done: true,
323
+ };
324
+ }
325
+ else {
326
+ const firstProvider = availableProviders[0];
327
+ const exampleModel = firstProvider
328
+ ? this.getExampleModel(firstProvider)
329
+ : 'model-name';
330
+ yield {
331
+ response: `🔧 No model selected.\n\nAvailable providers: ${availableProviders.join(', ')}\n\nUse /model <provider> <model> to get started.\n\nExample: /model ${firstProvider} ${exampleModel}`,
332
+ toolCalls: [],
333
+ done: true,
334
+ };
335
+ }
336
+ return;
337
+ }
338
+ // Handle agent messages (streaming)
339
+ try {
340
+ const generator = this.agentService.sendMessage(message);
341
+ for await (const chunk of generator) {
342
+ yield {
343
+ response: chunk.response,
344
+ toolCalls: chunk.toolCalls,
345
+ thought: chunk.thought,
346
+ isCommand: false,
347
+ done: false,
348
+ };
349
+ }
350
+ yield { done: true };
351
+ }
352
+ catch (error) {
353
+ Logger.error('Error sending message via Agent service', {
354
+ error: error instanceof Error ? error.message : 'Unknown error',
355
+ stack: error instanceof Error ? error.stack : undefined,
356
+ });
357
+ yield {
358
+ response: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
359
+ thought: undefined,
360
+ done: true,
361
+ };
362
+ }
363
+ }
364
+ /**
365
+ * Returns an example model name for a given provider.
366
+ * @param provider The name of the LLM provider.
367
+ * @returns An example model name string.
368
+ */
369
+ getExampleModel(provider) {
370
+ const examples = {
371
+ openai: 'gpt-4o-mini',
372
+ anthropic: 'claude-3-5-sonnet-20241022',
373
+ google: 'gemini-1.5-pro',
374
+ mistral: 'mistral-large-latest',
375
+ };
376
+ return examples[provider] || 'model-name';
377
+ }
378
+ /**
379
+ * Checks if the CLI service has been initialized.
380
+ * @returns True if the service is initialized, false otherwise.
381
+ */
382
+ isReady() {
383
+ // The CLI is always "ready" to take commands, but the agent might not be.
384
+ // We rely on agentService.isReady() inside sendMessage.
385
+ return this.isInitialized;
386
+ }
387
+ /**
388
+ * Gets a formatted string representing the current model.
389
+ * @returns A string like "provider/model-name" or a status message.
390
+ */
391
+ getCurrentModel() {
392
+ const config = this.llmService.getCurrentConfig();
393
+ if (!config) {
394
+ const availableProviders = this.llmService.getAvailableProviders();
395
+ if (availableProviders.length === 0) {
396
+ return 'No API keys configured';
397
+ }
398
+ return 'No model selected';
399
+ }
400
+ return `${config.provider}/${config.model}`;
401
+ }
402
+ /**
403
+ * Gets a list of all configured server names from persistent storage.
404
+ * @returns An array of configured server names.
405
+ */
406
+ getConfiguredServers() {
407
+ const storedServers = this.mcpConfigService.getConfiguredServers();
408
+ return Object.keys(storedServers);
409
+ }
410
+ /**
411
+ * Gets a list of currently connected server names.
412
+ * @returns An array of connected server names.
413
+ */
414
+ getConnectedServers() {
415
+ return this.agentService.getConnectedServerNames();
416
+ }
417
+ /**
418
+ * Gets the list of available tools from the agent.
419
+ * @returns A promise that resolves to an object containing the tools or an error.
420
+ */
421
+ async getAvailableTools() {
422
+ return this.agentService.getAvailableTools();
423
+ }
424
+ /**
425
+ * Handles the /servers command by combining configuration and connection status.
426
+ * @returns A CommandResult with the server list including connection status
427
+ */
428
+ handleListServersCommand() {
429
+ const configuredServers = this.mcpConfigService.getAllServers();
430
+ const connectedServerNames = this.agentService.getConnectedServerNames();
431
+ if (configuredServers.length === 0) {
432
+ return {
433
+ type: 'info',
434
+ message: 'No custom servers configured.\n\nUse /server add to configure servers, then /server connect <name> to connect.',
435
+ };
436
+ }
437
+ // Add connection status to each server
438
+ const serversWithStatus = configuredServers.map(server => ({
439
+ ...server,
440
+ isConnected: connectedServerNames.includes(server.name),
441
+ }));
442
+ return {
443
+ type: 'list_servers',
444
+ message: 'MCP Server Status:',
445
+ data: { servers: serversWithStatus },
446
+ };
447
+ }
448
+ /**
449
+ * Handles the base /server command to show subcommands.
450
+ * @param args - Command arguments
451
+ * @returns A CommandResult with help information
452
+ */
453
+ handleServerCommand(args) {
454
+ if (args.length === 0) {
455
+ return {
456
+ type: 'info',
457
+ message: 'Server management commands:\n\n/server add - Configure a new server (stored but not connected)\n/server connect <name> - Connect to a configured server by name\n/server disconnect <name> - Disconnect from a connected server\n/servers - List configured servers and connection status\n\nUse /server <command> for specific help.',
458
+ };
459
+ }
460
+ // If we get here, it means the subcommand wasn't recognized
461
+ return {
462
+ type: 'error',
463
+ message: 'Usage: /server <command>\n\nCommands:\n add - Configure server\n connect <name> - Connect to server\n disconnect <name> - Disconnect server\n\nExample: /server connect airbnb',
464
+ };
465
+ }
466
+ /**
467
+ * Handles the /server add subcommand.
468
+ * @returns A CommandResult to start server configuration
469
+ */
470
+ handleServerAddCommand() {
471
+ return {
472
+ type: 'prompt_server_config',
473
+ message: 'Let\'s configure a new MCP server!\n\nYou can either:\n1. Enter a server name for interactive setup\n2. Paste a complete JSON configuration\n\nExample JSON:\n{\n "mcpServers": {\n "myserver": {\n "command": "npx",\n "args": ["-y", "@example/server"]\n }\n }\n}\n\nEnter server name or paste JSON:',
474
+ data: { step: 'name_or_json' },
475
+ };
476
+ }
477
+ /**
478
+ * Handles the /server connect subcommand.
479
+ * @param args - Array where args[0] is the server name
480
+ * @returns A CommandResult with connection status
481
+ */
482
+ async handleServerConnectCommand(args) {
483
+ if (args.length === 0) {
484
+ const configuredServers = Object.keys(this.mcpConfigService.getConfiguredServers());
485
+ if (configuredServers.length === 0) {
486
+ return {
487
+ type: 'error',
488
+ message: 'No servers configured. Use /server add to configure servers first.\n\nUsage: /server connect <server_name>',
489
+ };
490
+ }
491
+ return {
492
+ type: 'error',
493
+ message: `Usage: /server connect <server_name>\n\nConfigured servers: ${configuredServers.join(', ')}`,
494
+ };
495
+ }
496
+ const serverName = args[0];
497
+ if (!serverName) {
498
+ return {
499
+ type: 'error',
500
+ message: 'Server name is required.\n\nUsage: /server connect <server_name>',
501
+ };
502
+ }
503
+ // Get the server configuration
504
+ const serverConfig = this.mcpConfigService.getServerConfig(serverName);
505
+ if (!serverConfig) {
506
+ return {
507
+ type: 'error',
508
+ message: `Server "${serverName}" is not configured.`,
509
+ };
510
+ }
511
+ // Check if already connected
512
+ if (this.agentService.isServerConnected(serverName)) {
513
+ return {
514
+ type: 'info',
515
+ message: `Server "${serverName}" is already connected.`,
516
+ };
517
+ }
518
+ try {
519
+ // Get current sessions and add the new server
520
+ await this.agentService.connectServer(serverName, serverConfig);
521
+ return {
522
+ type: 'success',
523
+ message: `✅ Connected to server "${serverName}"!`,
524
+ data: { reinitializeAgent: true },
525
+ };
526
+ }
527
+ catch (error) {
528
+ Logger.error(`Failed to connect to server ${serverName}`, {
529
+ error: error instanceof Error ? error.message : String(error),
530
+ });
531
+ return {
532
+ type: 'error',
533
+ message: `Failed to connect to server "${serverName}": ${error instanceof Error ? error.message : 'Unknown error'}`,
534
+ };
535
+ }
536
+ }
537
+ /**
538
+ * Handles the /server disconnect subcommand.
539
+ * @param args - Array where args[0] is the server name
540
+ * @returns A CommandResult with disconnection status
541
+ */
542
+ async handleServerDisconnectCommand(args) {
543
+ if (args.length === 0) {
544
+ const connectedServers = this.agentService.getConnectedServerNames();
545
+ if (connectedServers.length === 0) {
546
+ return {
547
+ type: 'info',
548
+ message: 'No servers currently connected.\n\nUsage: /server disconnect <server_name>',
549
+ };
550
+ }
551
+ return {
552
+ type: 'error',
553
+ message: `Usage: /server disconnect <server_name>\n\nConnected servers: ${connectedServers.join(', ')}`,
554
+ };
555
+ }
556
+ const serverName = args[0];
557
+ if (!serverName) {
558
+ return {
559
+ type: 'error',
560
+ message: 'Server name is required.\n\nUsage: /server disconnect <server_name>',
561
+ };
562
+ }
563
+ // Check if server is connected
564
+ if (!this.agentService.isServerConnected(serverName)) {
565
+ return {
566
+ type: 'error',
567
+ message: `Server "${serverName}" is not connected.`,
568
+ };
569
+ }
570
+ try {
571
+ // Get current sessions and remove the server
572
+ this.agentService.disconnectServer(serverName);
573
+ return {
574
+ type: 'success',
575
+ message: `✅ Disconnected from server "${serverName}".`,
576
+ data: { reinitializeAgent: true },
577
+ };
578
+ }
579
+ catch (error) {
580
+ Logger.error(`Failed to disconnect from server ${serverName}`, {
581
+ error: error instanceof Error ? error.message : String(error),
582
+ });
583
+ return {
584
+ type: 'error',
585
+ message: `Failed to disconnect from server "${serverName}": ${error instanceof Error ? error.message : 'Unknown error'}`,
586
+ };
587
+ }
588
+ }
589
+ }
590
+ // Export a singleton instance
591
+ export const cliService = new CLIService();
@@ -0,0 +1,4 @@
1
+ export { LLMService, type LLMConfig } from './llm-service.js';
2
+ export { MCPConfigService, type MCPServerConfig } from './mcp-config-service.js';
3
+ export { AgentService } from './agent-service.js';
4
+ export { UtilityService } from './utility-service.js';
@@ -0,0 +1,4 @@
1
+ export { LLMService } from './llm-service.js';
2
+ export { MCPConfigService } from './mcp-config-service.js';
3
+ export { AgentService } from './agent-service.js';
4
+ export { UtilityService } from './utility-service.js';