简短回答
MCP 工具调用超时时,你无法判断改动有没有发生。你的 AI 可能只是丢了回复,工作本身未必丢失。重试之前先检查:去工具里找它想要做出的东西。只有找不到时才重试。绝不要自行重新发送消息。
本文内容
为什么超时不能告诉你改动有没有发生?
你的 AI 请工具做一项改动,然后一直等。没有回复,于是你的 AI 应用停止等待,并报告了失败。这个标签描述的是等待,不是改动。如果重试一项已经完成的改动,你就会得到两张工单、两个页面或两条消息。
开发者把这类改动称为“写入”。可能发生了三种情况。
| 发生了什么 | 工具里有这项改动吗? | 如果重试 |
|---|---|---|
| 请求从未到达。 | 没有。 | 这样做是对的:改动只会做一次。 |
| 工具仍在运行。 | 还没有。它会在你的 AI 放弃之后才出现。 | 改动会被做两次,除非重复它本来就无害。 |
| 工具已经完成,但回复丢失了。 | 有。 | 改动会被做两次,除非重复它本来就无害。 |
MCP 规范预料到了这种情况。客户端应当为每个请求设置超时;超时之后,取消请求,并停止等待。取消并不能保证什么。服务器可能在工作已经完成或无法中止时忽略取消请求。取消请求也可能在回复已经发出之后才到达。
Stripe 的 API 指南也这样说:连接失败之后,你可能不知道请求有没有执行。它还告诉你,服务器错误同样视为结果未知。
超时之后,按什么顺序做?
按顺序做这些。前两步只需一分钟。
- 先停止重试现在
告诉你的 AI 不要重复调用:“先别重试,先查一下它有没有做成。” 光靠重试,改动就会被做两次。
- 去工具里查看,而不是在聊天里查1 分钟
打开工具本身:Notion 页面、GitHub 议题、那个文件夹。搜索你要求的标题或 id。聊天只知道调用失败了。
- 读一读你找到的内容2 分钟
找到了,并且完整:改动已经完成。继续往下做,不要重复。
找到了,但只完成了一半:用一次更新补上缺的部分,而不是再新建一次。
没有找到:它可能从未到达,也可能还在运行。等一分钟,再看一次。 - 只对安全的调用,重试一次然后
如果仍然找不到,重试一次。下表列出了哪些调用可以安全地重复。发送之前,先看它会送到哪里。
- 如果一直超时,就解决根源之后
总是超时的调用,要么是时限太短,要么是任务太大。提高该服务器的时限,或者让每次调用的工作量少一些。
哪些调用可以安全地重试?
当调用两次和调用一次的结果相同时,这个调用就可以安全地重试。读取符合这一条,许多改动则不符合。HTTP 标准把 PUT(设置一个值)和 DELETE 视为可以安全重复,下表遵循这一标准。工具自己的 idempotentHint 或描述,优先于这些规则。
| 调用 | 能原样重试吗? | 先检查什么 |
|---|---|---|
| 读取:搜索、列出、打开 | 能。它不改动任何东西。 | 没有需要检查的。 |
| 设置一个值:状态、标题、标签 | 通常可以。把同一个值设置两次,结果相同,就像 HTTP PUT 一样。 | 读取这个字段。如果之后有人改过它,重试会覆盖他们的修改。 |
| 向某物添加:评论、行、一行内容 | 不能。添加两次,就会添加两份。 | 打开该项,查找你添加的内容。 |
| 创建:页面、议题、文件 | 不能。重试会再创建一个。 | 按你给的标题或 id 搜索。只有在没有任何匹配时才重试。 |
| 删除 | 通常可以,前提是它指向一个确切的项目,与 HTTP DELETE 一样。不是“最新的那个”:第二次调用会打到另一个项目。 | 查找这个项目。找不到,就说明已经完成。 |
| 发送:消息、电子邮件、通知 | 绝不自行重试。发送之后无法收回。 | 看它最终落在哪里:已发送列表、频道或对方那边。如果无法判断,在再次发送之前先问一下。 |
幂等键能防止重复吗?
有时可以。幂等键是随请求一起发送的唯一标签。如果同一个标签到达两次,服务只做一次工作,并重复返回第一次的结果。它是为那些没有收到回复的请求设计的。
- 幂等键在 Stripe 上的工作方式。 它的 v1 API 在
POST请求上接受一个键。它会保存第一次的结果,即使是错误,并在用同一个键重试时再次返回。它至少保留键 24 小时。同一个键搭配不同的参数,会被拒绝。 - 重试时必须做什么。 发送同一个键和同样的参数。Stripe 说,在你知道第一次的结果之前,不要换一个新键重试。每次尝试都换新键,起不到任何保护作用。
- MCP 提供了什么。 一个
tools/call请求携带工具名和它的参数。规范的模式没有为它定义幂等键。不过工具仍然可以把它当作自己的一个参数来接收,所以要读一读它的参数。 - 工具可以声明什么。
idempotentHint表示,用同样的参数再次调用这个工具,不会产生额外的效果。它只是一个提示。规范说,客户端绝不应该依据不可信服务器给出的提示做决定。
所以,幂等键是额外的好处,而不是计划。工具没有提供时,上面的检查才能保护你。
怎样修改 MCP 超时时限?
时限太短,会切断本来正常的工作;太长,你又要一直等。在哪里设置,取决于你的 AI 应用。下面是 Claude Code 的设置。
| 设置 | 限制什么 | 默认值 |
|---|---|---|
MCP_TOOL_TIMEOUT | 一次工具调用最多可以运行多久,单位是毫秒。 | 100,000,000 ms,约 28 小时 |
.mcp.json 里的 timeout | 同上,但只针对一个服务器。它会为该服务器覆盖这个变量。这是硬性时限:进度通知不会延长它。 | 变量的值 |
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT | 一次调用在没有回复、也没有进度的情况下,最多可以沉默多久,超过就中止。设为 0 则关闭这项检查。 | 网络服务器 5 分钟,stdio 服务器 30 分钟 |
MCP_TIMEOUT | 启动服务器的时限。对于远程服务器,它也计入下面的单次请求计时器。 | 30,000 ms,即 30 秒 |
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS | 在主对话中仍在运行的调用,何时转入后台任务。设为 0 则关闭。需要版本 2.1.212 或更高。 | 120,000 ms,即 2 分钟 |
远程服务器默认的 60 秒。通过 HTTP、SSE 或作为 claude.ai 连接器访问的服务器,还有第二个计时器。它在每个请求上运行,直到服务器返回第一个字节为止。除非 MCP_TOOL_TIMEOUT、服务器的 timeout 或 MCP_TIMEOUT 被设得更高,它就是 60 秒。本地 stdio 服务器没有单次请求计时器。
要为某一个服务器设置,就在它在 .mcp.json 里的条目中加上 "timeout": 600000。这相当于 10 分钟。
慢的调用不一定是失败的调用。从 2.1.212 版本起,Claude Code 会在两分钟后,把主对话里的 MCP 调用转入后台任务。调用结束时,它会交付结果。
Cursor 的 MCP 文档没有描述超时设置。MCP 规范没有给出具体的数字。它说,SDK 应当允许你按请求配置超时,而客户端应当始终保留一个最大值。
对于需要几分钟的工作,服务器可以使用 MCP Tasks。它立即返回一个句柄,客户端则轮询结果,即使在重新连接之后也一样。两端都必须支持它,而客户端的支持各不相同。
回复丢失时,Delta MCP 会做什么?
Delta MCP 是你电脑上的一款免费应用,位于你的 AI 和它的工具之间。当一项改动得不到回复时,它不猜,也不只是重试。它会去读工具。
改动发出之前,Delta MCP 会先选一个能看出它是否已经发生的读取。这个读取是再次读取同一对象,或再次读取一个列表。没有回复时,它立即执行这个读取。读取的结果决定下一步:
| 读取显示 | Delta MCP 做什么 |
|---|---|
| 改动已经完成。 | 任务继续进行,回复会说明它已被核对。 |
| 改动没有完成。 | 它会用同样的参数再发送一次改动。对于消息或其他发送,它从不自行这样做。对于这些,回复会说明它没有被看到、它可能还会出现,任务随之停止。 |
| 不清楚,或者无法读取任何内容来判断。 | 回复会写明结果未知,并说明原因。任务停止。在再次做这项改动之前,先看看工具里的情况。 |
按原样调用的工具,Delta MCP 无法回滚。如果较早的调用已经成功,它会保持已完成的状态,回复会把它列出来,免得你的 AI 再做一遍。每个改动了内容的任务,都保存在 Activity 里,附带每处改动的前后对比。
常见问题
超时后重试 MCP 工具调用安全吗?
读取是安全的。改动在核对之前不安全。超时只说明没有收到回复:工具可能仍然做出了改动。去工具里找找看,只有确认它不存在时才重试。绝不要自行重新发送消息。
MCP 请求超时了,我的写入有没有成功?
只看超时,你无法判断。请求可能从未到达,工具可能仍在运行,也可能已经完成而回复丢失了。打开工具,查找这项改动。
在 Claude Code 里,怎样增加 MCP 工具超时时间?
用毫秒设置 MCP_TOOL_TIMEOUT,或者在 .mcp.json 里该服务器的条目中添加一个 timeout 字段。对于远程服务器,把它设为 60,000 以上,就能解除那个 60 秒的单次请求计时器。MCP_TIMEOUT 是启动的等待时间,不是工具调用的时限。
在 Cursor 里怎样修改 MCP 超时时间?
Cursor 的 MCP 文档没有描述超时设置。它说,失败的调用会在聊天里标为失败,你可以重试,或查看日志。先检查工具里已经有了什么。
MCP 有幂等键吗?
没有。工具调用携带的是工具名和参数,规范的模式没有为它定义幂等键。工具可以把一个键当作它自己的参数来接收。它也可以设置 idempotentHint,但那只是提示。
工具调用得不到回复时,Delta MCP 会做什么?
它立即读取工具,看改动有没有发生。已完成:任务继续。未完成:它会再发送一次改动。消息或其他发送,绝不会自行再次发送。不清楚:回复会写明结果未知,任务停止。
来源
- Model Context Protocol, Cancellation 客户端应当设置超时、取消请求并停止等待;取消可能在工作完成之后才到达(修订版 2026-07-28)。
- Model Context Protocol, Schema Reference 工具调用携带名称和参数,没有幂等键;idempotentHint 注解,而注解只是提示(修订版 2026-07-28)。
- Model Context Protocol, Tasks 长时间操作的持久句柄,重新连接后仍可轮询并取回结果;两端都必须主动启用。
- Claude Code, Connect Claude Code to tools via MCP 每个服务器的超时、远程服务器 60 秒的单次请求计时器、空闲窗口,以及两分钟后转入后台。
- Claude Code, Environment variables MCP_TOOL_TIMEOUT、MCP_TIMEOUT、CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT 和 CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS,及其默认值。
- Cursor, Model Context Protocol (MCP) 失败的 MCP 调用会在聊天里标为失败;重试或查看日志;文中没有描述超时设置。
- Stripe, Idempotent requests 幂等键如何工作:保存第一次的结果并再次返回;键至少保留 24 小时;其他参数会被拒绝。
- Stripe, Advanced error handling 连接失败之后,你可能不知道请求有没有执行;服务器错误即结果未知;结果未知之前,不换新键。
- IETF, RFC 9110: HTTP Semantics 幂等的方法(安全方法、PUT 和 DELETE),以及除非能确定第一次从未生效,否则不重试非幂等请求。
- Delta MCP, Writing a task 改动得不到回复时 Delta MCP 的做法:已完成、未完成或结果未知;发送不会自行再次发送。
- Delta MCP, Activity and Undo 每个改动了内容的任务都保存在 Activity 中,附带每处改动的前后对比。