Claude Media
MCPサーバーに接続できないときの切り分け手順 — 設定・起動・認証・ツール表示の4層で原因を絞る

MCPサーバーに接続できないときの切り分け手順 — 設定・起動・認証・ツール表示の4層で原因を絞る

MCPサーバーに接続できないときの切り分け手順。設定ファイル・プロセス起動・認証・ツール表示の4層を上から潰す進め方と、stdioとリモートで違うエラーの出方を扱います。

MCPサーバーにつながらないときは、4つの層を上から順に潰すと原因が一意に決まります。①設定ファイルが読まれているか、②サーバーのプロセスが起動しているか、③認証が通っているか、④ツールが会話から見えているか。この順序が最短です。

逆から入ると遠回りになります。ツールが呼ばれない理由をモデル側の問題だと考えて調べ続け、実は設定を書いたファイルが読まれていなかった、という着地は珍しくありません。まず claude mcp list を打ち、そこに名前が出るかどうかで①と②以降を分けます。

症状から入る層を決める

最初に見るのは3つのコマンドの出力だけです。症状と入り口の対応は次のようになります。

見えている症状疑う層最初に見るもの
一覧にサーバー名が出ない疑う層設定ファイル最初に見るものclaude mcp list
名前は出るが接続していない疑う層プロセス起動最初に見るもの起動コマンドを手で実行
「認証が必要」と出る / 毎回ログインを求められる疑う層認証最初に見るもの/mcp
接続済みなのにツールが呼ばれない疑う層ツール表示最初に見るもの/mcp のツール数

claude mcp list は設定済みサーバーの一覧と接続状態を出します。個別に踏み込むなら claude mcp get <name> で、そのサーバーがどのスコープに定義されていて認証情報を持っているかまで確認できます。

claude mcp list          # 一覧と接続状態
claude mcp get github    # 個別サーバーのスコープと認証状態
claude doctor            # 設定の読み込み状況と矛盾の検出

追加コマンドの構文やスコープの選び方そのものに迷いがある場合は、Claude CodeへのMCPサーバー追加手順をまとめた設定ガイドが対応します。ここから先は、追加までは済んでいる前提で進めます。

第1層: 設定ファイルが読まれているか

一覧に名前が出ないなら、書いた場所か構文のどちらかです。まず押さえたいのは、MCPサーバーの定義を settings.json には書かないという点。保存先は2系統に分かれます。

スコープ保存先チーム共有
local(既定)保存先~/.claude.jsonチーム共有しない
project保存先プロジェクトルートの .mcp.jsonチーム共有する
user保存先~/.claude.jsonチーム共有しない

permissionsやHooksを置く settings.json にMCPの定義を書いても、エラーにならずそのまま無視されます。設定ファイルの系統全体はClaude Codeの設定ファイル完全ガイドで扱っています。

構文側で踏みやすいのは次の4つです。

  • オプションの位置: --transport --env --scope --header はすべてサーバー名の前に置きます。claude mcp add myserver --env KEY=value -- npx server の順序は意図通りに解釈されません
  • 環境変数の展開失敗: .mcp.json${VAR} を参照した変数が未設定で、デフォルト値もない場合、設定自体は読み込まれますが、claude mcp list に変数不足の警告が出て ${VAR} の文字列がそのまま使われます。認証情報がこの状態だと接続は失敗するため、${VAR:-default} でデフォルトを与えるか変数を設定します
  • 予約名: workspace は内部用に予約されており、設定しても読み込み時にスキップされます
  • 未承認: .mcp.json 由来のprojectスコープは初回利用前に承認が必要で、未承認のあいだは一覧に「⏸ Pending approval」と出ます。対話モードで claude を起動して承認するか、選び直すなら claude mcp reset-project-choices を実行します

同じ名前が複数スコープにあるときの優先順位は、local → project → user → プラグイン提供 → Claude.aiコネクタの順です。優先されたスコープの定義が丸ごと使われ、フィールド単位ではマージされません。「projectの定義をベースにlocalでトークンだけ差し替える」は成立せず、片方が丸ごと勝ちます。ここは「チームでは動くのに自分の環境だけ別のエンドポイントを向いている」の主な発生源で、v2.1.110以降は同一サーバーを異なるスコープで別エンドポイント定義していると /doctor が警告してくれます。

第2層: サーバーのプロセスが起動しているか

この層はstdio、つまりローカルで子プロセスとして起動するサーバー固有の問題です。原因の大半は commandargs のパス誤りで、確かめ方は単純です。設定に書いたコマンドを、そのままターミナルで手で実行します。

npx -y airtable-mcp-server
node ./tools/mcp-server.js

手で叩いて起動しないなら、Claude Code側から起動しても結果は同じです。パスの相対基準がずれている場合は、stdioサーバーへ自動で渡される環境変数 CLAUDE_PROJECT_DIR を使い、${CLAUDE_PROJECT_DIR:-.}/tools/mcp-server.js のように書くと作業ディレクトリに依存しなくなります。

手元では動くのにClaude Codeからは失敗する場合、疑う先は3つです。

  • 起動が遅い: サーバーの起動タイムアウトは既定30,000ミリ秒です。MCP_TIMEOUT=60000 claude のように延ばして起動します
  • 標準出力の汚染: 自作サーバーが console.log で標準出力にプロトコル外のデータを書くと、通信そのものが壊れます。ログは console.error に寄せます
  • 環境変数の欠落: 手元のシェルには通っているAPIキーが、--env.mcp.jsonenv に書かれていないケースです

第3層: 認証が通っているか

リモートサーバーが401か403を返すと、Claude Codeはそのサーバーを「認証が必要」とマークし、/mcp のパネルに表示します。セッション内で /mcp を実行してブラウザーでログインすれば接続され、取得したトークンは保存されて自動更新されます。

/mcp

ログインまで進めない、あるいは進んでも状態が残らないケースは3つに分かれます。

動的クライアント登録に非対応のサーバー。「Incompatible auth server: does not support dynamic client registration」というエラーで止まります。サーバー側の開発者ポータルでOAuthアプリを登録し、--client-id--client-secret、登録済みリダイレクトURIと一致する --callback-port を付けて追加し直します。

認証ヘッダーとOAuthの取り合いheaders.Authorization を設定したサーバーがそのヘッダーを拒否すると、Claude CodeはOAuthへフォールバックせず接続失敗として報告します。トークンがMCPエンドポイントで有効かを確かめるか、OAuthを使うならヘッダー設定を消します。

claude.ai側のコネクタが出てこない。この場合はアクティブな認証方法を確認します。コネクタが読み込まれるのはClaude.aiサブスクリプションで認証しているときだけで、ANTHROPIC_API_KEY やBedrock / Vertex経由の認証では読み込まれません。

一度認証したのに毎回ログインを求められる類の症状は、更新で解消している可能性が高い領域です。MCPのOAuth経路をまとめて修正したv2.1.118では、/mcp メニューの認証アクション欠落、expires_in 省略時の毎時再認証、macOSキーチェーンの競合などが同時に塞がれています。

第4層: 接続済みなのにツールが呼ばれない

/mcp で接続済みと出ているのにClaudeがツールを使わないなら、接続の問題ではありません。ツールが見えていないか、呼ぶ判断がされていないかのどちらかです。

最初に /mcp でそのサーバーのツール数を見ます。0ならサーバー側がツールを公開できていません。数が出ているなら、次の3点を確認します。

  • モデルの前提: 既定で有効なツール検索は、セッション開始時にツール名と説明だけを読み込み、定義の本体は必要になった時点で遅延読み込みします。この仕組みはtool_referenceブロックに対応するモデル(Sonnet 4.5 / Haiku 4.5 / Opus 4.5以降)が前提です
  • 常時読み込みの指定: 特定のサーバーを毎回すべて読ませたい場合は、そのサーバー定義に alwaysLoad: true を付けます。ENABLE_TOOL_SEARCH=false で全サーバーを事前読み込みに戻す方法もあります
  • 指名して呼べるか: 「GitHubのissueを見て」ではなく mcp__github__list_issues のようにツール名で指名すると、呼ばれない原因が認識側にあるのか接続側にあるのかを分けられます

出力側で切れている場合も、見え方はよく似ています。ツール出力が10,000トークンを超えると警告が出て、既定25,000トークンの上限(MAX_MCP_OUTPUT_TOKENS)を超える結果は打ち切られます。大きなスキーマやログを返すサーバーでは、上限を引き上げてから起動する手があります。

stdioとリモートではエラーの出方がどう違うか

同じ「つながらない」でも、トランスポートによって失敗の現れ方が違います。ここを知っていると、症状を見た時点で調べる層を絞れます。

観点stdio(ローカル)HTTP(リモート)
失敗の見え方stdio(ローカル)起動の時点で一気に失敗HTTP(リモート)追加は成功し、後から認証待ちで止まる
主な原因stdio(ローカル)パス誤り / 環境変数 / 標準出力の汚染HTTP(リモート)認証 / ネットワーク / エンドポイント違い
自動再接続stdio(ローカル)なしHTTP(リモート)指数バックオフで最大5回
確認の起点stdio(ローカル)コマンドを手で実行HTTP(リモート)/mcp の認証状態

stdioは「起動できたか」が二値で決まるため、手元でコマンドを実行すればその場で結論が出ます。リモートは追加そのものが成功してしまい、実際に叩く段になって401 / 403で止まります。一覧に名前が並んでいることは、接続できている証拠になりません。この非対称性が、切り分けの順序を層で固定する理由です。

なお、v2.1.121以降は起動時の初期接続についても、5xx応答やタイムアウトのような一時エラーであれば最大3回まで再試行します。ネットワークが安定しない環境での「たまに繋がらない」は、この再試行の範囲に収まっていることがあります。

それでも切り分かないとき

ログを見る手が残っています。デバッグログは既定で無効なので、claude --debug で起動するか、セッションの途中で /debug を打ってその時点から記録を始めます。ファイルに落とすなら --debug-file です。

claude --debug
claude --debug-file /tmp/claude.log

もう一つ効くのが、自分の環境ではなくバージョンを疑うことです。MCPの接続まわりは修正が続いている領域で、症状がそのまま過去の修正項目に一致することがあります。SSE / HTTPの接続が応答途中で落ちたときの無限ハングはv2.1.110で、stdioのツール実行中にEscを押すとサーバー接続そのものが閉じるリグレッションはv2.1.120で、それぞれ解消しました。claude update を先に走らせてから再現を取ると、調査自体が不要になることもあります。

MCPに限らずClaude Code全般の詰まりどころは起動失敗から権限まで10種のエラーと対処をまとめた記事に並べてあります。そもそもMCPがどういう層で何を運んでいるのかを掴み直したいときはMCPの仕組みと採用状況の解説が土台になります。

まとめ

接続できないときの手順は、層を固定して上から潰すことに尽きます。

  1. claude mcp list に名前が出るか(設定ファイルの場所と構文)
  2. 起動コマンドを手で実行して動くか(stdioのプロセス起動)
  3. /mcp で認証が通るか(リモートのOAuth)
  4. /mcp のツール数とモデル(接続後のツール表示)

原因の見当が付かないまま設定を書き換えると、直った理由も分からないまま次の環境で再発します。層を1つずつ確定させた記録が残っていれば、チームの誰かが同じ症状を踏んだときに再利用できます。Claude Code全体の機能とMCPの位置付けを見渡したい場合はClaude Code完全ガイドが起点になります。

この記事を共有:XはてブLinkedIn