Configure Cedar policy enforcement and Ed25519 signed
protect-mcp — Policy Enforcement + Signed Receipts

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.
--- 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
Overview
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.
Manual install (npx, ZIP)
npx skills add wshobson/agents --skill protect-mcp-setup -g -a claude-codemkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \
| tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/protect-mcp/skills/protect-mcp-setupNew-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/f9ad7f16929591dc3315/protect-mcp-setup.zip" -OutFile "$env:TEMP\protect-mcp-setup.zip"; Expand-Archive "$env:TEMP\protect-mcp-setup.zip" -DestinationPath "$HOME\.claude\skills" -ForceConnects with Agent Alley MCP · agentalley.io/mcp
Files included
SKILL.md6.6 KB
Read the files here
wshobson/
Shared references3SKILL.md reads these from elsewhere in the repo. Not in the ZIP.
- evaluate.shplugins/protect-mcp/hooks/1.5 KB
- hooks.jsonplugins/protect-mcp/hooks/459 B
- sign.shplugins/protect-mcp/hooks/656 B
Show the full text215 lines
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 each decision with its inputs, the policy that governed it, and the outcome. Receipts are hash-chained.
- 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. Start the receipt-signing server (runs locally, no external calls)
npx protect-mcp@latest serve --enforce
# 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. Signs a receipt containing the
tool name, input hash, output hash, decision, policy digest, and timestamp.
Writes the receipt to ./receipts/<timestamp>.json.
Cedar Policy File
Create ./protect.cedar at the project root:
// Allow read-only tools by default
permit (
principal,
action in [Action::"Read", Action::"Glob", Action::"Grep", Action::"WebFetch"],
resource
);
// Require explicit allow for destructive tools
permit (
principal,
action == Action::"Bash",
resource
) when {
// Allow safe commands only
context.command_pattern in ["git", "npm", "ls", "cat", "echo", "pwd", "test"]
};
// Never allow recursive deletion
forbid (
principal,
action == Action::"Bash",
resource
) when {
context.command_pattern == "rm -rf"
};
// Require confirmation for writes outside the project
forbid (
principal,
action in [Action::"Edit", Action::"Write"],
resource
) when {
context.path_starts_with != "."
};
Verification
Verify a single receipt:
npx @veritasacta/verify receipts/2026-04-15T10-30-00Z.json
# Exit 0 = valid
# Exit 1 = tampered
# Exit 2 = malformed
Verify the entire chain:
npx @veritasacta/verify receipts/*.json
Use the plugin's slash commands from within Claude Code:
/verify-receipt receipts/latest.json
/audit-chain ./receipts/ --last 20
Receipt Format
Each receipt is a JSON file with this structure:
{
"receipt_id": "rec_8f92a3b1",
"receipt_version": "1.0",
"issuer_id": "claude-code-protect-mcp",
"event_time": "2026-04-15T10:30:00.000Z",
"tool_name": "Bash",
"input_hash": "sha256:a3f8...",
"decision": "allow",
"policy_id": "autoresearch-safe",
"policy_digest": "sha256:b7e2...",
"parent_receipt_id": "rec_3d1ab7c2",
"public_key": "4437ca56815c0516...",
"signature": "4cde814b7889e987..."
}
- Ed25519 signatures (RFC 8032)
- JCS canonicalization (RFC 8785) before signing
- Hash-chained to the previous receipt via
parent_receipt_id - Offline verifiable — no network call, no vendor lookup
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
- npm: protect-mcp
- Verify CLI: @veritasacta/verify
- Source: github.com/ScopeBlind/scopeblind-gateway
- Protocol: veritasacta.com
- Integrations: Microsoft Agent Governance Toolkit (PR #667), AWS cedar-policy/cedar-for-agents (PR #64)
| 1 | |
| 2 | name protect-mcp-setup |
| 3 | 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. |
| 4 | |
| 5 | |
| 6 | # protect-mcp — Policy Enforcement + Signed Receipts |
| 7 | |
| 8 | Cryptographic governance for every Claude Code tool call. Each invocation is |
| 9 | evaluated against a Cedar policy and produces an Ed25519-signed receipt that |
| 10 | anyone can verify offline. |
| 11 | |
| 12 | ## Overview |
| 13 | |
| 14 | Claude Code runs powerful tools: `Bash`, `Edit`, `Write`, `WebFetch`. By default |
| 15 | there is no audit trail, no policy enforcement, and no way to prove what was |
| 16 | decided after the fact. `protect-mcp` closes all three gaps: |
| 17 | |
| 18 | **Cedar policies** (AWS's open authorization engine) evaluate every tool call |
| 19 | before execution. Cedar deny is authoritative. |
| 20 | **Ed25519 receipts** record each decision with its inputs, the policy that |
| 21 | governed it, and the outcome. Receipts are hash-chained. |
| 22 | **Offline verification** via `npx @veritasacta/verify`. No server, no account, |
| 23 | no trust in the operator. |
| 24 | |
| 25 | ## Problem |
| 26 | |
| 27 | AI agents make decisions that affect money, safety, and rights. The Claude Code |
| 28 | session log records what happened, but the log is: |
| 29 | |
| 30 | Mutable — anyone with access can edit it |
| 31 | Unsigned — there is no way to prove integrity |
| 32 | Operator-bound — verification requires trusting whoever holds the log |
| 33 | |
| 34 | For compliance contexts (finance, healthcare, regulated research), this is not |
| 35 | sufficient. You need tamper-evident evidence that can be verified by third |
| 36 | parties without trusting you. |
| 37 | |
| 38 | ## Solution |
| 39 | |
| 40 | Add `protect-mcp` to your Claude Code project: |
| 41 | |
| 42 | |
| 43 | # 1. Install the plugin (adds hooks + skill to your project) |
| 44 | claude plugin install wshobson/agents/protect-mcp |
| 45 | |
| 46 | # 2. Create ./protect.cedar (see below). The plugin installs the hooks. |
| 47 | |
| 48 | # 3. Start the receipt-signing server (runs locally, no external calls) |
| 49 | npx protect-mcp@latest serve --enforce |
| 50 | |
| 51 | # 4. Use Claude Code normally. Every tool call is now policy-evaluated |
| 52 | # and produces a signed receipt in ./receipts/ |
| 53 | |
| 54 | |
| 55 | ## Hook Configuration |
| 56 | |
| 57 | Installing the plugin adds both hooks from `hooks/hooks.json`. Each hook runs a |
| 58 | script bundled with the plugin: |
| 59 | |
| 60 | |
| 61 | { |
| 62 | "hooks": { |
| 63 | "PreToolUse": [ |
| 64 | { |
| 65 | "matcher": ".*", |
| 66 | "hooks": [ |
| 67 | { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/evaluate.sh" } |
| 68 | ] |
| 69 | } |
| 70 | ], |
| 71 | "PostToolUse": [ |
| 72 | { |
| 73 | "matcher": ".*", |
| 74 | "hooks": [ |
| 75 | { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/sign.sh" } |
| 76 | ] |
| 77 | } |
| 78 | ] |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | |
| 83 | Claude Code passes the hook event to the command as JSON on stdin and does not |
| 84 | set `TOOL_NAME` or `TOOL_INPUT` variables. `evaluate.sh` reads `tool_name` and |
| 85 | `tool_input` from that payload and passes them to `protect-mcp` as flags; `sign.sh` reads |
| 86 | `tool_name` only, because the 0.7.4 signer records nothing else. Set |
| 87 | `PROTECT_MCP_POLICY`, `PROTECT_MCP_RECEIPTS`, and `PROTECT_MCP_KEY` to change the |
| 88 | default paths. When the policy file is missing, the PreToolUse hook prints a |
| 89 | warning to stderr and allows the call. |
| 90 | |
| 91 | ### What each hook does |
| 92 | |
| 93 | **PreToolUse** — Runs BEFORE the tool executes. Evaluates the tool call against |
| 94 | your Cedar policy file. If Cedar returns `deny`, the hook exits with code 2 and |
| 95 | Claude Code blocks the tool call entirely. |
| 96 | |
| 97 | **PostToolUse** — Runs AFTER the tool completes. Signs a receipt containing the |
| 98 | tool name, input hash, output hash, decision, policy digest, and timestamp. |
| 99 | Writes the receipt to `./receipts/<timestamp>.json`. |
| 100 | |
| 101 | ## Cedar Policy File |
| 102 | |
| 103 | Create `./protect.cedar` at the project root: |
| 104 | |
| 105 | |
| 106 | // Allow read-only tools by default |
| 107 | permit ( |
| 108 | principal, |
| 109 | action in [Action::"Read", Action::"Glob", Action::"Grep", Action::"WebFetch"], |
| 110 | resource |
| 111 | ); |
| 112 | |
| 113 | // Require explicit allow for destructive tools |
| 114 | permit ( |
| 115 | principal, |
| 116 | action == Action::"Bash", |
| 117 | resource |
| 118 | ) when { |
| 119 | // Allow safe commands only |
| 120 | context.command_pattern in ["git", "npm", "ls", "cat", "echo", "pwd", "test"] |
| 121 | }; |
| 122 | |
| 123 | // Never allow recursive deletion |
| 124 | forbid ( |
| 125 | principal, |
| 126 | action == Action::"Bash", |
| 127 | resource |
| 128 | ) when { |
| 129 | context.command_pattern == "rm -rf" |
| 130 | }; |
| 131 | |
| 132 | // Require confirmation for writes outside the project |
| 133 | forbid ( |
| 134 | principal, |
| 135 | action in [Action::"Edit", Action::"Write"], |
| 136 | resource |
| 137 | ) when { |
| 138 | context.path_starts_with != "." |
| 139 | }; |
| 140 | |
| 141 | |
| 142 | ## Verification |
| 143 | |
| 144 | Verify a single receipt: |
| 145 | |
| 146 | |
| 147 | npx @veritasacta/verify receipts/2026-04-15T10-30-00Z.json |
| 148 | # Exit 0 = valid |
| 149 | # Exit 1 = tampered |
| 150 | # Exit 2 = malformed |
| 151 | |
| 152 | |
| 153 | Verify the entire chain: |
| 154 | |
| 155 | |
| 156 | npx @veritasacta/verify receipts/*.json |
| 157 | |
| 158 | |
| 159 | Use the plugin's slash commands from within Claude Code: |
| 160 | |
| 161 | |
| 162 | /verify-receipt receipts/latest.json |
| 163 | /audit-chain ./receipts/ --last 20 |
| 164 | |
| 165 | |
| 166 | ## Receipt Format |
| 167 | |
| 168 | Each receipt is a JSON file with this structure: |
| 169 | |
| 170 | |
| 171 | { |
| 172 | "receipt_id": "rec_8f92a3b1", |
| 173 | "receipt_version": "1.0", |
| 174 | "issuer_id": "claude-code-protect-mcp", |
| 175 | "event_time": "2026-04-15T10:30:00.000Z", |
| 176 | "tool_name": "Bash", |
| 177 | "input_hash": "sha256:a3f8...", |
| 178 | "decision": "allow", |
| 179 | "policy_id": "autoresearch-safe", |
| 180 | "policy_digest": "sha256:b7e2...", |
| 181 | "parent_receipt_id": "rec_3d1ab7c2", |
| 182 | "public_key": "4437ca56815c0516...", |
| 183 | "signature": "4cde814b7889e987..." |
| 184 | } |
| 185 | |
| 186 | |
| 187 | **Ed25519** signatures (RFC 8032) |
| 188 | **JCS canonicalization** (RFC 8785) before signing |
| 189 | **Hash-chained** to the previous receipt via `parent_receipt_id` |
| 190 | **Offline verifiable** — no network call, no vendor lookup |
| 191 | |
| 192 | ## Why This Matters |
| 193 | |
| 194 | | Before | After | |
| 195 | |--------|-------| |
| 196 | | "Trust me, the agent only read files" | Cryptographically provable: every Read logged and signed | |
| 197 | | "The log shows it happened" | The receipt proves it happened, and no one can edit it | |
| 198 | | "You'd have to audit our system" | Anyone can verify every receipt offline | |
| 199 | | "Logs might be different by now" | Ed25519 signatures lock the record at signing time | |
| 200 | |
| 201 | ## Standards |
| 202 | |
| 203 | **Ed25519** — RFC 8032 (digital signatures) |
| 204 | **JCS** — RFC 8785 (deterministic JSON canonicalization) |
| 205 | **Cedar** — AWS's open authorization policy language |
| 206 | **IETF draft** — [draft-farley-acta-signed-receipts] |
| 207 | |
| 208 | ## Related |
| 209 | |
| 210 | **npm**: [protect-mcp] |
| 211 | **Verify CLI**: [@veritasacta/verify] |
| 212 | **Source**: [github.com/ScopeBlind/scopeblind-gateway] |
| 213 | **Protocol**: [veritasacta.com] |
| 214 | **Integrations**: Microsoft Agent Governance Toolkit (PR #667), AWS cedar-policy/cedar-for-agents (PR #64) |
| 215 |
Details
- Updated
- Sep 21, 2026
- License
- MIT
- Stars on the repo
- ★ 39,857
- Checked
- Source
- wshobson/agents ↗
- Creator
- wshobson · 179 listings
Similar skills
See all →
SkillTests in real browsers via Chrome DevTools MCPBrowser testing with devtools
MCPThis MCP server attempts to exercise all the featuresEverything MCP Server
MCPA Model Context Protocol server that provides web contentFetch MCP Server
MCPNode.js server implementing Model Context ProtocolFilesystem MCP Server
SkillAbout libraries, frameworks, API referencesContext7 MCP
SkillUses Chrome DevTools via MCP for efficient debuggingMore from wshobson
SkillMaster C/.NET backend development patterns for building
SkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliance
SkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Design
SkillMigrate from AngularJS to Angular using hybrid modeAngular migration
SkillUnderstand anti-reversing, obfuscationAnti reversing techniques
SkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patterns