コンテンツへスキップ

MCP

セルフホスト環境における Claude Code と MCP サーバーの監査

著者 Olivares AI 1 分で読めます

あるプラットフォームチームが、十数名のエンジニアに Claude Code を展開します。実用的にするために、いくつかの MCP サーバーへ接続します。モノレポを読み取るもの、レポーティング用レプリカへ問い合わせるもの、チケットを起票するものです。1 週間も経たないうちに、エージェントはソースコードを読み、データベースに触れ、社内ツールを呼び出すようになります。そして、監査人がいずれ必ず投げかける問いに、誰も答えられません。どのエージェントが、どのリソースに対して、を行ったのか。そしてそれが後から改ざんされていないことを証明できるのか、という問いです。

これは仮想的なギャップではありません。独立した業界調査(CSA/Token、n=418)によれば、約 82% の組織が把握していない AI エージェントを稼働させており、それらをリアルタイムでインベントリ管理しているのはわずか約 21% に過ぎません。Claude Code と MCP は、まさに導入が速く、監査体制が追いつかなくなりがちな種類の機能です。良い知らせとしては、防御可能な証跡は、ペイロードやシークレットを一切ペリメーターの外に出すことなく、自社のペリメーター内で完結して実現できます。

なぜ典型的な構成は監査に耐えられないのか

最初の展開でよく見られるのは、単一の認証情報を共有するやり方です。すべての Claude Code インスタンスが、同じサービスアカウント(mcp-runnerci-bot といった汎用的なもの)として MCP レイヤーや下流のデータベースに認証します。これは動作はしますが、帰属を静かに破壊します。

10 個のエージェントが単一のプリンシパルとして動作すると、データベースの監査ログには mcp-runner からの 10 件の書き込みが記録されるだけで、それ以上の情報はありません。どのエンジニアのセッションが UPDATE を発行したのか、それが対話的な Claude Code のプロンプトから来たのか無人ジョブから来たのか、どの MCP ツールがその経路にあったのかを判別できません。独立した調査(Optro)は、エージェントの操作を人物まで遡れる組織の割合をおよそ 28% としています。共有サービスアカウントは、帰属が崩壊する構造的な理由の一つです。監査ログは何が起きたかは示せても、どのエージェントが行ったのかは決して示せません。

2 つ目の失敗は完全性です。アクションごとにログを記録しているチームでさえ、通常は変更可能なストアに書き込んでいます。攻撃者(あるいはバグのあるエージェント)が到達できるのと同じシステムにログが置かれている場合、「ログがある」ことは「証拠がある」ことと同義ではありません。監査人はこの両者を明確に区別します。

エージェントごとの ID が土台となる

下流のすべては帰属に依存するため、まず ID を正しく整えます。単一の共有トークンではなく、エージェントごと、できればセッションごとに、固有で短命な ID を発行します。その ID はリクエストとともに MCP サーバーへ、そしてエージェントが到達するあらゆるリソースへと伝播するため、データベースに記録されるプリンシパルは汎用的なランナーではなく、エージェントそのものになります。

これこそが最小権限を意味あるものにします。レポーティングエージェントはレポーティング用レプリカに対して読み取り専用に固定でき、リリースエージェントは自身が所有するアーティファクトに対してのみ書き込みを得ます。こうすれば、その範囲を逸脱した書き込みが 1 件観測されただけでも、共有アカウントの中のノイズではなく、正確で帰属可能なシグナルになります。ポリシーとして表現すると、その意図は単刀直入です。

agent "reporting-assistant" {
  # レポーティング MCP サーバー経由の Claude Code セッション
  resource "prod-postgres/reporting_replica" {
    access     = "read"      # SELECT のみ
    deny       = ["write", "ddl"]
  }
  resource "s3://billing-exports" {
    access = "read"
  }
  on_violation {
    action = "block_and_alert"   # アクセス時に拒否、単なるログではなく
  }
}

重要なのは構文ではありません。ポリシーがエージェントを名指しし、リソースを名指しし、読み取りと読み取り/書き込みを分離している点です。この分離こそが本質のすべてです。

MCP アノテーションは信頼できないシグナルとして扱う

MCP ツールは、readOnlyHintdestructiveHint といったアノテーションで自身を記述できます。これらはトリアージに本当に役立ちます。自らを破壊的だと宣言するツールは、より厳格なポリシーに値します。しかし MCP 仕様は、これらがヒントであり、クライアントはセキュリティ上の判断をこれらに依存してはならないと明示しています。これらはサーバー側から発せられるものであり、まさにその当のサーバーこそ、あなたが監査している対象です。ツールは readOnlyHint: true を宣言しながら、バグ、設定ミス、あるいは意図的な回避によって、依然として書き込みを発行しうるのです。

したがって正しい姿勢は、信頼ではなく裏付けです。アノテーションを一つの主張として受け取り、ツールが制御できないレイヤーから得たグラウンドトゥルースと照合します。

  • データベースの監査ログ(例:PostgreSQL の pgAudit)は、SELECTUPDATE が実際に実行されたかどうかを教えてくれます。
  • MCP サーバーや下流サービスからの OpenTelemetry のスパンは、コールグラフと実行された操作を示します。
  • eBPF のカーネルシグナルは回避対策の最後の砦です。ファイルやソケットへの書き込みシステムコールは、ツールがユーザー空間で何を主張していようと、カーネルレベルで観測可能です。

アノテーションが読み取り専用だと言っているのに、カーネルが書き込みを観測した場合、その矛盾こそが見出しとなる発見です。readOnlyHint のツールが prod-postgres に書き込んだという事象は、まさに誰かを叩き起こす価値のある最小権限のドリフトです。ポリシーが許可したものと、コレクターが観測したものとの差分にこそ、本当のリスクが潜んでいます。

監査人が受け入れる台帳

証跡が証拠たりうるのは、それが改ざん検知可能である場合のみです。各イベントを追記専用のハッシュチェーン化された台帳に書き込みます。すべてのレコードが直前のレコードのハッシュを含むため、下流での編集や削除はチェーンを破壊し、検知可能になります。各行は、操作を特定のエージェントに帰属させ、リソースを名指しし、読み取りか読み取り/書き込みかを記録し、信頼度を付与します。ID と結果の両方が裏付けられている場合は attributed、何かを推定せざるを得なかった場合は approximate です。信頼度は正直に表示されます。approximate な一致が、証明済みであるかのように装われることは決してありません。

ts=2026-06-08T09:14:02Z agent=reporting-assistant@s3f1 tool=sql-read     resource=prod-postgres/reporting_replica  op=R   outcome=allow   conf=attributed   prev=8a1c…
ts=2026-06-08T09:14:05Z agent=reporting-assistant@s3f1 tool=export-writer resource=s3://billing-exports          op=R   outcome=allow   conf=attributed   prev=2f90…
ts=2026-06-08T09:17:48Z agent=data-export-job@b22e     tool=sql-write     resource=prod-postgres/customers          op=RW  outcome=DENY    conf=attributed   prev=c7d3…  policy=read_only_violation

監査人が気にするのは、その 3 行目です。エージェントが書き込み権限を持たないテーブルへの書き込み試行が、アクセス時点で拒否され、名指しされたエージェントに帰属し、チェーンに固定されています。アクセスが発生した時点でポリシーが強制される(単に事後にログ記録されるのではない)ため、この拒否は事後検証ではなく、コントロール(統制)そのものです。

さらに 2 つの性質が、この証跡の信頼性を支えます。特権的なビュー自体も監査されます。アクセスマップを閲覧したことが記録されるため、「誰が何を見たか」に答えられます。そして証拠のエクスポートは改ざん検知可能です。監査人に手渡すのは、信用に頼るしかない CSV ではなく、独立して検証できる署名済みのチェーンの一部です。

性質共有サービスアカウントエージェントごとの ID + ハッシュチェーン化された台帳
帰属すべてのエージェントが単一のプリンシパル操作が特定のエージェント/セッションに紐づく
読み取り対書き込み混同される区別され、ポリシーで検査される
完全性変更可能なログ追記専用、編集でチェーンが破壊される
監査対応のエクスポート信用に頼る CSV署名済みで独立検証可能な一部

ここでセルフホストが重要になる理由

これらすべては、ネットワークの外に何も出すことなく機能します。コレクターはエージェントのデータ経路の中に居座るのではなく、観測します。ログ、OpenTelemetry、そしてカーネルレベルの最後の砦としての eBPF を通じてです。そのため、コレクターが障害を起こしても、エージェントやその背後にある本番リクエストを決して壊しません。台帳が保存するのはアクセスの関係であって、ペイロードではありません。reporting-assistantreporting_replica を読み取ったことは記録しますが、返された行は記録しません。シークレットや PII を含みうる入力は、何かが書き込まれる前にレダクションされ、シークレットスキャンが行われます。エアギャップ環境、GDPR の制約下、あるいはデータレジデンシーに制約のある資産にとって、これは防御できる監査体制とできない監査体制を分ける違いです。あなたの Claude Code と MCP の利用について、何も外部に通報されません。システムがそもそもデータを一切見ないからです。

Claude Code と MCP は展開する価値があります。ただし、他のあらゆる特権的な自動化と同じやり方で構築された監査証跡が必要なだけです。すなわち、ID を最優先し、結果を裏付け、証拠を固定するというやり方です。アクセスマップと改ざん検知可能な台帳がどのように組み合わさるかをご覧になりたい場合は、セキュリティモデル製品概要でそれぞれをより深く解説しています。

よくある質問

MCP ツールの readOnlyHint を、ある操作が読み取り専用であったことの証明として信頼できますか?

いいえ。MCP 仕様は、readOnlyHint や destructiveHint といったツールアノテーションはあくまでヒントであり、信頼できないものとして扱わなければならないと明記しています。これらはサーバー側から提供されるものであって、強制レイヤーから提供されるものではないためです。トリアージや矛盾の検出には活用できますが、実際の読み取り/書き込みの結果は、テレメトリやカーネルレベルのシグナル(OpenTelemetry のスパン、データベースの監査ログ、eBPF)で証明してください。信頼すべきはアノテーションではなく、裏付けの取れた結果です。

Claude Code の操作を、共有サービスアカウントではなく特定のエージェントに帰属させるにはどうすればよいですか?

単一の共有トークンではなく、エージェントごと、あるいはセッションごとに、固有で短命な ID を発行してください。エージェントがデータベースや MCP サーバーに到達する際、その ID がリクエストとともに伝播するため、どのエージェントが何を行ったかを監査台帳に記録できます。共有サービスアカウントはすべてのエージェントを単一のプリンシパルに集約してしまい、エージェントごとの最小権限と改ざん検知可能な帰属を事後的に不可能にします。

エージェントが到達できる範囲を可視化

Olivares AIは、お客様のAI環境のためのオープンなセルフホスト型プラットフォームです。ご自身のインフラ上に展開すれば、セキュリティチームやプラットフォームチームがこれまで求めてきたアクセスマップが手に入ります。