第 8 章:MCP、工具与 RAG —— 能力如何进入模型上下文¶
8.1 三类工具来源¶
MCP tools ← 外部 MCP server(stdio / SSE / streamable HTTP)
RAG tools ← 附件解析 + embedding + vector DB
Built-in tools ← web_search / web_fetch / 本地产品工具
它们在 Web 层最终都被规整成模型可接受的 function tool schema,再由 CustomChatTransport 统一执行/审批。
8.2 MCP 的 Rust 状态模型¶
AppState 中与 MCP 相关的字段非常多,说明 MCP 不是一个静态列表:
| 状态 | 用途 |
|---|---|
mcp_servers |
已建立的 RunningService 连接 |
mcp_active_servers |
当前配置中应保持 active 的 server |
mcp_server_pids |
stdio 子进程 PID,便于清理 |
mcp_monitoring_tasks |
健康检查/自动重连任务 |
mcp_starting |
防止同一个 server 并发 serve() |
mcp_last_known_tools |
短暂断线时保留稳定 schema |
tool_call_cancellations |
取消正在运行的 tool call |
mcp_reconnect_notify |
立即唤醒 monitor,而不必等待 30 秒 |
这些字段共同形成一个小型连接管理器。
8.3 启动与重连流程¶
stateDiagram-v2
[*] --> Configured
Configured --> Starting: active + start task
Starting --> Connected: initialize / list tools OK
Starting --> Disconnected: timeout / transport error
Connected --> Connected: health check every 30s
Connected --> Reconnecting: list_tools failed
Reconnecting --> Connected: backoff + start success
Reconnecting --> Reconnecting: failure count grows
Connected --> Stopped: deactivate / app exit
Reconnecting --> Stopped: shutdown flag
helpers.rs::monitor_mcp_server_handle 每 30 秒或收到 notify 后检查 list_all_tools;失败时删除旧 service、清理 PID、发出状态事件,按 base_restart_delay_ms * multiplier^n 做 capped exponential backoff,然后确认 server 仍 active 再重连。
最值得注意的是幂等保护:boot startup 和前端 activation 可能同时请求同一 server,如果没有 mcp_starting,两个 serve() 会发重复 initialize,streamable HTTP server 可能以 400 拒绝第二个连接。
8.4 工具 schema 是上下文成本¶
工具不是“白送给模型”的。每个工具的 name、description、inputSchema 都会占用 prompt tokens。Jan 的 mcp-orchestrator 通过 intent classifier、server summaries 和 model filter 选择工具集合,目标是只把当前任务需要的工具给模型。
全部 MCP tools
→ 服务器摘要 / intent 分类
→ selected server names
→ getToolsForServers
→ 规范化 JSON Schema
→ 当前 chat request
这和 RAG 的检索思想相似:不是把所有知识塞进上下文,而是按需选择可用能力。
8.5 Tool approval 的位置¶
Web 层的 ToolApproval、useToolApproval、useToolApprovalRequests 管理用户可见的审批。批准之前,tool call 可能已经作为 assistant 的“待处理意图”出现在 UI;批准之后才真正执行,并把 result 送回模型。
但通过本地 API proxy 开启 server-side tool execution 时,审批边界会改变。文档和配置必须明确指出:UI 中的审批不自动覆盖外部 API 调用。
8.6 RAG 的两条管线¶
RAG extension 负责产品语义,两个 Tauri plugin 负责系统能力:
附件
→ tauri-plugin-rag:PDF / DOCX / CSV / HTML / XML / 文本解析
→ chunking
→ embedding model(可由 llama.cpp 提供)
→ tauri-plugin-vector-db
→ sqlite-vec 或线性 fallback
→ search tool
→ message context / citations
Vector DB plugin 的 API 包括 create collection、create file、insert chunks、search、list attachments、delete collection 和 chunk text。删除 thread 时,useThreads 也会清理 attachments_<threadId> collection,避免业务数据已删但向量残留。
8.7 为什么工具系统必须读失败路径¶
- MCP server 初始化失败不阻塞其他 server。
- 短暂断线不让工具 schema 反复消失,减少上下文漂移。
- tool call 可取消,避免应用退出时后台子进程继续跑。
- JSON Schema 需要适配 llama.cpp GBNF 限制。
- RAG plugin 不可用时,产品仍应允许普通聊天。
Jan 的工具架构本质上是“可失效能力”:工具是增强项,不应让聊天核心变成全有或全无。