CLAUDE_CODE_MCP_ALLOWLIST_ENVとは — stdio MCPサーバーへの環境変数漏えいを防ぐ
stdio MCPサーバーが起動時にシェルの環境変数をまるごと継承する既定動作を止め、安全なベースラインとサーバー設定のenvだけに絞る設定を解説します。
CLAUDE_CODE_MCP_ALLOWLIST_ENVとは
CLAUDE_CODE_MCP_ALLOWLIST_ENV は、stdio(標準入出力)方式のMCPサーバーに渡す環境変数を絞り込む環境変数です。1 に設定すると、Claude Codeはシェルの環境変数をまるごと引き継ぐ既定の起動方式をやめ、安全なベースラインの環境と、そのサーバー用に .mcp.json の env で明示した変数だけを渡すようになります。
既定では逆で、stdio MCPサーバーはClaude Codeを起動したシェルの環境変数にそのままアクセスできます。手動で追加したサーバーだけでなく、プラグイン同梱のMCPサーバーも、手動で追加したサーバーと同じ範囲の環境変数にアクセスできます。由来を問わず継承の範囲は同一です。
値の指定方法は他の真偽値系のClaude Code環境変数と共通です。オンにするときは 1 または true、オフに戻すときは 0 または false を使い、大文字・小文字は区別されません。設定を書いたのに変わらないときは、シェルと設定ファイルの優先順位を確認してください。同じ変数がシェルと設定ファイルのenvブロック両方に設定されている場合、設定ファイル側の値が優先されます。~/.claude/settings.jsonに値を書いたつもりでもシェル側のexportが残っていると、そちらではなく設定ファイルの値で上書きされるため、「シェルで変更したのに反映されない」という混乱が起きやすい箇所です。
なぜ絞り込みが必要か
stdio MCPサーバーはローカルプロセスとして起動します(通信方式の詳細はMCP stdioトランスポートの仕様を参照してください)。シェルの環境変数を丸ごと渡す既定動作では、ANTHROPIC_API_KEY のような認証情報、クラウドの資格情報、社内システムのトークンなど、そのシェルに存在するあらゆる変数がサーバープロセスから読み取り可能になります。
npx -y <package> のように外部レジストリから取得して実行するサーバーや、サードパーティ製のMCPサーバーを追加する場面では、次の2点が問題になります。
- サーバーの実装者を完全には信頼していない
- そのサーバーが本来必要とする変数は数個だけなのに、シェル全体を見せてしまう
この構図はプロンプトインジェクション経由の情報持ち出しにも関係します。悪意のある入力でサーバー内部の処理を誘導されたとき、渡っている環境変数が多いほど持ち出せる情報も増えます。CLAUDE_CODE_MCP_ALLOWLIST_ENV は、渡す変数そのものを最小化してこのリスクの範囲を狭める設定です。
具体的には、開発マシンのシェルには複数のプロジェクト・複数のサービス分の認証情報が同居しがちです。あるプロジェクト用に追加したサーバー1本の脆弱性やサプライチェーン侵害が、そのシェルに存在する無関係な別サービスの資格情報まで晒す経路になり得ます。ベースライン+個別env方式なら、サーバーAの侵害がサーバーBやシェル全体の秘密情報にまで波及する経路自体を塞げます。
有効化する方法
シェルで一時的に有効にする場合はこうなります。
export CLAUDE_CODE_MCP_ALLOWLIST_ENV=1
claudeチーム全体や組織全体に適用したい場合は、設定ファイルの env キーに書きます。~/.claude/settings.json なら自分だけ、プロジェクトの .claude/settings.json ならそのプロジェクトで作業する全員に、管理者が配布するmanaged settingsなら組織全体に適用されます。組織全体でMCPサーバーの利用そのものを制御したい場合は、Managed MCPの許可リスト・拒否リストをCLAUDE_CODE_MCP_ALLOWLIST_ENVと併用する構成になります。
{
"env": {
"CLAUDE_CODE_MCP_ALLOWLIST_ENV": "1"
}
}CLAUDE_CODE_MCP_ALLOWLIST_ENV はproject / local settingsが書き込めない変数の一覧(CLAUDE_CONFIG_DIR やOpenTelemetry関連の一部など)には含まれていません。つまりproject settingsやlocal settingsのenvキーでも設定でき、managed settingsに限らずチーム単位・プロジェクト単位での適用も選べます。
有効化後、サーバーは何を受け取るか
有効化すると、stdio MCPサーバーが受け取る環境変数は次の2種類に絞られます。
- Claude Codeが用意する安全なベースライン環境
- そのサーバーの
.mcp.jsonエントリでenvに明示した変数
2番目は通常のMCPサーバー設定と同じ書き方です。
{
"mcpServers": {
"local-weather": {
"command": "/path/to/weather-cli",
"args": ["--api-key", "abc123"],
"env": {
"CACHE_DIR": "/tmp"
}
}
}
}この例なら、CLAUDE_CODE_MCP_ALLOWLIST_ENV=1 の状態でも CACHE_DIR はサーバーに渡ります。書いていない変数(シェルにある他のAPIキーなど)は渡りません。サーバーが追加の変数を必要とするなら、env に書き足すのが正しい対応で、変数を丸ごと見せる方向に戻す必要はありません。
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB との違い
似た目的の変数に CLAUDE_CODE_SUBPROCESS_ENV_SCRUB があります。この変数自体の仕組みはCLAUDE_CODE_SUBPROCESS_ENV_SCRUBの記事で扱っており、本記事ではCLAUDE_CODE_MCP_ALLOWLIST_ENVとの役割分担(許可リスト方式・stdio専用という違い)に絞ります。両者はアプローチが逆です。
| 方式 | 対象プロセス | |
|---|---|---|
CLAUDE_CODE_MCP_ALLOWLIST_ENV | 方式ホワイトリスト方式。安全なベースライン+設定したenvだけを渡す | 対象プロセスstdio MCPサーバー |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB | 方式ブラックリスト方式。Anthropicおよびクラウドプロバイダーの資格情報、Claude Codeが資格情報と認識するその他の変数、パッケージレジストリURLに埋め込まれた資格情報を取り除く | 対象プロセスBashツール・hooks・stdio MCPサーバー |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB はBashツールやhooksコマンドの実行にも効く範囲の広い対策です。一方 CLAUDE_CODE_MCP_ALLOWLIST_ENV はstdio MCPサーバー専用で、資格情報の判定に頼らず「渡す変数を明示したものだけに限定する」という、より厳格な絞り込みです。
両方とも既定はオフです。stdio MCPサーバーを複数運用していて、サーバーごとに必要な変数を.mcp.jsonのenvで管理できているなら、CLAUDE_CODE_MCP_ALLOWLIST_ENVを有効にする方が漏えい経路を小さくできます。Bashツールやhooksからの資格情報漏えいも合わせて塞ぎたい場合は、CLAUDE_CODE_SUBPROCESS_ENV_SCRUBを併用する構成になります。
有効化前に確認すること
有効化すると、これまでシェルの環境変数に頼っていたstdio MCPサーバーが動かなくなることがあります。次の手順で影響範囲を洗い出してから切り替えるのが安全です。
- 使用中のstdio MCPサーバーを
claude mcp listで洗い出す - 各サーバーのドキュメントを確認し、APIキー・接続先URL・キャッシュディレクトリなど、起動時に実際に読んでいる環境変数を特定する。ソースコードが公開されているサーバーなら、
process.env(Node)やos.environ(Python)で参照している変数名を検索するのが確実です .mcp.jsonの該当サーバーのエントリにenvフィールドを追加し、2で特定した変数を書き足す。値を直書きせず${API_KEY}のように展開参照にしておけば、シェル側の値を書き換えるだけで済みますCLAUDE_CODE_MCP_ALLOWLIST_ENV=1を一時的にシェルへ設定し、claudeを再起動して各サーバーが/mcp上で正常に接続し、ツール呼び出しが従来どおり動くことを確認する- 動作に問題がなければ、シェルでの一時設定をやめ、managed settingsやプロジェクトの
.claude/settings.jsonのenvキーに恒久設定として書く。個人利用なら~/.claude/settings.jsonでも構いません
途中で接続エラーが出たサーバーは、ステップ2に戻って見落とした変数がないかを確認します。渡す変数を都度追加していく運用は手間に見えますが、そのサーバーが実際に何を必要としているかを可視化する副次効果もあり、設定ファイルを見るだけで依存関係が分かるようになります。
許可リストを有効にした直後によく起きるのは、/mcp でサーバーの状態が接続失敗のまま止まる、あるいはツール一覧がいつまでも増えてこない症状です。多くの場合はサーバー起動時に必要な変数(APIキーや接続先URLなど)が.mcp.jsonのenvに書かれておらず、サーバー側が起動や認証に失敗しています。切り分けの手順は単純で、まず対象サーバーだけCLAUDE_CODE_MCP_ALLOWLIST_ENVを外した状態(既定のシェル環境継承)に戻して同じ操作を試します。それで直るなら原因は渡しているenvの不足、それでも直らないならサーバー自体や接続先の問題と判断できます。
${VAR} 展開を使っている場合も注意が必要です。展開元の変数が未設定でデフォルトも無いときは、Claude Codeはclaude mcp listで警告を出したうえで ${VAR} の文字列をそのまま使います。許可リストを有効にした状態でサーバーが接続できないときは、渡しているenvの値が${VAR}のまま展開されずに残っていないかを最初に疑ってください。
使い分けの目安
| 状況 | 有効化の判断 | 理由 |
|---|---|---|
| npm/PyPIから取得したstdio MCPサーバーを使う | 有効化の判断効果が大きい | 理由実装者を完全には検証できないため、渡す変数を最小化する価値が大きい |
| 社内で自作したstdio MCPサーバーのみ | 有効化の判断任意 | 理由信頼できる実装でも、意図しない依存(暗黙にシェル変数を読む処理)が混入していないかは.mcp.jsonのenvで棚卸しできる |
| リモート(HTTP/SSE)MCPサーバーのみで運用 | 有効化の判断効果なし | 理由本設定はstdio専用で、リモート接続には影響しない |
| プラグイン同梱のMCPサーバーを複数有効化している | 有効化の判断有効化の効果が大きい | 理由プラグインのMCPサーバーも手動設定サーバーと同じ範囲でシェル環境にアクセスできるため |
社内の秘密情報とstdio MCPサーバーが同じ開発マシン・同じシェルセッションに同居している構成ほど、有効化の効果が大きくなります。逆に、そのマシンに機密性の高い環境変数がそもそも存在しない検証環境では、有効化してもリスクは大きく減りません。
リモートMCPサーバーには効かない
CLAUDE_CODE_MCP_ALLOWLIST_ENV が絞るのはstdio(ローカルプロセス)サーバーへの環境変数だけです。HTTP・SSE・WebSocket・claude.aiコネクタ経由のリモートMCPサーバーは別の接続方式で、ローカルプロセスとしてシェル環境を継承する仕組みそのものがありません。リモートサーバー側の認証情報の扱いは、.mcp.jsonのheadersやheadersHelper、あるいは資格情報変数の展開ルールで別途管理します。
なお、SSE(Server-Sent Events)方式のリモートトランスポートは公式docsでHTTPへの移行が推奨されています。新規にリモートMCPサーバーを構成するなら通常のHTTPトランスポートを選ぶのが無難です。いずれの方式でも、CLAUDE_CODE_MCP_ALLOWLIST_ENVが絞り込む対象はstdioサーバーだけという点は変わりません。
まとめ
CLAUDE_CODE_MCP_ALLOWLIST_ENV=1 は、stdio MCPサーバーへの環境変数の渡し方を「シェル全部」から「安全なベースライン+明示したenvだけ」に切り替える設定です。サードパーティ製や信頼度の低いstdio MCPサーバーを使っているチーム、社内の秘密情報が同じシェル環境に同居している開発環境では、有効化の効果が大きくなります。切り替え前に .mcp.json の env を各サーバーの必要変数で埋めておけば、動作を止めずに継承範囲だけを最小化できます。
新しいstdio MCPサーバーを追加するたびに、この設定が有効な状態でまず動作確認する運用にしておくと、必要な環境変数の棚卸しが後回しにならず、継承範囲が知らないうちに広がっていく事態を防げます。