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(