Edit: Initialize will now attempt to ensure all mcps are globally installed when the system starts.

deci committed May 13, 2025 at 23:45 UTC 48fedd2fc9546e563329185461e02aa857410b1a
1 file changed +77 -19
initialize.py
+77 -19
@@ -1,4 +1,5 @@
1 import asyncio
2 +import json
3 import models
4 from agent import AgentConfig, ModelConfig
5 from python.helpers import dotenv, files, rfc_exchange, runtime, settings, docker, log
@@ -7,59 +8,116 @@ import shutil
8 from python.helpers.print_style import PrintStyle
9
10
10 -def initialize():
11 -
11 +# Helper function to ensure an MCP package is globally installed
12 +def _ensure_mcp_package_globally_installed(package_name: str, executable_name: str):
13 PrintStyle(background_color="blue", font_color="white", padding=True).print(
13 - "Attempting to ensure MCP server 'mcp-server-sequential-thinking' is available..."
14 + f"Attempting to ensure MCP server executable '{executable_name}' (from package '{package_name}') is available..."
15 )
15 - # Check if npm is available first, as it's needed for the install.
16 if shutil.which("npm"):
17 - if not shutil.which("mcp-server-sequential-thinking"):
17 + if not shutil.which(executable_name):
18 PrintStyle(font_color="yellow", padding=True).print(
19 - "'mcp-server-sequential-thinking' not found in PATH. Attempting global npm install..."
19 + f"'{executable_name}' not found in PATH. Attempting global npm install of '{package_name}'..."
20 )
21 try:
22 - # Attempt to install @modelcontextprotocol/server-sequential-thinking globally
23 - npm_command = ["npm", "i", "-g", "@modelcontextprotocol/server-sequential-thinking", "--no-fund", "--no-audit"]
22 + npm_command = ["npm", "i", "-g", package_name, "--no-fund", "--no-audit"]
23 process = subprocess.run(npm_command, capture_output=True, text=True, check=False)
24 if process.returncode == 0:
25 PrintStyle(font_color="green", padding=True).print(
27 - "Successfully installed @modelcontextprotocol/server-sequential-thinking globally via npm."
26 + f"Successfully installed '{package_name}' globally via npm."
27 )
29 - # Re-check if it's available in PATH now. This depends on npm's global bin location being in PATH.
30 - if shutil.which("mcp-server-sequential-thinking"):
28 + if shutil.which(executable_name):
29 PrintStyle(font_color="green", padding=True).print(
32 - "'mcp-server-sequential-thinking' is now available in PATH after install."
30 + f"'{executable_name}' is now available in PATH after install."
31 )
32 else:
33 PrintStyle(font_color="orange", padding=True).print(
36 - "WARNING: npm install reported success, but 'mcp-server-sequential-thinking' still not found in PATH by shutil.which(). " +
37 - "The 'npx' command in settings.json might still be necessary and hopefully works."
34 + f"WARNING: npm install of '{package_name}' reported success, but '{executable_name}' still not found in PATH. " +
35 + "The 'npx' command in settings.json might still be necessary or there might be an issue with PATH."
36 )
37 else:
38 PrintStyle(font_color="red", padding=True).print(
41 - f"Failed to install @modelcontextprotocol/server-sequential-thinking globally via npm. Return code: {process.returncode}"
39 + f"Failed to install '{package_name}' globally via npm. Return code: {process.returncode}"
40 )
41 PrintStyle(font_color="red", padding=False).print(f"npm stdout: {process.stdout.strip()}")
42 PrintStyle(font_color="red", padding=False).print(f"npm stderr: {process.stderr.strip()}")
43 except FileNotFoundError:
44 PrintStyle(font_color="red", padding=True).print(
47 - "ERROR: 'npm' command not found. Cannot attempt to install @modelcontextprotocol/server-sequential-thinking."
45 + f"ERROR: 'npm' command not found. Cannot attempt to install '{package_name}'."
46 )
47 except Exception as e:
48 PrintStyle(font_color="red", padding=True).print(
51 - f"Exception during npm install of @modelcontextprotocol/server-sequential-thinking: {e}"
49 + f"Exception during npm install of '{package_name}': {e}"
50 )
51 else:
52 PrintStyle(font_color="green", padding=True).print(
55 - "'mcp-server-sequential-thinking' already found in PATH."
53 + f"'{executable_name}' (from package '{package_name}') already found in PATH."
54 )
55 else:
56 PrintStyle(font_color="red", padding=True).print(
59 - "ERROR: 'npm' command not found. Cannot check for or install 'mcp-server-sequential-thinking'."
57 + f"ERROR: 'npm' command not found. Cannot check for or install '{executable_name}' from '{package_name}'."
58 )
59 + PrintStyle().print() # For a blank line after each attempt
60 +
61
62 +def initialize():
63 current_settings = settings.get_settings()
64 + mcp_servers_json_string = current_settings.get("mcp_servers", "[]")
65 +
66 + try:
67 + mcp_server_configs = json.loads(mcp_servers_json_string)
68 + if not isinstance(mcp_server_configs, list):
69 + PrintStyle(font_color="red", padding=True).print(
70 + f"Error: Parsed mcp_servers from settings is not a list. Value: {mcp_server_configs}"
71 + )
72 + mcp_server_configs = []
73 + except json.JSONDecodeError as e:
74 + PrintStyle(font_color="red", padding=True).print(
75 + f"Error decoding mcp_servers JSON string from settings: {e}. String was: '{mcp_servers_json_string}'"
76 + )
77 + mcp_server_configs = []
78 +
79 + if shutil.which("npm"):
80 + for server_config in mcp_server_configs:
81 + if not isinstance(server_config, dict):
82 + PrintStyle(font_color="orange", padding=True).print(
83 + f"Warning: Skipping MCP server config item as it's not a dictionary: {server_config}"
84 + )
85 + continue
86 +
87 + command = server_config.get("command")
88 + args = server_config.get("args", [])
89 + server_name = server_config.get("name", "Unknown MCP Server")
90 +
91 + if command == "npx" and "--package" in args:
92 + try:
93 + package_keyword_index = args.index("--package")
94 + # Expect package name at +1 and executable name at +2 from "--package"
95 + if package_keyword_index + 2 < len(args):
96 + package_name = args[package_keyword_index + 1]
97 + executable_name = args[package_keyword_index + 2]
98 + if package_name and executable_name: # Ensure they are not empty strings
99 + _ensure_mcp_package_globally_installed(package_name, executable_name)
100 + else:
101 + PrintStyle(font_color="orange", padding=True).print(
102 + f"Warning: Skipping MCP server '{server_name}' due to empty package or executable name extracted from args: {args}"
103 + )
104 + else:
105 + PrintStyle(font_color="orange", padding=True).print(
106 + f"Warning: Skipping MCP server '{server_name}' as package name or executable name could not be determined from args: {args}"
107 + )
108 + except ValueError: # Should not happen if "--package" is in args, but good for safety
109 + PrintStyle(font_color="orange", padding=True).print(
110 + f"Warning: '--package' keyword found but .index() failed for args: {args} in server '{server_name}'"
111 + )
112 + except Exception as e:
113 + PrintStyle(font_color="red", padding=True).print(
114 + f"Error processing npx args for server '{server_name}': {e}. Args: {args}"
115 + )
116 + else:
117 + PrintStyle(font_color="red", padding=True).print(
118 + "ERROR: 'npm' command not found. Cannot attempt to install any MCP server packages."
119 + )
120 + PrintStyle().print() # Extra blank line after all attempts or npm not found message
121
122 # chat model from user settings
123 chat_llm = ModelConfig(