zai-org / zai-org/feedback

# [需求] 让 MCP 工具调用超时可配置(目前硬编码 30 秒,且无法覆盖)

Open
#30 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2 status: 待评估 type: 功能建议
Dominant language
No language data
Stars
22
Forks
1
PR merge metrics
No merged PRs in 30d

Description

提交前确认 · Pre-submission checklist
  • 我已搜索过现有 issue,确认这不是重复提议 / I searched existing issues and confirmed this isn't a duplicate.
  • 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category

工具调用 / MCP · Tool use / MCP

涉及的 Agent 框架 · Agent framework

ZCode Agent(自研)

使用场景 · Use case

概述

MCP 工具的宿主端单次调用超时被硬编码为 30 秒在任何地方都无法配置,且
per-call 覆盖被显式禁用(allowCallOverride: false)。这会让一类合法但耗时长于
30 秒的 MCP 工具静默失效——全文/PDF 抽取、语义/向量检索、仓库索引等。希望能开放
可配置的超时。

环境信息

  • ZCode v3.1.2(bundle 路径:D:\Program Files\ZCode\resources\glm\zcode.cjs

复现步骤

  1. 配置 Zotero MCP server(zotero-mcp),库中放一篇长 PDF(30+ 页综述 / 书籍章节)。
  2. 让 agent 通过 zotero_get_item_fulltext 读取全文。
  3. 约 30 秒后调用被取消,提示 MCP tool … was cancelled
    • 短文档(7 页论文,约 182 KB)能在预算内返回并成功,证明 server 本身健康——
      瓶颈是上限,不是 server。

根因

zcode.cjs 反混淆后,MCP 工具注册逻辑:

// 全局默认值——纯字面量,不读取任何 env/config
qWr = 30000;

// 每个 MCP 工具
let timeoutMs = toolDescriptor.timeoutMs ?? qWr;        // (A) 宿主默认 = 30 秒
// ...
timeout: {
    defaultMs: timeoutMs,
    allowCallOverride: false                             // (B) 不允许 per-call 覆盖
},
cancellation: { supported: true, cleanup: "bestEffort" },// (C) 超时即放弃
handler: async (input, ctx) => {
    let result = await client.callTool({ ... },
        { signal: ctx.abortSignal, timeoutMs });         // (D) 30 秒在此实际生效
}
  • (A) 只要 server 未在 tool descriptor 中声明 timeoutMs,宿主就套用自己的 30 秒
    默认——而绝大多数 server(含 zotero-mcp)都不声明,所以 30 秒实际上是普遍值。
  • (B)/(D) 没有任何逃逸口;这 30 秒就是实际触发 JSON-RPC 调用中止的值。
内部不一致

同一 bundle 中的内置 web 工具拿到了 6 倍的预算:

工具类别 defaultMs allowCallOverride
内置 WebFetch 180 000 false
MCP(任意) 30 000 false

外部工具恰恰是宿主最难以预测延迟的一类——它们却拿到了最低、且不可配置的上限。

建议方案 · Proposal

建议改法

三层方案,全部向后兼容(未配置时回落到 30 秒)。任一层即可解决;三层合一则与
pi-zai-mcpZ_AI_MCP_TIMEOUT_MS 先例一致。

  1. 环境变量(一行改动):
    qWr = Number.isFinite(+process.env.ZCODE_MCP_TIMEOUT_MS)
        ? Math.max(1000, +process.env.ZCODE_MCP_TIMEOUT_MS) : 30000;
    
  2. per-server 覆盖,写在 .mcp.json
    { "mcpServers": { "zotero": { "command": "...", "timeoutMs": 120000, "env": {} } } }
    
    把它透传进 tool descriptor,让现有的 ?? qWr 自动拾取。
  3. 放开 overrideallowCallOverride: true 并设置有上限的 maxMs,让 agent 能为
    单个已知耗时的调用申请更大预算。

参考

  • 同产品家族的 pi-zai-mcp 已有 Z_AI_MCP_TIMEOUT_MS(默认 180 000 毫秒),可作为
    命名与语义的先例。
预期价值 · Expected value

No response

你认为的优先级 · Your perceived priority

高 · High

你使用的 ZCode 版本 / 环境 · ZCode version / environment

No response

补充材料 · Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by checking whether the referenced resources/glm/zcode.cjs bundle is available in this repository and locate the MCP tool registration entry point. Review how .mcp.json server settings are handled and whether tests cover tool cancellation or timeout behavior. Done means a supported timeout configuration works while the 30-second default remains unchanged when no setting is provided.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.