[BUG] MCP tool calls hang indefinitely with no way to cancel byt itself
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?
Description
When an MCP tool call hangs (due to a stale session, backend restart, or slow response), Claude Code freezes completely with no timeout and no way to cancel the pending call. The user must kill and restart Claude Code to recover.
We discovered this while building https://openfactory.tech — an AI-powered Linux OS image builder that exposes 30+ MCP tools for build management, VM provisioning, and GUI-based testing. Our development workflow relies heavily on MCP tool calls (creating VMs, taking screenshots, interacting with desktop UIs), and
this hang issue blocks the entire session with no recovery path except killing Claude Code.
Steps to Reproduce
- Configure an MCP server using mcp-remote as a stdio bridge in ~/.claude.json:
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:8000/mcp", "--header", "Authorization: Bearer <token>"]
}
}
}
- Start Claude Code and verify MCP tools load (e.g., /mcp shows tools)
- Restart the MCP backend server (e.g., the HTTP server at localhost:8000)
- Invoke any MCP tool — the call hangs indefinitely
- Try to cancel — there is no way to break out. Ctrl+C doesn't work. The UI shows the tool call spinner forever.
Expected Behavior
- MCP tool calls should have a configurable timeout (e.g., 30-60 seconds)
- When a timeout is hit, Claude Code should:
- Cancel the pending call
- Show an error message ("MCP tool call timed out after 60s")
- Return control to the conversation so the user can retry or take a different approach
- Ideally, Ctrl+C or Escape should cancel a pending MCP tool call
Actual Behavior
- The tool call hangs forever with no timeout
- The Claude Code UI is completely frozen — no input accepted
- The only recovery is to kill the Claude Code process (Ctrl+C in terminal, or kill the process)
- After restart, the stale mcp-remote processes may still be running and need manual cleanup (kill <pid>)
Root Cause Analysis
The hang occurs in the mcp-remote npm package (stdio-to-HTTP bridge). When the backend restarts, the HTTP session ID that mcp-remote was using becomes invalid. mcp-remote attempts to re-establish the session but hangs during the reconnection handshake. Claude Code's MCP client waits indefinitely for the stdio
response from mcp-remote with no timeout.
The issue is compounded because:
- mcp-remote doesn't detect stale sessions and reconnect cleanly
- Claude Code has no timeout on MCP tool invocations
- There's no user-facing cancel mechanism for in-flight tool calls
Impact
For MCP-heavy workflows like ours at https://openfactory.tech — where Claude Code drives VM creation, desktop GUI testing via screenshots, and build pipelines through MCP tools — this is a session-killer. Every backend restart (common during development with --reload) risks hanging the next MCP call and losing the
entire conversation context.
Environment
- Claude Code version: 2.1.x (CLI)
- OS: Fedora 43 (Linux 6.19.9)
- MCP transport: mcp-remote (npm, stdio -> HTTP bridge)
- MCP server: Custom Streamable HTTP server (https://openfactory.tech backend, 30+ tools)
- Node.js: v22.x
Workaround
After the hang occurs:
- Kill Claude Code (Ctrl+C in another terminal)
- Kill stale mcp-remote processes: pkill -f mcp-remote
- Restart Claude Code
- Run /mcp — if it shows "Reconnected", the tools work again
To prevent the hang after a backend restart:
- Run /mcp in Claude Code immediately after restarting the backend — this triggers a reconnect before any tool call
Suggested Fix
- Add a timeout to MCP tool calls — configurable per-server or global (default 60s)
- Add a cancel mechanism — Ctrl+C or Escape during a pending tool call should abort it
- Detect stale mcp-remote sessions — if the bridge process stops responding to stdio writes, kill and respawn it
- Surface connection health — show MCP server connection status in /mcp (connected/disconnected/reconnecting)
What Should Happen?
Claude should be able to cancel MCP tool calling after some time
Error Messages/Logs
Steps to Reproduce
MCP tool calls hang indefinitely with no way to cancel
Description
When an MCP tool call hangs (due to a stale session, backend restart, or slow response), Claude Code freezes completely with no timeout and no way to cancel the pending call. The user must kill and restart Claude Code to recover.
We discovered this while building https://openfactory.tech — an AI-powered Linux OS image builder that exposes 30+ MCP tools for build management, VM provisioning, and GUI-based testing. Our development workflow relies heavily on MCP tool calls (creating VMs, taking screenshots, interacting with desktop UIs), and this hang issue blocks the entire session with no recovery path except killing Claude Code.
Steps to Reproduce
- Set up a minimal MCP server
Create server.js:
const { McpServer } = require("@modelcontextprotocol/sdk/server/mcp.js");
const { StreamableHTTPServerTransport } = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
const express = require("express");
const app = express();
app.use(express.json());
const server = new McpServer({ name: "test-server", version: "1.0.0" });
server.tool("hello", "Says hello", {}, async () => {
return { content: [{ type: "text", text: "Hello from MCP!" }] };
});
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID() });
app.all("/mcp", async (req, res) => { await transport.handleRequest(req, res, req.body); });
server.connect(transport);
app.listen(9999, () => console.log("MCP server on :9999"));
npm install @modelcontextprotocol/sdk express
node server.js
- Configure Claude Code to use it via mcp-remote
Add to ~/.claude.json:
{
"mcpServers": {
"test": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:9999/mcp"]
}
}
}
- Start Claude Code and verify tools load
claude
Type /mcp — should show the hello tool from test server.
- Restart the MCP backend
In another terminal:
# Kill and restart the server
pkill -f "node server.js"
node server.js
- Call any MCP tool — it hangs
In Claude Code, ask: "call the hello tool"
Result: Claude Code invokes the hello MCP tool. The call hangs indefinitely. The UI shows a spinner with no way to cancel. Ctrl+C does nothing. Escape does nothing. The session is frozen.
- Only recovery: kill Claude Code
# From another terminal
pkill -f "claude"
pkill -f "mcp-remote"
Expected Behavior
- MCP tool calls should have a configurable timeout (e.g., 30-60 seconds)
- When a timeout is hit, Claude Code should:
- Cancel the pending call
- Show an error message ("MCP tool call timed out after 60s")
- Return control to the conversation so the user can retry or take a different approach
- Ideally, Ctrl+C or Escape should cancel a pending MCP tool call
Actual Behavior
- The tool call hangs forever with no timeout
- The Claude Code UI is completely frozen — no input accepted
- The only recovery is to kill the Claude Code process
- After restart, stale mcp-remote processes may still be running and need manual cleanup
Root Cause Analysis
The hang occurs in the mcp-remote npm package (stdio-to-HTTP bridge). When the backend restarts, the HTTP session ID that mcp-remote was using becomes invalid. mcp-remote attempts to re-establish the session but hangs during the reconnection handshake. Claude Code's MCP client waits indefinitely for the stdio response from mcp-remote with no timeout.
The issue is compounded because:
- mcp-remote doesn't detect stale sessions and reconnect cleanly
- Claude Code has no timeout on MCP tool invocations
- There's no user-facing cancel mechanism for in-flight tool calls
Impact
For MCP-heavy workflows like ours at https://openfactory.tech — where Claude Code drives VM creation, desktop GUI testing via screenshots, and build pipelines through MCP tools — this is a session-killer. Every backend restart (common during development with --reload) risks hanging the next MCP call and losing the entire conversation context.
Environment
- Claude Code version: 2.1.x (CLI)
- OS: Fedora 43 (Linux 6.19.9)
- MCP transport: mcp-remote v0.x (npm, stdio -> HTTP bridge)
- MCP server: Custom Streamable HTTP server
- Node.js: v22.x
Workaround
After the hang occurs:
- Kill Claude Code from another terminal
- Kill stale mcp-remote processes: pkill -f mcp-remote
- Restart Claude Code
- Run /mcp — if it shows "Reconnected", the tools work again
To prevent the hang after a backend restart:
- Run /mcp in Claude Code immediately after restarting the backend — this triggers a reconnect before any tool call
Suggested Fix
- Add a timeout to MCP tool calls — configurable per-server or global (default 60s)
- Add a cancel mechanism — Ctrl+C or Escape during a pending tool call should abort it
- Detect stale mcp-remote sessions — if the bridge process stops responding to stdio writes, kill and respawn it
- Surface connection health — show MCP server connection status in /mcp (connected/disconnected/reconnecting)
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
- Claude Code version: 2.1.x (CLI)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗