Claude Agent SDK init message: check the Sume server status first
Read the init message's mcp_servers statuses before a paid Sume call. failed and needs-auth mean the tools are not usable. pending is not a failure on its own.

Read the system init message and check each server's status before any paid call. Per the Claude Agent SDK docs, the status is one of pending, connected, failed, needs-auth or disabled, and a server that fails to connect does not throw (read 2026-10-05). Without that check, an agent can run a whole session without any Sume tools and still answer, which hides the problem.
Which statuses mean trouble
The docs say to check for failed or needs-auth to detect servers that will not be usable, and not to treat pending as a failure by itself (read 2026-10-05). Pending can mean the server has not connected yet, that its tool list came from a cache and connects on first use, or that the deadline expired.
Timing matters for a remote server without a cached tool list: the first turn waits up to MCP_TIMEOUT, 30 seconds by default, and the connection fails at that deadline. CLAUDE_CODE_MCP_STARTUP_WAIT_MS sets the wait yourself and requires Claude Code v2.1.274 or later.
| Status | Meaning | Action for a Sume session |
|---|---|---|
| connected | Server reachable, tools listed | Proceed |
| pending | Not connected yet, or cached list | Re-check status later; do not abort |
| failed | Could not connect | Stop; check URL and network |
| needs-auth | Credentials missing or rejected | Stop; check the API key or OAuth login |
| disabled | Turned off | Stop; enable the server |
A status gate in Python
This loop reads the init message, stops if the Sume server is unusable, and otherwise lets the query continue. It needs the claude-agent-sdk package and a key.
import asyncio, os
from claude_agent_sdk import (query, ClaudeAgentOptions,
SystemMessage, ResultMessage)
BAD = ("failed", "needs-auth", "disabled")
async def main() -> None:
options = ClaudeAgentOptions(
mcp_servers={"sume": {
"type": "http", "url": "https://mcp.sume.com/mcp",
"headers": {"Authorization":
"Bearer " + os.environ["SUME_API_KEY"]}}},
allowed_tools=["mcp__sume__mcp_health"])
async for msg in query(prompt="Call mcp_health.", options=options):
if isinstance(msg, SystemMessage) and msg.subtype == "init":
for s in msg.data.get("mcp_servers", []):
if s.get("name") == "sume" and s.get("status") in BAD:
raise SystemExit("sume unusable: " + s["status"])
if isinstance(msg, ResultMessage) and msg.subtype == "success":
print(msg.result)
asyncio.run(main())Confirm the auth source too
A connected server is not enough. Sume's quickstart suggests calling mcp_health first. For an OAuth session, authenticated.auth_source should read mcp_oauth, which confirms the session is the one you expect before anything that changes data runs.
The status can change after it first reports connected. The SDK docs note that a dropped remote server returns to pending while it reconnects, so re-check before a paid step in a long session.
What a silent failure looks like
Without a gate, the agent would carry on without Sume tools. It might tell the user it cannot generate media, or it might improvise with whatever other tools it has. Neither outcome raises an error, and you only notice when a deliverable is missing.
A status gate turns that into a visible, early failure with a reason. In a scheduled job, that is the difference between an alert at start-up and a gap in output discovered next week.
Checklist
Wire these into the worker's start-up path so a missing tool surface fails loudly.
- Fail fast on
failed,needs-authanddisabled. - Re-check status before each paid tool, not only once.
- Call
mcp_healthas the first tool, a free read. - Log the status value, never the headers.
Sources
Related posts
More in Developers
- Claude Agent SDK allowedTools mcp__sume__* also allows paid Sume tools
A wildcard in allowedTools approves every tool the Sume server exposes. With an API key that includes paid ones. Name the read tools instead.
- claude -p total_cost_usd vs your Sume bill: which number to trust
claude -p prints total_cost_usd for the Claude side of a run. Sume's generation spend is billed on Sume and read from GET /v1/usage. Here is how to log both.
- Sonnet 5.5 token bill vs Sume spend cap: two meters on one agent run
Sonnet 5.5 tokens bill at the model vendor. Sume generation bills in the Sume wallet. A worked example shows why one cap cannot cover both.
- Cloudflare Worker for a social video pipeline: SDK verifyWebhook
@sume-com/sdk 0.2.0 needs only fetch and WebCrypto, so verifyWebhook runs in a Cloudflare Worker. Verify the raw body, then answer 2xx before you post.
Written by Sume