mcpField
P
protect-mcp-setup

protect-mcp-setup

github.com/wshobsonセキュリティ41.9k6.1k 回インストール2 週間前に更新
リポジトリ

protect-mcp-setup について

protect-mcp の設定スキルです。Claude Code のツール呼び出しに Cedar ポリシーを適用し、オフライン検証可能な Ed25519 署名付きレシートを作成します。規制対象の環境を含め、ポリシー適用と検証可能な記録を必要とするチーム向けです。

主な機能

  1. 01Cedar ポリシーによる呼び出し評価
  2. 02ツール実行後のレシート署名
  3. 03レシートのオフライン検証
  4. 04フックとレシートのパス設定
  5. 05レシート監査コマンドの提供

活用シーン

  1. 01エージェントツール実行前のポリシー適用
  2. 02コンプライアンス用の検証可能な記録作成
  3. 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 はこの 3 つのギャップをすべて埋めます:

  • Cedar ポリシー(AWS のオープンな認可エンジン)が、実行前にすべてのツール呼び出しを 評価します。Cedar の deny は絶対です。
  • Ed25519 レシートは、実行された各ツールの名前を、あなたの鍵で署名して 記録します。
  • オフライン検証は npx @veritasacta/verify で行えます。サーバーもアカウントも、 運用者への信頼も不要です。

問題

AI エージェントは、お金、安全、権利に影響を与える決定を下します。Claude Code の セッションログは何が起きたかを記録しますが、そのログは:

  • 変更可能 — アクセスできる誰もが編集できます
  • 署名なし — 完全性を証明する方法がありません
  • 運用者依存 — 検証にはログを保持する誰かを信頼する必要があります

コンプライアンスが求められる文脈(金融、医療、規制対象の研究)では、これでは不十分です。 あなたを信頼することなく第三者によって検証できる、改ざん検知可能な証拠が必要です。

解決策

Claude Code プロジェクトに protect-mcp を追加します:

# 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/

フック設定

プラグインをインストールすると、hooks/hooks.json の両方のフックが追加されます。各フックは プラグインに同梱されたスクリプトを実行します:

{
  "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 としてコマンドに渡し、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 フックは stderr に警告を出力し、 呼び出しを許可します。

各フックの動作

PreToolUse — ツールが実行される前に実行されます。ツール呼び出しを Cedar ポリシーファイルに対して評価します。Cedar が deny を返した場合、フックは終了コード 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 は独自のファイルに 1 つのレシートを受け取ります。たとえば、 tail -n 1 ./receipts/receipts.jsonl > receipt.json から取得します。

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

レシート形式

各レシートは ./receipts/receipts.jsonl の 1 行です。サンプルについては references/receipt-format.md を参照してください。

  • signature 以外のすべてのフィールドに対する Ed25519 署名(RFC 8032)
  • 署名前の JCS 正規化(RFC 8785)
  • レシートに公開鍵を含まないため、--key で渡す
  • 前のレシートへのリンクがないため、削除された行は検知されない

これが重要な理由

導入前導入後
「信じてください、エージェントはファイルを読んだだけです」暗号学的に証明可能: すべての Read が記録され署名される
「ログにそう起きたと表示されている」レシートがそれが起きたことを証明し、誰も編集できない
「私たちのシステムを監査する必要があるでしょう」誰でもすべてのレシートをオフラインで検証できる
「ログは今では違っているかもしれません」Ed25519 署名が署名時点で記録を固定する

標準

  • Ed25519 — RFC 8032(デジタル署名)
  • JCS — RFC 8785(決定論的 JSON 正規化)
  • Cedar — AWS のオープンな認可ポリシー言語
  • IETF ドラフト — draft-farley-acta-signed-receipts

関連

コメント