跳转至

MCP 服务器

Eagle-RAG 为 LLM Agent 暴露仅 RAG 的 MCP 工具:Core 工具 core_ingestcore_querycore_retrieve_textcore_retrieve_visual,以及来自活跃 profile 的 {namespace}_* 工具。服务器复用与 REST 相同的服务层 — 无 HTTP 自调用。

源模块: eagle_rag/api/mcp_server.pyeagle_rag/plugins/mcp_registry.pyeagle_rag/api/mcp_http.pyeagle_rag/mcp_resilience.pyeagle_rag/mcp_cache.py

产品边界

MCP 仅用于摄取与检索上下文 — 无 SQL 执行等副作用工具。见 ADR-008


1. 理论背景

1.1 Model Context Protocol

MCP(Anthropic,2024)标准化 LLM Agent 发现与调用外部工具的方式。Eagle-RAG 的 MCP 服务器使 Agent(Claude、LlamaIndex FunctionAgent 等)无需自定义 HTTP 集成即可摄取文档并查询知识库。

1.2 面向 Agent 的基于工具的 RAG

Agent 框架用工具做检索增强推理(Schick 等,Toolformer,arXiv:2302.04761)。Eagle-RAG 的 Core 四个工具映射到 RAG 管线阶段:

工具 RAG 阶段
core_ingest 索引
core_retrieve_text / core_retrieve_visual 检索
core_query 检索 + 生成

将检索与生成工具分离,使 Agent 可在综合回答前检查证据。

1.3 韧性模式

MCP 工具用断路器超时重试模式包装服务调用(Nygard,Release It!)— 防止 Milvus 或 VLM 不可用时 Agent 会话挂起。


2. 工具定义

Core 工具经 eagle_rag/plugins/mcp_registry.py@register_mcp_tool 注册,经 FastMCP 暴露。域插件注册 {namespace}_{name} 工具;实例仅暴露 core_*settings.plugins.default_namespace 的工具(G3 过滤)。assert_rag_only_tool_name 拒绝副作用片段(execute_sqlsend_email 等)。插件前的裸名(ingestquery做别名。

元数据镜像于 TOOL_DEFINITIONS,供 GET /mcp/tools REST 发现。

2.1 core_ingest

core_ingest(source_uri: str, source_type: str | None, kb_name: str | None)
 {"job_id", "status", "document_id", "dedup_hit"}

runner.ingest() 派发到 Celery。接受文件路径或 URL。

2.2 core_query

core_query(query: str, mode: str | None, scope: list[str] | None,
           kb_name: str | None, scope_filter: dict | None)
 {"answer", "sources", "route", "steps"}

EagleRouterQueryEngine.query() 做完整多模态问答。域插件活跃时,检索可经 RetrieverOrchestrator + RRF 合并扇出到多个 Milvus collection。

2.3 core_retrieve_text

core_retrieve_text(query: str, scope: list[str] | None, top_k: int, kb_name: str | None)
 [{"node_id", "text", "score", "metadata": {path, level, summary, document_id, source_type}}]

纯文本检索,经 KnowhereGraphRetriever(Core)或 RetrieverOrchestrator(多 collection)— 无 LLM 生成。

2.4 core_retrieve_visual

core_retrieve_visual(query: str, scope: list[str] | None, top_k: int, kb_name: str | None)
 [{"image_id", "document_id", "page", "position", "score"}]

纯视觉检索,经 PixelRAGVisualRetriever

2.5 域插件工具

域插件在加载时注册额外工具(如 biomed_query_entitieslakehouse_bi_query_semantic_context)。仅绑定 default_namespace 的工具与 core_* 一并暴露。见插件架构 § MCP 表面。


3. 传输模式

3.1 HTTP(默认)

可流式 HTTP 挂载于主 FastAPI 应用的 /mcp

mcp:
  transport: http
  streamable_http_path: /mcp
  stateless_http: true
  json_response: true
  port: 8081          # 独立模式
  workers: 4

无状态模式(FASTMCP_STATELESS_HTTP=true)支持水平扩展,无需粘性会话。

3.2 stdio(回退)

python -m eagle_rag.api.mcp_server
# mcp.run(transport="stdio")

用于本地 Agent 子进程集成(LlamaIndex BasicMCPClient)。


4. 韧性层

模块: eagle_rag/mcp_resilience.py

resilient_call("core_query", _do_query)
特性 配置 行为
超时 mcp.tool_timeout: 30 抛出 TimeoutError
断路器 circuit_fail_threshold: 5 5 次失败后打开
重试 max_retries: 3 指数退避

错误以 {"error": "..."} 返回 — MCP 会话继续。


5. 缓存

模块: eagle_rag/mcp_cache.py

检索工具在 Redis 中缓存结果:

ckey = cache_key("core_retrieve_text", query, scope=..., top_k=..., kb_name=...)
cached = get_cached(ckey)  # TTL 来自 mcp.cache_ttl(300s)

缓存键包含 plugin_namespace,用于多实例 MinIO/Redis 隔离。

仅缓存非空结果。缓存命中记入 MCP 调用日志。


6. 认证

函数: configure_mcp_auth()

提供者 配置 机制
禁用 auth.enabled: false 无认证(内网)
static-token auth_provider: static-token Bearer API key
oauth-github auth_provider: oauth-github GitHub OAuth 2.1
oauth-custom auth_provider: oauth-custom 经 JWKS 的 JWT

REST API 无认证;MCP HTTP 可独立加固以用于云部署。


7. 经工具的 Milvus 过滤用法

工具接受 kb_namescope 参数,翻译为 Milvus 过滤器:

# core_retrieve_text,kb_name="finance"
MetadataFilter(key="kb_name", value="finance", operator=EQ)
# → kb_name == "finance"

# core_query,scope_filter
{"kb_names": ["finance"], "tags": ["增值税"]}
# → (kb_name in ["finance"] or document_id in [resolved...])

8. LlamaIndex Agent 集成

使用 llama-index-tools-mcp 的 Agent 经 stdio 或 HTTP 连接:

from llama_index.tools.mcp import BasicMCPClient
client = BasicMCPClient("python -m eagle_rag.api.mcp_server")
tools = client.list_tools()  # core_ingest, core_query, core_retrieve_text, core_retrieve_visual, …

工具输出为 JSON dict/list — 兼容 LlamaIndex FunctionAgent 工具调用。


9. 设计张力与调优

张力 MCP 层 效果 缓解
断路器打开 N 次失败后 mcp_resilience 工具返回 {error: ...} 而非 HTTP 503 — Agent 可能误解析 教导 Agent 读取 error 字段
工具超时 vs 摄取 默认 mcp.tool_timeout 30s core_ingest 在 Celery 完成前返回 — 需单独轮询任务 文档化异步摄取模式
缓存陈旧 相同检索上的 mcp_cache KB 已更新但 Agent 在 TTL 内看到旧节点 批量摄取后降低 TTL
Agent 省略 scope core_query 可选 scope_filter 全 KB 搜索成本 + 跨文档噪声 在 Agent 提示中传入 kb_name + scope
G3 工具过滤 加载时 PluginManager 其他 namespace 的域工具不列出 default_namespace 与 profile 匹配
仅 RAG 守卫 assert_rag_only_tool_name 副作用工具名注册失败 域工具仅保留 retrieve/ingest
stdio vs HTTP 传输 不同连接生命周期 长运行 stdio Agent 占用 API 连接 连接池优先用可流式 HTTP
OAuth 可选 启用时 /mcp 上的 auth 长会话中 token 过期 长 Agent 运行前刷新

10. 配置与调优

mcp:
  transport: http
  tool_timeout: 30
  max_retries: 3
  circuit_fail_threshold: 5
  cache_ttl: 300
  redis_url: ""               # 回退到 celery.broker_url
  auth_provider: static-token

auth:
  enabled: false
  api_key: ${AUTH_API_KEY}

11. 测试

测试文件 契约
tests/test_mcp_http_transport.py HTTP 挂载、工具列表
tests/test_mcp_resilience.py 断路器、超时
tests/test_mcp_cache.py Redis 缓存命中/未命中
tests/test_mcp_metrics.py 调用日志
tests/test_mcp_auth.py 静态 token 校验
tests/test_mcp_config.py 传输配置
tests/plugins/test_manager.py G3 MCP 工具过滤

12. 参考文献