关于 protect-mcp-setup
这是 protect-mcp 的配置技能,可对 Claude Code 工具调用应用 Cedar 策略,并生成可离线验证的 Ed25519 签名回执。它面向需要策略执行和可验证记录的团队,包括受监管行业。
主要功能
- 01使用 Cedar 策略评估调用
- 02工具执行后签署回执
- 03支持离线验证回执
- 04配置钩子与回执路径
- 05提供回执审计命令
适用场景
- 01在 Agent 工具运行前执行策略
- 02为合规留存可验证记录
- 03无需网络连接即可检查回执
MCP 相关
README 将 protect-mcp 描述为 Claude Code 治理插件,并列出面向 MCP 主机的实现。它没有说明此配置会向 MCP 客户端暴露哪些服务端工具或资源。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wshobson/ agents --skill protect-mcp-setup安装后在 Claude Code 中输入/protect-mcp-setup确认已加载。
附带文件references/receipt-format.md
详细介绍
protect-mcp — 策略执行 + 签名回执
为每次 Claude Code 工具调用提供密码学治理。每次调用都会根据 Cedar 策略进行评估,并生成一份 Ed25519 签名的回执,任何人都可以离线验证。
概述
Claude Code 运行着功能强大的工具:Bash、Edit、Write、WebFetch。默认情况下,既没有审计追踪,也没有策略执行,更无法在事后证明当时做出了什么决策。protect-mcp 填补了这三项空白:
- Cedar 策略(AWS 的开源授权引擎)在执行前评估每次工具调用。Cedar 的拒绝具有权威性。
- Ed25519 回执记录每个运行过的工具的名称,并使用你的密钥签名。
- 离线验证通过
npx @veritasacta/verify完成。无需服务器、无需账户、无需信任运营方。
问题
AI Agent 做出的决策会影响金钱、安全和权利。Claude Code 的会话日志记录了发生的事情,但日志存在以下问题:
- 可变——任何有访问权限的人都可以编辑它
- 未签名——无法证明其完整性
- 绑定于运营方——验证需要信任持有日志的人
对于合规场景(金融、医疗、受监管的研究),这还不够。你需要可由第三方在不信任你的情况下验证的防篡改证据。
解决方案
将 protect-mcp 添加到你的 Claude Code 项目:
# 1. Install the plugin (adds hooks + skill to your project)
claude plugin install wshobson/agents/protect-mcp
# 2. Create ./protect.cedar (see below). The plugin installs the hooks.
# 3. Create the signing key once (protect-mcp 0.7.4 sign does not create it).
# An existing key is never replaced. See references/receipt-format.md to rotate.
if [ ! -e ./protect-mcp.key ]; then
d=$(mktemp -d) && npx [email protected] init --dir "$d" && mv "$d/keys/gateway.json" ./protect-mcp.key
fi
echo "/protect-mcp.key" >> .gitignore
# 4. Use Claude Code normally. Every tool call is now policy-evaluated
# and produces a signed receipt in ./receipts/
Hook 配置
安装该插件会添加 hooks/hooks.json 中的两个 hook。每个 hook 运行一个随插件捆绑的脚本:
{
"hooks": {
"PreToolUse": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/evaluate.sh" }
]
}
],
"PostToolUse": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/sign.sh" }
]
}
]
}
}
Claude Code 通过 stdin 以 JSON 形式将 hook 事件传递给命令,且不会设置 TOOL_NAME 或 TOOL_INPUT 变量。evaluate.sh 从该载荷中读取 tool_name 和 tool_input,并将它们作为标志传递给 protect-mcp;sign.sh 只读取 tool_name,因为 0.7.4 的签名器不记录其他内容。设置 PROTECT_MCP_POLICY、PROTECT_MCP_RECEIPTS 和 PROTECT_MCP_KEY 可更改默认路径。当策略文件缺失时,PreToolUse hook 会向 stderr 打印警告并允许该调用。
每个 hook 的作用
PreToolUse — 在工具执行之前运行。根据你的 Cedar 策略文件评估工具调用。如果 Cedar 返回 deny,该 hook 以代码 2 退出,Claude Code 会完全阻止该工具调用。
PostToolUse 在工具完成后运行。它会签署一份回执,记录工具名称,并将其追加到 ./receipts/receipts.jsonl。protect-mcp 0.7.4 不记录工具输入或输出。
Cedar 策略文件
在项目根目录创建 ./protect.cedar:
// Read-only tools: one rule can name several tools in `when`. Add WebFetch
// with your own URL rule.
permit (principal, action == Action::"MCP::Tool::call", resource) when {
resource == Tool::"Read" || resource == Tool::"Glob" || resource == Tool::"Grep"
};
// Safe commands only; git limited to read subcommands
permit (principal, action == Action::"MCP::Tool::call", resource == Tool::"Bash") when {
context has input && context.input has command &&
(context.input.command like "git status*" || context.input.command like "git diff*" ||
context.input.command like "git log*" || context.input.command like "git show*" ||
context.input.command like "npm*" || context.input.command like "ls*" ||
context.input.command like "cat*" || context.input.command like "echo*" ||
context.input.command like "pwd*" || context.input.command like "test*")
};
// No chaining (`&` also denies `2>&1`), `$` expansion, redirection (`>` or
// `<`, which covers `<(`), file output (`git diff --output`), or rm -rf
forbid (principal, action == Action::"MCP::Tool::call", resource == Tool::"Bash") when {
context has input && context.input has command &&
(context.input.command like "*;*" || context.input.command like "*&*" ||
context.input.command like "*|*" || context.input.command like "*$*" ||
context.input.command like "*`*" || context.input.command like "*>*" ||
context.input.command like "*<*" || context.input.command like "*\n*" ||
context.input.command like "*--output*" || context.input.command like "*rm -rf*")
};
// Writes only inside the project (paths are absolute), never via `..`
permit (principal, action == Action::"MCP::Tool::call", resource) when {
(resource == Tool::"Write" || resource == Tool::"Edit") &&
context has input && context.input has file_path &&
context.input.file_path like "/path/to/project/*"
};
forbid (principal, action == Action::"MCP::Tool::call", resource) when {
(resource == Tool::"Write" || resource == Tool::"Edit") &&
context has input && context.input has file_path &&
(context.input.file_path like "*/../*" || context.input.file_path like "*/..")
};
字符串匹配是尽力而为:like 检查的是原始字符串,而不是解析后的路径,而且 npm* 许可会运行任意代码,因此其安全性仅与项目的脚本相当。
验证
使用 ./protect-mcp.key 中的公钥验证每一份回执:
PUB=$(node -p 'JSON.parse(require("fs").readFileSync("./protect-mcp.key")).publicKey')
npx @veritasacta/[email protected] --replay-chain ./receipts/receipts.jsonl --key "$PUB"
# Exit 0 = every receipt verified
# Exit 1 = a receipt failed (tampered, wrong key, or malformed line)
# Exit 2 = the file could not be read
该插件的斜杠命令在 Claude Code 内部执行相同的操作。/verify-receipt 接受一份单独文件中的回执,例如来自 tail -n 1 ./receipts/receipts.jsonl > receipt.json。
/verify-receipt receipt.json
/audit-chain --last 20
回执格式
每份回执是 ./receipts/receipts.jsonl 中的一行。示例见 references/receipt-format.md。
- 对除
signature之外的所有字段使用 Ed25519 签名(RFC 8032) - 签名前进行 JCS 规范化(RFC 8785)
- 回执中不含公钥,因此需通过
--key传入 - 与上一份回执无关联,因此删除某一行不会被发现
为何重要
| 之前 | 之后 |
|---|---|
| “相信我,Agent 只读取了文件” | 密码学上可证明:每次 Read 都被记录并签名 |
| “日志显示它发生了” | 回执证明它发生了,且无人可以编辑 |
| “你得审计我们的系统” | 任何人都可以离线验证每一份回执 |
| “日志到现在可能已经不一样了” | Ed25519 签名在签名时锁定记录 |
标准
- Ed25519 — RFC 8032(数字签名)
- JCS — RFC 8785(确定性 JSON 规范化)
- Cedar — AWS 的开放授权策略语言
- IETF 草案 — draft-farley-acta-signed-receipts
相关
- npm:protect-mcp
- Verify CLI:@veritasacta/verify
- 源码:github.com/ScopeBlind/scopeblind-gateway
- 协议:veritasacta.com
- 集成:Microsoft Agent Governance Toolkit(PR #667)、AWS cedar-policy/cedar-for-agents(PR #64)