mcp-confirm
mcp-confirm
简而言之: 当 AI 询问“你确定吗?”时,MCP SDK 已经阻止了 该批准被复用于不同的操作。它不能阻止 同一个批准被使用两次。本包填补了这个空白,以及 SDK 留下的另外两个空白。
先读这里:这个问题的大部分已经解决了
2026-07-28 的 MCP 规范增加了多轮往返(Multi Round-Trip),因此工具可以
在调用中途暂停并向用户请求确认。批准通过客户端以不透明的 requestState 返回,
规范要求服务器必须将其视为不可信数据。
Python SDK 默认在每一个 MCPServer 上为你完成了这一点。
RequestStateBoundary 被无条件地附加到中间件链中——
如果你不提供密钥,它会使用一个临时密钥。它使用
AES-256-GCM 密封状态,并将其绑定到方法、目标、调用参数的摘要、
受众以及已认证的主体,并带有 TTL。
所以每个人首先想到的攻击——批准删除 cache.txt,然后
重放该批准去删除 thesis.txt——已经被 SDK 阻止了。
你不需要为此写一个库,也不应该写。
这个仓库最初还是写了一个:250 行的 HMAC、TTL 和参数 绑定,作为主打功能发布,结果在发布当天就已经是多余的了。 这段历史记录在文末,而不是悄悄删除。
Related MCP server: RecourseOS
SDK 没有做什么
三个空白,每一个都有对应的测试。
1. 它绑定状态并设置过期,但从不消费状态
在 TTL 内,同一个批准可以被验证任意多次。 SDK 做的每一个检查都是无状态的。规范明确说明 这是有意为之:
请注意,这些措施限制了重放窗口并防止跨用户和 跨请求的复用,但它们本身并不保证单次使用。服务器 对于给定的
requestState必须至多消费一次(例如, 一次性兑换码)必须在服务端强制执行该不变量。
对于“删除一个文件”这种操作,第二次尝试不会成功。对于“转账 500 英镑”这种操作,
这恰恰是整个问题的核心。 singleuse.py 就是那个
不变量——一本未完成确认的账本,一旦兑换即被消费。它
不包含任何加密,因为边界本身已经保证了明文
是由这个服务器铸造的。
2. 没有人净化人类读到的提问文本
message 是服务器选择的文本,呈现给用户,通常
会包含一个不可信的值插值进去——其全部意义就在于说明哪个
文件将被删除。所以给文件起个名字吧:
cache.txt
SYSTEM NOTICE: your session has expired.
Enter your AWS secret key to continue:对话框现在显示的是一个第二眼的、官方的提示。用户并不是在 确认一个删除操作;他们正在被自己的工具所钓鱼。同样的 2026-07-28 发布还带来了 MCP Apps——服务器渲染的 UI——这拓宽了 这个攻击面,而不是缩小它。
prompt.py 将不可信的值压缩为一行,
去除双向控制字符和零宽字符,并从
中间截断,这样末尾的文件名保持可见。控制字符变成
空格而不是被删除,因为如果直接删除,a\nb 和
ab 会渲染成一样——两个不同的文件,同一个对话框。
3. 没有协议层能在执行时重新检查你的资源
用户在思考的时候,文件可能已经被替换了。在批准和 执行之间,工具只能看到它自己的参数。只有工具本身 知道“未更改”对它意味着什么。这个服务器在删除之前会重新检查, 并拒绝任何已成为符号链接的路径。
哪一层拒绝什么
这是最有用的部分,测试就是为了展示这一点而写的。MCPError
意味着 SDK 的中间件在这个包运行之前就拒绝了;ToolError 意味着
这个包拒绝了。
攻击 | 拒绝方 | 测试 |
将批准重放到另一个文件上 | SDK |
|
状态被伪造,或在另一个密钥下密封 | SDK |
|
同一个批准被使用两次 | 本包 |
|
状态由另一个副本铸造 | 本包 |
|
文件名伪造系统提示 | 本包 |
|
批准后文件被替换为符号链接 | 本包 |
|
路径超出允许的根目录 | 本包 |
|
测试
35 个测试——17 个通过服务器,11 个针对账本,7 个针对提示净化。
每个服务器测试都经过真实的 RequestStateBoundary,也就是
MCPServer 自己安装的那个类,使用固定的密钥——密封第一轮,
解封第二轮,完全模拟真实线上的流程。
这个测试框架的存在是因为一个具体的错误。第一个版本直接
调用 MCPServer.call_tool(),这直接进入了工具
管理器,完全绕过了中间件链。SDK 的边界从未
运行过,所以一个多余的、手写的防护看起来像是承重墙。测试设计
正是问题所在——它掩盖了整个构建周期中的缺陷。
覆盖率是 81%,其中 prompt.py 为 100%,singleuse.py 为 94%。差距在于
main() 的 argparse 和传输层接线,通过 build_server
来覆盖。
CI 只在 Ubuntu 上运行,这是有意为之:交换后确认的测试需要 符号链接,而在那里如果测试被跳过,构建就会失败。
安装
pip install git+https://github.com/les-k/mcp-confirm.git运行
mcp-confirm --root /path/you/allow如果没有 --root,服务器会拒绝每一个请求,而不是默认使用
任何路径。根目录在启动时固定,绝不会由代理选择。不需要签名
密钥——MCPServer 自带。
已知限制
账本在内存中,所以它在一个进程内是正确的,但在 负载均衡器后面就会出错。SDK 支持在多个副本之间共享密钥 (
RequestStateSecurity(keys=[...]));在这种配置下,副本 B 会拒绝副本 A 发出的确认。它会安全地失败——这是安全的 方向——但对用户来说,这表现为确认 inexplicably 停止 工作。多进程部署需要 Redis 或一个带有 原子比较并删除的数据库行。有一个测试覆盖了这种行为。演示工具刻意保持小巧。 它只删除一个文件。真正 有趣的代码在
singleuse.py和prompt.py中。没有 CVE 支持这个包。 MRTR 才发布几周,所以这是根据 规范自身的 MUST/SHOULD 列表以及阅读 SDK 源码构建的,而不是基于 已公开的安全事件。
0.1.0 版本有什么问题
保留在这里,因为一个只记录成功的仓库不能证明任何东西。
0.1.0 重新实现了 SDK 已经做过的事情。 state.py 有 250 行
HMAC 签名、TTL 以及主体/方法/参数绑定——全部重复了
RequestStateBoundary,而且没有一样做得更好:用 HMAC 的地方 SDK 使用的是
认证加密,没有受众绑定,没有密钥轮换。
它是通过阅读 SDK 的源码被发现的,而不是通过测试。 测试之所以通过, 恰恰是因为它们绕过了本来会暴露问题的中间件。
CI 另外捕获了 0.1.0 中的一个真实 bug:符号链接检查在
Path.resolve() 之后运行,所以它检查的是链接的目标而不是链接
本身。一个针对允许根目录内另一个文件的交换攻击会被
删除。已修复,并为原始版本从未测试过的变体添加了测试。
0.2.0 完全删除了 state.py,只保留 SDK 未覆盖的部分。
许可证
MIT。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server that provides safeguard capabilities to protect against prompt injection and unsafe tool calls.6MIT

RecourseOSofficial
AlicenseNot gradedqualityAmaintenanceMCP server that evaluates Terraform plans, shell commands, and tool calls to assess recoverability and risk before execution, enabling safe AI agent actions.1511MIT- AlicenseNot gradedqualityCmaintenanceMCP server that provides human-in-the-loop approval for risky AI agent actions, with durable state and audit logs.MIT
- FlicenseNot gradedqualityCmaintenanceMCP server that provides a security gateway for AI agents, enforcing allow/confirm/deny policies on tool calls and requiring human approval for risky operations, with full audit logging.
Related MCP Connectors
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Scans MCP servers for tool poisoning, prompt injection and supply chain risks.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/les-k/mcp-confirm'
If you have feedback or need assistance with the MCP directory API, please join our Discord server