Claude Media
GitHub MCPプラグインがHTTP 400で失敗する原因と対処法

GitHub MCPプラグインがHTTP 400で失敗する原因と対処法

公式マーケットプレイスのgithubプラグインが「HTTP 400」で接続に失敗する既知issueを、公式docsのMCP設定の仕組みと突き合わせて原因を切り分け、settings.jsonでの対処法をまとめます。

Claude Codeの公式マーケットプレイスからplugin:github:githubを有効にすると、https://api.githubcopilot.com/mcp/への接続が「HTTP 400」で失敗する報告がGitHub Issue #64654として続いています。2026年6月2日に登録され、2026年8月19日の追加報告以降もopenのままの既知issueです。原因は1つではなく、少なくとも2種類の異なる400が同じエラー文言の裏に隠れています。本記事では、まず自分のケースがどちらに当たるかを見分ける手順と、公式MCP docsの仕様と突き合わせた対処法を扱います。報告はmacOSラベルで登録されていますが、コメントにはWindowsとLinuxでの再現も含まれており、OS固有の不具合ではありません。

症状 — 接続表示が「Connected」でも失敗する場合がある

典型的な症状は、/mcpパネルまたはセッション起動時に次のエラーが表示され、githubプラグインのツールが呼び出せないというものです。

Failed to reconnect to plugin:github:github: HTTP 400 at https://api.githubcopilot.com/mcp/

厄介なのは、claude mcp list/mcpのステータス表示が「Connected」のまま変わらないケースがIssueのコメントで報告されている点です。実際にツールを呼び出すと失敗するのに、接続状態の表示だけでは異常に気づけません。この状態で切り分けを進めると、正常なはずの箇所を疑って時間を浪費しやすくなります。

まずclaude --debugでエラーの中身を確認する

/mcpのエラーメッセージだけでは、後述する2種類の原因のどちらかを区別できません。公式CLIリファレンスにあるデバッグログを使い、実際にGitHub側が返した文言を確認するのが最初の一歩です。

claude --debug='mcp' -p "say ok"

--debugはカテゴリを絞って有効化でき、ログはデフォルトで~/.claude/debug/<セッションID>.txtに書き出されます(CLAUDE_CODE_DEBUG_LOGS_DIRで変更可能)。ファイルの出力先を固定したい場合は--debug-fileで直接パスを指定できます。

claude --debug-file /tmp/claude-debug.log -p "say ok"

ログの中でgithubプラグインに関する行を探すと、次のいずれかの文言が見つかります。この文言の違いが、そのまま原因の切り分けになります。

ログに現れる文言意味する原因
Authorization header is badly formatted意味する原因ヘッダーの環境変数が展開されずリクエストされた
malformed payload: invalid message version tag意味する原因JSON-RPCペイロードの形式に関する問題(未確定)

原因1: 環境変数が展開されずヘッダーが空になる

Issueで最も裏付けの強い原因は、プラグインの.mcp.jsonが参照する環境変数がClaude Codeの実行プロセスに渡っていないケースです。githubプラグインの設定は次のように、${GITHUB_PERSONAL_ACCESS_TOKEN}をAuthorizationヘッダーに埋め込む形になっています。

{ "headers": { "Authorization": "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}" } }

公式MCP docsによると、${VAR}参照先の環境変数が未設定でデフォルト値もない場合、Claude Codeはclaude mcp list/mcpに警告を出したうえで、${VAR}をそのままの文字列として使ってサーバーを起動します。つまりヘッダーはBearer ${GITHUB_PERSONAL_ACCESS_TOKEN}という未展開の文字列のまま送信され、GitHub側がこれを不正な形式のAuthorizationヘッダーとして400で拒否します。なおGITHUB_PERSONAL_ACCESS_TOKENは、Claude Code自身の認証情報(ANTHROPIC_API_KEY等)のように常に空として扱われる予約名の対象外なので、正しく環境変数に値が入っていれば通常どおり展開されます。

Issueのコメントでは、この原因を実際にA/Bテストで切り分けた報告があります。同じアカウント・同じエンドポイントに対し、有効なトークンでの通常リクエストは200、トークンを空にしたリクエストと${GITHUB_PERSONAL_ACCESS_TOKEN}を未展開のまま送ったリクエストはどちらも「Authorization header is badly formatted」の400になったとしています。この報告によれば、シェルの.zshrc.zshenvexportしただけでは、その変数がClaude Codeを起動する子プロセスに確実に継承されるとは限らず、~/.claude/settings.jsonenvブロックに書いた場合だけ確実に展開されたということです。

原因2: JSON-RPCペイロードの版タグ欠落(未確定)

Issueを最初に報告した投稿者は、空のペイロードでエンドポイントに直接curlするとmalformed payload: invalid message version tag ""; expected "2.0"というエラーが返ることを確認し、プラグインが"jsonrpc": "2.0"を含まないリクエストを送っているのではないかと推測しています。ただしこの推測は、空ペイロードを手動で送った場合の挙動から逆算したものであり、プラグインが実際に送信しているリクエストの中身そのものを確認したものではありません。

後日、原因1を特定した報告者が同じエンドポイントへ4パターンの組み合わせで直接リクエストを送っていますが、有効なトークンで空ボディを送った場合に返った文言はPOST requires a non-empty bodyで、最初の報告者が引用したinvalid message version tagとは一致しませんでした。同じ「空のリクエストを送る」という条件でもエンドポイント側の応答が食い違っており、原因2を再現条件込みで裏付けるコメントはIssue上に見当たりません。両方の文言が同じ「HTTP 400」として括られているため、まずはデバッグログで自分のケースがどちらの文言かを確認するのが手戻りを避ける近道です。

対処 — envブロックにトークンを書く

原因1に当てはまる場合の対処は、GitHubのPersonal Access Tokenを~/.claude/settings.jsonenvブロックに直接書くことです。

{
  "env": {
    "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
  }
}

保存後はターミナルを再起動してからClaude Codeを起動し直し、claude --debug='mcp' -p "say ok"のログでAuthorization header is badly formattedが出なくなっているかを確認します。シェルのexportだけで解決したという報告もありますが、起動経路によっては変数が引き継がれないため、settings.json側に書いておくほうが再現性のある対処です。

変数名はGITHUB_PERSONAL_ACCESS_TOKENである必要があります。GITHUB_PATGITHUB_TOKENのような別名で設定しても、プラグインの.mcp.jsonが参照している変数名と一致しないため展開されません。トークン自体は、GitHubの個人アクセストークン設定でfine-grainedトークンを発行して使います。元の報告環境ではgh auth login時にcopilotgistread:orgrepoworkflowのスコープを付与しており、リポジトリへの読み書きに加えてCopilot関連の操作を含むスコープ構成になっています。トークンの発行手順や有効にするtoolsetsの絞り方はGitHub MCPサーバーの使い方にまとめてあります。

古いローカル設定が残っていないかも確認する

settings.jsonを直しても直らない場合、過去にclaude mcp addで手動追加したgithubサーバーの設定がローカルスコープに残っていて、プラグイン側の設定より優先されているケースがあります。Issueのコメントでは、次のコマンドで既存設定を確認し、重複していれば削除してからプラグインを再度有効化する対処が共有されています。

claude mcp list
claude mcp remove github

claude mcp listは登録されているMCPサーバーとスコープを一覧表示します。同じgithubという名前でプラグイン外の定義が見つかった場合は、claude mcp removeで削除してからプラグインを再読み込みします。ローカルスコープの定義とプラグイン由来の定義が同じ名前で共存すると、どちらの設定が実際に使われているのか/mcpの表示だけでは判別しづらく、settings.jsonを直した効果が反映されないように見えることがあります。設定を変えても症状が変わらないときは、まずこの重複が無いかを確認してから、環境変数側の見直しに戻るのが手順として確実です。

エラー文言別の対処早見表

デバッグログで確認した文言ごとに、試す順番をまとめると次のようになります。

デバッグログの文言まず試すこと次に試すこと
Authorization header is badly formattedまず試すことsettings.jsonenvにトークンを設定次に試すこと古いローカルgithub設定の削除(claude mcp remove)
Incompatible auth server: does not support dynamic client registrationまず試すこと「Authenticate」ボタンを使わずヘッダー方式に切り替え次に試すことOAuth接続エラーの記事を参照
malformed payload: invalid message version tagまず試すことまずAuthorization header is badly formattedが別に出ていないか再確認次に試すこと環境変数の展開を疑って同じ対処を試す
ログにgithubプラグイン関連の行がないまず試すことclaude mcp listでスコープの重複を確認次に試すことGitHub本体の障害状況を確認

3行目は、原因2として報告された文言そのものへの確定的な対処が無いため、まず原因1と同じ環境変数の展開ミスを疑うのが現実的な順序です。

この不具合の現在地点

時期出来事
2026-06-02出来事Issue #64654登録。Claude Code v2.1.150で「malformed payload」文言のHTTP 400を報告
2026-06〜07出来事複数の利用者が同じ400を再現。macOSだけでなくLinuxでも発生すると追認
2026-08-19出来事Claude Code v2.1.235で「Authorization header is badly formatted」という別の文言を確認し、環境変数の展開失敗をA/Bテストで特定した報告が追加
2026-08-19以降出来事新たなコメントは付いておらず、Issueはopenのまま。Anthropic側の修正コミットや公式な原因確定のコメントは見当たらない

2種類の文言はどちらも同じ「plugin:github:githubがHTTP 400で失敗する」という症状として括られていますが、原因も再現条件も異なります。githubプラグイン以外のMCPサーバーで接続エラーが起きた場合の一般的な切り分け手順はMCPサーバーに接続できないときの切り分け手順にまとめています。

まとめ

githubプラグインのHTTP 400は、claude --debugのログに現れる文言で少なくとも2種類に分かれます。最も報告数が多く原因も特定されているのは、.mcp.jsonが参照するGITHUB_PERSONAL_ACCESS_TOKENがClaude Codeの実行プロセスに渡らず、Authorizationヘッダーが未展開の文字列のまま送られるケースです。この場合は~/.claude/settings.jsonenvブロックにトークンを書くことで解決します。設定を直しても直らないときは、ローカルスコープに古いgithub設定が重複していないかも合わせて確認します。もう一方のJSON-RPCペイロードに関する原因は、Issue上でも未確定のままです。Issue #64654自体は2026年8月19日の追加報告以降もopenの状態が続いており、公式な修正は確認できていません。

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