keyless-web-search-mcp
keyless-web-search-mcp
独立的 MCP stdio 服务器:两个免密钥工具 —— web_search(基于自运营引擎池:Bing、360、Baidu、Google、Naver、Yandex、DuckDuckGo)和 web_fetch(匿名 HTTP(S) 页面读取器)。每次搜索最多保留两个可用引擎,按查询语言设置默认优先级,在有界的尝试预算内回填失败或无关的引擎,按相关性排序结果、合并,并按规范 URL 去重。自带完整目录,零构建步骤,不属于工具包软件包系统 —— 可随意移动。
存在的理由
工具包内置的 web_search(DeepSeek 提供商)需要 DEEPSEEK_API_KEY,并且每次查询都会发送到 DeepSeek 云端。此服务器是本地模型友好的替代方案:无需密钥、不依赖厂商搜索 API,可在中国大陆和香港网络下工作(大陆线路使用 Bing/360/Baidu,测试过的香港线路使用 Bing/360/Naver/Yandex;DuckDuckGo 在任何线路都不可达)。
web_fetch 在读取侧也有同样的理由:web 配置文件挂载了搜索提供商,但未挂载抓取提供商,因此内置的 web_fetch 工具(即使预设启用了它)每次调用都会失败并返回 WEB_PROVIDER_UNAVAILABLE。此工具通过同一免密钥服务器读取完整页面内容。
Related MCP server: web-search-mcp
运行
npm install --cache ./.npm-cache # deps: @modelcontextprotocol/sdk, zod
node index.js # speaks MCP over stdio
npm test # run deterministic ranking/fallback tests无需客户端的快速探测:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| node index.js在 Claude Code 中安装
为当前用户安装,以便每个 Claude Code 项目都能使用。注册服务器时解析两个路径;这样可以避免依赖 shell 的工作目录或 PATH:
claude mcp add --transport stdio --scope user web-search-self -- "$(command -v node)" "/absolute/path/to/keyless-web-search-mcp/index.js"
claude mcp get web-search-self改用 --scope local 可将其限制在当前项目内,或使用 --scope project 写入可共享的 .mcp.json。Claude Code 将用户/本地注册存储在 ~/.claude.json 中;MCP 服务器定义不属于 settings.json。
注册后,claude mcp list 应显示 web-search-self 已连接。工具以 mcp__web-search-self__web_search 和 mcp__web-search-self__web_fetch 的形式出现。
工具
web_search
web_search({ query, count?, maxSources?, engines? })
参数 | 默认值 | 含义 |
| — | 搜索查询,支持任何语言 |
|
| 最大合并结果数(1–20) |
|
| 每次搜索最大可用引擎数(硬上限 2;回退尝试有界) |
| 取决于查询语言 | 可选显式池,按优先级排列;省略时,中文/韩文/日文/俄文查询使用适合地区优先级的顺序 |
双源策略。 省略 engines 时,按查询语言路由引擎池:中文优先使用 360/Baidu/Bing;英文优先使用 Bing/Google/Naver/360,因此四次尝试的预算在测试过的大陆/香港网络下保留可用的回退项。显式提供的 engines 列表仍具权威性。候选引擎在受限的并行轮次中运行;只有在返回可解析结果并通过保守的词法相关性过滤后,引擎才占用一个源槽位。失败、被挑战、空结果或无关的引擎会在尝试和收集预算内回填,诊断信息显示在"引擎说明"行中。结果按查询重叠度排序,并附加轻微的来源质量调整:明显的转载/内容农场信号会被扣分,官方/文档/教育/GitHub 信号则获加分,但不会硬性屏蔽普通网站。合并仍采用轮询交错(引擎 A 的第 1 条、引擎 B 的第 1 条、A 的第 2 条……),规范 URL 去重会移除片段、常见跟踪参数和无害的 www. 差异。
结果:编号列表,包含 title [engine] / 真实目标 URL / 摘要。按引擎进行链接清理:Bing 点击跟踪链接本地解码(base64 的 u 参数);360 读取 data-mdurl 属性;Baidu 读取区块的 mu 属性(直接 URL,仅对旧式 link?url= 包装器做一次尽力而为的重定向 GET);Naver 和 Yandex 标题的锚点中带有直接 URL;Google 的 /url?q= 包装器解包;DuckDuckGo 的 /l/?uddg= 跟踪器解包。各引擎探测预算:10 秒(Bing、Baidu)、8 秒(360、Naver、Yandex)、5 秒(Google、DuckDuckGo)—— 全部并行运行,因此一轮只取决于最慢的成员。
web_fetch
web_fetch({ url, maxChars? })
参数 | 默认值 | 含义 |
| — | 绝对 |
|
| 返回的最大内容字符数(1000–100000) |
匿名公共网络读取,无需凭据:浏览器 User-Agent,最多五次重定向,涵盖请求头和响应体的 20 秒总时限,响应体精确截断在 5 MB。每个初始目标和重定向目标在 DNS 解析后都会检查;回环、私网、链路本地、运营商级 NAT、保留地址、组播地址以及本地主机名都会被拒绝,以防 SSRF 进入本机或云元数据服务。HTML 被剥离为可见文本(script/style/noscript/svg/head/iframe/canvas/form 被丢弃,块边界转换为换行符,<title> 放在头部中);文本型、JSON 和 XML 内容按其声明的字符集进行实体解码后原样输出,而二进制媒体类型会被拒绝。输出先是状态头部 —— status、最终 url、content-type、截断标志 —— 然后是内容。非 2xx 响应返回状态头部和一条说明(403/429 视为机器人检测或限流),不会伪造页面。
引擎及其状态
在三条线路上验证(一条较早的大陆线路、一条上海电信线路和一条香港数据中心线路):
引擎 | 端点 | 来自这些网络的状态 |
|
| ✅ 两条线路上均有约 10 个自然结果块。取决于线路, |
|
| ✅ 干净的 200;自然结果块在 |
|
| 可达(200),但此客户端/IP 不被信任用于纯 HTML SERP:响应体是无 JS 的 |
|
| ✅ 在上海和香港线路上:风险控制会拦截脚本形态的请求(仅 UA 的 302 到 |
|
| ✅ 在香港线路上(200,约 10 个 |
|
| ✅ 在香港线路上:与百度相同的导航签名教训——脚本形态的请求会收到 SmartCaptcha“不是机器人”复选框,但完整的文档导航头集合加上主页的 cookie 会话(yandexuid 等)会获得纯 HTML SERP(约 50 个 |
|
| ❌ 在所有三条测试线路上 TCP 不可达(包括香港);在可用的网络上作为最后手段引擎 |
刻意不在池中:搜狗——302 到 sogou.com/antispider/,与百度覆盖的 IP 墙同类。还从香港线路扫描并拒绝:Mojeek(提供验证码页面)、Ecosia(403“Ecosia 防火墙”)、MetaGer(重定向到非结果页面)、以及 Yahoo/Brave/Qwant/Startpage/goo.ne.jp(从大陆和香港线路均 TCP 不可达)。
Google 墙:尝试了什么
来自此 IP 的 200 响应不是封锁,而是 JS 挑战拦截页(约 90 KB 的混淆/加密 JavaScript;无 JS 路径是 meta-refresh 进入死胡同)。这堵墙实际上是两层:
JS 挑战(计算型)——解码后,它计算一个证明值并设置
SG_SScookie(5 分钟过期),然后重新加载。这一层可以在浏览器之外解决:在普通 Node.js 中运行页面脚本,配合轻量 DOM 垫片(cookie jar、navigator、Image、document)完成计算,生成的SG_SScookie 被接受了一次——Google 返回 200 并颁发了它通常不会向此 IP 发送的NID/AEC信任 cookie。会话模式层(行为型)——后续的纯 HTTP 跟进,包括脚本自身重载流程的精确副本(
emsg=SG_REL+ 匹配的sei、jar 合并的 cookie、浏览器头),升级到google.com/sorry429 异常墙。这一层判断整个会话(TLS/HTTP2 指纹、请求节奏、方法混合),Node 的 OpenSSL/undici 栈无法匹配。
已测试且未改变第 1 层答案的客户端杠杆:gbv=1 参数、cookie 预热、完整浏览器指纹头、retry/enablejs 流程、/m 入口、文本浏览器/功能手机/IE6/旧 Android UA、伪造的 Googlebot UA(Google 会验证)、CONSENT cookie、POST 提交(405)、备用 TLD,以及不带 cookie 的“点击此处”emsg=SG_REL 链接。Google 代理替代方案在此网络上也不可达或被墙:Startpage 和 Qwant 超时,Mojeek 提供验证码页面,Ecosia 403。
结论:第 1 层可用 Node 解决(已证明);第 2 层无法从非浏览器网络栈解决。从这台机器访问 Google 的唯一可靠路径是干净 IP 代理或真实浏览器上下文(无头 Chromium);两者都处于爬虫无法诚实绕过的 IP/流量模式层,且反复探测有延长 IP 异常窗口的风险——因此此服务器不尝试它们。Google 保持为后备引擎,在能提供纯 HTML SERP 的网络上激活。
挂载到 DeepSeek Harness
添加到你的 cordis.yml(MCP 桥会热重载此条目):
- id: mcp-search
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: search
transport: stdio
command: node
args: ['/absolute/path/to/keyless-web-search-mcp/index.js']模型随后将工具视为 mcp__search__web_search 和 mcp__search__web_fetch。
限制
搜索质量是启发式的:词汇相关性处理明显的离题结果和中文 n-gram;内部搜索引擎页面被排除;内容农场/转载信号仅调整排序,而非普遍信任判断。相关结果并不证明其声明正确——请获取并交叉核对重要事实。
抓取而非 API:布局变化可能破坏解析器;失败是明显的(“无可解析的自然结果”),绝不会伪造。Google 和 DuckDuckGo 解析器是根据文档化的 SERP 结构编写的,无法从该网络实时验证——在它们实际应答时首次调整。
速率控制:两个公共引擎容忍随意使用;滥用会招致机器人挑战。
查询离开机器,发送给被咨询的引擎(这是无密钥搜索的代价);在双源上限下,每次搜索最多有两个引擎看到查询。
Fetch 是无密钥的公共页面读取器,而非浏览器或内网客户端:JS 渲染的内容对它不可见(与搜索解析器同类的限制);对匿名客户端返回 403/429 的页面会被报告,而非绕过。本地/私有/保留网络目标被刻意阻止,包括重定向目标。
Available Tools
2 toolsweb_fetchWeb Fetch (keyless anonymous HTTP(S) reader)A
Fetch one HTTP(S) URL anonymously and return the page as readable text: HTML is stripped to visible text with block structure preserved; text/markdown/JSON/XML pass through decoded. No credentials: browser User-Agent, up to five validated redirects, bounded output. Local, private, link-local, and reserved network targets are blocked, including after DNS resolution and redirects. The result is a status header (status code, final URL, content-type, truncation) followed by the content. Use it to read full page content for a URL, e.g. one found by web_search.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL to fetch. | |
| maxChars | No | Maximum content characters to return (default 20000, hard cap 100000). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full responsibility. It discloses anonymous access, no credentials, browser User-Agent, redirect limits, target blocking, and truncation behavior, which is strong transparency for a network tool.
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 purposeful sentences: main behavior, safety boundaries, and output/usage context. No filler, no redundant schema echoing, and key constraints are front-loaded.
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?
With no output schema or annotations, the description still explains output format, status header components, redirects, target restrictions, and content conversion. This is an unusually complete one-paragraph contract for a fetch tool.
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?
The schema already clearly documents both parameters at 100% coverage, with maxChars including a default and limits. The description affirms bounded output but does not add substantial meaning about parameter formats beyond the schema.
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, resource, and output: fetches one HTTP(S) URL and returns readable text. It also references web_search, making the distinction between search and fetch explicit without ambiguity.
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?
Description explicitly says to use it to read page content for a URL and gives a web_search output as an example, naming the sibling tool. It does not explicitly state when not to use it, so it stops short of a full when/when-not map.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
web_searchWeb Search (self pool: Bing / 360 / Baidu / Google / Naver / Yandex / DuckDuckGo)A
Search the web without any API key from a self-operated pool: Bing, 360, Baidu, Google, Naver, Yandex, and DuckDuckGo. Each search keeps at most two usable engines — the pool is routed by query language when no explicit pool is given, failed or irrelevant engines are back-filled within a bounded attempt budget, and results are relevance-ranked, quality-adjusted, and deduplicated by canonical URL. Each result includes a title, the real destination URL, a snippet, and its engine. Engines unreachable from the local network, or walled by captcha/JS/bot checks, are skipped and reported in an engine note; the remaining engines still answer.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Maximum merged results to return (default 8). | |
| query | Yes | Search query in any language. | |
| engines | No | Optional explicit engine pool in priority order; omitted uses query-language routing. | |
| maxSources | No | Maximum usable engines per search (default 2, hard cap 2; fallback attempts are bounded). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly discloses behavioral details: no API key needed, engine pool self-operated, at most two usable engines, back-fill on failures, relevance/quality ranking, deduplication, skipping unreachable or walled engines, and reporting an engine note. This exceeds the baseline and compensates for the absence of annotations. No contradiction with annotations since none are provided.
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?
The description is concise and front-loaded with the primary purpose (search the web without API key) and then provides relevant behavioral details in a structured manner. Each sentence adds value; it is not overly verbose. Slight redundancy with the engines list in the title but overall well-structured.
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?
The description covers key aspects: purpose, engine selection, failure handling, result format, and edge cases (captcha/JS/bot walls). No output schema exists, but the description mentions what each result includes (title, URL, snippet, engine), which partially compensates. The absence of annotations is mitigated by the detailed description. Minor gaps remain about the return structure of the full response, but the information is sufficient for an agent to invoke the tool correctly.
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?
The input schema already has complete (100% coverage) descriptions for all four parameters: count, query, engines, and maxSources. The description adds contextual insight on routing by query language and back-fill behavior but does not add substantial new parameter semantics beyond what the schema provides. Per the guideline, high schema coverage means baseline 3 is appropriate.
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?
The description clearly states the tool performs a web search using a self-operated engine pool, listing the supported engines and the result characteristics (title, URL, snippet, engine). It does not explicitly contrast with the sibling tool web_fetch, but the purpose is distinct and clear.
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?
The description explains how the engine pool is selected (query-language routing when no explicit pool), how failures are handled (back-filling, bounded attempts), and how results are ranked and deduplicated. It does not explicitly state 'when to use' versus 'when not to use' but provides contextual routing guidance. The sibling tool web_fetch is not referenced, so no alternative routing is mentioned.
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.
2 tool updates
v1.1.0- First observed
web_fetch - First observed
web_search
TDQS
Scored across 2 tools
The two tools are completely distinct: web_search performs web searches across multiple engines, while web_fetch retrieves the content of a specific URL. There is no overlap or ambiguity between them.
Both tool names follow the same verb_noun pattern: web_search and web_fetch. The naming is clear, consistent, and predictable.
The server has only two tools, which is slightly below the typical well-scoped range of 3-15. However, each tool is essential and covers the core functionality of keyless web search and fetching, so the count is reasonable for the narrow scope.
The tool surface fully covers the stated purpose of keyless web search: web_search finds relevant results and web_fetch retrieves full page content. There are no obvious missing operations for this domain.
Maintenance
Related MCP Connectors
Google, Bing, DuckDuckGo and Google Maps search results, free without an API key.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Keyless web, GitHub, YouTube and Reddit search and read. Delegated shop, booking and signup.
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables web search without API keys using DuckDuckGo and Bing search engines, and retrieves webpage content. Supports multiple search engines simultaneously with privacy protection and asynchronous processing.263 PyPI10MIT
- FlicenseNot gradedqualityDmaintenanceProvides free web search, content fetching, image search, and deep research via SearXNG, no API keys required.-
- AlicenseAqualityCmaintenanceEnables keyless multi-engine web, news, image, and video metasearch plus full-page markdown extraction for AI agents over MCP, with resilient fallback across DuckDuckGo, Bing, Brave, Google, and other backends.6MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to perform free web search and read web pages as markdown without paid APIs, Docker, or a background service, by querying multiple free search engines in parallel with optional fallbacks and extracting clean page content. Also supports fetching a site's llms.txt documentation files.MIT