claude-code - 💡(How to fix) Fix Claude Desktop silently disconnects remote MCP servers (mcp-remote) and fails to auto-relaunch

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Claude Desktop closes the stdin pipe to remote MCP child processes (specifically mcp-remote via npx) at unpredictable intervals during active app usage, with no diagnostic log entry on the Claude Desktop side. The child process exits cleanly in response to the EOF, but Claude Desktop does not auto-relaunch the MCP server. The user must fully quit and restart Claude Desktop to recover the connection, and the issue then repeats.

Error Message

2026-05-21T03:47:53.437Z [scribe] [error] Server disconnected.

  • mcp-remote's _startOrAuthSse handles 405 gracefully (chunk-65X3S4HB.js:19679-19681): it cancels the body and returns without throwing. No reconnection loop, no error propagated upward.
  • mcp-remote internal idle timeout: No such timer exists in v0.1.38; the only exits are SIGINT, fatal error during connect, and the stdin end handler.
  1. Add an explicit log entry whenever Claude Desktop closes a remote MCP child's stdin or sends a signal, including the reason (cleanup, error, watchdog, renderer-bound lifecycle, etc.). The current silent close makes this class of bug effectively un-diagnosable without /usr/bin/log show.

Root Cause

For the most recent disconnect (2026-05-21T03:47:53 UTC = 2026-05-20T20:47:53 PT), I traced the event chain end-to-end.

Code Example

{
  "mcpServers": {
    "scribe": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://mcp.scribe.com/mcp", "--debug"]
    }
  }
}

---

2026-05-20 20:47:53.425129-0700  runningboardd: [anon<node>(501):7783] termination reported by proc_exit

---

function setupSignalHandlers(cleanup) {
  process.on("SIGINT", async () => { ... process.exit(0); });
  process.stdin.resume();
  process.stdin.on("end", async () => {
    log("\nShutting down...");
    await cleanup();
    process.exit(0);
  });
}

---

2026-05-20 20:47:14 [info] [EventLogging] Flushing 11 events
2026-05-20 20:48:23 [info] [EventLogging] Flushing 1 events

---

2026-05-21T03:46:45.040Z [scribe] [info] Server started and connected successfully
... (tools/list, prompts/list, resources/list all succeed within ~3s)
2026-05-21T03:47:53.437Z [scribe] [info] Server transport closed
2026-05-21T03:47:53.437Z [scribe] [info] Server transport closed unexpectedly, this is likely due to the process exiting early.
2026-05-21T03:47:53.437Z [scribe] [error] Server disconnected.

---

# Watch silent kills of the child:
/usr/bin/log stream --predicate 'eventMessage CONTAINS "mcp-remote"'

# Correlate with Node clean exits:
/usr/bin/log stream --predicate 'subsystem CONTAINS "runningboard" AND eventMessage CONTAINS "proc_exit"'

# Tail Claude's own MCP logs in parallel:
tail -F ~/Library/Logs/Claude/main.log ~/Library/Logs/Claude/mcp.log ~/Library/Logs/Claude/mcp-server-scribe.log
RAW_BUFFERClick to expand / collapse

Bug Report: Claude Desktop silently disconnects remote MCP servers and fails to auto-relaunch

Summary

Claude Desktop closes the stdin pipe to remote MCP child processes (specifically mcp-remote via npx) at unpredictable intervals during active app usage, with no diagnostic log entry on the Claude Desktop side. The child process exits cleanly in response to the EOF, but Claude Desktop does not auto-relaunch the MCP server. The user must fully quit and restart Claude Desktop to recover the connection, and the issue then repeats.

Environment

  • macOS: 26.4.1 (Darwin 25.4.0, Build 25E253)
  • Claude Desktop: 1.8089.1 (bundle id com.anthropic.claudefordesktop)
  • Node / npx: spawned automatically through Claude Desktop's MCP config
  • mcp-remote: 0.1.38
  • Remote MCP server under test: https://mcp.scribe.com/mcp (FastMCP, json_response=True, OAuth via OAuthProxy)

Configuration

~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "scribe": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://mcp.scribe.com/mcp", "--debug"]
    }
  }
}

Reproduction

  1. Configure a remote MCP server in Claude Desktop using mcp-remote (as above).
  2. Launch Claude Desktop. OAuth/DCR completes; tools/list succeeds.
  3. Use the MCP tool successfully at least once.
  4. Wait. At some point (the lifetime is not deterministic), the MCP server shows as disconnected in the UI.
  5. Claude Desktop does NOT spawn a replacement child process; the only way to recover is Cmd+Q and relaunch.

Observed disconnect lifetimes

Times measured from Server started and connected successfully to Server transport closed in ~/Library/Logs/Claude/mcp-server-scribe.log for a single user across several days:

Started (UTC)Closed (UTC)Lifetime
2026-05-07T18:19:352026-05-07T18:21:352m 00s
2026-05-07T19:47:532026-05-07T19:48:4552s
2026-05-14T02:10:032026-05-14T02:18:368m 33s
2026-05-14T18:25:162026-05-14T18:25:3620s
2026-05-14T19:38:562026-05-14T19:45:426m 46s
2026-05-19T07:37:452026-05-19T07:47:119m 26s
2026-05-20T17:51:102026-05-20T17:53:472m 37s
2026-05-20T23:03:482026-05-20T23:04:1426s
2026-05-20T23:05:452026-05-20T23:14:158m 30s
2026-05-21T03:46:452026-05-21T03:47:531m 08s

The variance (20s up to 9m 26s) is the strongest signal that this is not a fixed idle timeout on either the server, mcp-remote, or a network edge proxy.

Root cause analysis

For the most recent disconnect (2026-05-21T03:47:53 UTC = 2026-05-20T20:47:53 PT), I traced the event chain end-to-end.

1. mcp-remote exited cleanly via process.exit(0) on stdin EOF

The Node child process (PID 7783) calls proc_exit at exactly 20:47:53.425129:

2026-05-20 20:47:53.425129-0700  runningboardd: [anon<node>(501):7783] termination reported by proc_exit

This is a normal exit, not a kill. There is no SIGKILL, SIGTERM, or jetsam event in /usr/bin/log show --predicate 'subsystem CONTAINS "runningboard"'.

The exit originates inside mcp-remote, in setupSignalHandlers (file dist/chunk-65X3S4HB.js, lines 20877-20888):

function setupSignalHandlers(cleanup) {
  process.on("SIGINT", async () => { ... process.exit(0); });
  process.stdin.resume();
  process.stdin.on("end", async () => {
    log("\nShutting down...");
    await cleanup();
    process.exit(0);
  });
}

For the end event to fire, stdin must have received EOF. EOF on a child's stdin can only happen when the parent (Claude Desktop) closes its write end of the pipe.

2. Claude Desktop's main log shows no shutdown event at that moment

~/Library/Logs/Claude/main.log filtered for the minute of the disconnect:

2026-05-20 20:47:14 [info] [EventLogging] Flushing 11 events
2026-05-20 20:48:23 [info] [EventLogging] Flushing 1 events

There is no Shutting down MCP Server: scribe, no Killing utiltiy proccess, no beforeQuit, no onQuitCleanup near 20:47:53. Those entries appear only during real Cmd+Q sequences (20:46:39 and 20:49:39 in this same run), and the child correctly exits at those points. The 20:47:53 disconnect is silent on the Claude Desktop side.

3. mcp-server-scribe.log reflects the same picture

2026-05-21T03:46:45.040Z [scribe] [info] Server started and connected successfully
... (tools/list, prompts/list, resources/list all succeed within ~3s)
2026-05-21T03:47:53.437Z [scribe] [info] Server transport closed
2026-05-21T03:47:53.437Z [scribe] [info] Server transport closed unexpectedly, this is likely due to the process exiting early.
2026-05-21T03:47:53.437Z [scribe] [error] Server disconnected.

A full 65 seconds of idle, then the child is gone.

4. Claude Desktop does NOT auto-relaunch

Between the silent disconnect at 20:47:53 and the next Shutting down MCP Server: scribe (during Cmd+Q at 20:49:39), there is no MCP Server connection requested for: scribe / Launching MCP Server: scribe pair. The MCP entry is left in the "disconnected" state and a user-driven app restart is required.

For comparison, the previous Cmd+Q at 20:46:39 was correctly followed by a relaunch at 20:46:45 (this is the manual recovery path that works).

5. Server side is healthy and behaving per spec

  • The FastMCP server runs with json_response=True, so POST /mcp returns application/json and GET /mcp returns HTTP 405 Method Not Allowed (allow: DELETE, POST). Verified directly with curl against https://mcp.scribe.com/mcp.
  • mcp-remote's _startOrAuthSse handles 405 gracefully (chunk-65X3S4HB.js:19679-19681): it cancels the body and returns without throwing. No reconnection loop, no error propagated upward.
  • All POST request/response pairs in the failing session completed successfully (tools/list, prompts/list, resources/list).
  • OAuth tokens are valid for 3600s; the disconnects routinely happen with isExpired: false and 50+ minutes of validity remaining.

In short: the remote server, the network path, and mcp-remote are all behaving correctly when stdin EOF arrives. The unexplained event is the EOF itself, which can only come from the parent Claude Desktop process closing the pipe.

What I have ruled out

  • Idle timeout on server / Cloudflare / load balancer: Wouldn't manifest as stdin EOF on the child, and the timing variance is wrong.
  • OAuth token expiry: Tokens are valid; disconnects happen well within the 1h TTL.
  • macOS jetsam / OOM kill: No jetsam events in runningboard logs; proc_exit is a clean exit.
  • macOS App Nap on the child: runningboard records the node child as "not memory-managed" and "not lifecycle managed"; no suspend/throttle event at the time of exit.
  • mcp-remote internal idle timeout: No such timer exists in v0.1.38; the only exits are SIGINT, fatal error during connect, and the stdin end handler.
  • SSE-stream-related disconnects: With json_response=True the server returns 405 to the SSE GET, mcp-remote handles it cleanly, and no SSE stream is held open.
  • User-driven Cmd+Q: When the user actually quits, main.log shows the full beforeQuit / onQuitCleanup / Shutting down MCP Server chain. The disconnects we are investigating happen with none of those entries present.

Why this points to Claude Desktop

The MCP child process can only see EOF on stdin if Claude Desktop (the spawning parent) closes its write end of the pipe. There is no third process in between. The fact that this happens silently (no log entry on the host side) and is not followed by an automatic relaunch is what makes the bug user-visible: the MCP integration looks dead until the app is restarted.

Suggested investigation areas inside Claude Desktop

  1. Look for any code path in the Electron renderer/main that calls child.stdin.end() or child.kill() against an MCP ChildProcess outside the explicit onQuitCleanup / Shutting down MCP Server path. Candidates worth auditing:
    • Workspace / conversation / sidebar mode switches.
    • Renderer process refresh, navigation, or hot reload events.
    • Memory-pressure or background-throttle handlers in the main process.
    • Any "MCP host" supervisor watchdog timers (especially anything keyed on response latency).
  2. If a renderer process owns the ChildProcess handle, a renderer crash/restart will collapse the pipe even though main.log only records something innocuous (or nothing). Check whether MCP children are spawned from the main process or from a renderer/utility process, and whether the lifetime is bound to a renderer.
  3. Add an explicit log entry whenever Claude Desktop closes a remote MCP child's stdin or sends a signal, including the reason (cleanup, error, watchdog, renderer-bound lifecycle, etc.). The current silent close makes this class of bug effectively un-diagnosable without /usr/bin/log show.
  4. Implement automatic relaunch of disconnected MCP servers (with backoff), independent of how the previous child exited. Today, only the initial Cmd+Q -> relaunch cycle re-spawns them.

Verification commands the Claude Desktop team can run locally

# Watch silent kills of the child:
/usr/bin/log stream --predicate 'eventMessage CONTAINS "mcp-remote"'

# Correlate with Node clean exits:
/usr/bin/log stream --predicate 'subsystem CONTAINS "runningboard" AND eventMessage CONTAINS "proc_exit"'

# Tail Claude's own MCP logs in parallel:
tail -F ~/Library/Logs/Claude/main.log ~/Library/Logs/Claude/mcp.log ~/Library/Logs/Claude/mcp-server-scribe.log

A reliable repro: configure any remote MCP server via mcp-remote, let the app sit, and watch for the pattern Server transport closed unexpectedly in mcp-server-scribe.log with no matching Shutting down MCP Server in main.log at the same timestamp.

Severity / impact

  • For users relying on remote (HTTP/OAuth) MCP servers, the integration is effectively unusable for any session longer than a few minutes.
  • The "fix" of restarting Claude Desktop loses any in-progress conversation state and forces a fresh OAuth introspection round-trip on every reconnect.
  • Local stdio MCP servers do not appear to hit this (their lifetime is naturally bound to the app process, so a silent stdin close from the parent is not observed in the same way).

Logs / attachments to include when filing

  • ~/Library/Logs/Claude/main.log (filtered to a window covering one disconnect)
  • ~/Library/Logs/Claude/mcp.log
  • ~/Library/Logs/Claude/mcp-server-scribe.log
  • Output of /usr/bin/log show --predicate 'subsystem CONTAINS "runningboard"' --start "<T-30s>" --end "<T+30s>" around a disconnect
  • This document

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Claude Desktop silently disconnects remote MCP servers (mcp-remote) and fails to auto-relaunch