CLAUDE LABEN
2.1.273 — 接続まわりがまとめて整理されました。LLM ゲートウェイ向けの 5 ヘッダが opt-in で追加され、MCP が再接続を諦めたときにも通知が出ます09/29 — 廃止予定表にある claude-sonnet-4-5 の日付は残り 12 日ですが、これは「最も早い場合」の暫定日です。現在も Active で、公開モデルの廃止は最低 60 日前に告知されますMCP — セッションを畳まずに繋ぎ直したい、という要望が続いています。切断の通知は出るようになりましたが、再接続そのものはまだ手元の操作に委ねられていますNEW — 定期タスクが動く日と動かない日があったのは、フォルダを1つしか指定していなかったからでしたWINDOWS — Cowork が最初のタスクから失敗するときは、原因を探す前に開発者モードとセットアップの状態を確認しますHANDOFF — 会話が重くなった原稿を次のチャットへ渡すとき、要約に必ず残しておく項目を先に 3 つ決めておきます2.1.273 — 接続まわりがまとめて整理されました。LLM ゲートウェイ向けの 5 ヘッダが opt-in で追加され、MCP が再接続を諦めたときにも通知が出ます09/29 — 廃止予定表にある claude-sonnet-4-5 の日付は残り 12 日ですが、これは「最も早い場合」の暫定日です。現在も Active で、公開モデルの廃止は最低 60 日前に告知されますMCP — セッションを畳まずに繋ぎ直したい、という要望が続いています。切断の通知は出るようになりましたが、再接続そのものはまだ手元の操作に委ねられていますNEW — 定期タスクが動く日と動かない日があったのは、フォルダを1つしか指定していなかったからでしたWINDOWS — Cowork が最初のタスクから失敗するときは、原因を探す前に開発者モードとセットアップの状態を確認しますHANDOFF — 会話が重くなった原稿を次のチャットへ渡すとき、要約に必ず残しておく項目を先に 3 つ決めておきます
記事一覧/Claude Code
Claude Code/2026-09-01上級

MCPサーバが十数個を超えてから、起動直後の一覧を信用しなくなりました

起動直後に「接続できません」と並ぶサーバのうち、こちらから手を打てるものは一部だけです。応答なし・起動失敗・プロトコル拒否を分けて返すプローブを実装し、14台構成で逐次22.03秒が並列5.09秒まで縮むところ、待ち時間を詰めると健全なサーバが失敗に化けるところを実測で残しました。

MCP53Claude Code254起動時診断並行処理3運用設計26

プレミアム記事

朝いちばん、いつもの作業を始めようとして手が止まりました。前日まで使っていたサーバが、一覧のどこにもありません。

代わりに並んでいたのは「接続に失敗しました」という行が七つでした。設定は触っていません。ネットワークも生きています。首をかしげながら別の調べ物を五分ほどして、もう一度一覧を開いたら、七つのうち四つが何事もなかったように戻っていました。

壊れていたのではなく、まだ握手が終わっていなかっただけでした。

この日から、起動直後の一覧をそのまま信じるのをやめました。信じる代わりに、自分で握手して結果を分類するようにしました。今日はその実装と、十四台まで増やして測った数字を残しておきます。

「使えません」の中に、性質の違うものが混ざっていました

一覧に出る文言は一種類でも、その裏側で起きていることは同じではありません。手元で拾ったものを並べると、少なくとも四つに分かれていました。

結末裏で起きていることこちらの取れる手
応答なしプロセスは生きているが initialize への返事が期限内に来ない待つ・並列度を上げる。設定をいじっても直らない
起動失敗プロセスがすぐ落ちる。標準エラーに理由が出ているその場で直せる。資格情報・パス・実行権限
プロトコル拒否握手は成立したが、サーバがこちらの申告を受け付けないその場で直せる。バージョン整合・クライアント名
正常initialize が結果を返した何もしない

肝心なのは、この四つに割り当てるべき行動が全部違うという点です。応答なしのサーバに資格情報を入れ直しても徒労ですし、起動失敗しているサーバを待っても永遠に戻ってきません。一覧が「接続に失敗しました」の一語でまとめてしまうと、この使い分けができないまま総当たりで時間が溶けます。

もうひとつ、ここに含まれない層があります。握手も tools/list も成功しているのに、ツールが一件も生えていない状態です。あれは接続の層ではなく権限の層の話なので、MCPサーバーは繋がっているのに、ツールが0件で返る の方で扱いました。今日は握手が終わる手前だけを見ます。

分類して返すプローブを書く

やることは単純です。サーバを起動し、initialize を一通だけ投げ、期限つきで一行読みます。返ってきたものと、返ってこなかった理由で場合分けします。それだけです。

一点だけ、素直に書くと必ず踏む落とし穴があります。readline() には期限を渡せません。標準入出力の読み取りは、相手が黙り込んだらそのまま返ってこないので、timeout を書ける場所がないのです。ここは読み取りを別スレッドへ追い出し、スレッドの join(timeout) を期限として使います。

# probe.py — MCPサーバの起動時状態を四つに分類する
import json, os, subprocess, sys, threading, time
 
READY, TIMEOUT, EXITED, PROTOCOL_ERROR = "READY", "TIMEOUT", "EXITED", "PROTOCOL_ERROR"
 
def probe(name, command, env_overrides, timeout):
    """1台のMCPサーバへ initialize を投げ、(名前, 結末, 経過秒, 詳細) を返す。"""
    env = dict(os.environ)
    env.update(env_overrides)
    t0 = time.monotonic()
 
    try:
        proc = subprocess.Popen(
            command,
            stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
            text=True, env=env,
        )
    except OSError as ex:
        # 実行ファイルが無い・権限が無い。ここは握手以前の失敗
        return (name, EXITED, round(time.monotonic() - t0, 3), str(ex))
 
    request = {
        "jsonrpc": "2.0", "id": 1, "method": "initialize",
        "params": {
            "protocolVersion": "2025-06-18",
            "capabilities": {},
            "clientInfo": {"name": "startup-probe", "version": "1.0"},
        },
    }
 
    box = {}
    def read_one_line():
        box["line"] = proc.stdout.readline()   # 期限を渡せないのでスレッドへ隔離する
 
    reader = threading.Thread(target=read_one_line, daemon=True)
    try:
        proc.stdin.write(json.dumps(request) + "\n")
        proc.stdin.flush()
    except (BrokenPipeError, OSError):
        pass    # 既に落ちている。下の EXITED 判定で理由を拾う
 
    reader.start()
    reader.join(timeout)
    elapsed = round(time.monotonic() - t0, 3)
 
    if reader.is_alive():
        proc.kill()
        return (name, TIMEOUT, elapsed, f"initialize への応答が {timeout}s 以内に無し")
 
    line = box.get("line") or ""
    if not line:
        proc.kill()
        stderr_tail = (proc.stderr.read() or "").strip().splitlines()
        detail = stderr_tail[-1] if stderr_tail else "応答せずに標準出力を閉じた"
        return (name, EXITED, elapsed, detail)
 
    message = json.loads(line)
    proc.kill()
    if "error" in message:
        return (name, PROTOCOL_ERROR, elapsed, message["error"]["message"])
    return (name, READY, elapsed, message["result"]["serverInfo"]["name"])

この形は一点だけ足りません。後述の「診断ログの多いサーバ」の節で stderr の扱いを補うので、実際に回す前にそちらまで目を通していただければと思います。

proc.kill() を各分岐に置いているのは、握手だけ確かめて用済みにするからです。プローブが起動したプロセスを残したまま本体がもう一度起動すると、同じサーバが二重に立ち上がります。片付けを忘れると、調べるために作った仕組みが調べたい対象を汚します。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
動かないサーバを応答なし・起動失敗・プロトコル拒否の三つに切り分けて、自分の手で直せるものだけに時間を使えるようになります
健全なのに応答が遅いだけのサーバを失敗として切り捨てる設定を、本番の起動処理へ入れてしまう前に避けられるようになります
14台構成で逐次22.03秒が並列5.09秒へ縮んだ実測をもとに、自分の台数でプローブの並列度と待ち時間を決められるようになります
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

Claude Code2026-07-29
MCPサーバーは繋がっているのに、ツールが0件で返る — 無人実行の権限劣化をツール表の差分で止める
資格情報が抜けてもMCPのハンドシェイクは成功し、tools/list は空配列を返します。例外が飛ばないまま実行が完走する構造と、期待ツール表との差分で無人実行を止めるpreflightの実装を、実測値つきで記録しました。
Claude Code2026-07-16
夜間セッションの常駐メモリが朝には数GB — 蓄積の四つの出どころと、RSS を刻んで切り分ける
夜間に回した Claude Code のプロセスを朝に見ると、常駐メモリが数GBまで膨らんでいました。2.1.209 で塞がれた四つの蓄積源と、自分の構成に残る分を RSS の傾きで切り分ける方法、しきい値で畳む運用までを個人開発の目線で整理します。
Claude Code2026-09-04
~/.claude.json の巻き戻しは v2.1.259 で直りました。消えた設定は自分で戻します
同時に走らせたセッションが ~/.claude.json を互いに巻き戻す不具合が v2.1.259 で修正されました。消えた信頼設定と MCP を洗い出して戻すまでを、キー集合の差分を取る小さなスクリプトとあわせて書き残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます