diff --git a/backend/api/chat_router.py b/backend/api/chat_router.py index 84aa407..b549278 100644 --- a/backend/api/chat_router.py +++ b/backend/api/chat_router.py @@ -28,7 +28,7 @@ from core.llm_catalog import ( validate_request_can_use_provider, ) from core.database import get_db_pool, get_checkpointer, reset_db_pools_on_connection_error -from core.mcp_client import get_mcp_client +from core.mcp_client import load_mcp_tools_safe from core.dependencies import get_current_user, get_moderation_service from core.exceptions import ModerationError from models.user import User @@ -771,9 +771,8 @@ async def _create_agent_for_request( checkpointer=checkpointer ) - # 普通聊天模式 - mcp_client = await get_mcp_client() - mcp_tools = await mcp_client.get_tools() + # 普通聊天模式(MCP 不可用时降级为无 MCP 工具,不阻断聊天) + mcp_tools = await load_mcp_tools_safe() mcp_tools = [_wrap_mcp_tool_safe(t) for t in mcp_tools] logger.info(f"成功加载 {len(mcp_tools)} 个 MCP 工具") diff --git a/backend/core/mcp_client.py b/backend/core/mcp_client.py index b8ee202..cc0550f 100644 --- a/backend/core/mcp_client.py +++ b/backend/core/mcp_client.py @@ -6,6 +6,7 @@ MCP 客户端管理模块 """ from typing import Optional +from langchain_core.tools import BaseTool from langchain_mcp_adapters.client import MultiServerMCPClient from core.config import settings @@ -58,6 +59,44 @@ async def get_mcp_client() -> MultiServerMCPClient: return _mcp_client +async def load_mcp_tools_safe() -> list[BaseTool]: + """ + 加载 MCP 工具;单个服务器连接/鉴权失败时跳过并继续,不阻断聊天。 + """ + if not is_mcp_enabled(): + return [] + + client = await get_mcp_client() + if not client.connections: + return [] + + all_tools: list[BaseTool] = [] + for server_name in client.connections: + conn = client.connections[server_name] + url = conn.get("url", "?") + try: + tools = await client.get_tools(server_name=server_name) + all_tools.extend(tools) + logger.info( + "MCP 服务器 {} ({}) 已加载 {} 个工具", + server_name, + url, + len(tools), + ) + except Exception as exc: + logger.warning( + "MCP 服务器 {} ({}) 不可用,已跳过: {}", + server_name, + url, + exc, + ) + + if not all_tools and client.connections: + logger.warning("所有 MCP 服务器均不可用,聊天将继续但不提供 MCP 工具") + + return all_tools + + async def close_mcp_client(): """关闭 MCP 客户端""" global _mcp_client