diff --git a/src/mcp_client.py b/src/mcp_client.py index 3fa8fca..5950c16 100644 --- a/src/mcp_client.py +++ b/src/mcp_client.py @@ -999,10 +999,13 @@ class StdioMCPServer: return str(result) class ExternalMCPManager: + """Manages external MCP servers using the StdioMCPServer class.""" def __init__(self): + """Initialize the manager with an empty server registry.""" self.servers = {} async def add_server(self, config: models.MCPServerConfig): + """Add and start a new MCP server from a configuration object.""" if config.url: # RemoteMCPServer placeholder return @@ -1011,11 +1014,13 @@ class ExternalMCPManager: self.servers[config.name] = server async def stop_all(self): + """Stop all managed MCP servers and clear the registry.""" for server in self.servers.values(): await server.stop() self.servers = {} def get_all_tools(self) -> dict: + """Retrieve a dictionary of all tools available across all managed servers.""" all_tools = {} for sname, server in self.servers.items(): for tname, tool in server.tools.items(): @@ -1023,9 +1028,11 @@ class ExternalMCPManager: return all_tools def get_servers_status(self) -> dict[str, str]: + """Get the current operational status of all managed servers.""" return {name: server.status for name, server in self.servers.items()} async def async_dispatch(self, tool_name: str, tool_input: dict) -> str: + """Dispatch a tool call to the appropriate external MCP server asynchronously.""" for server in self.servers.values(): if tool_name in server.tools: return await server.call_tool(tool_name, tool_input) @@ -1034,11 +1041,10 @@ class ExternalMCPManager: _external_mcp_manager = ExternalMCPManager() def get_external_mcp_manager() -> ExternalMCPManager: + """Retrieve the global ExternalMCPManager instance.""" global _external_mcp_manager return _external_mcp_manager -TOOL_NAMES: set[str] = {"read_file", "list_directory", "search_files", "get_file_summary", "py_get_skeleton", "py_get_code_outline", "py_get_definition", "get_git_diff", "web_search", "fetch_url", "get_ui_performance", "get_file_slice", "set_file_slice", "edit_file", "py_update_definition", "py_get_signature", "py_set_signature", "py_get_class_summary", "py_get_var_declaration", "py_set_var_declaration", "py_find_usages", "py_get_imports", "py_check_syntax", "py_get_hierarchy", "py_get_docstring", "get_tree"} - def dispatch(tool_name: str, tool_input: dict[str, Any]) -> str: """ Dispatch an MCP tool call by name. Returns the result as a string. @@ -1598,6 +1604,8 @@ MCP_TOOL_SPECS: list[dict[str, Any]] = [ } ] +TOOL_NAMES: set[str] = {t['name'] for t in MCP_TOOL_SPECS} + diff --git a/src/shell_runner.py b/src/shell_runner.py index dd02106..6652a00 100644 --- a/src/shell_runner.py +++ b/src/shell_runner.py @@ -1,4 +1,11 @@ # shell_runner.py +""" +Shell Runner - Execution engine for PowerShell scripts. + +This module provides utilities to run PowerShell scripts in a subprocess, +configuring the environment via mcp_env.toml. It handles timeouts, +logging, and optional QA/patch callbacks for error recovery. +""" import os import subprocess import shutil @@ -14,7 +21,7 @@ TIMEOUT_SECONDS: int = 60 _ENV_CONFIG: dict = {} def _load_env_config() -> dict: - """Load mcp_env.toml from project root (sibling of this file or parent dir).""" + """Load mcp_env.toml from project root or environment variable.""" env_path = os.environ.get("SLOP_MCP_ENV") if env_path and Path(env_path).exists(): with open(env_path, "rb") as f: @@ -30,7 +37,7 @@ def _load_env_config() -> dict: return {} def _build_subprocess_env() -> dict[str, str]: - """Build env dict for subprocess: current env + mcp_env.toml overrides.""" + """Build environment dictionary for subprocess with overrides from mcp_env.toml.""" global _ENV_CONFIG if not _ENV_CONFIG: _ENV_CONFIG = _load_env_config()