refactor(mcp): 优化MCP配置和Docker构建流程

- 移除不再使用的paddleocr依赖
- 清理并注释MCP服务器配置,增加错误追踪
- 重构Dockerfile以提高构建效率和减小镜像体积
- 更新文档添加MCP服务器配置方式的详细说明
This commit is contained in:
Wenjie Zhang 2025-12-01 00:42:58 +08:00
parent 1c4511a719
commit 697b7d4b3a
4 changed files with 140 additions and 35 deletions

View File

@ -1,35 +1,40 @@
# 使用轻量级Python基础镜像
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:0.7.2 /uv /uvx /bin/
COPY --from=node:20-slim /usr/local/bin /usr/local/bin
COPY --from=node:20-slim /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node:20-slim /usr/local/include /usr/local/include
COPY --from=node:20-slim /usr/local/share /usr/local/share
# 设置工作目录
WORKDIR /app
# 环境变量设置
ENV TZ=Asia/Shanghai \
UV_LINK_MODE=copy \
UV_PROJECT_ENVIRONMENT="/usr/local" \
UV_COMPILE_BYTECODE=1 \
DEBIAN_FRONTEND=noninteractive
RUN npm install -g npm@latest && npm cache clean --force
# 设置代理和时区,更换镜像源,安装系统依赖 - 合并为一个RUN减少层数
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
# 更换为阿里云镜像源加速下载
sed -i 's|http://deb.debian.org/debian|http://mirrors.tuna.tsinghua.edu.cn/debian|g' /etc/apt/sources.list.d/debian.sources && \
sed -i 's|http://security.debian.org/debian-security|http://mirrors.tuna.tsinghua.edu.cn/debian-security|g' /etc/apt/sources.list.d/debian.sources && \
# sed -i 's|mirrors.aliyun.com|mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources && \
# 清理apt缓存并更新避免空间不足问题
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* && \
apt-get update && \
# 安装系统依赖,减少缓存占用
apt-get install -y --no-install-recommends --fix-missing \
python3-dev \
RUN set -ex \
# (A) 设置时区
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
# (B) 替换清华源 (针对 Debian Bookworm 的新版格式)
&& sed -i 's|deb.debian.org|mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources \
&& sed -i 's|security.debian.org/debian-security|mirrors.tuna.tsinghua.edu.cn/debian-security|g' /etc/apt/sources.list.d/debian.sources \
# (C) 安装必要的系统库
&& apt-get update \
&& apt-get install -y --no-install-recommends --fix-missing \
curl \
ffmpeg \
libsm6 \
libxext6 \
curl \
&& apt-get autoremove -y && \
apt-get autoclean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* /tmp/* /var/tmp/*
# (D) 清理垃圾,减小体积
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 复制项目配置文件
COPY ../pyproject.toml /app/pyproject.toml

View File

@ -108,6 +108,113 @@ async def get_graph(self):
工具的启用状态和描述由配置文件或环境变量决定当依赖缺失时会被中间件自动忽略从而避免在图中加载不可用能力。MCP Server 的接入方式保持不变,只需在 `src/agents/common/mcp.py``MCP_SERVERS` 中填入服务地址与 `transport` 类型,如需更多范式可参阅 LangChain 官方文档。
### MCP 服务器配置方式
系统支持四种 MCP 服务器配置方式,可根据具体场景选择:
#### 1. 远程 HTTP 服务器
```python
MCP_SERVERS = {
"sequentialthinking": {
"url": "https://remote.mcpservers.org/sequentialthinking/mcp",
"transport": "streamable_http",
}
}
```
**特点**
- 通过 HTTP 远程访问,无需本地安装,适合公开可用的 MCP 服务
- 启动速度快,无需本地依赖
#### 2. 使用 npx 运行 Node.js 包
```python
MCP_SERVERS = {
"mcp_server_chart": {
"command": "npx",
"args": ["-y", "@antv/mcp-server-chart"],
"transport": "stdio"
},
}
```
**特点**
- 使用 npx 直接运行 Node.js 包,`-y` 参数自动下载并运行指定包
- 适合 Node.js 生态的 MCP 服务,需要确保 npx 可以使用
#### 3. 使用 uvx 运行 Python 包
```python
MCP_SERVERS = {
"mysql-mcp-server": {
"command": "uvx",
"args": ["mysql_mcp_server"],
"env": {
"MYSQL_DATABASE": "your_database",
"MYSQL_HOST": "localhost",
"MYSQL_PASSWORD": "your_password",
"MYSQL_PORT": "3306",
"MYSQL_USER": "your_username"
},
"transport": "stdio"
}
}
```
**特点**
- 使用 uvx 运行已发布的 Python 包,自动管理虚拟环境和依赖
- 适合 PyPI 上已发布的 MCP 服务
#### 4. 使用 uv 运行本地仓库
```python
MCP_SERVERS = {
"arxiv-mcp-server": {
"command": "uv",
"args": [
"tool",
"run",
"arxiv-mcp-server",
"--storage-path", "src/agents/mcp_repos/arxiv-mcp-server"
],
"transport": "stdio"
}
}
```
**特点**
- 直接运行本地 git 仓库中的 MCP 服务
- 加载速度快,支持热重载,适合开发调试和自定义 MCP 服务
- 需要先 git clone 对应仓库到指定路径
### 配置参数说明
- `url`: 远程 HTTP 服务器的 URL仅 streamable_http 传输)
- `command`: 启动 MCP 服务的命令
- `args`: 启动参数列表
- `env`: 环境变量配置,用于数据库连接等敏感信息
- `transport`: 传输协议,支持 `stdio`(本地)和 `streamable_http`(远程)
### 动态工具加载
系统支持动态加载 MCP 工具:
```python
from src.agents.common.mcp import get_mcp_tools, add_mcp_server
# 获取特定服务器的工具
tools = await get_mcp_tools("sequentialthinking")
# 动态添加新的 MCP 服务器
add_mcp_server("custom-server", {
"url": "https://your-mcp-server.com/mcp",
"transport": "streamable_http"
})
# 获取所有 MCP 工具
all_tools = await get_all_mcp_tools()
```
### MySQL 数据库
设置数据库连接时,在 `.env` 中提供以下字段:

View File

@ -32,7 +32,6 @@ dependencies = [
"networkx>=3.5",
"openai>=1.109",
"opencv-python-headless>=4.11.0.86",
"paddleocr>=3.3",
"pyjwt>=2.8.0",
"pymilvus>=2.5.8",
"pymupdf>=1.25.5",

View File

@ -1,7 +1,9 @@
"""MCP Client setup and management for LangGraph ReAct Agent."""
import os
from collections.abc import Callable
from typing import Any, cast
import traceback
from langchain_mcp_adapters.client import ( # type: ignore[import-untyped]
MultiServerMCPClient,
@ -18,32 +20,24 @@ MCP_SERVERS = {
"url": "https://remote.mcpservers.org/sequentialthinking/mcp",
"transport": "streamable_http",
},
# "zhipu-web-search-sse": {
# "url": f"https://open.bigmodel.cn/api/mcp/web_search/sse?Authorization={os.getenv('ZHIPU_API_KEY')}",
# "transport": "streamable_http",
# },
# 这些 stdio 的 MCP server 需要在本地启动,启动的时候需要安装对应的包,需要时间
# "time": {
# "command": "uvx",
# "args": ["mcp-server-time"],
# "transport": "stdio",
# },
# "mcp-server-chart": {
# "url": "https://mcp.api-inference.modelscope.net/9993ae42524c4c/mcp",
# "transport": "streamable_http",
# },
# 需要在 docker 内安装 npx
# "mysql": {
# "mcp_server_chart": {
# "command": "npx",
# "args": ["-y", "@benborla29/mcp-server-mysql@2.0.2"],
# "env": {
# "MYSQL_HOST": "172.19.13.6",
# "MYSQL_PORT": "3306",
# "MYSQL_USER": "read-only",
# "MYSQL_PASS": "password123",
# "MYSQL_DB": "feed"
# },
# "args": ["-y", "@antv/mcp-server-chart"],
# "transport": "stdio"
# }
# },
# 更多用法参考https://xerrors.github.io/Yuxi-Know/latest/advanced/agents-config.html#内置工具与-mcp-集成
}
async def get_mcp_client(
server_configs: dict[str, Any] | None = None,
) -> MultiServerMCPClient | None:
@ -85,7 +79,7 @@ async def get_mcp_tools(server_name: str, additional_servers: dict[str, dict] =
logger.warning(f"Failed to load tools from MCP server '{server_name}': {e}")
return []
except Exception as e:
logger.error(f"Failed to load tools from MCP server '{server_name}': {e}")
logger.error(f"Failed to load tools from MCP server '{server_name}': {e}, traceback: {traceback.format_exc()}")
return []