Claude Codeセルフホスト環境にMCPサーバーを届ける3つの経路
セルフホスト環境の全セッションにMCPサーバーを届ける3つの経路と、claude.aiコネクタが自動では届かない理由をまとめます。
Claude Codeのセルフホスト環境は、クラウドセッションの実行場所を自社のマシンやコンテナに置き換える機能です。ただしMCPサーバーは自動では引き継がれません。Runnerが起動するセッションは、開発者のマシンにある~/.claude/の設定を丸ごと持ち込むわけではないからです。MCPサーバーを全セッションに届けるには、Runnerホスト側で明示的に用意する経路が3つあります。
Claude Codeセルフホスト環境でMCPサーバーが自動で使えない理由
セルフホスト環境のRunnerは、セッションごとに隔離された設定ディレクトリを起動時にゼロから作ります。ローカル端末でclaude mcp addを実行してMCPサーバーを追加していても、その設定はローカル端末の~/.claude.jsonにしかなく、Runnerのセッションには存在しません。アカウント状態やプロジェクト履歴も同様に引き継がれず、セッションはRunnerホスト側に用意された設定だけを見ます。
つまり、セルフホスト環境でMCPサーバーを使うには「Runnerホスト側に事前にMCPサーバーを登録しておく」か「セッションに設定ファイルを渡す」かのどちらかが要ります。公式ドキュメントが挙げる経路は3つで、優先順位や適用範囲がそれぞれ違います。
経路1: イメージビルド時にclaude mcp add --scope userで組み込む
もっとも標準的な経路は、コンテナイメージのビルド時にclaude mcp addコマンドをそのまま実行しておくことです。デスクトップ環境でMCPサーバーを追加するときと同じコマンドが、Dockerfile内でも使えます。
RUN claude mcp add --scope user sidecar -- /usr/local/bin/mcp-sidecar
RUN claude mcp add --scope user --transport http internal http://mcp-gateway.svc.cluster.local:8080Runnerがベアプロセス(コンテナを介さない直接起動)の場合は、同じコマンドをRunnerを動かすユーザーの権限でホスト上に実行し、Runnerを再起動します。Runnerはホスト設定を起動時に1回だけ読み込むため、コマンドを流し込んだだけでは反映されず、再起動が必要です。
Runnerはホストの設定を起動時に1回だけスナップショットする
Runnerは起動時に、ホストの.claude.json(~/.claude/の内部ではなく隣に置かれるファイル)からmcpServersキーだけを読み取り、各セッションの隔離された設定に書き写します。アカウント情報やプロジェクト履歴はこのスナップショットに含まれません。
反映されているかどうかは、実際にセッションを1つ立ち上げて「使えるMCPツールを一覧にして」とClaudeに尋ねるのが確実な確認方法です。Runnerは、認識できないtypeを持つエントリを見つけると起動時の警告としてログに残し、そのエントリをセッションから除外します。ツールが足りないときは、まずこの警告を疑うと早く原因にたどり着けます。
ホスト設定の読み込み先はSELF_HOSTED_RUNNER_HOST_CONFIG_DIRで変更できます。空のディレクトリを指しておくと、MCPサーバーのシーディングそのものを止めることもできます。
経路2: 管理者だけが配布できるmanaged-mcp.json
社内の許可済みサーバーだけをRunner全体に強制したい場合は、エンタープライズスコープのmanaged-mcp.jsonを使います。標準のシステムパスに置くだけで有効になり、通常のclaude mcp addより優先度が高い排他制御として働きます。
/etc/claude-code/managed-mcp.json # Linuxランナー
/Library/Application Support/ClaudeCode/managed-mcp.json # macOSランナーこのファイルがRunnerホストにあると、Claude Codeはコントロールプレーンが配信しようとするMCPサーバー(claude.aiコネクタを含む)をスキップし、セッション子プロセスのstderrにその名前を警告として出します(Runnerはdebugログレベルで記録)。v2.1.229より前は、この状況でセッションが「動的にMCPサーバーを構成できません」というエラーとともに起動時に終了していました。現在は警告に留まり、セッション自体は続行します。
managed-mcp.jsonは「配布したサーバー以外を一切読み込ませない」排他制御なので、許可リスト・拒否リストで既存サーバーを絞り込みたいだけの場合は性質が異なります。組織単位でMCPサーバーの利用を絞り込む運用はManaged MCPで許可リスト・拒否リストを組織管理するにまとめています。
経路3: チームで共有するなら.mcp.jsonをリポジトリにコミットする
プロジェクトスコープの.mcp.jsonをリポジトリのルートに置いてコミットしておく方法もあります。この経路は個々のRunnerホストの設定に依存しないため、リポジトリを扱うすべてのRunner・すべての開発者に一律で届く点が前の2つと違います。
{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}ローカル端末のインタラクティブセッションでは、.mcp.json由来のサーバーを使う前に承認ダイアログが出ます。クラウドセッション(セルフホスト環境のセッションもここに含まれます)ではこの確認を挟めないため、.mcp.jsonのサーバーは自動承認扱いで読み込まれます。承認プロンプトを出す前提の運用を想定している場合は、この違いを踏まえておく必要があります。
3つの経路をどう使い分けるか
| 経路 | 適用範囲 | 誰が管理するか | 向いている場面 |
|---|---|---|---|
イメージビルド(--scope user) | 適用範囲そのRunnerが生成する全セッション | 誰が管理するかインフラ担当がDockerfileで管理 | 向いている場面全社共通のツール(社内APIゲートウェイ等)を一律配布したい |
managed-mcp.json | 適用範囲そのRunnerホスト全体、排他制御 | 誰が管理するか管理者がホストに配置 | 向いている場面許可済みサーバー以外を一切読み込ませたいロックダウン環境 |
.mcp.json | 適用範囲リポジトリをチェックアウトする全員 | 誰が管理するか開発者がリポジトリにコミット | 向いている場面プロジェクト固有のMCPサーバーをチーム全体で共有したい |
claude.aiコネクタはセルフホスト環境に自動では届かない
組織でconnector deliveryが有効な場合、claude.ai上で設定したコネクタは、インタラクティブに作成されたセッションにはAnthropicのコントロールプレーンからapi.anthropic.com経由で自動的に届きます。ところが、CLIディスパッチのようにプログラムから作成されたセッションはこの配信の対象外です。セッション子プロセスが持つOAuthトークンにはコネクタを取得するスコープが与えられておらず、そもそも取得を試みる動作自体をしません。
プログラムから作成されるセッションにコネクタ相当のMCPサーバーを渡したい場合は、上で挙げた3つの経路(ホストのスナップショット・managed-mcp.json・.mcp.json)のいずれかを使う必要があります。「claude.aiで設定したのに使えない」と感じたら、まずそのセッションがインタラクティブに作られたものかプログラムから作られたものかを確認してください。
複数のMCPサーバーを配布するならツール検索の設定も見ておく
イメージビルドで複数のMCPサーバーを一度に組み込むと、セッションが最初に読み込むツール定義の量も増えます。Claude Codeにはこれを抑える「ツール検索」という仕組みがあり、既定ではツール名とサーバー側の説明文だけをセッション開始時に読み込み、実際に使うツールの詳細はClaudeが必要になった時点で検索して取得します。セッションはRunnerの環境変数をそのまま引き継ぐため、ENABLE_TOOL_SEARCHをRunner側に設定しておけば、そのRunnerが生成するすべてのセッションに一律で効きます。
| 値 | 挙動 |
|---|---|
| 未設定 | 挙動既定で全ツールを遅延読み込み。ただしANTHROPIC_BASE_URLがAnthropic以外のホストを指す場合などは先読みにフォールバックする |
true | 挙動全ツールを遅延読み込みに固定する |
auto | 挙動ツール定義の合計がコンテキストウィンドウの10%未満なら先読み、10%に達したら遅延読み込みに切り替える閾値モード |
auto:N | 挙動閾値をNパーセント(0〜100)で指定する閾値モード |
false | 挙動全ツールを起動時に先読みする(遅延読み込みなし) |
社内ゲートウェイのように毎セッションで確実に使うサーバーがある場合は、そのサーバーの設定にalwaysLoad: trueを立てておくと、ENABLE_TOOL_SEARCHの設定にかかわらずそのサーバーのツールだけは起動時から読み込まれた状態になります。ツール検索が使えるモデル(Sonnet 4.5・Haiku 4.5・Opus 4.5以降)かどうかや、プロキシ経由での制約は一般のMCPページ側の解説に譲ります。基本構文とスコープの全体像はClaude Code MCP設定ガイドにまとめています。
settings.jsonにMCPサーバーは書けない
混同しやすい点として、settings.jsonとmanaged-settings.jsonにはMCPサーバーの定義を書けません。設定スキーマにトップレベルのmcpServersフィールドが存在しないためです。設定ファイル経由でMCPサーバーを配布しようとして動かない場合は、経路そのものを間違えている可能性があります。上で挙げた3つの経路(イメージビルド・managed-mcp.json・.mcp.json)のいずれかに書き直してください。
よくあるつまずき
--scope userを忘れる: 既定のlocalスコープで追加すると、カレントディレクトリのパスをキーにした場所に書き込まれ、Runnerのスナップショットには一切含まれません- 認識できない
typeのエントリが黙って落ちる: Runnerは起動時の警告ログにしか記録しないため、セッションでツールが足りないと気づいてから原因を探ることになりがちです SELF_HOSTED_RUNNER_HOST_CONFIG_DIRを空ディレクトリに向けてしまう: 意図せずMCPサーバーのシーディングそのものを無効化してしまいます.mcp.jsonは自動承認されると思い込む: 自動承認になるのはクラウドセッション側だけで、ローカル端末のインタラクティブセッションでは通常どおり承認ダイアログが出ます
ラッパースクリプトやライフサイクルフックで認証情報やチェックアウト処理そのものをカスタマイズしたい場合は、Claude Codeセルフホスト環境をラッパースクリプトとフックで拡張するで扱う拡張ポイントの方が適しています。MCPサーバーの配布はこの4つの拡張ポイントとは別枠の仕組みです。
まとめ
セルフホスト環境のセッションにMCPサーバーを届けるには、イメージビルド時のclaude mcp add --scope user、管理者が配布するmanaged-mcp.json、リポジトリにコミットする.mcp.jsonの3つの経路があります。全社共通のツールはイメージビルド、ロックダウンが必要な環境はmanaged-mcp.json、プロジェクト固有の共有は.mcp.jsonと、目的に応じて使い分けます。claude.aiコネクタはインタラクティブセッションにしか自動配信されないため、プログラムから作るセッションでは上の3経路のいずれかを別途用意してください。