Skip to content

Latest commit

 

History

History
91 lines (80 loc) · 5.1 KB

File metadata and controls

91 lines (80 loc) · 5.1 KB

Investigation: x_search TIMEOUT in MCP Inspector

Summary

x_search 超时的主因是默认 30 秒超时过短(该查询实测约 49~56 秒),并且当前 chat/completions 请求未显式传 stream:false,网关默认返回 SSE 流,导致当前 JSON-only 解析路径在超时放宽后会触发“非 JSON 数据”错误。

Symptoms

  • MCP Inspector 可成功连接并 list_tools
  • 调用 x_search 后返回:TIMEOUT / 请求超时(>30000ms)
  • 用户疑问:GROK_BASE_URL 是否需要带 /v1,模型名大小写是否有问题。

Investigation Log

Phase 1 - Code path triage

Hypothesis: 工具调用链中存在固定 30 秒超时或 URL 拼接问题。
Findings:

  • src/config.ts 默认超时是 30_000
  • src/httpClient.tsAbortControllertimeoutMs 到期时中断请求。
  • src/grokClient.ts 调 chat endpoint 使用 /v1/chat/completions
  • src/tools.tsx_search 未传 stream:falseEvidence:
  • src/config.ts lines 5, 31-41
  • src/httpClient.ts lines 24-30, 72-75
  • src/grokClient.ts lines 70-72
  • src/tools.ts lines 117-136 Conclusion: Confirmed(代码层面存在 30s 硬超时 + 默认未关闭 stream)

Phase 2 - URL behavior matrix

Hypothesis: Base URL 是否含 /v1 可能导致路由错误。
Findings: 当前实现 new URL('/v1/chat/completions', baseUrl + '/') 的结果:

  • https://host -> https://host/v1/chat/completions
  • https://host/v1 -> https://host/v1/chat/completions
  • https://host/proxy -> https://host/v1/chat/completions/proxy 被丢弃)
  • https://host/proxy/v1 -> https://host/v1/chat/completions/proxy/v1 被丢弃) Evidence: runtime URL matrix script output. Conclusion:
  • 对“仅 host 或 host/v1”两种形式都可工作。
  • 但若未来 base URL 带路径前缀(如 /proxy),当前代码会丢前缀,存在潜在路由风险。

Phase 3 - Live endpoint probes

Hypothesis: 网络/鉴权/模型名问题导致超时。
Findings:

  • 无效 token 调 /v1/chat/completions 返回 401(约 7.6s),说明网络可达。
  • 有效 token + stream:false + 简单 ping 返回 200(约 20s)。
  • 有效 token + 用户查询(请总结今天宝玉发布的内容)+ stream:false 返回 200(约 49.4s)。
  • 有效 token + 用户查询 + 默认 stream(未传 stream)返回 SSE(data: chunk),总时长约 56.4s。
  • 模型名改成大写 GROK-4.20-BETA,快速返回 400 model_not_found(约 9.3s)。 Evidence: curl probes to https://api-grok-21.beta.localcan.dev/v1/chat/completions. Conclusion:
  • 超时主要不是鉴权、DNS 或模型大小写问题。
  • 主要是请求耗时 >30s;且默认 stream 行为与当前 JSON 解析模型不匹配。

Phase 4 - In-process reproduction with current code

Hypothesis: 现有 MCP 代码可稳定复现该现象。
Findings:

  • 用当前 dist 代码直接调用 x_search:30 秒稳定报 请求超时(>30000ms)
  • 将同一路径 timeout 提高到 70 秒后,转为 Grok API 返回了非 JSON 数据(对应 SSE 响应)。 Evidence: Node scripts importing dist/httpClient.js, dist/grokClient.js, dist/tools.js. Conclusion: Confirmed(与用户在 Inspector 中表现一致)

Phase 5 - Git history

Hypothesis: 最近提交引入了回归。
Findings: 当前目录不是 git 仓库,无法获取提交历史。
Evidence: fatal: not a git repositoryConclusion: Eliminated(本地无历史可查)

Root Cause

  1. 主因:超时阈值过短
    • GROK_REQUEST_TIMEOUT_MS 默认 30000ms,而目标查询实测耗时约 49~56s。
  2. 次因:chat 默认流式响应未处理
    • 当前 x_search/general_search 未显式传 stream:false
    • 网关默认返回 SSE(data: ...),而当前客户端仅按 JSON 一次性解析。
    • 所以 timeout 增大后会暴露为“非 JSON 数据”错误。
  3. 非主因(本次环境)
    • Base URL 是否含 /v1:在当前域名下两者都可用;不是本次直接原因。
    • 模型大小写:当前代码使用的小写模型名是正确的;大小写错误会快速 400,不会表现为 30s TIMEOUT。

Recommendations

  1. 立刻修复 chat 请求参数
    • x_search/general_search/video_generation 的 chat/completions 请求中显式设置 stream:false
  2. 提高默认超时并支持按工具覆盖
    • 建议默认至少 90s(或 120s)。
    • 增加 GROK_X_SEARCH_TIMEOUT_MS / GROK_GENERAL_SEARCH_TIMEOUT_MS
  3. 增强错误可观测性
    • TIMEOUT/HTTP 错误里返回 URL(去敏)、elapsed、timeout、request id(如果有)。
  4. 修复 URL 拼接鲁棒性(预防)
    • 采用相对路径拼接并处理 /v1 去重,避免 base URL 带路径前缀时被吞掉。

Preventive Measures

  • 启动日志打印(脱敏)base URL、超时、模型名。
  • 增加一个“连通性自检”工具或启动自检(可选)验证 chat endpoint 响应类型。
  • 为 chat 响应增加 content-type 检查:若 text/event-stream 则提示 stream 配置问题。