StdIO MCP server disconnects after successful tools/call response when progress notifications are emitted

Resolved 💬 5 comments Opened Apr 26, 2026 by jacobcxdev Closed Jun 1, 2026

Summary

Claude Code disconnects a stdio MCP server after a successful tools/call response in a reproducible case where the request includes _meta.progressToken and the server emits progress notifications.

This appears to be a Claude Code client regression/compatibility issue, not a server crash:

  • the same server remains stable under repeated direct MCP SDK client calls
  • the server process does not throw or exit unexpectedly before responding
  • Claude Code closes stdin shortly after the successful response

Claude Code version

2.1.119

Regression context

These changelog entries seem related:

  • 2.1.105
  • “Fixed stdio MCP server emitting malformed (non-JSON) output hanging the session instead of failing fast with \"Connection closed\"”
  • “Fixed MCP tools missing on the first turn of headless/remote-trigger sessions when MCP servers connect asynchronously”
  • 2.1.110
  • “Fixed stdio MCP servers that print stray non-JSON lines to stdout being disconnected on the first stray line (regression in 2.1.105)”

This may be another stdio MCP regression in the same area.

What I expected

After a successful tools/call response, the stdio MCP server should remain connected and continue serving tools.

What happened

After a successful ping tool response, Claude Code removes the MCP tool registry for that server. The configured server may still show as connected via claude mcp get, but the tools are no longer callable in-session.

Repro characteristics

I narrowed this down to progress notifications:

  • With progress notifications enabled for tool calls:
  • Claude Code disconnects after a successful response.
  • With progress notifications disabled:
  • repeated live calls through Claude Code remain stable.

Evidence

Direct MCP SDK client is stable

The same server survives repeated:

  • tools/list
  • tools/call (ping)
  • tools/list

for 10 cycles under a direct MCP SDK client.

Claude Code-specific trace

The server writes file-only traces (not stdout/stderr). In the failing case, after a successful tools/call response, Claude Code closes stdin:

{"event":"transport.message","method":"tools/call","id":3}
{"event":"tools.call.received","name":"ping","params":{"_meta":{"progressToken":3,"claudecode/toolUseId":"..."}}}
{"event":"transport.send","method":"notifications/progress"}
{"event":"tools.call.execute.end","name":"ping","resultLength":10}
{"event":"transport.send","method":"notifications/progress"}
{"event":"tools.call.response","name":"ping","isError":false}
{"event":"transport.send","id":3}
{"event":"transport.send.done","id":3}
{"event":"stdin.end"}
{"event":"stdin.close"}
{"event":"process.beforeExit","code":0}
{"event":"process.exit","code":0}

In the stable case, with progress notifications disabled, Claude Code does not close stdin after the same successful response.

Minimal interpretation

Claude Code appears to be treating server-side progress notifications during a stdio tool call as connection-fatal for this server/client combination.

Additional notes

  • This is not caused by stray stdout.
  • Silencing routine stderr logging did not fix it.
  • Disabling progress notifications did fix it.

Request

Please investigate Claude Code’s stdio MCP handling when:

  • _meta.progressToken is present on tools/call
  • the server emits notifications/progress
  • the server then returns a normal successful tools/call result

I’m happy to provide a minimal repro server if useful.

View original on GitHub ↗

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