diff --git a/navi/mcp/client.py b/navi/mcp/client.py index d0f42cc..0ac823e 100644 --- a/navi/mcp/client.py +++ b/navi/mcp/client.py @@ -110,11 +110,22 @@ self._connected = False self._exit_stack = AsyncExitStack() + async def _ensure_connected(self) -> None: + """Reconnect if the underlying transport is dead.""" + if not self._connected or self._session is None: + logger.warning("MCP server %r disconnected, reconnecting...", self.name) + await self._cleanup() + await self.connect() + async def list_tools(self) -> list[Tool]: """Return the tools exposed by the remote MCP server.""" - if not self._session: - raise RuntimeError("Not connected") - result = await self._session.list_tools() + await self._ensure_connected() + try: + result = await self._session.list_tools() + except Exception: + await self._cleanup() + await self.connect() + result = await self._session.list_tools() return list(result.tools) async def call_tool(self, tool_name: str, arguments: dict[str, Any] | None = None) -> str: @@ -122,10 +133,13 @@ Text content is concatenated; images are reported as a placeholder. """ - if not self._session: - raise RuntimeError("Not connected") - - result = await self._session.call_tool(tool_name, arguments or {}) + await self._ensure_connected() + try: + result = await self._session.call_tool(tool_name, arguments or {}) + except Exception: + await self._cleanup() + await self.connect() + result = await self._session.call_tool(tool_name, arguments or {}) parts: list[str] = [] for item in result.content: