Skip to main content
Glama
kybll-cn

search-aggregation

by kybll-cn

ZCode Search Aggregation

ZCode 的多引擎并行搜索插件。一次调用同时查询 百度、必应、360、搜狗、GitHub、Google、Yahoo、DuckDuckGo,把结果汇总、跨引擎去重后交给模型;外网不可达时自动降级为只用大陆搜索引擎。

零依赖:只用 Node 内置模块,不需要 npm install。


特性

  • 真并行:八个引擎同时发起请求,总耗时约等于最慢的那一个,而不是八个串行相加。

  • 自动降级:境外引擎(Google / Yahoo / DuckDuckGo)一旦因网络不可达失败,会被记入"近期不可达"并跳过;后续检索不再重复等超时。

  • 代理自动发现:默认探测本机常见的代理端口(Clash 7897/7890、v2rayN 10809 等),探测不到就全部直连,无需手填配置。

  • 跨引擎去重:同一个 URL 只保留首次命中的那条,重复条数单独记录。

  • 诚实报错:被验证码、限流或反爬空壳页拦住时,明确说明是哪家、什么原因,不会静默返回 0 条让模型以为"网上没有"。

  • 两种呈现:按引擎分组(便于对比来源)或交错混排(便于通读)。

Related MCP server: websearch-ring

安装

通过插件市场

把本仓库根目录(marketplace.json 所在目录)作为插件市场添加:

插件市场 → 添加 → 添加插件市场,粘贴仓库绝对路径,然后 个人 → dev-zcode-plugins → 搜索聚合 → 安装。

手动配置 MCP

把 mcp/server.mjs 挂到任意 ZCode 配置的 mcpServers 下:

{
  "mcpServers": {
    "search-aggregation": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/ZCode-Search-Aggregation/mcp/server.mjs"],
      "env": { "SEARCH_PROXY": "auto", "SEARCH_TIMEOUT": "15000" },
      "timeoutMs": 120000
    }
  }
}

要求 Node 18+。装了插件市场后 .mcp.json 会用 command: "node" 启动,因此 node 需要在 PATH 里。

如果机器上没有全局 node,可以借 ZCode 自带的运行时(官方插件用的就是这个方式),把 command/args 换成:

{
  "command": "<ZCode 安装目录>/ZCode.exe",
  "args": [
    "<ZCode 安装目录>/resources/glm/zcode.cjs",
    "__zcode-plugin-host",
    "/absolute/path/to/ZCode-Search-Aggregation/mcp/server.mjs"
  ],
  "env": { "ELECTRON_RUN_AS_NODE": "1" },
  "timeoutMs": 120000
}

使用

模型侧的工具是 web_search:

web_search(query: "zcode 插件", limit: 5)
web_search(query: "react 19 新特性", engines: ["baidu", "bing"], mode: "interleave")
web_search(query: "python asyncio", force: true)     # 网络恢复后强制重试全部引擎

参数

默认

说明

query

必填

关键词,中英文皆可

engines

自动

指定引擎;默认选当前可达的全部

limit

5

每个引擎返回条数(1–20)

mode

group

group 按引擎分组;interleave 交错混排

force

false

忽略"近期不可达"缓存,强制重试

辅助工具 search_engines:查看各引擎可达状态;probe: true 时实际发探测请求,用来确认外网或代理是否通。

配套 /search <关键词> 命令,以及 search-aggregation 技能(模型在需要联网检索时会自动参考)。

各引擎是怎么抓的

所有解析规则都是按实测抓到的真实页面结构写的(样本存于 tests/fixtures/),不是照文档或记忆写的正则。各家的取数方式并不一样:

引擎

区域

实现方式

百度

直连

抓搜索结果页,从结果容器的 mu 属性取真实 URL(页面上可见的 baidu.com/link?url= 是跳转链,不含目标地址),标题取 h3。

必应

直连

走 www.bing.com 的 format=rss 官方结构化输出,直接拿到标题/URL/摘要,比抓 HTML 稳得多。

360搜索

直连

限定在结果列表 <ul class="result"> 内解析,用 data-mdurl 属性还原真实 URL(否则会把顶部导航的链接当结果)。

搜狗

直连

先取一次首页拿 Cookie 再检索;结果里的 /link?url= 是只含 JS 跳转的壳页,插件会并发把这几个壳页换回真实地址。

GitHub

直连/代理

走官方 Search API(仓库搜索),JSON 直读,不解析 HTML。

Google

需代理

网页版对无 JS 请求只返回"请升级浏览器"壳页面,稳定可用的是 Google 新闻的 RSS 检索——所以 Google 这一路给的是新闻条目,不是普通网页结果。

Yahoo

需代理

先回 307 到 beacon 并下发 Cookie,带 Cookie 重放才给结果;真实地址藏在 r.search.yahoo.com/.../RU=<编码地址>/RK= 里,会解码还原;广告位用 data-matarget="ad" 排除。

DuckDuckGo

需代理

必须带完整浏览器指纹头(Sec-Fetch-*、Sec-CH-UA 等),否则拿到的是 202 空壳页;结果链接的 uddg= 参数解出真实地址。

为什么必应要特意用 www 而不是 cn:实测 cn.bing.com 在本机网络下会返回与查询完全无关的降级内容(查 "zcode 插件" 却给出车牌号、儿歌),www.bing.com 才返回正确结果。这是踩过的坑,写在代码注释里了。

外网不可达时的行为

这是插件的核心设计之一,实测数据:

=== 第一次查询(代理关闭,境外引擎会超时)===
耗时 6.0s
成功: baidu, bing, so360, github
失败: google(connect timeout), yahoo(connect timeout), duckduckgo(connect timeout)

=== 第二次查询(跳过不可达引擎)===
耗时 0.9s
被跳过: google, yahoo, duckduckgo

机制:每个引擎的可达性带缓存。因网络原因失败(超时、连不上、5xx)标记为不可达并跳过,5 分钟后自动再试;被反爬拦截(验证码、安全验证)则冷却 15 分钟——因为 5 分钟就回去重试只会继续触发风控、反而拖长封禁。网络恢复时也可以直接 force: true 立即重试全部。

注意区分两类失败:网络不可达记为不可用并跳过;HTTP 正常但解析不出结果不记为网络问题(那多半是站点改版或关键词太窄),会照常重试。

已知限制(诚实地列出来)

  • 密集检索会被限流,这是所有抓取式搜索的通病。实测连续快速跑多轮测试后,搜狗会甩出验证码页、百度会要求安全验证、Yahoo 会回 500;正常使用频率(偶尔搜几次)下各家都稳定。插件遇到这类拦截会明确报出是哪家、什么原因并临时跳过它,不会静默返回"0 条结果"让模型误以为网上没有资料。

  • Google 只有新闻。网页搜索需要 JS,纯 HTTP 抓不到;Google 这一路给的是新闻条目,链接是 news.google.com 的跳转地址(在浏览器里能正常打开原文,但 URL 本身不是原文地址)。

  • 搜狗结果里的 /link?url= 需要在浏览器打开才跳转:插件会并发把它换成真实地址,少数换不出来的会保留原跳转链接。

  • GitHub 搜的是仓库,不是代码内容,且未认证 API 限速 10 次/分钟。

  • 站点改版会让解析失效。某个引擎持续返回 0 条但状态可达,通常意味着它的页面结构变了,需要按新结构更新 mcp/engines.mjs 里的解析器。

  • 结果质量受引擎本身影响:冷门或含歧义的关键词,引擎可能返回不相关内容,使用时应核对标题与摘要是否对题。

项目结构

.zcode-plugin/plugin.json   插件清单(含 userConfig:代理、超时)
.mcp.json                   MCP server 注册
mcp/http.mjs                零依赖 HTTP 客户端(直连/代理隧道、gzip、重定向、Cookie)
mcp/engines.mjs             八个引擎的定义、解析器、跳转链接还原
mcp/aggregator.mjs          并行调度、代理发现、可达性缓存、去重
mcp/server.mjs              MCP 协议层与工具定义
skills/                     技能说明(给模型的使用指引)
commands/search.md          /search 命令
tests/                      真实网络测试与页面样本

开发与测试

# HTTP 层单元测试:本地起服务器,验证 gzip/chunked/重定向/Cookie/超时,不依赖外网
node tests/test-http.mjs

# 引擎级:逐引擎真实查询,打印提取到的标题与 URL
node tests/test-engines.mjs "查询词"

# 稳定性:多查询词跑全部引擎,统计成功率
node tests/test-stability.mjs

# 降级:验证无外网时只用大陆引擎,且第二次查询会跳过不可达引擎
node tests/test-offline-fallback.mjs

# 端到端:真的把 server 当子进程启动,走 JSON-RPC 全流程
node tests/test-mcp.mjs

# 重新抓取各引擎真实响应,存到 tests/fixtures/(改解析器前先跑这个)
node tests/capture-fixtures.mjs "查询词"

改解析器的工作流:先 capture-fixtures.mjs 抓一份当前的真实页面,对着它写正则,再跑 test-engines.mjs 验证。

注意:测试会真实发请求,连续跑多轮会触发各家的 IP 限流(搜狗验证码、百度安全验证、Yahoo 500)。这是抓取式搜索的固有代价,不是测试或插件有问题——间隔几分钟再跑就恢复正常。

许可

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Free self-hosted web search for AI agents with multi-engine parallel search, semantic re-ranking, and native China network support. Zero API keys.
    2
    29 PyPI
    27
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to perform reliable web searches through multiple vendors with automatic failover, keyless-first access, TTL caching, and concurrent request coalescing.
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables querying multiple search engines and paid search APIs through a local aggregation service, returning deduplicated and RRF-ranked results via a single MCP tool.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables LLMs and coding assistants to run web searches by concurrently aggregating multiple commercial search engines per scenario, merging and deduplicating URL-normalized results with per-call fallback. When no API keys or all commercial engines fail, it automatically degrades to key-free DuckDuckGo and Bing channels so search never goes offline.
    59 npm
    MIT