diff --git a/src/kimi_cli/soul/kimisoul.py b/src/kimi_cli/soul/kimisoul.py index 6f27b4233..114ecd454 100644 --- a/src/kimi_cli/soul/kimisoul.py +++ b/src/kimi_cli/soul/kimisoul.py @@ -28,6 +28,7 @@ set_current_approval_source, ) from kimi_cli.background import build_active_task_snapshot +from kimi_cli.exception import MCPRuntimeError from kimi_cli.hooks.engine import HookEngine from kimi_cli.llm import ModelCapability from kimi_cli.notifications import ( @@ -532,7 +533,13 @@ async def wait_for_background_mcp_loading(self) -> None: """Wait for any in-flight MCP startup to finish.""" if not isinstance(self._agent.toolset, KimiToolset): return - await self._agent.toolset.wait_for_mcp_tools() + try: + await self._agent.toolset.wait_for_mcp_tools() + except MCPRuntimeError as exc: + logger.warning( + "MCP startup failed; continuing without unavailable servers: {error}", + error=exc, + ) async def _checkpoint(self): await self._context.checkpoint(self._checkpoint_with_user_message) diff --git a/tests/core/test_kimisoul_mcp.py b/tests/core/test_kimisoul_mcp.py new file mode 100644 index 000000000..7bd72496e --- /dev/null +++ b/tests/core/test_kimisoul_mcp.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +from types import SimpleNamespace + +import pytest + +import kimi_cli.soul.kimisoul as kimisoul_module +from kimi_cli.exception import MCPRuntimeError +from kimi_cli.soul.kimisoul import KimiSoul + + +class _FailingMCPToolset: + def __init__(self) -> None: + self.waited = False + + async def wait_for_mcp_tools(self) -> None: + self.waited = True + raise MCPRuntimeError("Failed to connect MCP servers: broken") + + +@pytest.mark.asyncio +async def test_background_mcp_loading_failure_does_not_stop_turn( + monkeypatch: pytest.MonkeyPatch, +) -> None: + toolset = _FailingMCPToolset() + soul = KimiSoul.__new__(KimiSoul) + soul._agent = SimpleNamespace(toolset=toolset) + monkeypatch.setattr(kimisoul_module, "KimiToolset", _FailingMCPToolset) + + await soul.wait_for_background_mcp_loading() + + assert toolset.waited