diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index ebd21e5634..e3fabb1e23 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -68,6 +68,7 @@ from openhands.runtime.utils import find_available_tcp_port from openhands.runtime.utils.async_bash import AsyncBashSession from openhands.runtime.utils.bash import BashSession from openhands.runtime.utils.files import insert_lines, read_lines +from openhands.runtime.utils.log_capture import capture_logs from openhands.runtime.utils.memory_monitor import MemoryMonitor from openhands.runtime.utils.runtime_init import init_user_and_working_directory from openhands.runtime.utils.system_stats import get_system_stats @@ -849,13 +850,22 @@ if __name__ == '__main__': # Manually reload the profile and update the servers mcp_router.profile_manager.reload() servers_wait_for_update = mcp_router.get_unique_servers() - await mcp_router.update_servers(servers_wait_for_update) + async with capture_logs('mcpm.router.router') as log_capture: + await mcp_router.update_servers(servers_wait_for_update) + router_error_log = log_capture.getvalue() + logger.info( f'MCP router updated successfully with unique servers: {servers_wait_for_update}' ) + if router_error_log: + logger.warning(f'Some MCP servers failed to be added: {router_error_log}') return JSONResponse( - status_code=200, content={'detail': 'MCP server updated successfully'} + status_code=200, + content={ + 'detail': 'MCP server updated successfully', + 'router_error_log': router_error_log, + }, ) @app.post('/upload_file') diff --git a/openhands/runtime/impl/action_execution/action_execution_client.py b/openhands/runtime/impl/action_execution/action_execution_client.py index 0a9d184409..abb2382158 100644 --- a/openhands/runtime/impl/action_execution/action_execution_client.py +++ b/openhands/runtime/impl/action_execution/action_execution_client.py @@ -400,10 +400,16 @@ class ActionExecutionClient(Runtime): json=stdio_tools, timeout=10, ) - + result = response.json() if response.status_code != 200: self.log('warning', f'Failed to update MCP server: {response.text}') else: + if result['router_error_log']: + self.log( + 'warning', + f'Some MCP servers failed to be added: {result["router_error_log"]}', + ) + # Update our cached list with combined servers after successful update self._last_updated_mcp_stdio_servers = combined_servers.copy() self.log( diff --git a/openhands/runtime/utils/log_capture.py b/openhands/runtime/utils/log_capture.py new file mode 100644 index 0000000000..4c7c798dfb --- /dev/null +++ b/openhands/runtime/utils/log_capture.py @@ -0,0 +1,27 @@ +import io +import logging +from contextlib import asynccontextmanager + + +@asynccontextmanager +async def capture_logs(logger_name, level=logging.ERROR): + logger = logging.getLogger(logger_name) + + # Store original handlers and level + original_handlers = logger.handlers[:] + original_level = logger.level + + # Set up capture + log_capture = io.StringIO() + handler = logging.StreamHandler(log_capture) + handler.setLevel(level) + + logger.handlers = [handler] + logger.setLevel(level) + + try: + yield log_capture + finally: + # Restore original configuration + logger.handlers = original_handlers + logger.setLevel(original_level) \ No newline at end of file