@teambit/cli-mcp-server 0.0.11 → 0.0.13

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.
@@ -18,6 +18,13 @@ function _child_process() {
18
18
  };
19
19
  return data;
20
20
  }
21
+ function _fsExtra() {
22
+ const data = _interopRequireDefault(require("fs-extra"));
23
+ _fsExtra = function () {
24
+ return data;
25
+ };
26
+ return data;
27
+ }
21
28
  function _cliMcpServer() {
22
29
  const data = require("./cli-mcp-server.aspect");
23
30
  _cliMcpServer = function () {
@@ -81,6 +88,20 @@ function _nodeFetch() {
81
88
  };
82
89
  return data;
83
90
  }
91
+ function _setupCmd() {
92
+ const data = require("./setup-cmd");
93
+ _setupCmd = function () {
94
+ return data;
95
+ };
96
+ return data;
97
+ }
98
+ function _setupUtils() {
99
+ const data = require("./setup-utils");
100
+ _setupUtils = function () {
101
+ return data;
102
+ };
103
+ return data;
104
+ }
84
105
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
85
106
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
86
107
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -213,6 +234,20 @@ class CliMcpServerMain {
213
234
  * Call bit-server API endpoint using cli-raw route
214
235
  */
215
236
  async callBitServerAPI(command, args = [], flags = {}, cwd, isReTrying = false) {
237
+ return this.callBitServerAPIWithRoute('cli-raw', command, args, flags, cwd, isReTrying);
238
+ }
239
+
240
+ /**
241
+ * Call bit-server API endpoint using IDE route
242
+ */
243
+ async callBitServerIDEAPI(method, args = [], cwd, isReTrying = false) {
244
+ return this.callBitServerAPIWithRoute('ide', method, args, {}, cwd, isReTrying, true);
245
+ }
246
+
247
+ /**
248
+ * Generic method to call bit-server API with different routes
249
+ */
250
+ async callBitServerAPIWithRoute(route, commandOrMethod, argsOrParams = [], flags = {}, cwd, isReTrying = false, isIDERoute = false) {
216
251
  if (!this.serverPort) {
217
252
  if (!cwd) throw new Error('CWD is required to call bit-server API');
218
253
  this.serverPort = await this.getBitServerPort(cwd);
@@ -232,27 +267,36 @@ class CliMcpServerMain {
232
267
  throw new Error('Unable to connect to bit-server. Please ensure you are in a valid Bit workspace.');
233
268
  }
234
269
 
235
- // Build the command array: [command, ...args, ...flagsAsArgs]
236
- const commandArray = [command, ...args];
270
+ // Resolve the real path to handle symlinks (e.g., /tmp -> /private/tmp on macOS)
271
+ const realCwd = _fsExtra().default.realpathSync(cwd);
272
+ let body;
273
+ let url;
274
+ if (isIDERoute) {
275
+ // For IDE route, use the method name and args directly
276
+ body = {
277
+ args: argsOrParams
278
+ };
279
+ url = `${this.serverUrl}/${route}/${commandOrMethod}`;
280
+ } else {
281
+ // For CLI route, build command array with flags
282
+ const commandArray = [commandOrMethod, ...argsOrParams];
237
283
 
238
- // Convert flags to command line arguments
239
- for (const [key, value] of Object.entries(flags)) {
240
- if (value === true) {
241
- commandArray.push(`--${key}`);
242
- } else if (value !== false && value !== undefined) {
243
- commandArray.push(`--${key}`, String(value));
284
+ // Convert flags to command line arguments
285
+ for (const [key, value] of Object.entries(flags)) {
286
+ if (value === true) {
287
+ commandArray.push(`--${key}`);
288
+ } else if (value !== false && value !== undefined) {
289
+ commandArray.push(`--${key}`, String(value));
290
+ }
244
291
  }
292
+ body = {
293
+ command: commandArray,
294
+ pwd: realCwd
295
+ };
296
+ url = `${this.serverUrl}/${route}`;
245
297
  }
246
-
247
- // Resolve the real path to handle symlinks (e.g., /tmp -> /private/tmp on macOS)
248
- const fs = require('fs');
249
- const realCwd = fs.realpathSync(cwd);
250
- const body = {
251
- command: commandArray,
252
- pwd: realCwd
253
- };
254
298
  try {
255
- const response = await (0, _nodeFetch().default)(`${this.serverUrl}/cli-raw`, {
299
+ const response = await (0, _nodeFetch().default)(url, {
256
300
  method: 'POST',
257
301
  headers: {
258
302
  'Content-Type': 'application/json'
@@ -276,7 +320,7 @@ class CliMcpServerMain {
276
320
  this.serverPort = undefined;
277
321
  this.serverUrl = undefined;
278
322
  this.logger.debug('[MCP-DEBUG] Connection refused, attempting to restart bit-server');
279
- return this.callBitServerAPI(command, args, flags, cwd, true);
323
+ return this.callBitServerAPIWithRoute(route, commandOrMethod, argsOrParams, flags, cwd, true, isIDERoute);
280
324
  }
281
325
  throw err;
282
326
  }
@@ -365,10 +409,9 @@ class CliMcpServerMain {
365
409
  // Register the bit_component_details tool
366
410
  this.registerComponentDetailsTool(server);
367
411
 
368
- // Register the bit_commands_info tool
369
- this.registerCommandsInfoTool(server);
370
-
371
- // Register arbitrary command execution tools
412
+ // Register command discovery and help tools
413
+ this.registerCommandsListTool(server);
414
+ this.registerCommandHelpTool(server);
372
415
  this.registerQueryTool(server);
373
416
  this.registerExecuteTool(server);
374
417
  await server.connect(new (_stdio().StdioServerTransport)());
@@ -602,37 +645,20 @@ class CliMcpServerMain {
602
645
  const schema = {
603
646
  cwd: _zod().z.string().describe('Path to workspace directory'),
604
647
  componentName: _zod().z.string().describe('Component name or component ID to get details for'),
605
- includeSchema: _zod().z.boolean().optional().describe('Include component public API schema (default: false)'),
606
- remote: _zod().z.boolean().optional().describe('Get details from remote scope (default: false)')
648
+ includeSchema: _zod().z.boolean().optional().describe('Include component public API schema (default: false)')
607
649
  };
608
650
  server.tool(toolName, description, schema, async params => {
609
651
  try {
610
652
  const includeSchema = params.includeSchema === true;
611
- const remote = params.remote === true;
612
653
  const componentName = params.componentName;
613
- const componentDetails = {};
614
654
 
615
- // Get basic component information using bit show
616
- const showFlags = {
617
- json: true
618
- };
619
- if (remote) {
620
- showFlags.remote = true;
621
- }
622
- const showExecution = await this.safeBitCommandExecution('show', [componentName], showFlags, params.cwd, 'get component show info', true);
623
- componentDetails.show = showExecution.result;
655
+ // Get component details using IDE API with includeSchema parameter
656
+ const ideApiResult = await this.callBitServerIDEAPI('getCompDetails', [componentName, includeSchema], params.cwd);
624
657
 
625
- // Get component schema (public API) if requested
626
- if (includeSchema) {
627
- const schemaFlags = {
628
- json: true
629
- };
630
- if (remote) {
631
- schemaFlags.remote = true;
632
- }
633
- const schemaExecution = await this.safeBitCommandExecution('schema', [componentName], schemaFlags, params.cwd, 'get component schema', true);
634
- componentDetails.schema = schemaExecution.result;
635
- }
658
+ // IDE API returns the result directly, not wrapped in success/error structure
659
+ const componentDetails = {
660
+ show: ideApiResult
661
+ };
636
662
  return this.formatAsCallToolResult(componentDetails);
637
663
  } catch (error) {
638
664
  this.logger.error(`[MCP-DEBUG] Error in bit_component_details tool: ${error.message}`);
@@ -640,134 +666,147 @@ class CliMcpServerMain {
640
666
  }
641
667
  });
642
668
  }
643
- registerCommandsInfoTool(server) {
644
- const toolName = 'bit_commands_info';
645
- const description = 'Get information about Bit commands and their groups. Specify command or subcommand to get detailed info.';
669
+ registerCommandsListTool(server) {
670
+ const toolName = 'bit_commands_list';
671
+ const description = 'Get all available Bit commands with descriptions and groups. Use this to discover what commands are available.';
646
672
  const schema = {
647
673
  extendedDescription: _zod().z.boolean().optional().describe('Include extended descriptions for commands (default: false)'),
648
- internal: _zod().z.boolean().optional().describe('Include internal/debug commands (default: false)'),
649
- command: _zod().z.string().optional().describe('Get info for a specific command only'),
650
- subcommand: _zod().z.string().optional().describe('Get info for subcommands of a specific main command')
674
+ internal: _zod().z.boolean().optional().describe('Include internal/debug commands (default: false)')
651
675
  };
652
676
  server.tool(toolName, description, schema, async params => {
653
677
  try {
654
678
  const {
655
679
  extendedDescription = false,
656
- internal = false,
657
- command: specificCommand,
658
- subcommand: specificSubcommand
680
+ internal = false
659
681
  } = params;
660
682
  const commandsInfo = [];
661
683
  const shouldSkipCommand = cmd => {
662
684
  return Boolean(cmd.private && !internal || cmd.description.startsWith('DEPRECATED'));
663
685
  };
664
- const buildCommandInfo = (cmd, parentName, parentGroup, detailed = false) => {
665
- if (shouldSkipCommand(cmd)) return null;
666
- const cmdName = parentName ? `${parentName} ${(0, _cli().getCommandName)(cmd)}` : (0, _cli().getCommandName)(cmd);
667
- const groupKey = cmd.group || parentGroup;
686
+
687
+ // Build list of all commands
688
+ this.cli.commands.forEach(cmd => {
689
+ if (shouldSkipCommand(cmd)) return;
690
+ const mainCmdName = (0, _cli().getCommandName)(cmd);
691
+ const groupKey = cmd.group;
668
692
  const commandInfo = {
669
- name: cmdName,
670
- description: cmd.description || ''
693
+ name: mainCmdName,
694
+ description: cmd.description || '',
695
+ alias: cmd.alias || ''
671
696
  };
672
697
  if (extendedDescription && cmd.extendedDescription) {
673
698
  commandInfo.extendedDescription = cmd.extendedDescription;
674
699
  }
675
700
  if (groupKey) commandInfo.group = this.cli.groups[groupKey] || groupKey;
676
- if (!detailed) return commandInfo;
677
-
678
- // Add detailed information
679
701
  if (cmd.helpUrl) commandInfo.helpUrl = cmd.helpUrl;
702
+
703
+ // Add subcommands summary
704
+ if (cmd.commands && cmd.commands.length > 0) {
705
+ commandInfo.subcommands = cmd.commands.filter(subCmd => !shouldSkipCommand(subCmd)).map(subCmd => ({
706
+ name: (0, _cli().getCommandName)(subCmd),
707
+ description: subCmd.description || '',
708
+ alias: subCmd.alias || ''
709
+ }));
710
+ }
711
+ commandsInfo.push(commandInfo);
712
+ });
713
+ commandsInfo.sort((a, b) => a.name.localeCompare(b.name));
714
+ const result = JSON.stringify({
715
+ total: commandsInfo.length,
716
+ commands: commandsInfo
717
+ }, null, 2);
718
+ this.logger.debug(`[MCP-DEBUG] Successfully retrieved commands list. Total: ${commandsInfo.length}`);
719
+ return this.formatAsCallToolResult(result);
720
+ } catch (error) {
721
+ this.logger.error(`[MCP-DEBUG] Error in bit_commands_list tool: ${error.message}`);
722
+ return this.formatErrorAsCallToolResult(error, 'getting commands list');
723
+ }
724
+ });
725
+ }
726
+ registerCommandHelpTool(server) {
727
+ const toolName = 'bit_command_help';
728
+ const description = 'Get detailed help for a specific Bit command including syntax, arguments, flags, and usage examples. Use this to understand exactly how to use a command.';
729
+ const schema = {
730
+ command: _zod().z.string().describe('The command name to get help for (e.g., "status", "install", "create")'),
731
+ subcommand: _zod().z.string().optional().describe('Optional subcommand name (e.g., for "lane show", use command="lane" and subcommand="show")')
732
+ };
733
+ server.tool(toolName, description, schema, async params => {
734
+ try {
735
+ const {
736
+ command: requestedCommand,
737
+ subcommand: requestedSubcommand
738
+ } = params;
739
+ let commandInfo = null;
740
+ const buildDetailedCommandInfo = (cmd, parentName) => {
741
+ const cmdName = parentName ? `${parentName} ${(0, _cli().getCommandName)(cmd)}` : (0, _cli().getCommandName)(cmd);
742
+ const info = {
743
+ name: cmdName,
744
+ description: cmd.description || '',
745
+ extendedDescription: cmd.extendedDescription || '',
746
+ alias: cmd.alias || '',
747
+ group: cmd.group ? this.cli.groups[cmd.group] || cmd.group : '',
748
+ helpUrl: cmd.helpUrl || '',
749
+ private: cmd.private || false
750
+ };
751
+
752
+ // Add arguments information
680
753
  const argsData = (0, _cli().getArgsData)(cmd);
681
754
  if (argsData.length > 0) {
682
- commandInfo.arguments = argsData.map(arg => ({
755
+ info.arguments = argsData.map(arg => ({
683
756
  name: arg.nameRaw,
684
757
  description: arg.description || '',
685
758
  required: arg.required,
686
759
  isArray: arg.isArray
687
760
  }));
688
761
  }
689
- commandInfo.options = (0, _cli().getFlagsData)(cmd);
690
- commandInfo.examples = cmd.examples;
762
+
763
+ // Add options/flags information
764
+ info.options = (0, _cli().getFlagsData)(cmd);
765
+
766
+ // Add examples if available
767
+ if (cmd.examples) {
768
+ info.examples = cmd.examples;
769
+ }
770
+
771
+ // Add subcommands if available (including private ones for help purposes)
691
772
  if (cmd.commands && cmd.commands.length > 0) {
692
- commandInfo.subcommands = cmd.commands.filter(subCmd => !shouldSkipCommand(subCmd)).map(subCmd => ({
693
- name: `${cmdName} ${(0, _cli().getCommandName)(subCmd)}`,
773
+ info.subcommands = cmd.commands.map(subCmd => ({
774
+ name: (0, _cli().getCommandName)(subCmd),
694
775
  description: subCmd.description || '',
695
- alias: subCmd.alias || '',
696
- private: Boolean(subCmd.private)
776
+ alias: subCmd.alias || ''
697
777
  }));
698
778
  }
699
- return commandInfo;
779
+ return info;
700
780
  };
701
781
 
702
- // Handle specific command + subcommand lookup
703
- if (specificCommand && specificSubcommand) {
704
- this.cli.commands.forEach(cmd => {
705
- if ((0, _cli().getCommandName)(cmd) === specificCommand && cmd.commands) {
706
- const subCmd = cmd.commands.find(sub => (0, _cli().getCommandName)(sub) === specificSubcommand);
782
+ // Search for the requested command
783
+ this.cli.commands.forEach(cmd => {
784
+ const mainCmdName = (0, _cli().getCommandName)(cmd);
785
+ if (requestedSubcommand) {
786
+ // Looking for a subcommand
787
+ if (mainCmdName === requestedCommand && cmd.commands) {
788
+ const subCmd = cmd.commands.find(sub => (0, _cli().getCommandName)(sub) === requestedSubcommand);
707
789
  if (subCmd) {
708
- const info = buildCommandInfo(subCmd, specificCommand, cmd.group, true);
709
- if (info) commandsInfo.push(info);
790
+ commandInfo = buildDetailedCommandInfo(subCmd, requestedCommand);
710
791
  }
711
792
  }
712
- });
713
- }
714
- // Handle subcommand-only lookup
715
- else if (specificSubcommand && !specificCommand) {
716
- this.cli.commands.forEach(cmd => {
717
- if ((0, _cli().getCommandName)(cmd) === specificSubcommand && cmd.commands) {
718
- cmd.commands.forEach(subCmd => {
719
- const info = buildCommandInfo(subCmd, specificSubcommand, cmd.group);
720
- if (info) commandsInfo.push(info);
721
- });
793
+ } else {
794
+ // Looking for a main command
795
+ if (mainCmdName === requestedCommand) {
796
+ commandInfo = buildDetailedCommandInfo(cmd);
722
797
  }
723
- });
724
- }
725
- // Handle specific command lookup or general listing
726
- else {
727
- const isDetailedMode = Boolean(specificCommand);
728
- this.cli.commands.forEach(cmd => {
729
- const mainCmdName = (0, _cli().getCommandName)(cmd);
730
-
731
- // Process main command
732
- if (!specificCommand || mainCmdName === specificCommand) {
733
- const info = buildCommandInfo(cmd, undefined, undefined, isDetailedMode);
734
- if (info && (!specificCommand || info.name === specificCommand)) {
735
- commandsInfo.push(info);
736
- }
737
- }
738
-
739
- // Process subcommands
740
- if (cmd.commands) {
741
- cmd.commands.forEach(subCmd => {
742
- const subCmdInfo = buildCommandInfo(subCmd, mainCmdName, cmd.group, isDetailedMode);
743
- if (subCmdInfo && (!specificCommand || subCmdInfo.name === specificCommand)) {
744
- commandsInfo.push(subCmdInfo);
745
- }
746
- });
747
- }
748
- });
749
- }
750
- commandsInfo.sort((a, b) => a.name.localeCompare(b.name));
751
- if (commandsInfo.length === 0) {
752
- let errorMessage = 'No commands found';
753
- if (specificCommand && specificSubcommand) {
754
- errorMessage = `No subcommand "${specificSubcommand}" found for command: ${specificCommand}`;
755
- } else if (specificCommand) {
756
- errorMessage = `No command found with name: ${specificCommand}`;
757
- } else if (specificSubcommand) {
758
- errorMessage = `No subcommands found for command: ${specificSubcommand}`;
759
798
  }
760
- return this.formatAsCallToolResult(errorMessage);
799
+ });
800
+ if (!commandInfo) {
801
+ const commandFullName = requestedSubcommand ? `${requestedCommand} ${requestedSubcommand}` : requestedCommand;
802
+ return this.formatAsCallToolResult(`Command not found: ${commandFullName}`);
761
803
  }
762
- const result = JSON.stringify({
763
- total: commandsInfo.length,
764
- commands: commandsInfo
765
- }, null, 2);
766
- this.logger.debug(`[MCP-DEBUG] Successfully retrieved commands info. Total: ${commandsInfo.length}`);
804
+ const result = JSON.stringify(commandInfo, null, 2);
805
+ this.logger.debug(`[MCP-DEBUG] Successfully retrieved command help for: ${commandInfo.name}`);
767
806
  return this.formatAsCallToolResult(result);
768
807
  } catch (error) {
769
- this.logger.error(`[MCP-DEBUG] Error in bit_commands_info tool: ${error.message}`);
770
- return this.formatErrorAsCallToolResult(error, 'getting commands info');
808
+ this.logger.error(`[MCP-DEBUG] Error in bit_command_help tool: ${error.message}`);
809
+ return this.formatErrorAsCallToolResult(error, 'getting command help');
771
810
  }
772
811
  });
773
812
  }
@@ -821,21 +860,30 @@ class CliMcpServerMain {
821
860
  }
822
861
  registerExecuteTool(server) {
823
862
  const toolName = 'bit_execute';
824
- const description = 'Execute any Bit command, including those that modify workspace or repository state. ⚠️ Use with caution as this can make permanent changes to your project. Consider using bit_query for read-only operations.';
863
+ const description = 'Execute Bit commands that make changes to workspace or components (not read-only).';
825
864
  const schema = {
826
865
  cwd: _zod().z.string().describe('Path to workspace directory'),
827
- command: _zod().z.string().describe('The Bit command to execute (e.g., "add", "tag", "export", "remove")'),
866
+ command: _zod().z.string().describe('The Bit command to execute (e.g., "import", "tag", "export", "remove")'),
828
867
  args: _zod().z.array(_zod().z.string()).optional().describe('Arguments to pass to the command'),
829
868
  flags: _zod().z.record(_zod().z.union([_zod().z.string(), _zod().z.boolean()])).optional().describe('Flags to pass to the command as key-value pairs')
830
869
  };
831
870
  server.tool(toolName, description, schema, async params => {
832
871
  try {
833
- const {
872
+ let {
834
873
  command,
835
- args = [],
874
+ args = []
875
+ } = params;
876
+ const {
836
877
  flags = {},
837
878
  cwd
838
879
  } = params;
880
+
881
+ // Handle sub-commands: if command has multiple words, move the second word to args
882
+ const commandParts = command.trim().split(/\s+/);
883
+ if (commandParts.length > 1) {
884
+ command = commandParts[0];
885
+ args = [commandParts[1], ...args];
886
+ }
839
887
  this.logger.debug(`[MCP-DEBUG] Executing command: ${command} with args: ${JSON.stringify(args)} and flags: ${JSON.stringify(flags)}`);
840
888
  const result = await this.callBitServerAPI(command, args, flags, cwd);
841
889
  return this.formatAsCallToolResult(result);
@@ -958,10 +1006,37 @@ class CliMcpServerMain {
958
1006
  }
959
1007
  }
960
1008
  }
1009
+
1010
+ // Setup command business logic methods
1011
+ getEditorDisplayName(editor) {
1012
+ return _setupUtils().McpSetupUtils.getEditorDisplayName(editor);
1013
+ }
1014
+ async setupEditor(editor, options, workspaceDir) {
1015
+ const supportedEditors = ['vscode', 'cursor', 'windsurf'];
1016
+ const editorLower = editor.toLowerCase();
1017
+ if (!supportedEditors.includes(editorLower)) {
1018
+ throw new Error(`Editor "${editor}" is not supported yet. Currently supported: ${supportedEditors.join(', ')}`);
1019
+ }
1020
+
1021
+ // Add workspaceDir to options if provided
1022
+ const setupOptions = _objectSpread({}, options);
1023
+ if (workspaceDir) {
1024
+ setupOptions.workspaceDir = workspaceDir;
1025
+ }
1026
+ if (editorLower === 'vscode') {
1027
+ await _setupUtils().McpSetupUtils.setupVSCode(setupOptions);
1028
+ } else if (editorLower === 'cursor') {
1029
+ await _setupUtils().McpSetupUtils.setupCursor(setupOptions);
1030
+ } else if (editorLower === 'windsurf') {
1031
+ await _setupUtils().McpSetupUtils.setupWindsurf(setupOptions);
1032
+ }
1033
+ }
961
1034
  static async provider([cli, loggerMain]) {
962
1035
  const logger = loggerMain.createLogger(_cliMcpServer().CliMcpServerAspect.id);
963
1036
  const mcpServer = new CliMcpServerMain(cli, logger);
964
- cli.register(new (_mcpServer().McpServerCmd)(mcpServer));
1037
+ const mcpServerCmd = new (_mcpServer().McpServerCmd)(mcpServer);
1038
+ mcpServerCmd.commands = [new (_mcpServer().McpStartCmd)(mcpServer), new (_setupCmd().McpSetupCmd)(mcpServer)];
1039
+ cli.register(mcpServerCmd);
965
1040
  return mcpServer;
966
1041
  }
967
1042
  }