@defai.digital/ax-cli 3.2.0 → 3.4.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.
Files changed (239) hide show
  1. package/.ax-cli/memory.json +8 -1
  2. package/README.md +118 -2
  3. package/config/models.yaml +13 -0
  4. package/config/settings.yaml +6 -0
  5. package/dist/agent/context-manager.d.ts +5 -5
  6. package/dist/agent/context-manager.js +19 -9
  7. package/dist/agent/context-manager.js.map +1 -1
  8. package/dist/agent/dependency-resolver.js +2 -1
  9. package/dist/agent/dependency-resolver.js.map +1 -1
  10. package/dist/agent/llm-agent.d.ts +3 -2
  11. package/dist/agent/llm-agent.js +64 -58
  12. package/dist/agent/llm-agent.js.map +1 -1
  13. package/dist/agent/subagent.js +2 -1
  14. package/dist/agent/subagent.js.map +1 -1
  15. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.d.ts +29 -0
  16. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js +103 -0
  17. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js.map +1 -0
  18. package/dist/analyzers/architecture/architecture-analyzer.d.ts +58 -0
  19. package/dist/analyzers/architecture/architecture-analyzer.js +276 -0
  20. package/dist/analyzers/architecture/architecture-analyzer.js.map +1 -0
  21. package/dist/analyzers/architecture/index.d.ts +12 -0
  22. package/dist/analyzers/architecture/index.js +14 -0
  23. package/dist/analyzers/architecture/index.js.map +1 -0
  24. package/dist/analyzers/architecture/pattern-detectors/base-detector.d.ts +27 -0
  25. package/dist/analyzers/architecture/pattern-detectors/base-detector.js +31 -0
  26. package/dist/analyzers/architecture/pattern-detectors/base-detector.js.map +1 -0
  27. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.d.ts +11 -0
  28. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js +57 -0
  29. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js.map +1 -0
  30. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.d.ts +11 -0
  31. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js +43 -0
  32. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js.map +1 -0
  33. package/dist/analyzers/architecture/pattern-detectors/repository-detector.d.ts +11 -0
  34. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js +49 -0
  35. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js.map +1 -0
  36. package/dist/analyzers/architecture/project-structure-scanner.d.ts +54 -0
  37. package/dist/analyzers/architecture/project-structure-scanner.js +200 -0
  38. package/dist/analyzers/architecture/project-structure-scanner.js.map +1 -0
  39. package/dist/analyzers/best-practices/base-rule.d.ts +45 -0
  40. package/dist/analyzers/best-practices/base-rule.js +45 -0
  41. package/dist/analyzers/best-practices/base-rule.js.map +1 -0
  42. package/dist/analyzers/best-practices/best-practice-validator.d.ts +35 -0
  43. package/dist/analyzers/best-practices/best-practice-validator.js +181 -0
  44. package/dist/analyzers/best-practices/best-practice-validator.js.map +1 -0
  45. package/dist/analyzers/best-practices/rules/index.d.ts +7 -0
  46. package/dist/analyzers/best-practices/rules/index.js +56 -0
  47. package/dist/analyzers/best-practices/rules/index.js.map +1 -0
  48. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.d.ts +17 -0
  49. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js +41 -0
  50. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js.map +1 -0
  51. package/dist/analyzers/best-practices/rules/typescript/function-complexity.d.ts +27 -0
  52. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js +76 -0
  53. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js.map +1 -0
  54. package/dist/analyzers/best-practices/rules/typescript/index.d.ts +15 -0
  55. package/dist/analyzers/best-practices/rules/typescript/index.js +16 -0
  56. package/dist/analyzers/best-practices/rules/typescript/index.js.map +1 -0
  57. package/dist/analyzers/best-practices/rules/typescript/max-file-length.d.ts +18 -0
  58. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js +25 -0
  59. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js.map +1 -0
  60. package/dist/analyzers/best-practices/rules/typescript/no-any-type.d.ts +17 -0
  61. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js +27 -0
  62. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js.map +1 -0
  63. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.d.ts +18 -0
  64. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js +39 -0
  65. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js.map +1 -0
  66. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.d.ts +17 -0
  67. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js +32 -0
  68. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js.map +1 -0
  69. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.d.ts +17 -0
  70. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js +36 -0
  71. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js.map +1 -0
  72. package/dist/analyzers/best-practices/rules/typescript/prefer-const.d.ts +17 -0
  73. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js +33 -0
  74. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js.map +1 -0
  75. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.d.ts +17 -0
  76. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js +34 -0
  77. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js.map +1 -0
  78. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.d.ts +17 -0
  79. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js +27 -0
  80. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js.map +1 -0
  81. package/dist/analyzers/best-practices/types.d.ts +86 -0
  82. package/dist/analyzers/best-practices/types.js +7 -0
  83. package/dist/analyzers/best-practices/types.js.map +1 -0
  84. package/dist/analyzers/cache/analysis-cache.d.ts +41 -0
  85. package/dist/analyzers/cache/analysis-cache.js +84 -0
  86. package/dist/analyzers/cache/analysis-cache.js.map +1 -0
  87. package/dist/analyzers/errors.d.ts +51 -0
  88. package/dist/analyzers/errors.js +79 -0
  89. package/dist/analyzers/errors.js.map +1 -0
  90. package/dist/commands/doctor.js +3 -2
  91. package/dist/commands/doctor.js.map +1 -1
  92. package/dist/commands/frontend.d.ts +9 -0
  93. package/dist/commands/frontend.js +645 -0
  94. package/dist/commands/frontend.js.map +1 -0
  95. package/dist/commands/mcp.js +652 -3
  96. package/dist/commands/mcp.js.map +1 -1
  97. package/dist/commands/models.js +2 -2
  98. package/dist/commands/models.js.map +1 -1
  99. package/dist/commands/setup.js +100 -41
  100. package/dist/commands/setup.js.map +1 -1
  101. package/dist/constants.d.ts +4 -0
  102. package/dist/constants.js +4 -0
  103. package/dist/constants.js.map +1 -1
  104. package/dist/hooks/use-enhanced-input.js +16 -3
  105. package/dist/hooks/use-enhanced-input.js.map +1 -1
  106. package/dist/hooks/use-input-handler.js +9 -4
  107. package/dist/hooks/use-input-handler.js.map +1 -1
  108. package/dist/index.js +5 -2
  109. package/dist/index.js.map +1 -1
  110. package/dist/llm/client.d.ts +1 -0
  111. package/dist/llm/tools.js +86 -0
  112. package/dist/llm/tools.js.map +1 -1
  113. package/dist/llm/types.d.ts +49 -22
  114. package/dist/llm/types.js +12 -8
  115. package/dist/llm/types.js.map +1 -1
  116. package/dist/mcp/client.d.ts +5 -0
  117. package/dist/mcp/client.js +55 -0
  118. package/dist/mcp/client.js.map +1 -1
  119. package/dist/mcp/config.d.ts +1 -1
  120. package/dist/mcp/config.js +2 -2
  121. package/dist/mcp/config.js.map +1 -1
  122. package/dist/mcp/health.d.ts +120 -0
  123. package/dist/mcp/health.js +267 -0
  124. package/dist/mcp/health.js.map +1 -0
  125. package/dist/mcp/reconnection.d.ts +93 -0
  126. package/dist/mcp/reconnection.js +216 -0
  127. package/dist/mcp/reconnection.js.map +1 -0
  128. package/dist/mcp/registry.d.ts +71 -0
  129. package/dist/mcp/registry.js +257 -0
  130. package/dist/mcp/registry.js.map +1 -0
  131. package/dist/mcp/resources.d.ts +53 -0
  132. package/dist/mcp/resources.js +135 -0
  133. package/dist/mcp/resources.js.map +1 -0
  134. package/dist/mcp/templates.d.ts +52 -0
  135. package/dist/mcp/templates.js +624 -0
  136. package/dist/mcp/templates.js.map +1 -0
  137. package/dist/mcp/validation.d.ts +25 -0
  138. package/dist/mcp/validation.js +209 -0
  139. package/dist/mcp/validation.js.map +1 -0
  140. package/dist/memory/context-generator.js +1 -2
  141. package/dist/memory/context-generator.js.map +1 -1
  142. package/dist/planner/types.d.ts +2 -2
  143. package/dist/schemas/api-schemas.d.ts +2 -1
  144. package/dist/schemas/api-schemas.js +6 -4
  145. package/dist/schemas/api-schemas.js.map +1 -1
  146. package/dist/schemas/index.d.ts +4 -4
  147. package/dist/schemas/tool-schemas.d.ts +2 -2
  148. package/dist/schemas/yaml-schemas.d.ts +15 -0
  149. package/dist/schemas/yaml-schemas.js +3 -0
  150. package/dist/schemas/yaml-schemas.js.map +1 -1
  151. package/dist/sdk/index.d.ts +138 -0
  152. package/dist/sdk/index.js +173 -0
  153. package/dist/sdk/index.js.map +1 -0
  154. package/dist/sdk/types.d.ts +53 -0
  155. package/dist/sdk/types.js +8 -0
  156. package/dist/sdk/types.js.map +1 -0
  157. package/dist/tools/analysis-tools/architecture-tool.d.ts +46 -0
  158. package/dist/tools/analysis-tools/architecture-tool.js +124 -0
  159. package/dist/tools/analysis-tools/architecture-tool.js.map +1 -0
  160. package/dist/tools/analysis-tools/validation-tool.d.ts +51 -0
  161. package/dist/tools/analysis-tools/validation-tool.js +121 -0
  162. package/dist/tools/analysis-tools/validation-tool.js.map +1 -0
  163. package/dist/tools/bash.js +25 -10
  164. package/dist/tools/bash.js.map +1 -1
  165. package/dist/tools/web-search/cache.d.ts +62 -0
  166. package/dist/tools/web-search/cache.js +105 -0
  167. package/dist/tools/web-search/cache.js.map +1 -0
  168. package/dist/tools/web-search/engines/brave.d.ts +16 -0
  169. package/dist/tools/web-search/engines/brave.js +99 -0
  170. package/dist/tools/web-search/engines/brave.js.map +1 -0
  171. package/dist/tools/web-search/engines/crates.d.ts +19 -0
  172. package/dist/tools/web-search/engines/crates.js +87 -0
  173. package/dist/tools/web-search/engines/crates.js.map +1 -0
  174. package/dist/tools/web-search/engines/npm.d.ts +18 -0
  175. package/dist/tools/web-search/engines/npm.js +86 -0
  176. package/dist/tools/web-search/engines/npm.js.map +1 -0
  177. package/dist/tools/web-search/engines/pypi.d.ts +18 -0
  178. package/dist/tools/web-search/engines/pypi.js +75 -0
  179. package/dist/tools/web-search/engines/pypi.js.map +1 -0
  180. package/dist/tools/web-search/engines/tavily.d.ts +17 -0
  181. package/dist/tools/web-search/engines/tavily.js +73 -0
  182. package/dist/tools/web-search/engines/tavily.js.map +1 -0
  183. package/dist/tools/web-search/index.d.ts +13 -0
  184. package/dist/tools/web-search/index.js +13 -0
  185. package/dist/tools/web-search/index.js.map +1 -0
  186. package/dist/tools/web-search/router.d.ts +36 -0
  187. package/dist/tools/web-search/router.js +280 -0
  188. package/dist/tools/web-search/router.js.map +1 -0
  189. package/dist/tools/web-search/types.d.ts +45 -0
  190. package/dist/tools/web-search/types.js +6 -0
  191. package/dist/tools/web-search/types.js.map +1 -0
  192. package/dist/tools/web-search/web-search-tool.d.ts +51 -0
  193. package/dist/tools/web-search/web-search-tool.js +256 -0
  194. package/dist/tools/web-search/web-search-tool.js.map +1 -0
  195. package/dist/types/analysis.d.ts +177 -0
  196. package/dist/types/analysis.js +8 -0
  197. package/dist/types/analysis.js.map +1 -0
  198. package/dist/ui/components/api-key-input.js +2 -2
  199. package/dist/ui/components/api-key-input.js.map +1 -1
  200. package/dist/ui/components/chat-history.js +14 -7
  201. package/dist/ui/components/chat-history.js.map +1 -1
  202. package/dist/ui/components/chat-input.js +12 -7
  203. package/dist/ui/components/chat-input.js.map +1 -1
  204. package/dist/ui/components/chat-interface.js +75 -54
  205. package/dist/ui/components/chat-interface.js.map +1 -1
  206. package/dist/ui/components/keyboard-hints.js +5 -4
  207. package/dist/ui/components/keyboard-hints.js.map +1 -1
  208. package/dist/ui/components/quick-actions.js +1 -0
  209. package/dist/ui/components/quick-actions.js.map +1 -1
  210. package/dist/ui/components/reasoning-display.js +14 -4
  211. package/dist/ui/components/reasoning-display.js.map +1 -1
  212. package/dist/ui/components/status-bar.d.ts +1 -0
  213. package/dist/ui/components/status-bar.js +37 -39
  214. package/dist/ui/components/status-bar.js.map +1 -1
  215. package/dist/ui/components/toast-notification.d.ts +29 -0
  216. package/dist/ui/components/toast-notification.js +17 -3
  217. package/dist/ui/components/toast-notification.js.map +1 -1
  218. package/dist/ui/components/welcome-panel.d.ts +1 -0
  219. package/dist/ui/components/welcome-panel.js +106 -4
  220. package/dist/ui/components/welcome-panel.js.map +1 -1
  221. package/dist/utils/analysis-logger.d.ts +47 -0
  222. package/dist/utils/analysis-logger.js +70 -0
  223. package/dist/utils/analysis-logger.js.map +1 -0
  224. package/dist/utils/automatosx-detector.d.ts +19 -0
  225. package/dist/utils/automatosx-detector.js +52 -0
  226. package/dist/utils/automatosx-detector.js.map +1 -0
  227. package/dist/utils/config-loader.d.ts +4 -0
  228. package/dist/utils/config-loader.js.map +1 -1
  229. package/dist/utils/confirmation-service.js +1 -1
  230. package/dist/utils/confirmation-service.js.map +1 -1
  231. package/dist/utils/init-previewer.js +26 -4
  232. package/dist/utils/init-previewer.js.map +1 -1
  233. package/dist/utils/setup-validator.js +1 -0
  234. package/dist/utils/setup-validator.js.map +1 -1
  235. package/dist/utils/text-utils.d.ts +1 -0
  236. package/dist/utils/text-utils.js +12 -0
  237. package/dist/utils/text-utils.js.map +1 -1
  238. package/package.json +19 -4
  239. package/vitest.config.ts +1 -0
@@ -1,10 +1,14 @@
1
1
  import { Command } from 'commander';
2
- import { addMCPServer, removeMCPServer, loadMCPConfig, PREDEFINED_SERVERS } from '../mcp/config.js';
2
+ import { addMCPServer, removeMCPServer, loadMCPConfig, PREDEFINED_SERVERS, getTemplate, generateConfigFromTemplate } from '../mcp/config.js';
3
+ import { getTemplateNames, getTemplatesByCategory } from '../mcp/templates.js';
3
4
  import { getMCPManager } from '../llm/tools.js';
4
5
  import { MCPServerIdSchema } from '@ax-cli/schemas';
5
6
  import chalk from 'chalk';
6
7
  import { ConsoleMessenger } from '../utils/console-messenger.js';
7
8
  import { extractErrorMessage } from '../utils/error-handler.js';
9
+ import { validateServerConfig, formatValidationResult } from '../mcp/validation.js';
10
+ import { listAllResources, listServerResources, searchResources } from '../mcp/resources.js';
11
+ import { searchRegistry, getRegistryServer, getPopularServers, generateConfigFromRegistry, formatRegistryServer } from '../mcp/registry.js';
8
12
  export function createMCPCommand() {
9
13
  const mcpCommand = new Command('mcp');
10
14
  mcpCommand.description('Manage MCP (Model Context Protocol) servers');
@@ -12,6 +16,8 @@ export function createMCPCommand() {
12
16
  mcpCommand
13
17
  .command('add <name>')
14
18
  .description('Add an MCP server')
19
+ .option('--template', 'Use pre-configured template for this server')
20
+ .option('--interactive', 'Prompt for required environment variables')
15
21
  .option('-t, --transport <type>', 'Transport type (stdio, http, sse, streamable_http)', 'stdio')
16
22
  .option('-c, --command <command>', 'Command to run the server (for stdio transport)')
17
23
  .option('-a, --args [args...]', 'Arguments for the server command (for stdio transport)', [])
@@ -20,9 +26,83 @@ export function createMCPCommand() {
20
26
  .option('-e, --env [env...]', 'Environment variables (key=value format)', [])
21
27
  .action(async (name, options) => {
22
28
  try {
23
- // Check if it's a predefined server
29
+ // Check if using template
30
+ if (options.template) {
31
+ const template = getTemplate(name);
32
+ if (!template) {
33
+ console.error(chalk.red(`āŒ Template "${name}" not found`));
34
+ console.log();
35
+ console.log(chalk.blue('Available templates:'));
36
+ const templateNames = getTemplateNames();
37
+ templateNames.forEach(t => {
38
+ const tmpl = getTemplate(t);
39
+ console.log(` ${chalk.bold(t)} - ${tmpl?.description}`);
40
+ });
41
+ process.exit(1);
42
+ }
43
+ // Display template information
44
+ console.log(chalk.blue(`\nšŸ“¦ Setting up ${chalk.bold(template.name)} MCP server`));
45
+ console.log(chalk.gray(template.description));
46
+ console.log();
47
+ // Check required environment variables
48
+ const envVars = {};
49
+ let missingEnvVars = false;
50
+ for (const envVar of template.requiredEnv) {
51
+ const value = process.env[envVar.name];
52
+ if (!value) {
53
+ console.log(chalk.yellow(`āš ļø Missing environment variable: ${chalk.bold(envVar.name)}`));
54
+ console.log(chalk.gray(` ${envVar.description}`));
55
+ if (envVar.url) {
56
+ console.log(chalk.gray(` More info: ${envVar.url}`));
57
+ }
58
+ console.log();
59
+ missingEnvVars = true;
60
+ }
61
+ else {
62
+ envVars[envVar.name] = value;
63
+ }
64
+ }
65
+ if (missingEnvVars) {
66
+ console.log(chalk.red('āŒ Setup cannot continue without required environment variables.'));
67
+ console.log();
68
+ console.log(chalk.blue('Setup instructions:'));
69
+ console.log(template.setupInstructions);
70
+ process.exit(1);
71
+ }
72
+ // Generate config from template
73
+ const config = generateConfigFromTemplate(name, envVars);
74
+ // Add to configuration
75
+ addMCPServer(config);
76
+ console.log(chalk.green(`āœ… Configuration saved`));
77
+ // Try to connect immediately
78
+ console.log(chalk.blue('šŸ”Œ Connecting to server...'));
79
+ const manager = getMCPManager();
80
+ await manager.addServer(config);
81
+ console.log(chalk.green('āœ… Connected successfully'));
82
+ // Show available tools
83
+ const tools = manager.getTools().filter(t => t.serverName === name);
84
+ console.log(chalk.blue(`\nšŸ”§ Available tools: ${chalk.bold(tools.length.toString())}`));
85
+ if (tools.length > 0 && tools.length <= 10) {
86
+ tools.forEach(tool => {
87
+ const displayName = tool.name.replace(`mcp__${name}__`, '');
88
+ console.log(` • ${chalk.bold(displayName)}: ${tool.description}`);
89
+ });
90
+ }
91
+ // Show usage examples
92
+ if (template.usageExamples.length > 0) {
93
+ console.log(chalk.blue('\nšŸ’” Usage examples:'));
94
+ template.usageExamples.slice(0, 3).forEach(example => {
95
+ console.log(chalk.gray(` • ${example}`));
96
+ });
97
+ }
98
+ console.log(chalk.green(`\n✨ ${name} MCP server is ready to use!`));
99
+ return;
100
+ }
101
+ // Check if it's a predefined server (legacy support)
24
102
  if (PREDEFINED_SERVERS[name]) {
25
- const config = PREDEFINED_SERVERS[name];
103
+ const template = PREDEFINED_SERVERS[name];
104
+ console.log(chalk.yellow(`šŸ’” Tip: Use ${chalk.bold('--template')} flag for guided setup`));
105
+ const config = template.config;
26
106
  addMCPServer(config);
27
107
  ConsoleMessenger.plain('mcp_commands.server_predefined', { name });
28
108
  // Try to connect immediately
@@ -248,6 +328,575 @@ export function createMCPCommand() {
248
328
  process.exit(1);
249
329
  }
250
330
  });
331
+ // Templates command - List available templates
332
+ mcpCommand
333
+ .command('templates')
334
+ .description('List available MCP server templates')
335
+ .option('--category <category>', 'Filter by category (design, deployment, testing, monitoring, backend, version-control)')
336
+ .action((options) => {
337
+ console.log(chalk.blue.bold('\nšŸ“¦ Available MCP Server Templates\n'));
338
+ let templates = Object.values(PREDEFINED_SERVERS);
339
+ if (options.category) {
340
+ templates = getTemplatesByCategory(options.category);
341
+ if (templates.length === 0) {
342
+ console.log(chalk.yellow(`No templates found for category "${options.category}"`));
343
+ console.log();
344
+ console.log(chalk.blue('Available categories:'));
345
+ console.log(' • design, deployment, testing, monitoring, backend, version-control');
346
+ return;
347
+ }
348
+ console.log(chalk.gray(`Showing ${options.category} templates:\n`));
349
+ }
350
+ // Group by category
351
+ const categories = templates.reduce((acc, template) => {
352
+ if (!acc[template.category]) {
353
+ acc[template.category] = [];
354
+ }
355
+ acc[template.category].push(template);
356
+ return acc;
357
+ }, {});
358
+ const categoryIcons = {
359
+ design: 'šŸŽØ',
360
+ 'version-control': 'šŸ“¦',
361
+ deployment: 'šŸš€',
362
+ testing: '🧪',
363
+ monitoring: 'šŸ“Š',
364
+ backend: 'šŸ—„ļø'
365
+ };
366
+ for (const [category, categoryTemplates] of Object.entries(categories)) {
367
+ const icon = categoryIcons[category] || 'šŸ“Œ';
368
+ console.log(chalk.bold(`${icon} ${category.toUpperCase()}`));
369
+ console.log();
370
+ categoryTemplates.forEach(template => {
371
+ const officialBadge = template.officialServer ? chalk.green('official') : chalk.gray('community');
372
+ console.log(` ${chalk.bold(template.name)} [${officialBadge}]`);
373
+ console.log(chalk.gray(` ${template.description}`));
374
+ if (template.requiredEnv.length > 0) {
375
+ const envVarNames = template.requiredEnv.map(e => e.name).join(', ');
376
+ console.log(chalk.gray(` Requires: ${envVarNames}`));
377
+ }
378
+ console.log(chalk.blue(` Usage: ax-cli mcp add ${template.name} --template`));
379
+ console.log();
380
+ });
381
+ }
382
+ console.log(chalk.gray('šŸ’” Tip: Use --category to filter templates by type'));
383
+ console.log(chalk.gray(`Example: ax-cli mcp templates --category design`));
384
+ console.log();
385
+ });
386
+ // Tools command - List tools from a specific server
387
+ mcpCommand
388
+ .command('tools <server-name>')
389
+ .description('List available tools from an MCP server')
390
+ .option('--json', 'Output in JSON format')
391
+ .option('--verbose', 'Show detailed tool schemas')
392
+ .action(async (serverName, options) => {
393
+ try {
394
+ const manager = getMCPManager();
395
+ // Ensure server is connected
396
+ const isConnected = manager.getServers().includes(serverName);
397
+ if (!isConnected) {
398
+ // Try to connect
399
+ const config = loadMCPConfig();
400
+ const serverConfig = config.servers.find(s => s.name === serverName);
401
+ if (!serverConfig) {
402
+ console.error(chalk.red(`āŒ Server "${serverName}" not found.`));
403
+ console.log(chalk.gray('\nAdd it first with:'));
404
+ console.log(chalk.blue(` ax-cli mcp add ${serverName} --template`));
405
+ process.exit(1);
406
+ }
407
+ console.log(chalk.blue(`Connecting to ${serverName}...`));
408
+ await manager.addServer(serverConfig);
409
+ console.log(chalk.green('āœ“ Connected\n'));
410
+ }
411
+ const tools = manager.getTools().filter(t => t.serverName === serverName);
412
+ if (tools.length === 0) {
413
+ console.log(chalk.yellow('āš ļø No tools found for this server.'));
414
+ console.log(chalk.gray('The server may be disconnected or have no tools available.'));
415
+ return;
416
+ }
417
+ if (options.json) {
418
+ console.log(JSON.stringify(tools, null, 2));
419
+ return;
420
+ }
421
+ // Pretty-print with tree structure
422
+ console.log(chalk.blue.bold(`\nšŸ”§ ${serverName} Tools (${tools.length} available)\n`));
423
+ tools.forEach((tool, i) => {
424
+ const isLast = i === tools.length - 1;
425
+ const prefix = isLast ? '└─' : 'ā”œā”€';
426
+ const displayName = tool.name.replace(`mcp__${serverName}__`, '');
427
+ console.log(chalk.bold(`${prefix} ${displayName}`));
428
+ console.log(` ${chalk.gray(tool.description || 'No description available')}`);
429
+ if (options.verbose && tool.inputSchema) {
430
+ console.log(chalk.gray(` Schema:`));
431
+ const schemaStr = JSON.stringify(tool.inputSchema, null, 2)
432
+ .split('\n')
433
+ .map(line => ` ${line}`)
434
+ .join('\n');
435
+ console.log(chalk.gray(schemaStr));
436
+ }
437
+ else if (tool.inputSchema?.properties) {
438
+ const params = Object.keys(tool.inputSchema.properties);
439
+ if (params.length > 0) {
440
+ const required = tool.inputSchema.required || [];
441
+ const paramList = params.map(p => required.includes(p) ? `${p}*` : p).join(', ');
442
+ console.log(chalk.gray(` Parameters: ${paramList}`));
443
+ }
444
+ }
445
+ if (!isLast)
446
+ console.log(' │');
447
+ });
448
+ console.log();
449
+ console.log(chalk.gray('šŸ’” Tip: Use --verbose to see full parameter schemas'));
450
+ console.log(chalk.gray(' Parameters marked with * are required'));
451
+ console.log();
452
+ }
453
+ catch (error) {
454
+ console.error(chalk.red(`āŒ Error: ${extractErrorMessage(error)}`));
455
+ process.exit(1);
456
+ }
457
+ });
458
+ // Search command - Search tools across all servers
459
+ mcpCommand
460
+ .command('search <query>')
461
+ .description('Search for tools across all MCP servers')
462
+ .option('--json', 'Output in JSON format')
463
+ .action((query, options) => {
464
+ const manager = getMCPManager();
465
+ const allTools = manager.getTools();
466
+ const lowerQuery = query.toLowerCase();
467
+ const matchingTools = allTools.filter(tool => tool.name.toLowerCase().includes(lowerQuery) ||
468
+ tool.description?.toLowerCase().includes(lowerQuery));
469
+ if (matchingTools.length === 0) {
470
+ console.log(chalk.yellow(`\nāš ļø No tools found matching "${query}"\n`));
471
+ console.log(chalk.gray('šŸ’” Try searching for:'));
472
+ console.log(chalk.gray(' • deploy, git, database, test, file'));
473
+ console.log();
474
+ return;
475
+ }
476
+ if (options.json) {
477
+ console.log(JSON.stringify(matchingTools, null, 2));
478
+ return;
479
+ }
480
+ console.log(chalk.blue.bold(`\nšŸ” Found ${matchingTools.length} tools matching "${query}"\n`));
481
+ // Group by server
482
+ const byServer = matchingTools.reduce((acc, tool) => {
483
+ if (!acc[tool.serverName]) {
484
+ acc[tool.serverName] = [];
485
+ }
486
+ acc[tool.serverName].push(tool);
487
+ return acc;
488
+ }, {});
489
+ for (const [serverName, serverTools] of Object.entries(byServer)) {
490
+ console.log(chalk.bold(`${serverName} (${serverTools.length} tools)`));
491
+ serverTools.forEach(tool => {
492
+ const displayName = tool.name.replace(`mcp__${serverName}__`, '');
493
+ console.log(` • ${chalk.bold(displayName)}`);
494
+ if (tool.description) {
495
+ console.log(chalk.gray(` ${tool.description}`));
496
+ }
497
+ });
498
+ console.log();
499
+ }
500
+ console.log(chalk.gray('šŸ’” Tip: Use "ax-cli mcp tools <server-name>" to see all tools from a server'));
501
+ console.log();
502
+ });
503
+ // Browse command - Interactive template browser (alias for templates)
504
+ mcpCommand
505
+ .command('browse')
506
+ .description('Browse available MCP server templates')
507
+ .action(() => {
508
+ console.log(chalk.blue.bold('\n🌟 MCP Server Template Browser\n'));
509
+ console.log(chalk.gray('Popular templates for front-end development:\n'));
510
+ const popular = ['figma', 'github', 'vercel', 'puppeteer', 'storybook', 'sentry'];
511
+ popular.forEach(name => {
512
+ const template = getTemplate(name);
513
+ if (template) {
514
+ const icon = template.category === 'design' ? 'šŸŽØ' :
515
+ template.category === 'version-control' ? 'šŸ“¦' :
516
+ template.category === 'deployment' ? 'šŸš€' :
517
+ template.category === 'testing' ? '🧪' :
518
+ template.category === 'monitoring' ? 'šŸ“Š' : 'šŸ—„ļø';
519
+ console.log(`${icon} ${chalk.bold(template.name)}`);
520
+ console.log(chalk.gray(` ${template.description}`));
521
+ console.log(chalk.blue(` Quick start: ax-cli mcp add ${name} --template`));
522
+ console.log();
523
+ }
524
+ });
525
+ console.log(chalk.gray('šŸ“š View all templates:'));
526
+ console.log(chalk.blue(' ax-cli mcp templates'));
527
+ console.log();
528
+ console.log(chalk.gray('šŸ” Search templates:'));
529
+ console.log(chalk.blue(' ax-cli mcp templates --category design'));
530
+ console.log();
531
+ });
532
+ // Health command - Check MCP server health
533
+ mcpCommand
534
+ .command('health [server-name]')
535
+ .description('Check health status of MCP servers')
536
+ .option('--json', 'Output in JSON format')
537
+ .option('--watch', 'Continuously monitor health (updates every 60s)')
538
+ .action(async (serverName, options) => {
539
+ try {
540
+ const { MCPHealthMonitor } = await import('../mcp/health.js');
541
+ const manager = getMCPManager();
542
+ const healthMonitor = new MCPHealthMonitor(manager);
543
+ if (options.watch) {
544
+ // Continuous monitoring mode
545
+ console.log(chalk.blue.bold('\nšŸ“Š MCP Server Health Monitoring\n'));
546
+ console.log(chalk.gray('Press Ctrl+C to stop\n'));
547
+ // Start monitoring
548
+ healthMonitor.start(60000);
549
+ // Display initial report
550
+ const displayHealth = async () => {
551
+ console.clear();
552
+ console.log(chalk.blue.bold('šŸ“Š MCP Server Health Report\n'));
553
+ console.log(chalk.gray(`Last updated: ${new Date().toLocaleTimeString()}\n`));
554
+ const health = serverName
555
+ ? [await healthMonitor.getServerStatus(serverName)].filter(Boolean)
556
+ : await healthMonitor.getHealthReport();
557
+ if (health.length === 0) {
558
+ console.log(chalk.yellow('No servers connected'));
559
+ return;
560
+ }
561
+ for (const server of health) {
562
+ const statusIcon = server.connected ? 'āœ“' : 'āœ—';
563
+ const statusColor = server.connected ? chalk.green : chalk.red;
564
+ const statusText = server.connected ? 'Connected' : 'Disconnected';
565
+ console.log(statusColor(`${statusIcon} ${chalk.bold(server.serverName)} (${statusText})`));
566
+ console.log(chalk.gray(` Transport: MCP`));
567
+ if (server.uptime) {
568
+ console.log(chalk.gray(` Uptime: ${MCPHealthMonitor.formatUptime(server.uptime)}`));
569
+ }
570
+ console.log(chalk.gray(` Tools: ${server.toolCount} available`));
571
+ if (server.avgLatency) {
572
+ console.log(chalk.gray(` Latency: avg ${MCPHealthMonitor.formatLatency(server.avgLatency)}, p95 ${MCPHealthMonitor.formatLatency(server.p95Latency || 0)}`));
573
+ }
574
+ const successRateColor = server.successRate >= 95 ? chalk.green :
575
+ server.successRate >= 80 ? chalk.yellow : chalk.red;
576
+ console.log(chalk.gray(` Success Rate: ${successRateColor(`${server.successRate.toFixed(1)}%`)} (${server.successCount}/${server.successCount + server.failureCount} calls)`));
577
+ if (server.lastError) {
578
+ console.log(chalk.red(` Last Error: ${server.lastError}`));
579
+ if (server.lastErrorAt) {
580
+ const timeSinceError = Date.now() - server.lastErrorAt;
581
+ console.log(chalk.gray(` ${MCPHealthMonitor.formatUptime(timeSinceError)} ago`));
582
+ }
583
+ }
584
+ console.log();
585
+ }
586
+ console.log(chalk.gray('Next update in 60 seconds...'));
587
+ };
588
+ // Display immediately
589
+ await displayHealth();
590
+ // Set up interval
591
+ const watchInterval = setInterval(displayHealth, 60000);
592
+ // Handle Ctrl+C
593
+ process.on('SIGINT', () => {
594
+ clearInterval(watchInterval);
595
+ healthMonitor.stop();
596
+ console.log(chalk.yellow('\n\nšŸ‘‹ Stopped health monitoring\n'));
597
+ process.exit(0);
598
+ });
599
+ }
600
+ else {
601
+ // One-time health check
602
+ const health = serverName
603
+ ? [await healthMonitor.getServerStatus(serverName)].filter(Boolean)
604
+ : await healthMonitor.getHealthReport();
605
+ if (options.json) {
606
+ console.log(JSON.stringify(health, null, 2));
607
+ return;
608
+ }
609
+ if (health.length === 0) {
610
+ if (serverName) {
611
+ console.log(chalk.yellow(`\nāš ļø Server "${serverName}" not found\n`));
612
+ }
613
+ else {
614
+ console.log(chalk.yellow('\nāš ļø No MCP servers connected\n'));
615
+ console.log(chalk.blue('To add a server:'));
616
+ console.log(chalk.cyan(' ax-cli mcp add figma --template'));
617
+ console.log();
618
+ }
619
+ return;
620
+ }
621
+ console.log(chalk.blue.bold('\nšŸ“Š MCP Server Health Report\n'));
622
+ for (const server of health) {
623
+ const statusIcon = server.connected ? 'āœ“' : 'āœ—';
624
+ const statusColor = server.connected ? chalk.green : chalk.red;
625
+ const statusText = server.connected ? 'Connected' : 'Disconnected';
626
+ console.log(statusColor(`${statusIcon} ${chalk.bold(server.serverName)} (${statusText})`));
627
+ console.log(chalk.gray(` Transport: MCP`));
628
+ if (server.uptime) {
629
+ console.log(chalk.gray(` Uptime: ${MCPHealthMonitor.formatUptime(server.uptime)}`));
630
+ }
631
+ console.log(chalk.gray(` Tools: ${server.toolCount} available`));
632
+ if (server.avgLatency) {
633
+ console.log(chalk.gray(` Latency: avg ${MCPHealthMonitor.formatLatency(server.avgLatency)}, p95 ${MCPHealthMonitor.formatLatency(server.p95Latency || 0)}`));
634
+ }
635
+ const successRateColor = server.successRate >= 95 ? chalk.green :
636
+ server.successRate >= 80 ? chalk.yellow : chalk.red;
637
+ console.log(chalk.gray(` Success Rate: ${successRateColor(`${server.successRate.toFixed(1)}%`)} (${server.successCount}/${server.successCount + server.failureCount} calls)`));
638
+ if (server.lastError) {
639
+ console.log(chalk.red(` Last Error: ${server.lastError}`));
640
+ if (server.lastErrorAt) {
641
+ const timeSinceError = Date.now() - server.lastErrorAt;
642
+ console.log(chalk.gray(` ${MCPHealthMonitor.formatUptime(timeSinceError)} ago`));
643
+ }
644
+ }
645
+ if (server.lastSuccess) {
646
+ const timeSinceSuccess = Date.now() - server.lastSuccess;
647
+ console.log(chalk.gray(` Last Successful Call: ${MCPHealthMonitor.formatUptime(timeSinceSuccess)} ago`));
648
+ }
649
+ console.log();
650
+ }
651
+ console.log(chalk.gray('šŸ’” Tip: Use --watch to continuously monitor server health'));
652
+ console.log();
653
+ }
654
+ }
655
+ catch (error) {
656
+ console.error(chalk.red(`\nāŒ Error: ${extractErrorMessage(error)}\n`));
657
+ process.exit(1);
658
+ }
659
+ });
660
+ // Validate server configuration (Phase 4)
661
+ mcpCommand
662
+ .command('validate <name>')
663
+ .description('Validate MCP server configuration with pre-flight checks')
664
+ .action(async (name) => {
665
+ try {
666
+ // Load configuration
667
+ const config = loadMCPConfig();
668
+ const serverConfig = config.servers.find(s => s.name === name);
669
+ if (!serverConfig) {
670
+ console.error(chalk.red(`\nāŒ Server "${name}" not found in configuration\n`));
671
+ console.log(chalk.gray('Available servers:'));
672
+ const availableServers = config.servers.map(s => s.name);
673
+ if (availableServers.length === 0) {
674
+ console.log(chalk.gray(' (none configured)'));
675
+ }
676
+ else {
677
+ availableServers.forEach(s => console.log(chalk.gray(` • ${s}`)));
678
+ }
679
+ console.log();
680
+ process.exit(1);
681
+ }
682
+ console.log(chalk.blue.bold(`\nšŸ” Validating "${name}" MCP server configuration...\n`));
683
+ // Run validation
684
+ const result = await validateServerConfig(serverConfig);
685
+ // Display results
686
+ console.log(formatValidationResult(result));
687
+ console.log();
688
+ if (!result.valid) {
689
+ console.log(chalk.yellow('šŸ’” Fix the errors above and try again'));
690
+ console.log();
691
+ process.exit(1);
692
+ }
693
+ else if (result.warnings.length > 0) {
694
+ console.log(chalk.blue('šŸ’” Configuration is valid but has warnings. Review them before connecting.'));
695
+ console.log();
696
+ }
697
+ else {
698
+ console.log(chalk.green('šŸš€ Ready to connect! Use: ax-cli mcp add ' + name + ' --template'));
699
+ console.log();
700
+ }
701
+ }
702
+ catch (error) {
703
+ console.error(chalk.red(`\nāŒ Error: ${extractErrorMessage(error)}\n`));
704
+ process.exit(1);
705
+ }
706
+ });
707
+ // List MCP resources (Phase 4)
708
+ mcpCommand
709
+ .command('resources [server-name]')
710
+ .description('List resources exposed by MCP servers')
711
+ .option('--search <query>', 'Search resources by name or URI')
712
+ .option('--json', 'Output in JSON format')
713
+ .action(async (serverName, options) => {
714
+ try {
715
+ const manager = getMCPManager();
716
+ // Get resources
717
+ const resources = serverName
718
+ ? await listServerResources(manager, serverName)
719
+ : await listAllResources(manager);
720
+ // Filter by search query if provided
721
+ const filteredResources = options.search
722
+ ? searchResources(resources, options.search)
723
+ : resources;
724
+ if (options.json) {
725
+ console.log(JSON.stringify(filteredResources, null, 2));
726
+ return;
727
+ }
728
+ // Display resources
729
+ if (filteredResources.length === 0) {
730
+ if (serverName) {
731
+ console.log(chalk.yellow(`\nāš ļø No resources found for server "${serverName}"\n`));
732
+ }
733
+ else {
734
+ console.log(chalk.yellow('\nāš ļø No resources found from any connected server\n'));
735
+ }
736
+ console.log(chalk.gray('Note: Not all MCP servers expose resources.'));
737
+ console.log();
738
+ return;
739
+ }
740
+ console.log(chalk.blue.bold('\nšŸ“¦ MCP Resources\n'));
741
+ // Group by server
742
+ const byServer = new Map();
743
+ for (const resource of filteredResources) {
744
+ if (!byServer.has(resource.serverName)) {
745
+ byServer.set(resource.serverName, []);
746
+ }
747
+ byServer.get(resource.serverName).push(resource);
748
+ }
749
+ for (const [server, serverResources] of byServer.entries()) {
750
+ console.log(chalk.bold(`${server} (${serverResources.length} resources)`));
751
+ for (const resource of serverResources) {
752
+ console.log(chalk.green(` ${resource.reference}`));
753
+ if (resource.description) {
754
+ console.log(chalk.gray(` ${resource.description}`));
755
+ }
756
+ if (resource.mimeType) {
757
+ console.log(chalk.gray(` Type: ${resource.mimeType}`));
758
+ }
759
+ }
760
+ console.log();
761
+ }
762
+ console.log(chalk.gray('šŸ’” Use resources in chat with: "Query the @mcp:server/uri"'));
763
+ console.log();
764
+ }
765
+ catch (error) {
766
+ console.error(chalk.red(`\nāŒ Error: ${extractErrorMessage(error)}\n`));
767
+ process.exit(1);
768
+ }
769
+ });
770
+ // Browse MCP Server Registry (Phase 5)
771
+ mcpCommand
772
+ .command('registry')
773
+ .description('Browse MCP server registry')
774
+ .option('--search <query>', 'Search for servers')
775
+ .option('--category <category>', 'Filter by category')
776
+ .option('--transport <type>', 'Filter by transport type (stdio, http, sse)')
777
+ .option('--json', 'Output in JSON format')
778
+ .action(async (options) => {
779
+ try {
780
+ console.log(chalk.blue.bold('\nšŸ“¦ MCP Server Registry\n'));
781
+ const searchOptions = {
782
+ query: options.search,
783
+ category: options.category,
784
+ transport: options.transport,
785
+ sortBy: 'stars',
786
+ limit: 20
787
+ };
788
+ const servers = options.search || options.category || options.transport
789
+ ? await searchRegistry(searchOptions)
790
+ : await getPopularServers();
791
+ if (options.json) {
792
+ console.log(JSON.stringify(servers, null, 2));
793
+ return;
794
+ }
795
+ if (servers.length === 0) {
796
+ console.log(chalk.yellow('āš ļø No servers found matching your criteria\n'));
797
+ console.log(chalk.gray('Try different search terms or browse all servers'));
798
+ console.log();
799
+ return;
800
+ }
801
+ console.log(chalk.gray(`Found ${servers.length} server(s)\n`));
802
+ for (const server of servers) {
803
+ const badge = server.verified ? chalk.green('āœ“ verified') : chalk.gray('community');
804
+ console.log(`${chalk.bold(server.displayName)} [${badge}] ⭐ ${server.stars}`);
805
+ console.log(chalk.gray(` ${server.description}`));
806
+ console.log(chalk.gray(` Category: ${server.category} | Transport: ${server.transport}`));
807
+ if (server.packageName) {
808
+ console.log(chalk.blue(` Install: ax-cli mcp install ${server.name}`));
809
+ }
810
+ else {
811
+ console.log(chalk.gray(` Repository: ${server.repository}`));
812
+ }
813
+ console.log();
814
+ }
815
+ console.log(chalk.gray('šŸ’” Use --search to find specific servers'));
816
+ console.log(chalk.gray('šŸ’” Use --category to filter by type (design, database, api, etc.)'));
817
+ console.log();
818
+ }
819
+ catch (error) {
820
+ console.error(chalk.red(`\nāŒ Error: ${extractErrorMessage(error)}\n`));
821
+ process.exit(1);
822
+ }
823
+ });
824
+ // Install MCP server from registry (Phase 5)
825
+ mcpCommand
826
+ .command('install <name>')
827
+ .description('Install MCP server from registry')
828
+ .option('--no-validate', 'Skip validation before installation')
829
+ .option('--no-connect', 'Add configuration but don\'t connect immediately')
830
+ .action(async (name, options) => {
831
+ try {
832
+ console.log(chalk.blue(`\nšŸ“¦ Installing "${name}" from registry...\n`));
833
+ // Search registry
834
+ const server = await getRegistryServer(name);
835
+ if (!server) {
836
+ console.error(chalk.red(`āŒ Server "${name}" not found in registry\n`));
837
+ console.log(chalk.gray('Available options:'));
838
+ console.log(chalk.gray(' • Search registry: ax-cli mcp registry --search <query>'));
839
+ console.log(chalk.gray(' • Browse all: ax-cli mcp registry'));
840
+ console.log();
841
+ process.exit(1);
842
+ }
843
+ // Display server info
844
+ console.log(formatRegistryServer(server, false));
845
+ console.log();
846
+ // Generate configuration
847
+ const config = generateConfigFromRegistry(server);
848
+ // Validate if requested
849
+ if (options.validate !== false) {
850
+ console.log(chalk.blue('šŸ” Validating configuration...\n'));
851
+ const validation = await validateServerConfig(config);
852
+ if (!validation.valid) {
853
+ console.log(formatValidationResult(validation));
854
+ console.log();
855
+ console.error(chalk.red('āŒ Validation failed. Fix errors and try again.\n'));
856
+ process.exit(1);
857
+ }
858
+ if (validation.warnings.length > 0) {
859
+ console.log(chalk.yellow('āš ļø Warnings:\n'));
860
+ validation.warnings.forEach(w => console.log(chalk.yellow(` • ${w}`)));
861
+ console.log();
862
+ }
863
+ }
864
+ // Add server to configuration
865
+ await addMCPServer(config);
866
+ console.log(chalk.green(`āœ… Server "${server.name}" added to configuration\n`));
867
+ // Connect if requested
868
+ if (options.connect !== false) {
869
+ console.log(chalk.blue('šŸ”Œ Connecting to server...\n'));
870
+ try {
871
+ const manager = getMCPManager();
872
+ await manager.addServer(config);
873
+ const tools = manager.getTools().filter(t => t.serverName === server.name);
874
+ console.log(chalk.green(`āœ… Connected successfully! ${tools.length} tool(s) available\n`));
875
+ // Show available tools
876
+ if (tools.length > 0) {
877
+ console.log(chalk.gray('Available tools:'));
878
+ tools.slice(0, 5).forEach(tool => {
879
+ console.log(chalk.gray(` • ${tool.name.replace(`mcp__${server.name}__`, '')}`));
880
+ });
881
+ if (tools.length > 5) {
882
+ console.log(chalk.gray(` ... and ${tools.length - 5} more`));
883
+ }
884
+ console.log();
885
+ }
886
+ }
887
+ catch (error) {
888
+ console.error(chalk.yellow(`āš ļø Server added but connection failed: ${extractErrorMessage(error)}\n`));
889
+ console.log(chalk.gray('You can try connecting manually with: ax-cli mcp add ' + server.name + ' --template'));
890
+ console.log();
891
+ }
892
+ }
893
+ console.log(chalk.green('šŸŽ‰ Installation complete!\n'));
894
+ }
895
+ catch (error) {
896
+ console.error(chalk.red(`\nāŒ Error: ${extractErrorMessage(error)}\n`));
897
+ process.exit(1);
898
+ }
899
+ });
251
900
  return mcpCommand;
252
901
  }
253
902
  //# sourceMappingURL=mcp.js.map