← 返回列表
⚠ 装前注意
English: 一个均衡的网页搜索插件 / MCP 服务器,在 KeenableKeen Search/ Exa /…
基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/15 · 已提供中文文档
Balanced web search plugin/MCP server for DeepSeek Harness: Keenable / Exa / Tavily round-robin with failover. / 均衡搜索插件:Keenable / Exa / Tavily 轮流调用,自动故障切换。
综合分
32.4
GitHub 分
32.4
用户评分
—
★ Stars
4
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add tianmingwan/dsh-balanced-search未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 3 天前真实安装成功(L4 · 真实安装)
- 是什么
- dsh 原生插件 · tool
- 装得上吗
- 本站已真实安装成功(L4 · 真实安装,非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 10 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/22
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-balanced-search(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
未发布到 npm registry,仅可从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/20 18:49:37
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-balanced-search
English: 一个均衡的网页搜索插件 / MCP 服务器,在 Keenable(Keen Search)/ Exa / Tavily 之间轮流调用,并自动故障转移到下一个提供商。返回规范化的标题、链接和内容摘要。
中文: 均衡搜索插件 / MCP 服务器:把 Keenable(Keen Search)/ Exa / Tavily 三个搜索 API 轮流调用(round-robin),某个服务失败时自动切换下一个,统一返回标题 / 链接 / 摘要。
本仓库同时提供两种形态 / 本仓库同时提供两种形态:
1. DeepSeek Harness 原生插件(推荐)/ dsh 原生插件(推荐) — 将 balanced_search / balanced_fetch 注册为 dsh 工具,并且自动接管内置的 web_search / web_fetch,无需 Python。/ 既注册 balanced_search / balanced_fetch 两个 dsh 工具,同时自动接管内置的 web_search / web_fetch,无需 Python。
2. 通用 MCP 服务器 / 通用 MCP 服务器 — 通过 server.py 以 stdio 方式暴露 search / fetch,可供任意 MCP 客户端使用。/ 通过 server.py 以 stdio 方式暴露 search / fetch,可供任意 MCP 客户端使用。
功能 / 功能
- 搜索网页并返回标题、链接和内容摘要。/ 搜索网页,返回标题、链接和内容摘要。
- 抓取 URL 并返回干净的 markdown 文本。/ 抓取指定 URL 的网页正文,返回 clean markdown。
- 在提供商之间轮流调用,并自动故障转移。/ 三个服务轮流调用,单个服务失败时自动切换下一个。
- 通过环境变量配置 API 密钥;没有密钥的提供商会跳过。/ 通过环境变量配置 API key;未配置的服务不会启用。
- 自动接管内置的 web_search / web_fetch — bundle 将 dsh 的 web 行固定到本插件的 balanced 提供商,因此无需手动编辑配置文件。/ 自动接管内置的 web_search / web_fetch:bundle 层把 dsh 的 web 行钉到本插件的 balanced provider,无需手工改任何配置。
- 抓取发生在服务端,由厂商完成 — 因此它也能在随附的本地 http 抓取提供商无法工作的环境中使用。参见配置说明。/ 抓取在厂商服务端完成,因此在 dsh 自带本地抓取 provider 无法工作的环境下依然可用,见配置说明。
环境变量 / 环境变量
至少配置一个搜索提供商 API 密钥 / 至少配置一个搜索服务的 API key:
KEENABLE_API_KEY=...
EXA_API_KEY=...
TAVILY_API_KEY=...
👉 在哪里注册并获取每个密钥 — 注册链接、密钥在各仪表盘中的位置、免费配额,以及一次调用消耗多少:API_KEYS.md。
三家的注册入口、key 在各家后台的哪个页面、免费额度、以及单次调用消耗,见 API_KEYS.md。
| 提供商 | 注册 / 注册 | 环境变量 | 免费额度 / 免费额度 |
|---|---|---|---|
| Keenable | | KEENABLE_API_KEY | 100,000 次请求 / 月 |
| Exa | | EXA_API_KEY | 注册时 $20 + 每月 $10 |
| Tavily | | TAVILY_API_KEY | 1,000 积分 / 月 |
dsh 原生插件直接读取进程环境变量。Python MCP 服务器还会加载同目录下的 .env 文件。/ dsh 原生插件直接读取进程环境变量;Python MCP 服务器还会自动读取同目录下的 .env 文件。
目录结构 / 目录结构
| 文件 / 文件 | 说明 / 说明 |
|---|---|
| index.js | dsh 原生插件入口;注册 balanced_search / balanced_fetch 以及 ctx.web provider balanced / dsh 原生插件入口:注册两个工具,并向 ctx.web 注册 balanced provider |
| cordis.patch.yml | dsh bundle 配置层;插入插件,并把 web 行钉到 balanced provider / dsh bundle 配置层:插入插件,并把 web 行钉到 balanced provider |
| package.json | dsh bundle 声明 / dsh bundle 声明 |
| server.py | 通用 MCP server(stdio);暴露 search / fetch / 通用 MCP server |
| providers.py | Python 版 API 客户端与轮换 / Python 版 API 客户端与轮换 |
| requirements.txt | Python MCP 服务器依赖 / Python MCP 服务器依赖 |
| .env.example | API key 配置模板(复制为 .env)/ API key 配置模板 |
| API_KEYS.md | 三个 API 的注册与 key 领取说明 / 三个 API 的注册与 key 领取说明 |
| .gitignore | 排除本地敏感与缓存文件 / 排除本地敏感与缓存文件 |
安装为 dsh 插件 / 安装为 dsh 插件
要求 / 要求:已安装 DeepSeek Harness (dsh),Node.js ≥ 20。
dsh plugin --profile web add github:tianmingwan/dsh-balanced-search
重启 dsh --profile web 之后 / 重启 dsh --profile web 之后:
- 新增两个工具 / 新增两个工具:balanced_search、balanced_fetch
- 内置的 web_search / web_fetch 被自动接管,无需手工修改 profile 配置 / 内置的 web_search / web_fetch 被自动接管,无需手工修改 profile 配置
无需安装 Python 依赖 / 无需安装 Python 依赖。
接管是怎么实现的 / 接管是怎么实现的
package.json 声明了 dsh.bundle.patch,这使该包成为一个 bundle 层。安装它时,会把 cordis.patch.yml 组合到它之前列出的 bundle 之上——尤其是挂载 web 行的 @deepseek-ai/dsh-base——而该层会钉住该行的 providers:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: balanced
fetchProvider: balanced
index.js 向该接缝的 search 和 fetch 注册表中同时注册一个 id 为 balanced 的 provider,因此该钉住配置覆盖两种能力。(patch 会替换目标行的整个 config,而不是合并,这就是为什么两个字段都要重新声明。)
key 要求 / key 要求
接管需要至少配置一个 KEENABLE_API_KEY / EXA_API_KEY / TAVILY_API_KEY。一个都没有时,balanced provider 会报告自身不可用,内置工具会以 WEB_PROVIDER_CONFIGURED_UNAVAILABLE 失败并指明 balanced。/ 接管需要至少配置一个 key;一个都没有时,balanced provider 会报告不可用,内置工具会以 WEB_PROVIDER_CONFIGURED_UNAVAILABLE 失败。
取消接管 / 取消接管
用户自己的 ~/.dsh/profiles//cordis.patch.yml 会在所有 bundle 层之后应用,因此可以在那里覆盖或删除该钉住配置——恢复 dsh 自带的 deepseek-official search / http fetch,同时保留两个额外工具。/ 用户自己的 cordis.patch.yml 在所有 bundle 层之后应用,因此可以在那里覆盖或删除这两行,恢复 dsh 自带的 provider,同时保留两个额外工具。
作为通用 MCP 服务器使用 / 作为通用 MCP 服务器使用
安装 / 安装
python -m venv .venv
Windows
.venv\Scripts\python.exe -m pip install -r requirements.txt
Linux / macOS
.venv/bin/python -m pip install -r requirements.txt
运行
stdio 模式,供 MCP 客户端连接
python server.py
或使用虚拟环境中的 Python
.venv\Scripts\python.exe server.py # Windows
.venv/bin/python server.py # Linux / macOS
MCP 客户端接入示例
{
"mcpServers": {
"balanced-search": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["/absolute/path/to/server.py"],
"env": {
"KEENABLE_API_KEY": "...",
"EXA_API_KEY": "...",
"TAVILY_API_KEY": "..."
}
}
}
}
工具用法
dsh 原生工具
- balanced_search — 参数:query / max_results / time_range
- balanced_fetch — 参数:url / max_chars / live
接管后的内置工具
它们沿用 dsh 自己的工具签名:本插件只提供检索后端,参数由 dsh 决定。
| | web_search | balanced_search |
|---|---|---|
| 查询 | queries: string[](一次最多 4 条) | query: string |
| 条数 | 部署配置,默认 8 | max_results 1–20 |
| 时间范围 | ✗(seam 明确暂不支持) | time_range |
- web_fetch — 参数:仅 url。没有 max_chars / live,超时与输出上限属部署策略。
- balanced_fetch — 保留 max_chars / live。
两套接口互补:使用 web_search / web_fetch 可获得 dsh 原生命名与多查询能力;当需要 time_range、live 或 max_chars 时,使用 balanced_search / balanced_fetch。
MCP 工具
- search — 参数:query / max_results / time_range
- fetch — 参数:url / max_chars / live
参数说明
- query(必填):搜索关键词或自然语言问题
- max_results:1–20,默认 8
- time_range:day / week / month / year(Tavily 原生;Exa 映射为 startPublishedDate;Keenable 映射为 published_after)
- max_chars:抓取内容最大字符数,默认 30000,上限 50000
- live:是否实时从源站抓取(绕过索引/缓存),默认 false
搜索返回 JSON:
{
"provider": "keenable|exa|tavily",
"count": 1,
"results": [
{"title": "...", "url": "...", "content": "...", "published_at": "...", "score": 0.5}
]
}
抓取返回 JSON:
{
"provider": "keenable|exa|tavily",
"result": {"url": "...", "title": "...", "content": "..."}
}
配置说明
- 换 key:dsh 插件使用环境变量;MCP 服务器使用 .env 或客户端 env 注入。
- 轮换策略:Balancer(当前为轮询 + 故障转移;可改为加权或健康感知)。搜索与抓取各自独立推进游标,一次抓取不会改变下次搜索的起点。
- 新增服务:在 providers.py 中添加一个 SearchProvider 子类,并在 build_balancer() 中注册;或在 index.js 中添加一个 Provider 类。
- 服务端抓取:抓取由 Keenable / Exa / Tavily 发起,网页是在它们的网络里取的。因此当本机 DNS 把域名解析到私有或保留网段(例如 Clash / mihomo TUN 的 fake-ip 模式返回 198.18.0.0/15 地址)时,抓取依然可用;而 dsh 自带的本地 http provider 会以 resolves to a non-public IP address 拒绝。
- 关于抓取状态码:seam 要求返回 statusCode,而三家厂商都是服务端抽取、不暴露原页面状态码,因此抽取成功即记为 200,truncated 按正文是否触顶推断。
许可证
MIT