Skip to content

mcp: restart a crashed stdio server with backoff #361

Description

@MitulShah1

Follow-up to #353, which defined two halves and shipped only the first.

What shipped in v1.3.2

Detection. A dead stdio subprocess is now noticed two ways — the child closing its error stream, confirmed with a ping so a server that closes it while still running keeps serving, and a tool call failing with a closed transport or a broken pipe. The server is marked unready, so its tools stop being advertised to the model and stop resolving.

What did not

Restart. Marking a server unready is terminal: nothing re-initializes it, so recovery requires a configuration reload or a process restart. A crashed MCP server stays withdrawn for the life of the process even though respawning it is straightforward.

Why it was deferred

Real supervision means one goroutine owning the child — StartWait → decide. The current library calls cmd.Wait() itself from Close() and keeps cmd unexported, so the gateway cannot own that loop. Blocked on #360.

Scope

  • Respawn an unready stdio server with exponential backoff.
  • Crash-loop protection: reset the backoff on sustained uptime, not on spawn. A server that dies immediately every time must not be restarted at full rate forever.
  • Bound the retry state so a permanently broken server settles rather than growing unboundedly.
  • Recovery should not require an operator action, which is the current situation.

No new machinery is needed for the respawn itself: RegisterConfig already closes the old client and spawns fresh, InitializeAll re-handshakes and re-indexes, and the entry retains its configuration. What is missing is a supervisor that can decide when to invoke them.

Related

A restart loop would also make withdrawal recoverable for the HTTP transport (#358), where a refused connection is routinely transient and terminal withdrawal is therefore unsafe on its own.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions