[BUG] disabledMcpServers with stdio plugin server causes silent exit(0)

Resolved 💬 3 comments Opened Mar 25, 2026 by bkatkam123 Closed Apr 23, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Trigger: Any entry in disabledMcpServers referencing a real stdio plugin MCP server
Symptom: TUI renders, REPL mounts, then process exits with code 0
Root cause: Node.js event loop drains - process.stdin not keeping event loop alive
Proof: Adding a long-lived child process (sleep 120 hook) prevents the exit
Versions: Confirmed on 2.1.50 and 2.1.71
Related: #33992 (same symptom, different trigger - may share root cause)

What Should Happen?

Session should remain running and accept user input. Disabled MCP servers should simply not connect, with no effect on the REPL lifecycle.

Error Messages/Logs

No error messages. Debug log (--debug) shows normal startup, MCP connection failures for non-disabled servers, then the log silently ends. strace -e trace=signal confirms exit_group(0) with no signals received.

Steps to Reproduce

  1. Install any plugin that defines a stdio MCP server
  2. In ~/.claude.json, add the server name to disabledMcpServers for the project:

"projects": {
"/path/to/project": {
"disabledMcpServers": ["plugin:PLUGIN_NAME:SERVER_NAME"]
}
}

  1. Run claude interactively in that project
  2. TUI renders the welcome screen and REPL prompt, then exits with code 0 within seconds

Note: disabling HTTP/SSE transport servers does NOT trigger this. Only stdio transport.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.71

Platform

AWS Bedrock

Operating System

Other Linux

Terminal/Shell

Xterm

Additional Information

  • Root cause: Node.js event loop drains. process.stdin is not keeping the event loop alive.
  • Proof: Adding a SessionStart hook that runs sleep 120 (a long-lived child process) prevents the exit entirely. This confirms stdin is unref'd and external handles are the only thing keeping the process alive.
  • The process survives exactly as long as other ref'd handles exist (MCP child processes, API TCP streams). When the last one closes, exit(0).
  • Possibly related to #33992 (same symptom, different trigger) - may share the same underlying stdin/event loop issue.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗