4
0

把 MCP 工具接进桌面端 Agent 前,我会先加一层本地工具网关

最近给一个 Electron 桌面端助手接 MCP 工具时,我先停在接入层做了一次整理。MCP 让工具接入变得很顺,服务端可以暴露可调用能力,客户端通过 tools/list 发现工具,再通过 tools/call 发起调用。OpenAI 的工具调用流程也很清晰:模型提出工具调用请求,应用侧执行,再把结果交回模型。真正落到桌面端时,问题会变细:谁能看到工具列表,谁能确认高风险操作,工具参数在哪里校验,调用失败后怎样复盘。

桌面端 Agent 工具网关、策略校验、用户确认和审计日志链路示意图

原创示意图:渲染进程、主进程工具网关、策略校验、外部 MCP server 和审计日志之间的调用链路。 来源:Codex image generation

问题背景

桌面端 Agent 常常同时面对三个边界。第一是渲染进程,用户在这里输入需求,也最容易混入不可信页面状态。第二是主进程,本地文件、系统能力和外部进程通常都在这里收口。第三是外部 MCP server,能力来源更多,工具质量也不完全一致。Electron 文档提醒我们,IPC 通过开发者定义的 channel 在主进程和渲染进程之间传消息;context isolation 场景下,推荐通过 contextBridge 暴露经过筛选的方法,而非把强能力 API 直接交给页面。

我的结论是:工具接入要先过本地工具网关。渲染进程只发起 agent.runtool.confirm 这类少量动作;主进程负责枚举 MCP 工具、生成本地清单、套权限策略、执行调用并记录审计事件。这样 Agent 看到的是可控能力集,UI 看到的是可解释状态,外部工具不会直接穿透到页面。

踩坑和关键难点

第一个坑是工具清单会变化。MCP 规范里有 listChanged 能力,工具集合也可能随着授权范围改变。早期我只在应用启动时拉一次工具列表,结果 server 更新后 UI 还显示旧能力,模型偶尔会选择已经不可用的工具。后来我给清单加了版本号和过期时间,收到变更信号后重新拉取,并把每次运行绑定到当时的工具快照。

第二个坑是工具名和描述不能全信。MCP 工具定义包含 namedescriptioninputSchema 和可选的 outputSchema,规范也提示客户端应谨慎看待来自非可信 server 的工具注解。多个 server 聚合后还可能出现同名工具。我的处理方式是给工具名加 server 前缀,展示名用于 UI,真实调用名走内部 serverId.toolName,并把高风险能力标记为必须人工确认。

第三个坑是只记录最终答案没有排障价值。一次工具调用失败,可能卡在模型选择、参数生成、schema 校验、用户确认、server 执行或结果回写任一环节。只看最终报错,很难判断问题在哪一层。

解决思路

本地工具网关分成五块:registry 负责工具发现和快照;policy 根据工作区、用户确认和工具风险决定是否放行;schema guard 校验模型生成的参数和工具返回结果;executor 只在主进程里真正调用 MCP server;audit log 记录每次调用的上下文。

这里我刻意让网关保持朴素。它不替模型做复杂推理,只回答几个工程问题:这个工具当前是否存在,当前用户是否允许调用,参数是否符合清单,调用是否需要确认,结果是否能被安全地回传给模型和 UI。

关键步骤

第一步是把 tools/list 的结果转换成本地 manifest。除了 MCP 原始字段,我会补上 serverIdcanonicalNameriskLeveltimeoutMsrequiresConfirmationsnapshotVersion。Agent 每次运行只拿到当前快照里的允许工具。

第二步是做参数闸口。模型生成的 arguments 先经过 schema 校验,再做业务限制,比如路径必须落在工作区根目录内,文本长度不能无限增长,写入、删除、网络提交类动作必须带确认事件。确认事件由 UI 展示,但最终放行由主进程决策。

第三步是统一执行事件。每次调用都会生成 runIdtoolCallIdgatewayDecision。审计日志至少记录工具快照、输入摘要、确认状态、执行耗时、输出摘要和错误类型。敏感字段只写哈希或脱敏片段,避免日志变成新的泄露面。

第四步是把结果包成稳定信封。成功时返回结构化结果和可展示摘要,失败时返回可分类错误,例如 tool_not_foundschema_invalidpermission_deniedserver_error。模型需要知道下一步怎么恢复,用户需要知道这次操作到底有没有落地。

可复用经验

MCP 的价值在于把外部能力标准化,桌面端应用仍然需要守住自己的运行边界。我的经验是,不要让工具清单直接等于权限清单,也不要让模型调用直接等于应用执行。中间多一层本地网关,代码量不大,却能把发现、选择、确认、执行和审计拆开。

以后再接远程 MCP server、内部自动化脚本或本地文件工具时,我会继续沿用这个形状:先生成工具快照,再套策略,再校验输入,最后保留可回放日志。Agent 能力越多,这层网关越像桌面端 AI 应用的操作系统接口。

主要来源

Model Context Protocol: Tools

OpenAI API: Function calling

OpenAI API: Using tools

Electron: Context Isolation

Electron: Inter Process Communication

评论