# 三行速读

  1. 外部能力(MCP)接入后,控制面仍必须统一。
  2. 插件负责发现,server 负责提供能力,tool 负责执行动作。
  3. native 与 mcp 工具走同一路由与权限门,系统才可控。

# 先修知识

  • 已完成 s07 权限管道与 s02 工具路由理解。
  • 对进程通信和 “工具名标准化” 有基本概念。

# 读完后你应该能做到(可检验清单)

# 本篇要解决什么

到 s19,系统已经有完整本地能力。接下来的问题是:如何安全接入外部能力(数据库、浏览器、第三方服务),并保持架构统一。

核心目标:外部能力进入同一工具管道,而不是另开一套系统。

# 用一个类比先理解

像公司接外包团队:

  • 外包也要走同一工单系统;
  • 同一审批规则;
  • 同一结果回执格式。

不能因为来源不同,就绕过管理流程。

# 为什么这一步必须现在做

如果 MCP 能力绕开现有权限和路由,系统会出现 “影子通道”。s19 正在避免这种分裂,确保控制面一致。

# 关键代码怎么读

# 1) 统一能力权限门

1
2
3
class CapabilityPermissionGate:
def normalize(self, tool_name: str, tool_input: dict) -> dict: ...
def check(self, tool_name: str, tool_input: dict) -> dict: ...

先归一化再决策,native 与 mcp 都走同一逻辑。

# 2) MCPClient 最小链路

1
2
3
4
class MCPClient:
def connect(self): ...
def list_tools(self) -> list: ...
def call_tool(self, tool_name: str, arguments: dict) -> str: ...

教学版只保留最小必要流程,便于理解 “如何连、如何列、如何调”。

# 3) 工具命名前缀标准化

1
prefixed_name = f"mcp__{self.server_name}__{tool['name']}"

这个前缀解决两件事:避免命名冲突、明确路由目标。

# 4) 插件发现与统一路由

1
2
3
4
5
class PluginLoader: ...
class MCPToolRouter: ...

def build_tool_pool() -> list: ...
def handle_tool_call(tool_name: str, tool_input: dict) -> str: ...

外部 server 通过插件发现,再并入统一工具池,最终仍由同一调用入口执行。

# 你可以怎么复现

  1. 配置一个最小插件清单指向 MCP server。
  2. 启动后查看 tool pool 中是否出现 mcp__ 前缀工具。
  3. 调用外部工具并观察权限门与结果回写是否一致。

# 常见误区

  • 误区 1:把 plugin 当 server 本身。
  • 误区 2:把 server 当单个工具。
  • 误区 3:给外部能力开权限后门。

# 一句话总结

s19 把整条主线收束为一个平台原则:能力来源可以多样,但控制面必须统一。

# 补充解读:MCP 接入时最关键的统一性

# A. CapabilityPermissionGate.normalize

它先把 native/mcp 调用都归一化成同一 intent 结构,再做风险分级。这让权限策略无需按来源写两套。

# B. MCPClient.get_agent_tools 的前缀规范

1
prefixed_name = f"mcp__{self.server_name}__{tool['name']}"

这不是命名小技巧,而是路由与审计的关键索引。

# C. PluginLoader 的定位

插件清单做的是 “发现与配置”,不是执行本体。执行本体始终是 MCP server + tool router。

# D. build_tool_pool / handle_tool_call 的核心意义

外部能力最终进入同一工具池、同一调用入口、同一结果回写路径。保持这三同,系统复杂度才可控。

# 进阶练习

  1. 接入两个 MCP server,验证工具命名冲突是否被前缀解决。
  2. 在权限门中为不同 server 设置差异化 risk 策略。
  3. 给 MCP 调用结果加统一 telemetry 字段,方便观测外部能力质量。

# 再补一层:MCP 接入的落地排错路径

# A. 先验证 “连接成功”,再验证 “工具可调”

排错顺序建议:

  1. server 进程是否启动;
  2. tools/list 是否返回;
  3. 工具是否被前缀化加入池;
  4. tools/call 是否可返回有效内容。

一步步排,比一次性全链路排错更高效。

# B. 区分三类失败来源

  • 插件配置失败(manifest 问题)。
  • MCP 连接失败(进程或传输问题)。
  • 工具调用失败(参数 / 业务问题)。

把失败来源分层,能快速定位责任边界。

# C. 统一结果封装的重要性

normalize_tool_result 的价值在于把 native/mcp 输出格式对齐。上层模型只处理一种回写风格,复杂度明显下降。

# D. 不要跳过权限门做 “临时放通”

短期看省事,长期看会形成不可控后门。外部能力越多,统一权限越关键。

# 统一术语口径(本章)

  • MCP Server :外部能力提供进程或连接端点。
  • Plugin Manifest :声明外部能力来源与配置的发现清单。
  • Capability Router :把 native 与 mcp 能力统一路由到执行通道。

# 章节衔接(从易到难)

  • 本章是主线收束:能力来源可扩,但控制面统一。
  • 读完可回看 s01 ,你会看到从最小 loop 到平台化能力总线的一条完整演进路径。