CLAUDE LABJP
PRICING — September 1 was the scheduled date for the Sonnet 5 price increase, and it did not happen. The introductory $2/$10 per MTok now stands as the regular pricePARTNER — Salesforce and Anthropic announced Claudeforce, an expanded partnership. The Salesforce in Claude plugin ships with 37 prebuilt sales skills, from meeting prep to pipeline managementTRUST — Claudeforce serves Claude through Amazon Bedrock inside the Salesforce Trust Boundary, so data and inference never leave the security perimeter — an answer aimed squarely at regulated industriesBETA — Salesforce in Claude is with select pilot customers for now, with an open beta expected during SeptemberLIMITS — The 50% weekly-limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promotion baseline, roughly a 17% cut from todayRELEASE — Claude Code has shipped nothing since v2.1.251 on August 28. Against a pace of one release every 0.8 days, a four-day gap is among the longest yetPRICING — September 1 was the scheduled date for the Sonnet 5 price increase, and it did not happen. The introductory $2/$10 per MTok now stands as the regular pricePARTNER — Salesforce and Anthropic announced Claudeforce, an expanded partnership. The Salesforce in Claude plugin ships with 37 prebuilt sales skills, from meeting prep to pipeline managementTRUST — Claudeforce serves Claude through Amazon Bedrock inside the Salesforce Trust Boundary, so data and inference never leave the security perimeter — an answer aimed squarely at regulated industriesBETA — Salesforce in Claude is with select pilot customers for now, with an open beta expected during SeptemberLIMITS — The 50% weekly-limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promotion baseline, roughly a 17% cut from todayRELEASE — Claude Code has shipped nothing since v2.1.251 on August 28. Against a pace of one release every 0.8 days, a four-day gap is among the longest yet
Articles/Claude Code
Claude Code/2026-09-01Advanced

Once I passed a dozen MCP servers, I stopped trusting the startup list

Only some of the servers that say connection failed at startup are ones you can actually fix. Here is a probe that separates no-response, launch failure, and protocol rejection, measured across a 14-server fleet where sequential 22.03s became parallel 5.09s, and where trimming the deadline quietly turned healthy servers into failures.

MCP52Claude Code242startup diagnosticsconcurrency2operations26

Premium Article

One morning I sat down to work and stopped short. A server I had used the day before was nowhere in the list.

In its place were seven lines reading "connection failed." I had not touched the config. The network was fine. I shrugged, spent five minutes on something else, and opened the list again — four of the seven were back as if nothing had happened.

They had not been broken. Their handshake simply had not finished yet.

From that morning on, I stopped reading the startup list at face value. Instead I shake hands myself and sort the results. Here is that implementation, along with the numbers I got after growing the fleet to fourteen.

"Unusable" turned out to cover several different things

The wording in the list is uniform, but what happens underneath is not. What I collected sorted into at least four outcomes.

OutcomeWhat is actually happeningWhat you can do about it
No responseThe process is alive, but no reply to initialize arrives before the deadlineWait, or raise concurrency. Config changes will not help
Launch failureThe process dies immediately, with a reason on stderrFixable right now: credentials, paths, execute permissions
Protocol rejectionThe handshake reached the server, which refused what you declaredFixable right now: version alignment, client identity
Readyinitialize returned a resultNothing

What matters is that each of these calls for a completely different action. Re-entering credentials on a server that never answers is wasted effort, and waiting on a server that crashed at launch means waiting forever. When the list collapses all four into a single "connection failed," you lose that distinction and burn time brute-forcing every fix in turn.

There is one more layer not covered here: the case where the handshake and tools/list both succeed but zero tools come back. That belongs to the permission layer rather than the connection layer, and I wrote about it separately in Your MCP server is connected, but it returns zero tools. Today I am only looking at what happens before the handshake completes.

Writing a probe that classifies

The job is simple. Launch the server, send exactly one initialize, read one line under a deadline, and branch on what came back — or on why nothing did.

There is one trap you will hit if you write it the obvious way. You cannot pass a deadline to readline(). Standard I/O reads have nowhere to put a timeout, so if the other side goes quiet, the call never returns. The fix is to push the read onto a separate thread and use that thread's join(timeout) as the deadline.

# probe.py - classify an MCP server's startup state into four outcomes
import json, os, subprocess, sys, threading, time
 
READY, TIMEOUT, EXITED, PROTOCOL_ERROR = "READY", "TIMEOUT", "EXITED", "PROTOCOL_ERROR"
 
def probe(name, command, env_overrides, timeout):
    """Send initialize to one MCP server; return (name, outcome, elapsed, detail)."""
    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:
        # Missing executable or no permission - this fails before any handshake
        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()   # no deadline available, so isolate it
 
    reader = threading.Thread(target=read_one_line, daemon=True)
    try:
        proc.stdin.write(json.dumps(request) + "\n")
        proc.stdin.flush()
    except (BrokenPipeError, OSError):
        pass    # already dead; the EXITED branch below recovers the reason
 
    reader.start()
    reader.join(timeout)
    elapsed = round(time.monotonic() - t0, 3)
 
    if reader.is_alive():
        proc.kill()
        return (name, TIMEOUT, elapsed, f"no response to initialize within {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 "closed stdout without responding"
        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"])

proc.kill() appears in every branch because the probe only needs the handshake and is done after that. If the probe leaves its processes running and the real client then starts, the same server comes up twice. Skip the cleanup and the tool you built to inspect things starts contaminating the thing you wanted to inspect.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to split unusable servers into no-response, launch failure, and protocol rejection, and spend your time only on the ones your own hands can fix
You will be able to avoid shipping a deadline setting that discards healthy-but-slow servers, before it reaches your startup path
You will be able to pick a probe concurrency and deadline for your own fleet size, using measurements where 14 servers dropped from 22.03s sequential to 5.09s parallel
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Claude Code2026-08-31
Half of My Scheduled Runs Vanished Without a Single Error
A batch job set to run twice a day was only firing once. No errors, no failure alerts. Here is how to expand your own schedule, count expected runs, and reconcile them against execution records to catch silent misses.
Claude Code2026-08-27
Curating the /model picker with modelPicker, and what replacing the lineup hides
Claude Code v2.1.242 added modelPicker, which lets you write the /model lineup yourself. Here is how appending differs from replacing, why project settings are ignored, and where it quietly narrows what availableModels allows.
Claude Code2026-08-25
One Space in a Folder Name Turned 80 Checks Into Zero
An inspection loop reported 80 files checked and 0 readable. The files were fine. Here is how word splitting turns path fragments into real directories, measured side by side, plus the count assertion I now put in front of every delete-heavy batch.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →