Claude Media
OAuth callback port is already in useの原因と対処 — Claude Code

OAuth callback port is already in useの原因と対処 — Claude Code

Claude CodeでリモートMCPサーバーにOAuthでサインインすると出るポート競合エラーの原因を整理し、lsofとnetstatで占有プロセスを特定して解消する手順を扱います。

リモートMCPサーバーへのOAuthサインインで「OAuth callback port <port> is already in use — another process may be holding it」と表示されたら、サインインの結果を受け取るためのローカルポートを別のプロセスが握っています。多くは固定コールバックポートの設定が原因です。メッセージに出ているコマンドで占有プロセスを見つけて止めるか、別のポートに切り替えれば解消します。

このエラーは何を意味しているか

リモートMCPサーバーにOAuthでサインインすると、Claude Codeはローカルで待ち受け用のリスナーを立て、ブラウザーからのコールバックを受け取ります。そのポートが別のプロセスに使われていると、サインインはここで失敗します。表示されるメッセージは次の形です。

OAuth callback port <port> is already in use — another process may be holding it. Run `lsof -ti:<port> -sTCP:LISTEN` to find it.

<port>には実際の番号が入ります。Windowsでは提案されるコマンドがnetstat -ano | findstr :<port>に変わります。

エラーの発生源はMCPサーバーでもブラウザーでもなく、手元のマシン上のポート競合です。サーバー側の設定を疑う前に、まず自分の環境を見ます。

なぜ固定ポートのときに起きやすいのか

Claude Codeは、ポートを指定しない場合は空いているポートを自分で選びます。競合がほとんど起きないのはこのためです。エラーが目立つのは、次のどちらかで固定ポートを指定した場合です。

  • 環境変数のMCP_OAUTH_CALLBACK_PORT
  • claude mcp addなどに渡す--callback-portフラグ

固定するのは、MCPサーバー側に「http://localhost:PORT/callback」の形のリダイレクトURIを事前登録する必要があるからです。登録した番号とClaude Codeの待ち受け番号が一致しなければならないので、空いているポートを自動で選ぶ挙動が使えなくなります。

# 固定コールバックポートでサーバーを追加する例
claude mcp add --transport http \
  --callback-port 8080 \
  my-server https://mcp.example.com/mcp

設定ファイルに書く場合は、oauthオブジェクトのcallbackPortで同じ指定ができます。

claude mcp add-json my-server \
  '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'

8080のような定番の番号を選ぶと、開発サーバーなど別の用途と衝突する可能性が上がります。どのプロセスが握っているかは環境ごとに違うため、次の節の手順で実物を確かめます。

占有しているプロセスを特定して止める

エラーメッセージのコマンドをそのまま実行します。macOSとLinuxの例です。

lsof -ti:8080 -sTCP:LISTEN

-tを付けているので出力はプロセスIDだけになり、-sTCP:LISTENで待ち受け状態のものに絞られます。何も出なければ、その時点でポートは空いています。

プロセスIDから中身を知りたいときは、続けてpsで名前を確認します。止めてよいプロセスかどうかは、この名前を見て判断します。

ps -p <PID> -o pid,command

Windowsではnetstatで待ち受けているプロセスのPIDを探します。

netstat -ano | findstr :8080
tasklist /FI "PID eq <PID>"

netstat -anoの最後の列がPIDです。tasklistで名前を引けます。

手順は「メッセージのコマンドで占有プロセスを見つけ、止めるか終わるのを待つ」です。止める操作はkill <PID>(Windowsはtaskkill /PID <PID>)などOS標準の方法で行います。ほかの作業で使っている開発サーバーやデータベースの可能性があるので、名前を確かめてから止めます。

解消したらサインインをやり直す

ポートが空いたら、サインインを最初からやり直します。例は/mcpでサーバーを選ぶやり方です。

/mcp

シェルから直接実行したい場合はclaude mcp login <name>でも同じOAuthフローを動かせます。SSHセッションなどブラウザーが開けない環境では、認可URLが表示されます。手元のマシンでURLを開き、ブラウザーのアドレスバーに出たリダイレクトURL全体をプロンプトに貼り戻します。この貼り付けには対話的な端末が必要で、ssh -tで接続します。

別のプロセスがそのポートを必要とし続ける場合

他のプログラムがそのポートを恒常的に使うなら、止めても再び競合します。この場合の対処は、サーバー側に別のリダイレクトURIを登録し、そのポート番号をClaude Code側に設定し直すことです。

  1. MCPサーバーの開発者ポータルなどで、空いている別の番号のhttp://localhost:PORT/callbackを登録する
  2. MCP_OAUTH_CALLBACK_PORTか--callback-portのうち、使っている方でその番号を指定する
  3. /mcpからサインインをやり直す

環境変数の例は次のとおりです。

export MCP_OAUTH_CALLBACK_PORT=8765
claude

MCP_OAUTH_CALLBACK_PORTは、事前設定済みの認証情報でMCPサーバーを追加するときに--callback-portの代わりに使える環境変数です。8765は例示用の番号で、実際にはサーバーに登録した番号に合わせます。どちらか一方だけを使い、番号がずれないようにします。

止めたのにまたエラーになるときの確認点

占有プロセスを止めて解決したはずなのに、同じエラーが戻ることがあります。多い原因は次の3つです。

  • 止めたプロセスが自動で再起動している: 開発サーバーの監視機能やコンテナーのポート公開などが、止めた直後に同じポートを取り直すことがあります。サインインの直前にlsof -ti:<port> -sTCP:LISTENをもう一度実行し、出力が空であることを見てから進めます
  • 番号を変えたのにサーバー側の登録を変えていない: 別のポートに切り替えても、MCPサーバーに登録済みのリダイレクトURIが元の番号のままだと、今度は不一致でサインインが失敗します。番号を変えたら、サーバー側のhttp://localhost:PORT/callbackも同じ番号に直します
  • 環境変数とフラグの番号がずれている: MCP_OAUTH_CALLBACK_PORT、--callback-port、設定ファイルのoauth.callbackPortのどれで指定しているか分からなくなり、片方だけ書き換えて古い番号が残ることがあります。どこで指定したかを控えておきます

エラーの見分け方

似たエラーが複数あるので、メッセージの文言で切り分けます。

表示意味見る場所
OAuth callback port <port> is already in use意味指定ポートを他プロセスが占有見る場所lsofまたはnetstatで特定
No available ports for OAuth redirect意味ローカルポートをそもそも待ち受けできない見る場所セキュリティソフトやサンドボックスの設定
Incompatible auth server: does not support dynamic client registration意味サーバーが自動登録に非対応見る場所事前設定済みの認証情報が必要

2行目の「No available ports」は、127.0.0.1での待ち受け自体が妨げられているときに出ます。原因の例はセキュリティソフトやサンドボックスの制限です。v2.1.268より前はOSが割り当てるポートへのフォールバックがなく、Claude Codeが自分で選ぶ範囲のポートがすべて使えない場合にも出ました。Windowsでは、Hyper-Vが予約したポート範囲が原因になることがあります。

3行目は、ポートではなくサーバー側の対応状況の問題です。詳しくはGitHub MCPサーバーのOAuth接続エラーが具体例になります。

リダイレクトURIの不一致と混同しない

固定ポートを使う設定では、ポートの競合とは別に「リダイレクトURIの不一致」でサインインが失敗する場合があります。v2.1.229のClaude Codeはhttp://127.0.0.1:PORT/callbackの形で送信しており、登録値を完全一致で照合するサーバーはこれを拒否しました。v2.1.231でlocalhostの形に戻っています。

v2.1.229を使っているなら、Claude Codeを更新するか、127.0.0.1形式のURIも一時的にサーバー側へ登録して回避できます。ポートが空いているのに失敗するときは、この不一致を確かめます。競合を解消してもエラーが変わるだけ、というケースの切り分けにもなります。

再発を減らす設定の考え方

同じ競合を繰り返さないために、次の点を確認しておきます。

  • 固定ポートは、ほかのツールが既定で使わない番号を選ぶ
  • 複数のMCPサーバーで同じ固定ポートを使い回さない。片方のサインインが終わるまでポートが使われる可能性があり、並行して認証すると競合することがある
  • CIやスクリプトで固定ポートを環境変数から渡すときは、その番号をチーム内で一覧にしておく

2つ目は、ドキュメントに書かれた挙動ではなく、上の仕組みからの推論です。同じ番号を共有する構成では、サインインを1つずつ順番に行うと問題を避けられます。

ポートを固定せずに済むなら、それが最も競合しにくい構成です。サーバー側が動的クライアント登録に対応していれば、--callback-portなしで追加でき、空いているポートが自動で選ばれます。固定が必要かどうかは、サーバーのドキュメントでリダイレクトURIの事前登録を求められているかで決まります。

固定するか、Claude Codeに任せるかは、接続先のサーバーの対応で分かれます。

サーバーの状況ポートの扱いこのエラーの起きやすさ
動的クライアント登録に対応ポートの扱い指定せず、空いているポートの自動選択に任せるこのエラーの起きやすさ起きにくい
リダイレクトURIの事前登録が必要ポートの扱い登録した番号を--callback-portなどで固定するこのエラーの起きやすさ固定ポートの衝突で起きうる
事前設定済みの認証情報を使うポートの扱いサーバーに登録した番号と揃えて固定するこのエラーの起きやすさ同上

判断の材料は、サーバーのドキュメントにリダイレクトURIの登録手順があるかどうかです。手順があるなら固定が必要で、その番号を他のツールと重ならないように選びます。

認証まわりのそのほかの不調は、次の記事が入口になります。

まとめ

このエラーの原因は、OAuthのコールバック用に固定したポートを別のプロセスが握っていることです。lsof -ti:<port> -sTCP:LISTEN(Windowsはnetstat -ano | findstr :<port>)で占有元を見つけ、止めてから/mcpでサインインをやり直します。そのポートが恒常的に必要なプロセスに使われているなら、サーバーに別のリダイレクトURIを登録し、MCP_OAUTH_CALLBACK_PORTか--callback-portの番号を合わせ直します。

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