diff --git a/src/serena/mcp.py b/src/serena/mcp.py index e307301..a7f9ea2 100644 --- a/src/serena/mcp.py +++ b/src/serena/mcp.py @@ -160,8 +160,12 @@ def create_mcp_server_and_agent( return # Get tool names from process-isolated agent + # Tools may change as a result of project activation. + # NOTE: While we could pass updated tool information on to the MCP server via the callback, Claude Desktop does not, + # unfortunately, query for changed tools. It only queries for changed resources and prompts regularly, + # so we need to register all tools at startup, unfortunately. try: - tool_names = process_agent.get_tool_instances() + tool_names = process_agent.get_exposed_tool_names() except Exception as e: log.error(f"Failed to get tool names from process agent: {e}") return diff --git a/src/serena/process_isolated_agent.py b/src/serena/process_isolated_agent.py index 543b5ec..741e848 100644 --- a/src/serena/process_isolated_agent.py +++ b/src/serena/process_isolated_agent.py @@ -80,8 +80,8 @@ class SerenaAgentWorker: return self._is_language_server_running(request_id) elif method == "reset_language_server": return self._reset_language_server(request_id) - elif method == "get_tool_instances": - return self._get_tool_instances(request_id) + elif method == "get_exposed_tool_names": + return self._get_exposed_tool_names(request_id) else: return {"id": request_id, "error": f"Unknown method: {method}"} @@ -160,7 +160,7 @@ class SerenaAgentWorker: except Exception as e: return {"id": request_id, "error": str(e), "traceback": traceback.format_exc()} - def _get_tool_instances(self, request_id: str) -> dict[str, Any]: + def _get_exposed_tool_names(self, request_id: str) -> dict[str, Any]: """Get exposed tool names for MCP tool creation.""" if self.agent is None: return {"id": request_id, "error": "SerenaAgent not initialized"} @@ -314,9 +314,14 @@ class ProcessIsolatedSerenaAgent: """Reset the language server.""" self._make_request_with_result("reset_language_server") - def get_tool_instances(self) -> list[str]: + def get_exposed_tool_names(self) -> list[str]: """Get tool names for MCP tool creation.""" - return self._make_request_with_result("get_tool_instances") + return self._make_request_with_result("get_exposed_tool_names") + + def get_exposed_tool_instances(self) -> list[ToolInterface]: + """Get exposed tool instances for MCP tool creation.""" + tool_names = self.get_exposed_tool_names() + return [ProcessIsolatedTool(self, tool_name) for tool_name in tool_names] def __enter__(self) -> Self: self.start() diff --git a/test/serena/test_make_tool_process_isolation.py b/test/serena/test_make_tool_process_isolation.py index f0fdda2..3404aa1 100644 --- a/test/serena/test_make_tool_process_isolation.py +++ b/test/serena/test_make_tool_process_isolation.py @@ -141,7 +141,7 @@ class TestMakeToolProcessIsolation: # Get tool names from both agents regular_active_tools = set(regular_agent.get_active_tool_names()) regular_all_tools = set(tool.get_name_from_cls() for tool in regular_agent.get_exposed_tool_instances()) - isolated_tool_names = set(process_isolated_agent.get_tool_instances()) + isolated_tool_names = set(process_isolated_agent.get_exposed_tool_names()) # The process isolated agent should have all tools (exposed, not just active) assert regular_all_tools == isolated_tool_names, (