Agent Skills › wshobson/agents › protect-mcp-setup

protect-mcp-setup

GitHub

为 Claude Code 配置 Cedar 策略执行与 Ed25519 签名收据,实现工具调用的密码学审计、合规性证据及离线验证,解决日志篡改与不可信问题。

plugins/protect-mcp/skills/protect-mcp-setup/SKILL.md wshobson/agents

Trigger Scenarios

需要为 AI 代理操作建立密码学审计追踪 要求对工具执行进行基于策略的访问控制 生成可第三方验证的合规性证据

Install

npx skills add wshobson/agents --skill protect-mcp-setup -g -y
More Options

Non-standard path

npx skills add https://github.com/wshobson/agents/tree/main/plugins/protect-mcp/skills/protect-mcp-setup -g -y

Use without installing

npx skills use wshobson/agents@protect-mcp-setup

指定 Agent (Claude Code)

npx skills add wshobson/agents --skill protect-mcp-setup -a claude-code -g -y

安装 repo 全部 skill

npx skills add wshobson/agents --all -g -y

预览 repo 内 skill

npx skills add wshobson/agents --list

SKILL.md

Frontmatter
{
    "name": "protect-mcp-setup",
    "description": "Configure Cedar policy enforcement and Ed25519 signed receipts for Claude Code tool calls. Use when setting up projects that need cryptographic audit trails, policy-gated tool execution, or compliance-ready evidence of agent actions."
}

protect-mcp — Policy Enforcement + Signed Receipts

Cryptographic governance for every Claude Code tool call. Each invocation is evaluated against a Cedar policy and produces an Ed25519-signed receipt that anyone can verify offline.

Overview

Claude Code runs powerful tools: Bash, Edit, Write, WebFetch. By default there is no audit trail, no policy enforcement, and no way to prove what was decided after the fact. protect-mcp closes all three gaps:

  • Cedar policies (AWS's open authorization engine) evaluate every tool call before execution. Cedar deny is authoritative.
  • Ed25519 receipts record the name of each tool that ran, signed with your key.
  • Offline verification via npx @veritasacta/verify. No server, no account, no trust in the operator.

Problem

AI agents make decisions that affect money, safety, and rights. The Claude Code session log records what happened, but the log is:

  • Mutable — anyone with access can edit it
  • Unsigned — there is no way to prove integrity
  • Operator-bound — verification requires trusting whoever holds the log

For compliance contexts (finance, healthcare, regulated research), this is not sufficient. You need tamper-evident evidence that can be verified by third parties without trusting you.

Solution

Add protect-mcp to your Claude Code project:

# 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 protect-mcp@0.7.4 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 Configuration

Installing the plugin adds both hooks from hooks/hooks.json. Each hook runs a script bundled with the plugin:

{
  "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 passes the hook event to the command as JSON on stdin and does not set TOOL_NAME or TOOL_INPUT variables. evaluate.sh reads tool_name and tool_input from that payload and passes them to protect-mcp as flags; sign.sh reads tool_name only, because the 0.7.4 signer records nothing else. Set PROTECT_MCP_POLICY, PROTECT_MCP_RECEIPTS, and PROTECT_MCP_KEY to change the default paths. When the policy file is missing, the PreToolUse hook prints a warning to stderr and allows the call.

What each hook does

PreToolUse — Runs BEFORE the tool executes. Evaluates the tool call against your Cedar policy file. If Cedar returns deny, the hook exits with code 2 and Claude Code blocks the tool call entirely.

PostToolUse runs AFTER the tool completes. It signs a receipt that names the tool and appends it to ./receipts/receipts.jsonl. protect-mcp 0.7.4 does not record the tool input or output.

Cedar Policy File

Create ./protect.cedar at the project root:

// 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 "*/..")
};

String matching is best-effort: like checks the raw string, not a resolved path, and an npm* permit runs arbitrary code, so it is only as safe as the project's scripts.

Verification

Verify every receipt against the public key in ./protect-mcp.key:

PUB=$(node -p 'JSON.parse(require("fs").readFileSync("./protect-mcp.key")).publicKey')
npx @veritasacta/verify@0.9.2 --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

The plugin's slash commands do the same inside Claude Code. /verify-receipt takes one receipt in its own file, e.g., from tail -n 1 ./receipts/receipts.jsonl > receipt.json.

/verify-receipt receipt.json
/audit-chain --last 20

Receipt Format

Each receipt is one line of ./receipts/receipts.jsonl. See references/receipt-format.md for a sample.

  • Ed25519 signatures (RFC 8032) over all fields but signature
  • JCS canonicalization (RFC 8785) before signing
  • No public key in the receipt, so pass it with --key
  • No link to the previous receipt, so a deleted line goes undetected

Why This Matters

Before After
"Trust me, the agent only read files" Cryptographically provable: every Read logged and signed
"The log shows it happened" The receipt proves it happened, and no one can edit it
"You'd have to audit our system" Anyone can verify every receipt offline
"Logs might be different by now" Ed25519 signatures lock the record at signing time

Standards

  • Ed25519 — RFC 8032 (digital signatures)
  • JCS — RFC 8785 (deterministic JSON canonicalization)
  • Cedar — AWS's open authorization policy language
  • IETF draft — draft-farley-acta-signed-receipts

Related

Version History

  • 9b15b34 Current 2026-09-28 06:56

    修复了保护-mcp审计轨迹在Claude Code钩子中的工作问题:适配0.7.4版本通过stdin传递JSON载荷而非环境变量;修正密钥和收据的gitignore路径;更新验证步骤以匹配新的收据格式(v2信封,无哈希链)。

  • 4236bb9 2026-09-22 19:53

    修复了Hook脚本从stdin正确读取JSON载荷以获取工具名称和输入的缺陷;修正异常退出码映射以防止策略误判;更新说明文档中sign.sh的参数行为描述。

  • 367cb6a 2026-08-20 06:54

Same Skill Collection

plugins/accessibility-compliance/skills/screen-reader-testing/SKILL.md
plugins/accessibility-compliance/skills/wcag-audit-patterns/SKILL.md
plugins/agent-teams/skills/multi-reviewer-patterns/SKILL.md
plugins/agent-teams/skills/parallel-debugging/SKILL.md
plugins/agent-teams/skills/task-coordination-strategies/SKILL.md
plugins/api-scaffolding/skills/fastapi-templates/SKILL.md
plugins/avoid-ai-writing/skills/avoid-ai-writing/SKILL.md
plugins/backend-development/skills/api-design-principles/SKILL.md
plugins/backend-development/skills/architecture-patterns/SKILL.md
plugins/backend-development/skills/cqrs-implementation/SKILL.md
plugins/backend-development/skills/event-store-design/SKILL.md
plugins/backend-development/skills/microservices-patterns/SKILL.md
plugins/backend-development/skills/projection-patterns/SKILL.md
plugins/backend-development/skills/temporal-python-testing/SKILL.md
plugins/backend-development/skills/workflow-orchestration-patterns/SKILL.md
plugins/before-you-build/skills/before-you-build/SKILL.md
plugins/block-no-verify/skills/block-no-verify-hook/SKILL.md
plugins/blockchain-web3/skills/defi-protocol-templates/SKILL.md
plugins/blockchain-web3/skills/nft-standards/SKILL.md
plugins/blockchain-web3/skills/solidity-security/SKILL.md
plugins/blockchain-web3/skills/web3-testing/SKILL.md
plugins/business-analytics/skills/data-storytelling/SKILL.md
plugins/business-analytics/skills/kpi-dashboard-design/SKILL.md
plugins/cicd-automation/skills/deployment-pipeline-design/SKILL.md
plugins/cicd-automation/skills/github-actions-templates/SKILL.md
plugins/cicd-automation/skills/gitlab-ci-patterns/SKILL.md
plugins/cicd-automation/skills/secrets-management/SKILL.md
plugins/cloud-infrastructure/skills/cost-optimization/SKILL.md
plugins/cloud-infrastructure/skills/hybrid-cloud-networking/SKILL.md
plugins/cloud-infrastructure/skills/istio-traffic-management/SKILL.md
plugins/cloud-infrastructure/skills/linkerd-patterns/SKILL.md
plugins/cloud-infrastructure/skills/mtls-configuration/SKILL.md
plugins/cloud-infrastructure/skills/multi-cloud-architecture/SKILL.md
plugins/cloud-infrastructure/skills/service-mesh-observability/SKILL.md
plugins/cloud-infrastructure/skills/terraform-module-library/SKILL.md
plugins/conductor/skills/track-management/SKILL.md
plugins/conductor/skills/workflow-patterns/SKILL.md
plugins/data-engineering/skills/airflow-dag-patterns/SKILL.md
plugins/data-engineering/skills/data-quality-frameworks/SKILL.md
plugins/data-engineering/skills/dbt-transformation-patterns/SKILL.md
plugins/data-engineering/skills/spark-optimization/SKILL.md
plugins/database-design/skills/postgresql-table-design/SKILL.md
plugins/database-design/skills/postgresql/SKILL.md
plugins/developer-essentials/skills/auth-implementation-patterns/SKILL.md
plugins/developer-essentials/skills/bazel-build-optimization/SKILL.md
plugins/developer-essentials/skills/code-review-excellence/SKILL.md
plugins/developer-essentials/skills/debugging-strategies/SKILL.md
plugins/developer-essentials/skills/e2e-testing-patterns/SKILL.md
plugins/developer-essentials/skills/error-handling-patterns/SKILL.md
plugins/developer-essentials/skills/git-advanced-workflows/SKILL.md

Metadata

Files
0
Version
9b15b34
Hash
dc42772a
Indexed
2026-08-20 06:54

홈 - 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-29 09:36
浙ICP备14020137号-1