# Claude Code で第三者の MCP サーバーを安全に使う — 信頼の判断、許可リスト、managed-mcp.json

> Claude Code に第三者の MCP サーバーをつなぐ前に。ローカルのサーバーはサンドボックスの外で動き、Anthropic は MCP サーバーを監査しない。.mcp.json の承認、許可・拒否リストの正しい書き方、managed-mcp.json、審査チェックリストを公式ドキュメントで整理します。

- 公開日: 2026-10-12
- 著者: 友田 陽大
- タグ: Claude Code, AI駆動開発, セキュリティ, AI
- URL: https://tomodahinata.com/blog/claude-code-mcp-server-security-third-party-trust-guide
- カテゴリ: AI駆動開発・開発生産性
- 総合ガイド: https://tomodahinata.com/blog/spec-driven-development-claude-code-ai-agent-production-workflow

## 要点

- MCP サーバーは Claude にツールを渡す外部のプログラムやサービス。ローカルで起動するサーバーは利用者のフル権限でサンドボックスの外で動き、外部の内容を取り込むサーバーはプロンプトインジェクションの入口になる
- Anthropic はディレクトリ掲載前に基準に沿った審査はするが、MCP サーバーのセキュリティ監査はしていないと公式に明記している。採否は利用する組織が判断する
- プロジェクトの .mcp.json は対話セッションでは承認を求めるが、claude -p・Agent SDK・クラウドのセッションでは確認なしで読み込まれる
- allowedMcpServers / deniedMcpServers はどの設定ファイルにも書けるため、managed settings で allowManagedMcpServersOnly を立てて初めて組織の許可リストになる。serverName は利用者が付ける名前なので統制にならず、serverUrl と serverCommand で書く
- 審査では、出どころと保守者、必要なトークンの範囲、通信先、外に出るデータ、版の固定を確認し、許可は最小限のスコープから始める

---

結論から書きます。**MCP サーバーをつなぐことは、Claude Code に新しい手足を渡すことです。Claude がそのツールを呼ぶ操作は権限ルール（allow・ask・deny）を通りますが、ローカルで起動するサーバーのプロセス自体はサンドボックスの外で利用者のフル権限で動き、プロセスの中で何をするかは権限ルールからは見えません。** だから組織で決めるべきなのは「便利なサーバーを探すこと」ではなく、**どのサーバーを、どの範囲の権限で、誰が承認して使うか**です。

公式の Security ページは、Anthropic はディレクトリに載せる前に掲載基準で審査するが、**MCP サーバーのセキュリティ監査や管理はしていない**と明記しています。採否の判断は、利用する側の仕事です。

この記事は、組織で Claude Code を使う前提の [セキュリティ・ガバナンス設計（権限・managed settings・サンドボックス）](/blog/claude-code-enterprise-security-governance-managed-settings-guide) のうち、MCP の部分を掘り下げたものです。設定キーと挙動は、2026年10月12日に取得した公式ドキュメントで確認しました。バージョンで変わる箇所があるので、導入時点の版で確かめてください。

---

## 1. MCP サーバーに何ができるか

**ローカルの MCP サーバーは、Claude Code が起動する別のプロセスで、利用者のフル権限で動きます。** サンドボックスのドキュメントは、command hooks や LSP サーバーと並べて「ローカルの MCP サーバーはフル権限で動く」と書いています。サンドボックスが囲うのは Claude が実行するシェルコマンドであり、MCP サーバーのプロセスではありません。

組織として想定すべきリスクは4つです。

| リスク | どういうことか |
|---|---|
| ローカルでの実行 | stdio のサーバーは端末上のプログラムなので、そのコードが読めるファイル、環境変数、通信先はすべて届く範囲になる |
| データの送り先 | リモートのサーバーには、ツールの呼び出しで渡す引数（コード、Issue の本文、顧客名など）が送られる |
| プロンプトインジェクション | 外部の内容を取り込むサーバーの応答は Claude の文脈に入る。公式も、外部の内容を取ってくるサーバーはプロンプトインジェクションのリスクにさらしうると警告している |
| 見えない追加 | `.mcp.json` 以外のスコープ、claude.ai のコネクタ、プラグインもサーバーを足せる。公式も「`.mcp.json` を見るだけでは、セッションが読み込むサーバーの全体は分からない」としている |

## 2. スコープ：local・project・user と優先順位

**MCP サーバーの設定は3つのスコープに置けて、同じサーバーが複数にあると、最上位のものだけが丸ごと使われます。**

| スコープ | 読み込まれる範囲 | チームと共有 | 保存場所 |
|---|---|---|---|
| local（既定） | 今のプロジェクトだけ | しない | `~/.claude.json` |
| project | 今のプロジェクトだけ | する（バージョン管理） | プロジェクトのルートの `.mcp.json` |
| user | すべてのプロジェクト | しない | `~/.claude.json` |

優先順位は local → project → user → プラグインのサーバー → claude.ai のコネクタです。フィールド単位で結合されることはありません。3つのスコープの重複は名前で、プラグインとコネクタは接続先で判定されます。組織が managed settings の `managedMcpServers` で配るサーバーは、これらすべてより上位です。

紛らわしい点が1つあります。MCP の「local スコープ」はホームディレクトリの `~/.claude.json` に保存され、一般の設定でいう `.claude/settings.local.json` とは別物です。

## 3. プロジェクトの .mcp.json と承認：-p と SDK の例外

**対話セッションでは、プロジェクトの `.mcp.json` にあるサーバーを使う前に承認を求められます。しかし `claude -p`、Agent SDK、クラウドのセッションではそのプロンプトを出せないため、確認なしで読み込まれます。**

対話セッションの側には、クローンしたリポジトリが自分で承認を済ませる抜け道を塞ぐ仕組みがあります。リポジトリの `.claude/settings.json` にコミットされた `enableAllProjectMcpServers` や `enabledMcpjsonServers` は、信頼していないフォルダでは無視され、サーバーは承認待ちのままです。

問題は非対話の実行です。権限のドキュメントの表では、`claude -p` や SDK で一度も信頼していないフォルダの `.mcp.json` のサーバーは「承認の有無にかかわらず、確認なしで接続される」とされています。CI で他人のリポジトリや外部からの PR に対して Claude を動かすなら、次のいずれかで閉じます。

- `disabledMcpjsonServers` に名前で載せる。すべての許可モードで止まります。
- `--setting-sources` や SDK の `settingSources` で、プロジェクトの設定を読ませない。
- `--strict-mcp-config` で起動し、`--mcp-config` で渡したサーバーだけを使う。
- `--bare` で起動し、プロジェクトの `.mcp.json` を含む自動検出を止める。

なお、`skipDangerousModePermissionPrompt` をユーザー設定か managed settings に入れて `bypassPermissions` で始めたセッションでも、この承認は省かれます。

## 4. 組織の統制パターンを選ぶ

**公式ドキュメントは統制の強さに応じたパターンを示しています。** まず、どれにするかを決めます。

| パターン | 何が起こるか | 設定 |
|---|---|---|
| MCP を無効化 | 例外を除いてどのサーバーも読み込まれない | 空のマップの `managed-mcp.json` |
| 固定配布 | 全員が同じサーバーを使い、他は足せない | `managed-mcp.json` |
| 組織が提供 | 指定したリモートのサーバーを全員に配り、各自のサーバーも残る | managed settings の `managedMcpServers` |
| 承認済みカタログ | 承認したサーバーの中から各自が選んで追加し、それ以外は止まる | `allowedMcpServers` + `allowManagedMcpServersOnly: true` |
| 緩い許可リスト | 許可リストはあるが、利用者が自分の設定で広げられる | `allowManagedMcpServersOnly` なしの `allowedMcpServers` |
| 拒否リストのみ | 既知の危険なものだけ止める | `deniedMcpServers` |

多くの組織にとって現実的なのは「承認済みカタログ」です。Claude Code には利用者が閲覧してインストールできる組み込みの MCP レジストリはないので、承認したサーバーと `claude mcp add` のコマンドを社内 wiki などで共有するか、管理されたプラグインのマーケットプレイスで配ります。

## 5. allowedMcpServers / deniedMcpServers の正しい書き方

**許可・拒否リストの各エントリは、`serverUrl`・`serverCommand`・`serverName` のどれか1つだけを持つオブジェクトです。統制に使えるのは `serverUrl` と `serverCommand` で、`serverName` は使えません。**

- **`serverUrl`**：リモート（HTTP・SSE）のサーバーの URL。`*` のワイルドカードが使えます。ホスト名を完全に書いたパターンは既定のポート（https なら 443）だけに一致し、ホスト名に `*` を含むパターンはすべてのポートに一致します。
- **`serverCommand`**：stdio のサーバーを起動するコマンドと引数の配列。引数の順番まで完全一致です。`["npx", "-y", "server"]` は `["npx", "server"]` にも、`--flag` を足したものにも一致しません。ただし `env` ブロックは比較されません。
- **`serverName`**：利用者が付けるラベル。公式は「どちらのリストでもセキュリティの統制ではない」としています。誰でも任意のサーバーに `github` と名前を付けられるからです。

評価の順番は、リストの結合 → 拒否リストの確認 → 許可リストの確認です。拒否リストに一致したサーバーは、何があっても止まります。許可リストに `serverUrl` のエントリが1つでもあれば、リモートのサーバーは URL で一致しなければならず、名前だけで通ることはなくなります（stdio と `serverCommand` も同様です）。

未設定と空の配列の違いも押さえます。

| 設定 | 未設定（既定） | 空の配列 `[]` | 値あり |
|---|---|---|---|
| `allowedMcpServers` | すべて許可 | 利用者が足すサーバーはすべて拒否 | 一致するものだけ許可 |
| `deniedMcpServers` | 何も止めない | 何も止めない | 一致するものを止める |

そして最も誤解されやすい点です。**`allowedMcpServers` と `deniedMcpServers` は managed 専用のキーではなく、どの設定ファイルにも書けます。** `allowManagedMcpServersOnly` を立てないと、ユーザーの `~/.claude/settings.json` を含む各スコープの許可リストが結合され、利用者が許可を広げられます。また、`allowManagedPermissionRulesOnly`（権限ルールの鍵）を立てても、MCP の許可リストは強制されません。別の鍵です。

## 6. managed-mcp.json でサーバーを固定する

**`managed-mcp.json` を置くと、その端末で使える MCP サーバーは組織が決めたものだけになります。** 利用者は他のサーバーを追加・変更・使用できず、プラグインが提供するサーバーや `--mcp-config` で渡すサーバーも止まります。`claude mcp add` は企業ポリシーのエラーで失敗します。

置き場所は managed settings と同じシステムディレクトリです。

| OS | パス |
|---|---|
| macOS | `/Library/Application Support/ClaudeCode/managed-mcp.json` |
| Linux と WSL | `/etc/claude-code/managed-mcp.json` |
| Windows | `C:\Program Files\ClaudeCode\managed-mcp.json` |

形式はプロジェクトの `.mcp.json` と同じです。注意点が3つあります。

- **サーバー管理設定では配れません。** 独立したファイルなので、MDM・グループポリシー・構成管理など、管理者権限でシステムパスに書ける仕組みで置きます。排他制御が不要で、claude.ai から配りたいなら `managedMcpServers` を使います。
- **空のマップで MCP をほぼ無効にできます。** ただし `managedMcpServers` で配ったサーバーなど、併用を許したものは読み込まれます。
- **`${VAR}` を使うエントリは許可リストの確認を受けます。** 変数展開を使わない組織のサーバーは確認を省かれますが、展開を使うと許可リストと照合されます。

ブロックされたサーバーは、利用者には理由が示されないまま `/mcp` と `claude mcp list` から消えます。新しい制限を入れるときは、どのサーバーが止まるかを事前に知らせてください。

## 7. 権限ルールで MCP のツールを絞る

**サーバーを許可したあとも、ツール単位で ask や deny をかけられます。** 権限ルールでは、MCP のツールを次の名前で指定します。

- `mcp__puppeteer`：`puppeteer` というサーバーのすべてのツール
- `mcp__puppeteer__*`：同じく、ワイルドカードでのすべてのツール
- `mcp__puppeteer__puppeteer_navigate`：そのサーバーの特定のツール

deny と ask では `"mcp__*"` ですべてのサーバーのすべてのツールを指定できます。一方、allow のワイルドカードは `mcp__<server>__` という具体的な接頭辞のあとでしか使えず、`"mcp__*"` を allow に書いても警告とともに無視されます。サーバー全体を一括で自動承認させない設計です。

運用の目安としては、読み取り系のツールは allow、書き込みや外部への送信をするツールは ask、使わせないツールは deny にします。また、リモートのサーバーで OAuth を使う場合は、`oauth.scopes` で要求するスコープを固定できます。公式は、認可サーバーが広いスコープを提示するときに、セキュリティチームが承認した範囲に絞る方法として案内しています。

## 8. 第三者の MCP サーバーの審査チェックリスト

**採否は「便利かどうか」ではなく、「そのサーバーに渡すものと、そのサーバーが届く範囲」で判断します。** 次の項目を、導入申請のテンプレートにすると運用しやすくなります。

| 観点 | 確認すること |
|---|---|
| 出どころ | ソースコードが公開されているか。誰が保守し、最近まで更新されているか。自社で書けるならそれが一番確実 |
| 動く場所 | ローカル（stdio）か、リモート（HTTP）か。ローカルならフル権限で動く前提で、そのコードを読めるか |
| 必要な権限 | どのトークンや API キーを要求するか。読み取りだけで足りるのに書き込み権限を求めていないか |
| トークンの範囲 | 専用のアカウントや最小権限のトークンを発行できるか。OAuth なら `oauth.scopes` で絞れるか |
| 通信先 | サーバーがどこへ通信するか。外部の Web やメールなど、信頼できない内容を取り込むか（インジェクションの入口） |
| 外に出るデータ | ツールの引数として、コード・顧客情報・社内文書が送られるか。リモートの提供元の保持方針は社内規程に合うか |
| 版の固定 | `npx` などで最新版を毎回取ってくる構成になっていないか。版を固定し、更新は審査を通してから |
| 統制の書き方 | 許可リストに `serverUrl` か `serverCommand` で書けるか。必要なツールだけを allow にできるか |

ローカルのサーバーに環境変数の秘密が渡るのが心配なら、`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1` で、stdio の MCP サーバーを含む子プロセスの環境から認証情報を取り除けます（GitHub トークンとプロキシ設定は残ります）。

## 9. 許可リストの設定例

**次の例は、公式ドキュメントで確認したキーだけで組んだ「承認済みカタログ」の出発点です。** URL とパッケージ名は例なので、自社で審査したものに置き換えてください。

```json
{
  "allowManagedMcpServersOnly": true,
  "allowedMcpServers": [
    { "serverUrl": "https://api.githubcopilot.com/*" },
    { "serverUrl": "https://mcp.example.internal/*" },
    { "serverCommand": ["npx", "-y", "@example-org/docs-mcp-server@1.4.2"] }
  ],
  "deniedMcpServers": [
    { "serverUrl": "https://*.untrusted.example.com/*" }
  ],
  "permissions": {
    "ask": [
      "mcp__github"
    ]
  }
}
```

この例の意図を補足します。

- `allowManagedMcpServersOnly` があるので、ユーザーやプロジェクトの設定で許可リストを広げても無視されます。拒否リストは各スコープから結合されるので、利用者が自分でさらに止めることはできます。
- `serverCommand` には版を含めた引数を完全な形で書いています。引数が1つでも違えば一致しないので、利用者が別の版や別の引数で起動したサーバーは止まります。
- 拒否リストの `https://*.untrusted.example.com/*` は、ホスト名に `*` を含むのでそのサブドメインのすべてのポートに一致します。ホスト名を完全に書いてポートを書かないパターンは既定のポートにしか一致しないので、特定のホストを止めるときはポートの書き方に注意します。
- `mcp__github` を ask にしているのは、利用者が `github` と名付けたサーバーのツールを毎回確認させるためです。名前は利用者が付けるので、どのサーバーを動かすかの統制は上の許可リストが担い、ask は確認の手間を足す補助です。
- managed settings として配るので、ファイル・MDM・サーバー管理設定のどれでも配れます（`managed-mcp.json` と違い、サーバー管理設定でも配れます）。

## 10. 導入後に見ること

**MCP の統制は、配って終わりではありません。** OpenTelemetry を設定しているなら、`OTEL_LOG_TOOL_DETAILS=1` でツールのイベントに MCP のサーバー名とツール名が入り、利用者が実際にどのサーバーにつないでいるかを集計できます（この変数は既定では無効です）。許可リストに載せたのに使われていないサーバーは外し、申請が多いサーバーは審査にかけます。

---

## まとめ：MCP は「信頼の判断」を設定に落とす仕事

MCP サーバーは、Claude Code の能力を大きく広げる一方で、ローカルのサーバーのプロセスはサンドボックスの外で利用者のフル権限で動き、外部の内容を Claude の文脈に持ち込みます。権限ルールが統制するのは Claude によるツールの呼び出し（第7節）であって、サーバーのプロセスの振る舞いではありません。Anthropic はサーバーを監査していないので、**審査し、許可リストを `serverUrl` と `serverCommand` で書き、`allowManagedMcpServersOnly` で組織のリストだけを有効にし、CI では `.mcp.json` を読ませない**。この4点が組織の基本線です。

権限モードやサンドボックスなど、MCP 以外の統制は [Claude Code を組織に導入するときのセキュリティ・ガバナンス設計](/blog/claude-code-enterprise-security-governance-managed-settings-guide) にまとめています。自社の MCP の審査基準や許可リストの設計を外部に相談したい場合は、[Claude Code 組織導入のセキュリティ・ガバナンス設計](/security-audit/claude-code) で受け付けています。
