websearch-ring
Use it as a stdio MCP search server that performs resilient web searches through the web_search tool.
Search the web with a required
querystring and optionalnumResultsinteger (default 8, max 20).Automatically rotate across multiple backends (
exa,tavily,bing) with failover on failure, timeout, or rate limiting.Return titles, URLs, snippets, the serving backend, cache/coalescing status, and attempts on failure.
Benefit from keyless operation, optional API keys, bounded TTL caching, concurrent request coalescing, cancellation, and bounded upstream concurrency.
Configure vendor order, timeouts, result text limits, cache TTL/size, max inflight requests, and Bing user agent via environment variables.
Receive explicit configuration and parameter-validation errors instead of silent failures.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@websearch-ringsearch for MCP server best practices"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
websearch-ring
多后端轮询 · 自动故障转移 · Keyless 优先 的网页搜索 MCP Server。
一份 index.js,零 npm 依赖,接到任意支持 stdio MCP 的客户端即可稳定联网搜索——不绑模型、不绑厂商、不强制 API Key。
3 results for "杭州周末天气" (via exa, cached)
1. 杭州天气预报…
https://…首行标明实际来源(via exa / tavily / bing),以及是否命中缓存(, cached)或被并发合并(, shared with a concurrent call)。
为什么需要它
痛点 | websearch-ring 的做法 |
单一搜索 API 挂了 / 限流 | 按环顺序自动换下一家 |
不想管一堆 API Key | 默认 keyless 通道开箱即用 |
同样 query 被子代理打爆 | 有界 TTL 缓存 + 相同并发请求合并 |
长驻进程内存越用越多 | LRU 容量上限 + 周期清理,缓存不会无限增长 |
出站带用户标识 | 请求不携带任何用户标识 |
换模型后内置 websearch 不可用 | 独立 stdio MCP,客户端无关 |
Related MCP server: GroundRoute
特性
✅ 厂商轮盘:默认
exa → tavily → bing,失败 / 超时 / 限流自动 failover✅ Keyless 优先:可选
EXA_API_KEY/TAVILY_API_KEY提额度✅ 有界 TTL 缓存:默认 20 分钟(
WEBSEARCH_TTL_MS)+ 容量上限(WEBSEARCH_CACHE_MAX,默认 512 条,LRU 淘汰)+ 周期过期清理✅ 并发合并:相同 query 并发只打一次后端
✅ 支持取消:
notifications/cancelled会真正中止上游请求,且不写入缓存✅ 并发有界:
WEBSEARCH_MAX_INFLIGHT(默认 16)限制同时打到厂商的请求数,超出排队而非拒绝✅ 响应体限长:上游响应封顶 5MB,异常/被劫持的上游无法耗尽内存
✅ 配置严格校验:数值型变量非法时给出明确错误(变量名、收到的值、期望格式),不会被「全部厂商失败」吞掉
✅ 可审计:via 来源 + 失败 attempts + 截断标记 + stderr 上的缓存命中/容量诊断
✅ 单文件:约 870 行有效代码,无构建、无 dependencies
快速开始
1. 测试(可选)
npm test # 确定性单测:47 项,不联网,全绿才算通过
node smoke-test.mjs --offline # 离线冒烟:initialize / tools/list / 参数校验 / 取消
node smoke-test.mjs "杭州周末天气" # 完整冒烟:真联网搜索 + 缓存断言冒烟测试对每个响应做真实断言(响应 id 匹配、content[0].text 非空且格式正确、错误路径返回正确错误码、stdout 只有 JSON-RPC 帧),任何一条不满足即 exit 1 并打印原因。
关于缓存断言:测试先等第一个搜索返回,再发一个参数完全相同的请求,断言首行为 (via …, cached),并断言服务端 stderr 里 vendor … served 只出现一次(上游没有被重复访问)、出现 cache hit for …。
注意区分两个标记:同一批次(未等返回)连发相同请求走的是 inflight 合并,首行是
shared with a concurrent call;只有前一次已经返回的相同请求才会命中缓存并显示, cached。
2. 接入(两种通用方式)
路径改成你机器上的绝对路径。
方式 A — CLI(例:Claude Code)
claude mcp add websearch-ring -- node /absolute/path/to/websearch-ring/index.js方式 B — 通用 mcpServers JSON
(Claude Desktop、Cursor 等;Codex 等 TOML 客户端把同样字段改成对应格式即可)
{
"mcpServers": {
"websearch-ring": {
"command": "node",
"args": ["/absolute/path/to/websearch-ring/index.js"],
"env": {
"WEBSEARCH_VENDORS": "exa,tavily,bing",
"WEBSEARCH_TIMEOUT_MS": "12000",
"WEBSEARCH_TTL_MS": "1200000",
"WEBSEARCH_MAX_CHARS": "12000",
"WEBSEARCH_CACHE_MAX": "512"
}
}
}
}任何支持 command + args + env 的 MCP 客户端都是同一套路。
环境变量(全部可选)
变量 | 默认 | 合法范围 | 说明 |
|
|
| 轮转顺序;未知名字视为配置错误 |
|
| 整数 1–600000 | 单厂商超时 |
|
| 整数 1–10000000 | 返回文本上限 |
|
| 整数 0–2592000000 | 缓存 TTL; |
|
| 整数 1–100000 | 缓存条目上限(超出按 LRU 淘汰);默认 512 条时约 512 × 8KB ≈ 4MB |
|
| 整数 1–256 | 同时进行的厂商请求数上限;超出的查询排队等待(stderr 提示),不报错 |
| (空) | — | 空则 keyless |
| (空) | — | 空则 keyless |
| Chrome UA | 非空字符串 | Bing 抓取 UA |
数值型变量严格校验,三种情况行为确定:
未设置 / 仅空白 → 用默认值;
合法值 → 生效;
非法值(
12s、1.5、0x10、超范围、负数等)→ 回落到默认值,并且服务器在 stderr 和每一次tools/call的返回里给出明确错误,例如:
websearch-ring is misconfigured, so no search was performed. Fix the environment variable(s) below and restart the MCP server:
- WEBSEARCH_TIMEOUT_MS="12s" is not a valid number: expected an integer between 1 and 600000 (received "12s").配置错误时 initialize / tools/list / ping 仍正常工作,只是不会发起任何搜索——这样错误一定能被调用方看到,而不是伪装成「全部厂商失败」。
架构与调用流程

要点:
优先级:缓存命中 → inflight 合并 → 新跑轮转(不可颠倒)
缓存命中:不写缓存、不续 TTL;
attempts: []+cached: true直接render,并在 stderr 打印cache hit for … (entries n/max)(可观测性)仅厂商成功 时
cacheSet;合并方与全失败都不写缓存有界:超过
WEBSEARCH_CACHE_MAX按 LRU 淘汰最久未用的条目(stderr 打印淘汰日志);过期条目除了在访问时删除,还有unref()定时器(TTL/4,1–60 秒)周期清理,进程不会因此被拖住取消:
notifications/cancelled会 abort 对应请求的上游 fetch,清理 inflight 记录,不写缓存也不回包;并发合并时只有发起取消的调用方失败,其余等待方继续拿到结果;stdin 关闭时等待在途请求回包后再退出(one-shot pipe 友好)全失败:正常返回
vendor: null+attempts,仍走render,isError: true标记:
cached>coalesced(shared)> 空;有失败才出 Note 行配置错误:直接返回配置错误文本(
isError: true),不进入厂商轮转
工具接口
Tool: web_search
参数 | 类型 | 必填 | 说明 |
| string | ✅ | 搜索词,非空、去首尾空格、最长 1000 字符 |
| integer | 默认 8;非整数向下取整( |
非法输入返回明确的 JSON-RPC 错误,而不是静默替换:
情况 | 返回 |
|
|
|
|
|
|
未知 tool / 未知方法 |
|
请求体不是合法 JSON |
|
全部厂商失败 | 正常响应 + |
测试与 CI
命令 | 内容 | 是否联网 |
|
| 否,确定性 |
| 离线冒烟:协议 + 参数校验 + 取消断言 | 否 |
| 完整冒烟:真实搜索 + 缓存命中断言 | 是 |
CI 的阻塞 job 只跑前两项(离线、确定性,失败即红灯);真实联网冒烟是独立、非阻塞的 job(continue-on-error: true,也可用 workflow_dispatch 手动触发),因为 keyless 后端从 CI runner 访问经常失败,不应该决定 CI 红绿。
与同类方案的差异
最轻:单文件、零依赖
Keyless-first,可选补 Key
有界缓存 + 并发合并 + 可取消 同时具备
via / attempts 透明,配置错误不会被吞
最轻量的高可用搜索环:一份 index.js,
WEBSEARCH_VENDORS自定义的厂商顺序自动故障转移 + 有界 TTL 缓存 + 并发合并。
许可证
MIT
Available Tools
1 toolweb_searchA
Search the web. Rotates across multiple keyless search backends with automatic failover, so it stays available regardless of which chat model or provider the client uses. Returns titles, URLs and snippets, and reports which backend served the result.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (1–1000 characters) | |
| numResults | No | Number of results to return (default 8; non-integers are truncated, values are clamped to 1–20) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses keyless backends, automatic failover, that results report which backend served them, and the return shape (titles, URLs, snippets). It omits rate limits, error behavior, and latency expectations, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the action, and each sentence adds distinct information (failover, return format). The phrase 'regardless of which chat model or provider the client uses' is slightly verbose but still earns its place as availability context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by describing return values (titles, URLs, snippets, serving backend). For a simple two-parameter search tool, this is nearly complete, missing only failure/rate-limit behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are documented in the schema, including clamping and truncation behavior. The description adds nothing about the parameters beyond what the schema already states, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search the web') up front, and clarifies the scope is keyless multi-backend web search. No siblings exist to differentiate from, so this is clear if not richly detailed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no alternatives are named. The failover note implies it works broadly but does not tell an agent when this is the right tool versus some other retrieval approach.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v1.2.0- Changed
web_search2 fields changed- changed
Input schema / properties / numResults / descriptionPrevious value: -"Number of results to return (default 8, max 20)"New value: +"Number of results to return (default 8; non-integers are truncated, values are clamped to 1–20)" - changed
Input schema / properties / query / descriptionPrevious value: -"Search query"New value: +"Search query (1–1000 characters)"
1 tool update
v1.0.0- First observed
web_search
TDQS
Scored across 1 tool
There is only one tool, so there is no possibility of confusion with another tool on the server. Its purpose is clearly stated as web search with automatic backend failover.
The single tool follows a clear, conventional snake_case verb_noun pattern (web_search). With only one tool, consistency is trivially satisfied.
A single tool is thin, but the server's stated purpose—reliable web search across keyless backends—is genuinely narrow, making one tool defensible. Still, it sits at the low end of the appropriate range.
The tool returns titles, URLs and snippets, which covers basic search, but offers no pagination, filtering, or fetch/content-retrieval options. Agents needing page content or advanced query controls would hit a dead end.
Maintenance
Related MCP Connectors
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
Agent-native search engine with live web research optimized for AI agents.
Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.
The best web search for your AI Agent
Related MCP Servers
- AlicenseCqualityAmaintenanceOne endpoint, five search providers. Search broker for AI agents with automatic fallback, RRF ranking, and budget enforcement. The LiteLLM of web search.1547 PyPI7MIT
- AlicenseAqualityFmaintenanceWeb search for AI agents across 6 engines (Serper, Brave, Exa, Tavily, Firecrawl, Perplexity) through one search tool. Routes each query to the cheapest engine that clears a quality bar and caches repeats. Hosted, streamable-HTTP, BYOK supported.11MIT
- AlicenseAqualityBmaintenanceEnables AI agents to perform unified web searches, GitHub, and GitLab searches with caching, reranking, and fallback across multiple providers.4921 npm19MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to search the web and extract content using multiple search providers, with caching, retry logic, and options for JavaScript-heavy page rendering.-