news 2026/8/19 1:26:27

【Bug已解决】MCP error -32001 (Request timed out) when connecting Claude to Node.js MCP server 解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Bug已解决】MCP error -32001 (Request timed out) when connecting Claude to Node.js MCP server 解决方案

【Bug已解决】MCP error -32001 (Request timed out) when connecting Claude to Node.js MCP server 解决方案

一、现象长什么样

你把自写的 Node.js MCP server 接进 Claude,调用工具时收到:

  • MCP error -32001 (Request timed out)
  • Request timed out在工具调用几秒后返回;
  • Claude 侧显示工具"超时",但你的 Node server 其实收到了请求、只是还没返回;
  • 有时 server 完全没收到请求(卡在初始化握手阶段);
  • 本地直连 server(用mcpCLI 或 inspector)有时正常,一接 Claude 就超时;
  • 工具逻辑里若有阻塞同步操作(大文件读取、同步网络请求),更容易触发。

一句话:MCP 客户端(Claude)在规定时间内没收到 server 的响应,于是按 JSON-RPC 协议返回 -32001 Request timed out——本质是 server 响应太慢或根本没响应。

二、背景

MCP 基于 JSON-RPC 2.0,客户端每发一个请求(如tools/call)都期待一个响应。协议层通常有一个超时:若 server 在超时窗口内未回response(或progress),客户端就主动判定Request timed out(-32001)。

Node.js MCP server 常见超时来源:

  1. 初始化握手慢:server 启动要做重活(加载大模型、连库),initialize阶段就超时;
  2. 工具调用是同步阻塞:在request处理器里写了fs.readFileSync大文件、或axios同步等待外部 API,事件循环被卡住,响应发不出去;
  3. 忘了await/ 返回 Promise:handler 里漏了return,客户端永远等不到结果;
  4. server 抛错但没回复错误响应:异常未被捕获,请求悬空。

三、根因

根因是server 在超时窗口内未能返回合法的 JSON-RPC 响应

// 伪代码:问题 handler server.setRequestHandler(CallToolRequestSchema, async (req) => { // 同步阻塞:事件循环卡住,超时 const data = fs.readFileSync("/huge/file"); // 阻塞 // 或:漏了 return / await doSomethingAsync(req); // 没 return,客户端等不到 response });

修复方向:把阻塞操作改成异步、确保 handler 一定return一个响应、给慢操作加进度通知(progress)、或在客户端侧调大超时。

四、最小可运行复现

下面用 Node 模拟"handler 忘记 return,导致请求永不响应":

// 用 @modelcontextprotocol/sdk 的简化示意 const handlers = {}; function register(name, fn) { handlers[name] = fn; } // bug:async 里没 return register("tools/call", async (req) => { await new Promise(r => setTimeout(r, 100)); // 漏了 return 响应 -> 客户端超时 const result = { content: [{ type: "text", text: "done" }] }; // 应该 return result; 但忘了 }); // 模拟客户端等待 + 超时判定 function clientCall(timeoutMs) { return new Promise((resolve, reject) => { const t = setTimeout(() => reject(new Error("MCP error -32001 (Request timed out)")), timeoutMs); Promise.resolve(handlers["tools/call"]({})).then(res => { clearTimeout(t); resolve(res); }); }); } clientCall(50).catch(e => console.log("ERR:", e.message));

运行后因为 handler 没返回,客户端在 50ms 后抛-32001 Request timed out

五、解决方案(第一层:最小直接修复)

最小修复:确保 handler异步化且一定返回响应,并给客户端合理超时:

import { readFile } from "fs/promises"; server.setRequestHandler(CallToolRequestSchema, async (req) => { // 1. 用异步 API,不阻塞事件循环 const data = await readFile("/huge/file", "utf8"); // 2. 务必 return 响应 return { content: [{ type: "text", text: String(data.length) }], }; });

客户端侧(如 Claude Desktop 配置)若 server 确实慢,可确认是否有超时配置可调;部分 MCP 客户端支持设置更长超时。同时,在慢操作里发进度通知:

await server.sendProgress({ progressToken: req.meta?.progressToken, progress: 0.5, total: 1 });

六、解决方案(第二层:结构化改进)

把"工具调用超时治理"抽成策略,集中管理超时、异步化、以及必须返回响应:

from dataclasses import dataclass, field from typing import Awaitable, Callable, Dict, Any @dataclass(frozen=True) class McpTimeout32001Policy: """MCP 工具调用策略:防 -32001 超时。 规则: - 每个 handler 必须返回响应(禁止漏 return) - 阻塞操作必须异步化(调用方用 asyncio.to_thread) - 慢操作发进度通知,重置客户端超时预期 """ client_timeout_ms: int = 10_000 async def run_handler( self, handler: Callable[[Dict], Awaitable[Dict]], req: Dict, slow_work: Callable[[], Any] = None, ) -> Dict: # 若有阻塞工作,丢到线程池,避免卡事件循环 import asyncio if slow_work is not None: await asyncio.to_thread(slow_work) result = await handler(req) if not isinstance(result, dict) or "content" not in result: raise ValueError("handler 必须返回含 content 的响应对象") return result def ensure_returns(self, handler) -> Callable: async def wrapped(req): res = await handler(req) assert res is not None, "handler 禁止返回 None(会导致 -32001)" return res return wrapped def demo() -> None: policy = McpTimeout32001Policy() wrapped = policy.ensure_returns(lambda req: {"content": [{"type": "text", "text": "ok"}]}) import asyncio print(asyncio.run(policy.run_handler(wrapped, {}))) if __name__ == "__main__": demo()

七、解决方案(第三层:断言 / CI 守护)

import asyncio import pytest from your_module import McpTimeout32001Policy def test_handler_must_return_content(): policy = McpTimeout32001Policy() async def bad(req): return {"no_content": 1} with pytest.raises(ValueError): asyncio.run(policy.run_handler(bad, {})) def test_handler_none_rejected(): policy = McpTimeout32001Policy() wrapped = policy.ensure_returns(lambda req: None) with pytest.raises(AssertionError): asyncio.run(wrapped({})) def test_valid_handler_ok(): policy = McpTimeout32001Policy() async def good(req): return {"content": [{"type": "text", "text": "ok"}]} res = asyncio.run(policy.run_handler(good, {})) assert res["content"][0]["text"] == "ok" def test_slow_work_offloaded(): import time policy = McpTimeout32001Policy() def blocking(): time.sleep(0.01) async def h(req): return {"content": [{"type": "text", "text": "done"}]} res = asyncio.run(policy.run_handler(h, {}, slow_work=blocking)) assert res["content"]

把这些测试加进 MCP server 的 CI,确保每个工具 handler 都返回合规响应,从根上杜绝 -32001。

八、排查清单

  • server 是否收到了请求?看 server 日志,没收到说明卡在初始化握手。
  • handler 里是否有同步阻塞(readFileSync / 同步网络)?改成异步。
  • handler 是否return了响应?漏 return 是超时头号原因。
  • 是否抛了异常却没回复错误响应?异常要转成 JSON-RPC error 返回。
  • 慢操作是否发了 progress 通知?没进度客户端会判超时。
  • 客户端超时是否可调大?确认 MCP 客户端配置。
  • 是否用 inspector 单独测过 server?先排除 server 自身问题。

九、小结

MCP error -32001 (Request timed out)是客户端在超时窗口内没收到 server 的 JSON-RPC 响应。根因几乎都在 server 侧:handler 同步阻塞、漏了return、异常未回复、或初始化过慢。最小修复是异步化阻塞操作、确保 handler 一定返回含content的响应、给慢操作发 progress;结构化做法是抽成McpTimeout32001Policy,集中治理超时与响应合规;最后用 pytest 守护"handler 必须返回合规响应",从根上消除 -32001。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/19 1:26:12

微交互性能,数据到底该怎么看

微交互性能,数据到底该怎么看 动画感觉发涩时,先看 trace,不要先改缓动曲线。输入之后的长任务、频繁布局和大面积绘制都会影响反馈;平均帧率很难说明是哪一个环节卡住。 在相同设备和路径下比较改动前后:按下、拖拽、…

作者头像 李华
网站建设 2026/8/19 1:23:43

基于nanoFramework在ESP32上构建轻量级Web Server的完整指南

1. 项目概述:为什么要在ESP32上跑一个Web Server?如果你手头有一块ESP32开发板,除了点灯、连Wi-Fi、采集传感器数据这些常规操作,有没有想过让它变得更“聪明”一点?比如,通过手机浏览器就能实时查看设备状…

作者头像 李华
网站建设 2026/8/19 1:22:44

无 TPM 老电脑升级 Win11:MediaCreationTool.bat 实操指南

无 TPM 老电脑升级 Win11:MediaCreationTool.bat 实操指南 【免费下载链接】MediaCreationTool.bat Universal MCT wrapper script for all Windows 10/11 versions from 1507 to 21H2! 项目地址: https://gitcode.com/gh_mirrors/me/MediaCreationTool.bat …

作者头像 李华
网站建设 2026/8/19 1:20:04

M3U8 视频下载终极指南:免费开源的 m3u8-downloader 完整下载不求人

M3U8 视频下载终极指南:免费开源的 m3u8-downloader 完整下载不求人 【免费下载链接】m3u8-downloader 一个M3U8 视频下载(M3U8 downloader)工具。跨平台: 提供windows、linux、mac三大平台可执行文件,方便直接使用。 项目地址: https://gitcode.com/gh_mirrors/…

作者头像 李华