我的 MCP 适配器不再只是管道工作的一天
Source: Dev.to
TL;DR: Remote MCP Adapter 最初是为远程 MCP 工作流提供的可用性层,但最近的 MCP 工具投毒研究让人痛感:路径中的中间件也是安全边界的一部分。在 v0.3.0 中,我加入了工具定义固定、漂移检测、元数据清理、描述最小化以及更严格的会话绑定,以降低不安全的上游元数据和会话误用可能造成的危害。
在完成 Remote MCP Adapter 的核心工作后,我像大多数人在交付终于可用的东西后会做的那样:退后一步,四处看看。
我想了解其他人是如何处理同类问题的。Remote MCP 很有用,但一旦客户端和服务器不再共享文件系统,情况就会迅速变得糟糕。上传变得尴尬,生成的文件变得尴尬,任何涉及截图、PDF、制品或会话范围状态的操作都变得尴尬。这正是我最初构建适配器的原因。
我在最初启发此工作的博客中写了更多关于这段故事的内容。
随后我在 DEV 上看到一篇文章:Your MCP server’s tool descriptions are an attack surface。
那篇文章以及它引用的底层研究让我产生了一个不舒服的认识。
我为使远程 MCP 可用而构建的适配器,已经置身于信任边界的中间。
而一旦某物位于信任边界的中间,它就不能再假装只是管道设施了。
实现
我的适配器已经在做严肃的工作。它位于客户端和上游 MCP 服务器之间。它转发模型可见的工具元数据。它管理上传、制品以及每个会话的状态。它在本地‑仅设置不存在的边界之间翻译行为。
这正是人们常常在脑海中把它归类为“薄中继”的那类组件。
它并不是。
一旦网关或适配器看到工具目录、模式文本、描述、会话标识符、上传、认证上下文以及返回的制品,它就已经成为系统安全姿态的一部分——不论维护者是否有此计划。
那一刻,我对项目的看法彻底改变了。
Remote MCP Adapter 不再仅仅是远程文件和制品处理的便利层。它也已经成为一个天然的强制执行点。
- 并非银弹。
- 也不是 AI 防火墙。
- 更不是 MCP 安全的神奇解决方案。
但它绝对是一个强制执行点。
v0.3.0 有哪些更改
v0.3.0 是我首次明确将适配器视为如此的发布版本。
目标 不是 解决所有 MCP 安全问题——那样不诚实。
目标更为狭窄且更实际:
- 停止盲目转发模型可见的工具元数据
- 检测工具定义在会话中途出现漂移
- 减少不安全或不必要的描述文本传递给模型的量
- 在涉及有状态特性和认证时,收紧适配器自身的会话语义
- 记录已实现的内容以及仍在范围之外的内容
于是产生了五项具体的更改。
1) 更安全的模型可见工具元数据默认设置
适配器现在对工具元数据采用更严格的默认立场。
core.tool_metadata_sanitization.mode = "sanitize"
core.tool_definition_pinning.mode = "warn"这个默认设置很重要。在此之前,用户必须事先像安全工程师一样思考并选择正确的行为。现在适配器从更安全的立场出发,如果环境需要,则会进一步收紧。
我更倾向于这种权衡。许多安全特性在实际使用中会失效,仅因为它们只是选项,却没有人启用。
2) 工具定义固定与漂移检测
此项针对一些人称之为 “rug pull” 的问题。
如果服务器在会话开始时提供一个工具目录,随后又更改工具标题、描述或模式,这不再是无害的外观更新,而是已建立信任关系下模型可见行为的改变。
适配器现在可以为会话基准化首次可见的工具目录,并将后续目录与之比较。检测到漂移时,策略决定接下来的处理方式:
warn– 记录警告block– 停止转发已更改的工具invalidate– 完全终止会话
这并非为了聪明,而是为了平淡可靠。如果模型看到的内容发生了变化,这种变化不应悄无声息地通过。
3) 在转发工具模式前进行元数据清理
工具投毒不仅仅涉及顶层工具描述。这是近期研究的最重要收获之一。一旦工具元数据进入模型上下文,任何模型可见的文本都可能成为指令表面:标题、描述、模式文本、注释标题、嵌套描述以及其他看似无害的字段。
v0.3.0 为以下模型可见的元数据添加了清理功能:
- 工具标题
- 工具描述
- 注释标题
- 模式文本
在更严格模式下,适配器可以阻止带有脏元数据的工具,而不是转发它们。这是保持保守的正确位置。如果中间件已经在路径上,它至少应停止默认将每个上游模式视为无辜。
4) 工具描述最小化与剥离
现在有统一的 tool_description_policy,适用于顶层工具描述和嵌套模式描述。它支持三种模式:
preserve– 保持描述不变truncate– 将其截断至可配置长度strip– 完全移除
此项对偏执或严格受控的环境尤为有用。有时正确的答案并不是 “尝试去…
(The original text ends abruptly here; the content is preserved as‑is.)
检测自由形式描述文本中的所有巧妙投毒技巧
- 有时正确的答案是:为什么会有如此多的散文传递给模型?*
这正是此策略的用途。
如果某个环境不需要丰富的描述文本,应允许将其最小化或完全移除。
5) 在启用适配器认证时更严格的会话绑定
此项不那么显眼,但很重要。
一旦适配器存储上传、制品、取消状态或其他每会话数据,会话完整性就不再仅仅是一个 MCP tr
运输关注——它成为产品自身安全模型的一部分。
启用适配器身份验证后,会话现在绑定到建立它们的已认证上下文。
- 重新使用的
Mcp-Session-Id不能简单地在不同的已认证上下文中被获取。 - 如果适配器拥有状态,它也必须承担该状态被滥用的后果。
为什么我不想夸大其词
要把所有这些都包装成:
“Remote MCP Adapter 现在可以保护你免受 MCP 中毒。”
那样既懒散又不实。
v0.3.0 所做的更为具体。它为适配器提供了足够的感知能力和策略表面,使其不再是盲目的模型可见工具元数据和状态的转发器。这有帮助,但它 并不会 神奇地解决:
- 首次出现且语义上看似合法的中毒
- 每一种新颖的编码技巧
- 每一种模式层面的 schema 操作
- 通过允许的下游工具进行的所有数据泄露路径
- 堆栈其他位置做出的所有错误信任决策
这些限制很重要,假装不存在只会让发布的可信度下降,而不是提升。
证据与实现轨迹
我不想让这次发布仅仅是伪装成安全帖子的更新日志,所以我还撰写并链接了支持材料。
GitHub 仓库:
安全快照:
专用安全文档:
Issue 22 — 工具定义固定与漂移检测:
Issue 23 — 在转发前规范化并清理工具模式:
Issue 24 — 工具描述最小化/剥离:
Issue 25 — 加固适配器管理的会话语义:
证据博客:
致谢
此版本并非凭空出现。
最直接的推动来自阅读 Your MCP server’s tool descriptions are an attack surface,以及围绕 MCP 工具投毒和模式操控的研究与指南。那篇文章值得一读,背后的工作同样值得关注。
如果你认真在探索 MCP 的安全方面,也可以看看 Pipelock。它作为专用的控制点采用了更注重安全的姿态,了解其他人如何处理同类问题也很有帮助。
如果你在团队或组织中运行远程 MCP 部署,并且在实际环境中遇到过投毒、模式异常或会话中工具漂移,我真诚地希望了解这些情况。真实的攻击样本和棘手的边缘案例比干净的玩具示例在决定下一步加固措施时更有价值。