feat: 接入 Tavily web_search MCP 工具替代失效的内置 WebSearch#260
Merged
Conversation
内置 WebSearch 是 Anthropic 服务端工具,当服务通过 ANTHROPIC_BASE_URL 走代理/网关(如 litellm)时网关不实现该工具导致其失效。新增的 web_search 作为客户端 MCP 工具在本进程内通过 Tavily API 执行 HTTP 请求,不依赖上游网关。 - src/websearch/tool.ts: web_search 工具 + createWebSearchMcpServer 工厂 + 纯函数 formatTavilyResponse - src/config.ts: config.websearch(配了 TAVILY_API_KEY 即自动启用) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
config.websearch.enabled 且配置了 apiKey 时注册 web-search MCP server; canUseTool 在 readOnly 模式下放行 mcp__web-search__ 工具(联网搜索为只读操作)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
覆盖成功/无结果/缺 key/HTTP 401·429·500/网络错误/超时/max_results 边界/ config 默认值回退/格式化纯函数;executor.test.ts 补充 websearch config mock。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
review 发现的两处低危问题: - 非数字的 WEBSEARCH_TIMEOUT_MS/WEBSEARCH_MAX_RESULTS 会得到 NaN, setTimeout(fn, NaN) 被强转为 0 立即触发,导致每次搜索秒超时。 新增 parsePositiveInt 守卫,非正整数回退默认值。 - Tavily 非 2xx 错误的完整 body 改为只写服务端日志(截断 500 字), 返回聊天的提示仍由 describeHttpError 截断到 200 字。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
enabled 改为以 key 为前提:未配 TAVILY_API_KEY 时即使 WEBSEARCH_ENABLED=true 也保持禁用。配了 key 后默认启用,WEBSEARCH_ENABLED 仅作为已配 key 情况下的 显式开/关覆盖。补充对应回归测试。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
|
Claude finished @lishuceo's task in 1m 34s —— View job Code Review — Tavily web_search MCP 工具
✅ Approved整体实现干净、测试充分,符合仓库约定。MCP 工具在客户端进程内发请求绕开上游网关的思路正确,按 per-query 模式注册、readOnly 放行联网搜索都沿用了 feishu/memory/cron 的既有先例。 做得好的点
两点非阻塞观察(confidence < 75,无需改动)
无需阻塞合并的问题。PR 质量良好。 ✅ |
Contributor
|
Claude finished @lishuceo's task in 1m 38s —— View job Code Review — Tavily web_search MCP 工具
✅ Approved本次为 PR synchronize 后的复审。自上一次 approve 以来唯一的新提交是 复核要点(均已满足)
非阻塞观察(confidence < 75,无需改动,沿用上轮结论)
PR 质量良好,可以合并。 ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

背景
anycode 通过
ANTHROPIC_BASE_URL走代理/网关(如 litellm)时,Claude Code 内置的WebSearch失效——因为它是 Anthropic 服务端工具,网关并不实现它。本 PR 新增一个客户端 MCP 工具web_search,在本进程内通过 Tavily Search API 发 HTTP 请求,绕开上游网关。改动
src/websearch/tool.ts(新)—web_search工具:POST https://api.tavily.com/search(Bearer 鉴权),返回标题/URL/摘要片段 + 可选综合答案。含纯函数formatTavilyResponse、HTTP 错误映射、AbortController 超时。src/config.ts— 新增config.websearch:配了TAVILY_API_KEY即自动启用(WEBSEARCH_ENABLED可显式覆盖)。新增parsePositiveInt守卫,非数字配置回退默认值。src/claude/executor.ts— 启用时按 per-query 模式注册web-searchMCP server;readOnly 模式放行mcp__web-search__(联网搜索为只读操作,沿用 feishu/memory/cron 先例)。.env.example— 文档化TAVILY_API_KEY等配置项。测试
src/websearch/__tests__/tool.test.ts(14 例):成功/无结果/缺 key/HTTP 401·429·500/网络错误/超时/max_results边界/config 默认值回退/格式化纯函数。src/__tests__/config.test.ts补充parsePositiveInt+ websearch 自动启用逻辑回归。npx vitest run:1462 通过;唯一失败的memory/quality.test.ts语义检索断言在干净 base 上同样失败,与本 PR 无关(预存在)。npm run typecheck通过。Review
经多 agent 对抗式 review(correctness / security / convention 三维 + 逐条对抗验证),确认 5 条均为低危:
WEBSEARCH_TIMEOUT_MS→NaN→setTimeout(fn, NaN)秒触发超时(parsePositiveInt守卫)。启用方式
在服务部署目录
.env配置TAVILY_API_KEY=tvly-xxx(https://app.tavily.com 获取),重启服务即可。🤖 Generated with Claude Code