Manifest 白名单 vs MCP 服务器注册表
状态: 描述运行时当前实际行为。 Crate:
librefang-types、librefang-kernel、librefang-extensions、librefang-api。
AgentManifest.mcp_servers(每个 agent 的白名单)和
KernelConfig.mcp_servers(全局服务器注册表)这两个字段在第一次读到
时常被误认为重复定义。它们存放的内容不同,所处的层次也不同。本页
记录边界、解析规则,以及谁有权限改谁。
三个值
| 位置 | 类型 | 存放什么 |
|---|---|---|
AgentManifest.mcp_servers | Vec<String>(服务器名字) | 单个 agent 的白名单。空 = "所有已配置服务器都对该 agent 可见"。位于 agent.toml。 |
KernelConfig.mcp_servers | Vec<McpServerConfigEntry>(完整配置) | 已安装服务器的全局注册表 —— transport、env、OAuth、taint 策略、headers。位于 ~/.librefang/config.toml。 |
kernel.mcp.effective_mcp_servers | RwLock<Vec<McpServerConfigEntry>> | KernelConfig.mcp_servers 的可热重载运行时镜像。与 mcp_generation 一起递增,保证缓存的 prompt 摘要原子失效。 |
引用位置:
crates/librefang-types/src/agent.rs:803—— manifest 字段。crates/librefang-kernel/src/kernel/subsystems/mcp.rs:63—— 运行时镜像。crates/librefang-kernel/src/kernel/mcp_setup.rs:324——reload_mcp_servers在热重载时把cfg.mcp_servers拷贝进effective_mcp_servers。
解析规则
注册表镜像不会预先和任何 agent 的白名单做交集。交集发生在 prompt 边界上,按 agent、按轮次:
render_mcp_summary(tool_names, configured_servers, mcp_allowlist)
—— crates/librefang-kernel/src/kernel/prompt_context.rs:281。其中
configured_servers 是注册表快照(effective_mcp_servers),
mcp_allowlist 是 agent 的 manifest 字段。空白名单表示该 agent
能看到所有已配置服务器。
任何需要"按 agent 视角看 MCP"的地方(tool 列表渲染、路由处理器)都 走同一套:先取注册表快照,再用 manifest 白名单过滤。永远不要缓存 交集结果。
为什么要拆开
- 变更频率不同。 注册表在运维安装 / 卸载 / 重新配置服务器时被改 写(少、全局、热重载)。白名单在运维决定"哪个 agent 能用哪个服务 器"时被改写(多、按 agent、不需要重连)。
- 影响范围不同。 从注册表里删一个服务器会断开连接。从某个 agent 的白名单里删一个服务器,仅仅是把它从该 agent 的 prompt 里隐藏 —— 连接对其他 agent 仍然有效。
- 所有权不同。 注册表归
librefang-extensions管理(catalog → installer → 写入[[mcp_servers]])。白名单是 agent 作者在agent.toml里编辑的。把两者合并会把 extension 安装器塞进 agent 作者的工作面,反之亦然。
librefang-extensions 的控制面边界
extensions crate 是唯一应该写注册表的代码路径。它负责:
catalog::McpCatalog—— 只读模板集合,从~/.librefang/mcp/catalog/*.toml加载。installer::install_integration—— 纯函数变换:catalog 条目 + 提供的凭据 → 新的McpServerConfigEntry。不写文件 —— 调用方负责把 返回值持久化进config.toml并触发 kernel 重载。credentials::CredentialResolver—— 在凭据被烧进注册表条目之前, 从 vault / env / dotenv 中取出。vault、oauth、health、dotenv、http_client—— 上面这些 模块依赖的叶子模块。
agent 端的白名单从不流经这个 crate。修改白名单是一次 kernel API
调用:KernelApi::set_agent_mcp_servers(agent_id, Vec<String>) ——
crates/librefang-kernel/src/kernel_api.rs:232,它会把变更写回磁盘
上的 agent manifest 并递增 per-agent 重载代际。
HTTP 接口
GET /api/agents/{id}/mcp_servers—— 返回 agent 的白名单和已解析 的有效列表(注册表经白名单过滤后的结果)。routes/agents.rs:4091。PUT /api/agents/{id}/mcp_servers—— 替换 agent 的白名单。routes/agents.rs:4162。不触碰注册表。GET /api/mcp/servers—— 注册表视图。routes/skills.rs:3972。 Dashboard 的 Integrations 页面用它来渲染安装 / 卸载。
对新代码意味着什么
- 给某个 agent 加 MCP 服务器: 通过
set_agent_mcp_servers写白 名单。不要改注册表。 - 安装新的服务器模板: 走
install_integration,把返回的McpServerConfigEntry持久化,然后调用reload_mcp_servers。 不要改任何 agent manifest。 - 读取"agent X 当前能看到哪些 MCP 工具": 从
effective_mcp_servers取注册表快照,再用 agent 的 manifest 白名单 过滤。过滤后的视图除了mcp_summary_cache之外不会跨轮缓存。该 缓存是一个DashMap<String, (u64, String)>,key 是排序后的白名单, value 存(mcp_generation, rendered_string)。注册表热重载会递增mcp_generation,下一次读取会发现存储的代际不再匹配,重新渲染 并覆盖旧条目 —— 见prompt_context.rs:252-285。