CLAUDE LABJP
SLACK — Claude Tag launches in beta on Slack: tag @Claude into channels to delegate tasks and connect tools, data, and codebasesSECURITY — Claude Code adds a sandbox.credentials setting to block sandboxed commands from reading credential files and secretsFIX — Remote MCP tool calls that once hung for five minutes now abort with an error instead of blockingMCP — Enterprise MCP connectors gain Okta provisioning, giving users zero-touch access on first loginMODEL — Claude Fable 5 offers a 1M-token context, always-on adaptive thinking, and 128K outputLINEUP — Opus 4.8, Sonnet 4.6, and Haiku 4.5 lead the lineup; pick the right one per taskSLACK — Claude Tag launches in beta on Slack: tag @Claude into channels to delegate tasks and connect tools, data, and codebasesSECURITY — Claude Code adds a sandbox.credentials setting to block sandboxed commands from reading credential files and secretsFIX — Remote MCP tool calls that once hung for five minutes now abort with an error instead of blockingMCP — Enterprise MCP connectors gain Okta provisioning, giving users zero-touch access on first loginMODEL — Claude Fable 5 offers a 1M-token context, always-on adaptive thinking, and 128K outputLINEUP — Opus 4.8, Sonnet 4.6, and Haiku 4.5 lead the lineup; pick the right one per task
Articles/Claude Code
Claude Code/2026-06-25Advanced

The Day a Non-Responding MCP Call Swallowed an Entire Unattended Run — Owning the Stop With Your Own Deadline

When a remote MCP tool call stops responding, an unattended scheduled run just keeps waiting. Instead of leaving the cutoff entirely to the platform, here is how I designed my own deadline and a per-connector circuit breaker to own the stop — with working code.

claude-code122mcp13agent11timeout7reliability8

Premium Article

In a scheduled run's log, a step that normally finishes in tens of seconds shows only "started," and then nothing after it. Re-run it and it passes fine. At first I let it go as a transient hiccup, but once it started landing on the same spot once or twice a week, I couldn't ignore it. The cause was a tool call sent to a remote MCP server that never returned a response — and our side kept waiting for it.

If you're working interactively, you step in the moment something feels stuck. But an unattended scheduled run has no one to step in. It burns the run's time budget still waiting for a response, and finishes without ever reaching the later steps. The worst part was that it wasn't even recorded as a failure.

The June 25 update fixed the behavior where a remote MCP tool call would wait indefinitely with no response; it now interrupts with an error after a set time instead of waiting forever. That's a real step forward. But what this fix gives you is a guarantee that "a failure will eventually come back" — not a decision about what your unattended run does with that failure. Today is my record of redesigning exactly that part, anchored to how I actually run things as an indie developer.

"Hanging" and "a failure returns" are two completely different operational modes

A state that hangs with no response and a state that returns an explicit error differ in operational character far more than the code suggests.

A hang robs you of the chance to actively decide anything. No exception and no return value arrive, so neither your try/except nor any downstream branch fires. The process just waits, and until the run's outer timeout arrives and kills it from the outside, the log holds only "started." Looking back afterward, there's barely a trace of where, or for how many minutes, it was waiting.

When a failure returns, on the other hand, you can decide. Retry, give up on this connector for now, or push the later steps forward anyway. Now that the platform interrupts a non-response, you finally stand at the entrance to that decision.

That said, the grace period before the platform cuts off can be long for an unattended run. When the overall run budget is short, cutting yourself off inside the outer limit leaves more time for later steps. Rather than delegating the cutoff wholesale to the platform, laying your own deadline further inside is the starting point.

Decide up front which layer stops the call

The most accident-prone part of timeout design is having several layers each hold a different limit, leaving it ambiguous who stops first. To keep this straight, narrow the layer that owns the stop down to one.

In my setup, I line them up from the inside out. First, each individual MCP tool call gets a call deadline, kept clearly shorter than the overall run budget. Next comes a step deadline for a step that bundles several calls. Finally there's a run deadline watching the whole scheduled run, and I make that one match the platform's limit.

The crucial part is keeping inner limits strictly shorter than outer ones. If the call deadline is longer than the step deadline, your own cutoff never fires and you end up swallowed by the outermost layer after all. When unsure of the numbers, work backward from what fraction of the outer budget you can spend on a single call. To leave time for the remaining steps, holding one call to at most roughly a third of the total budget felt realistic in my experience.

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
Separate what actually breaks when a remote MCP call hangs in an unattended run, so you can decide which layer should own the cutoff
Implement an asyncio wrapper that puts your own deadline inside the platform default and distinguishes a hang, a real error, and a normal response before retrying
Automate skip decisions with a per-connector circuit breaker so one broken connector can't drag the rest of the run's time down with it
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 $10 for lifetime access
View Membership →

Related Articles

Claude Code2026-06-18
Give an Unattended Agent Only the MCP Tools It Needs — Enforcing a Deny-by-Default Policy
An unattended Claude Code agent can't lean on a permission prompt, so whatever a tool can reach becomes the blast radius. Here's how to lock MCP servers and tools down to deny-by-default and hand back only what the job needs, with managed-settings.json examples.
Claude Code2026-06-14
Running Claude Code Hooks as a Quality Gate Without Breaking Your Pipeline
An implementation note on running Claude Code Hooks as a safety valve for automation: when to block with exit code 2 versus JSON output, how to keep formatters from looping or over-blocking, and how to log every hook firing so misfires are traceable.
Claude Code2026-06-12
A Three-Tier fallbackModel Setup for Claude Code — Keeping Unattended Runs Alive Through Overload Mornings
How I run Claude Code with a three-tier fallbackModel chain so overnight batches survive overload errors: logging which model actually ran, measuring quality drift on fallback days, and pairing it with deny rules.
📚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 →