Coverage for src/moai_adk/core/mcp/setup.py: 20.00%

55 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-19 20:11 +0900

1# MCP Setup - Cross-platform npx execution with Windows support 

2 

3import json 

4import platform 

5from pathlib import Path 

6 

7from rich.console import Console 

8 

9console = Console() 

10 

11 

12class MCPSetupManager: 

13 """Cross-platform MCP Setup Manager with Windows npx support""" 

14 

15 def __init__(self, project_path: Path): 

16 self.project_path = project_path 

17 self.is_windows = platform.system().lower() == "windows" 

18 

19 def _adapt_command_for_platform(self, command: str) -> str: 

20 """Adapt command for Windows compatibility. 

21 

22 Args: 

23 command: Original command (e.g., "npx") 

24 

25 Returns: 

26 Platform-adapted command (e.g., "cmd /c npx" on Windows) 

27 """ 

28 if self.is_windows and command == "npx": 

29 return "cmd /c npx" 

30 return command 

31 

32 def _adapt_mcp_config_for_platform(self, mcp_config: dict) -> dict: 

33 """Adapt MCP server commands for the current platform. 

34 

35 Args: 

36 mcp_config: Original MCP configuration 

37 

38 Returns: 

39 Platform-adapted MCP configuration 

40 """ 

41 adapted_config = mcp_config.copy() 

42 

43 if "mcpServers" in adapted_config: 

44 for server_name, server_config in adapted_config["mcpServers"].items(): 

45 if "command" in server_config: 

46 original_command = server_config["command"] 

47 adapted_command = self._adapt_command_for_platform(original_command) 

48 

49 if adapted_command != original_command: 

50 # Need to split command and args for Windows 

51 if self.is_windows and original_command == "npx": 

52 # Convert "command": "npx", "args": ["-y", "pkg"] 

53 # to "command": "cmd", "args": ["/c", "npx", "-y", "pkg"] 

54 server_config["command"] = "cmd" 

55 server_config["args"] = ["/c", "npx"] + server_config.get( 

56 "args", [] 

57 ) 

58 else: 

59 server_config["command"] = adapted_command 

60 

61 return adapted_config 

62 

63 def copy_template_mcp_config(self) -> bool: 

64 """Copy MCP configuration from package template with platform adaptation""" 

65 try: 

66 # Get the package template path 

67 import moai_adk 

68 

69 package_path = Path(moai_adk.__file__).parent 

70 template_mcp_path = package_path / "templates" / ".mcp.json" 

71 

72 if template_mcp_path.exists(): 

73 # Copy template to project 

74 project_mcp_path = self.project_path / ".mcp.json" 

75 

76 # Read template 

77 with open(template_mcp_path, "r") as f: 

78 mcp_config = json.load(f) 

79 

80 # Adapt for platform 

81 adapted_config = self._adapt_mcp_config_for_platform(mcp_config) 

82 

83 # Write adapted config to project 

84 with open(project_mcp_path, "w") as f: 

85 json.dump(adapted_config, f, indent=2) 

86 

87 server_names = list(adapted_config.get("mcpServers", {}).keys()) 

88 console.print("✅ MCP configuration copied and adapted for platform") 

89 

90 # Show platform info 

91 if self.is_windows: 

92 console.print( 

93 "🪟 Windows platform detected - npx commands wrapped with 'cmd /c'" 

94 ) 

95 

96 console.print(f"📋 Configured servers: {', '.join(server_names)}") 

97 return True 

98 else: 

99 console.print("❌ Template MCP configuration not found") 

100 return False 

101 

102 except Exception as e: 

103 console.print(f"❌ Failed to copy MCP configuration: {e}") 

104 return False 

105 

106 def setup_mcp_servers(self, selected_servers: list[str]) -> bool: 

107 """Complete MCP server setup process with platform adaptation""" 

108 if not selected_servers: 

109 console.print("ℹ️ No MCP servers selected") 

110 return True 

111 

112 console.print("🔧 Setting up MCP servers...") 

113 return self.copy_template_mcp_config()