[BUG] Desktop app cancels stdio MCP tool calls at ~60s and ignores MCP_TOOL_TIMEOUT; the CLI honors it

Resolved 💬 2 comments Opened May 28, 2026 by sfourdrinier Closed Jul 13, 2026

Summary

A long-running stdio MCP tool call is cancelled by the Claude Code desktop app with MCP error -32001: Request timed out after ~60 seconds, even though MCP_TOOL_TIMEOUT is set to a much larger value (e.g. 900000 = 15 min) in ~/.claude/settings.json env and is verifiably present in the process environment, and the Claude Code CLI runs the exact same stdio server and tool call past 60 seconds to completion.

The 60s figure matches the MCP TypeScript SDK default DEFAULT_REQUEST_TIMEOUT_MSEC = 60000, which suggests the desktop host uses the SDK default request timeout for tool calls and never threads MCP_TOOL_TIMEOUT (or the per-server .mcp.json timeout) into the client request options.

This is not the HTTP/SSE first-byte budget (the server is stdio), and not the 4-minute desktop cap reported in #44032 (we measured ~60s, not ~240s).

Environment

  • Host where it FAILS: Claude Code desktop app, version Claude 1.9659.1 (193bcb) (build 2026-05-28T16:22:15.000Z)
  • Host where it WORKS: Claude Code CLI 2.1.154
  • OS: macOS (Darwin 25.4.0, arm64); Node v22.22.2
  • MCP server transport: stdio (@modelcontextprotocol/sdk, StdioServerTransport)
  • ~/.claude/settings.json contains "env": { "MCP_TOOL_TIMEOUT": "900000" }
  • Confirmed in the failing session: printenv MCP_TOOL_TIMEOUT -> 900000 (the var is inherited by the process; it is simply not applied to MCP tool-call requests)

Expected behavior

A stdio MCP tool call should run until MCP_TOOL_TIMEOUT (or the per-server .mcp.json timeout) elapses, consistently across the CLI and the desktop app. Per the docs, MCP_TOOL_TIMEOUT is the per-tool-call execution timeout and a per-server timeout overrides it: https://code.claude.com/docs/en/mcp

Actual behavior

The desktop app cancels the tool call at ~60s with -32001: Request timed out regardless of MCP_TOOL_TIMEOUT. The CLI honors the configured timeout and the same call completes.

Measurement

Same stdio server, same tool, same machine, same ~/.claude/settings.json (with MCP_TOOL_TIMEOUT=900000, verified present in both hosts via printenv). The tool call genuinely takes ~66s of work.

| Host | Result | Wall-clock |
|---|---|---|
| Desktop app | MCP error -32001: Request timed out at ~60s | bracketed at 69.08s end-to-end incl. agent overhead; underlying timeout ~= 60s (= SDK DEFAULT_REQUEST_TIMEOUT_MSEC) |
| CLI | completed successfully (no -32001) | ~66s of actual work; 93.7s end-to-end incl. agent overhead |

The same call the CLI runs to completion is cancelled by the desktop app ~6s short of finishing, purely because the desktop host enforces the 60s SDK default and ignores MCP_TOOL_TIMEOUT.

Minimal reproduction

A ~15-line stdio MCP server with one tool that sleeps for a requested duration. This mirrors the sleep-based repro in #16837 (which covers the startup timeout MCP_TIMEOUT) but targets tool-call execution.

sleep-server.mjs:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "sleep-server", version: "1.0.0" });
server.tool(
  "sleep",
  { seconds: z.number() },
  async ({ seconds }) => {
    await new Promise((r) => setTimeout(r, seconds * 1000));
    return { content: [{ type: "text", text: `slept ${seconds}s` }] };
  },
);
await server.connect(new StdioServerTransport());

Steps:

  1. claude mcp add --transport stdio sleep -- node /abs/path/sleep-server.mjs
  2. Set "env": { "MCP_TOOL_TIMEOUT": "900000" } in ~/.claude/settings.json (and/or add "timeout": 900000 to the server's entry).
  3. Restart both hosts so the env is picked up.
  4. Invoke the sleep tool with seconds: 180.

Result:

  • CLI: returns slept 180s after ~180s (honors MCP_TOOL_TIMEOUT).
  • Desktop app: MCP error -32001: Request timed out at ~60s (ignores MCP_TOOL_TIMEOUT and the per-server timeout).

To pin the exact desktop cutoff, binary-search seconds (e.g. 50, 55, 59, 65) - the boundary lands at ~60s.

Impact

Any MCP server with a tool that legitimately takes >60s (LLM/agent calls with high reasoning effort, large builds, data exports, long queries) is unusable from the desktop app but fine from the CLI. There is no setting that raises the desktop limit: MCP_TOOL_TIMEOUT is ignored, the .mcp.json timeout field is reportedly ignored (#43791), and the server cannot extend it via progress notifications (the SDK request timeout does not reset on progress).

Relationship to existing issues (why this is distinct)

  • #16837 - MCP_TIMEOUT (server startup/connection) capped at ~60s, reproduced on the CLI. Different timeout (startup, not tool execution) and different host.
  • #44032 - desktop tool calls cancelled at ~240s, Windows + Obsidian servers, closed as "not planned/invalid." This report is macOS, stdio, measured at ~60s, and frames the precise CLI-honors / desktop-ignores MCP_TOOL_TIMEOUT contrast.
  • #43791 - timeout field in desktop config not honored (consistent with this report).
  • #47076 / #5221 / #22542 - feature requests to make the desktop tool timeout configurable (still open).

Ask

Make the desktop app honor MCP_TOOL_TIMEOUT and the per-server .mcp.json timeout for tool-call execution, matching the CLI - or, at minimum, document the desktop's fixed ~60s tool-call limit and expose a way to raise it.

View original on GitHub ↗

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