← 返回列表
未验证
面向 MCP 主机、命令行和主机适配器的弹性多提供商网页搜索与页面提取。
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/24 · 已提供中文文档
为 Claude Code、DeepSeek Harness 以及任何 MCP 主机提供弹性多提供商网页搜索与内容提取——配额感知故障转移、JS 渲染以及一个 CLI。
综合分
29.7
GitHub 分
29.7
用户评分
—
★ Stars
3
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/Tannnnhauser/pivot-web-search.git数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
Pivot Web Search
面向 MCP 主机、命令行和主机适配器的弹性多提供商网页搜索与页面提取。
Python 3.10+
License: Apache-2.0
[Tests: 358]()
这是什么?
Pivot Web Search 通过三个接口暴露一组共享的搜索、抓取和配置服务:
- MCP 服务器(pivot-web-search-mcp)—— 用于 Claude Code 以及任何支持 MCP 的主机
- CLI(pivot-web-search)—— 供人和 shell 脚本使用,无需 AI 主机
- JSON 桥接(pivot-web-search-bridge)—— 面向适配器的、与主机无关的子进程接口
它会将每个查询路由到多个提供商,在结果质量不佳或某个提供商不可用时自动故障转移,跟踪配额和健康状况,并在本地提取页面内容 —— 不依赖 Anthropic API,因此可在 Amazon Bedrock 和其他 API 提供商上运行。Claude Code 插件和可选的 DeepSeek Harness 适配器提供了针对特定主机的安装方式;采用 Pivot 从不需要修改主机源代码。
DuckDuckGo 无需 API 密钥即可使用;添加基于 API 的提供商(Tavily、Brave、Gemini)可提升可靠性。
选择你的接口
| 你使用…… | 从这里开始 |
|---|---|
| Claude Code | 安装插件 |
| 其他 MCP 主机(Cursor、Claude Desktop 等) | 配置 pivot-web-search-mcp |
| 终端 / 脚本 / CI | 安装并运行 CLI |
| DeepSeek Harness | 安装运行时 + DSH 包 |
主要特性
- 一个运行时,三个接口 —— 同一套搜索/抓取/配置服务支撑 MCP、CLI 和 JSON 桥接。
- 多提供商故障转移 —— 感知配额的路由;跳过结果质量不佳或已耗尽的提供商,保留部分结果作为回退。
- 超级模式 —— 并行查询所有提供商,按 URL 去重,依据跨提供商一致性排序。
- 本地页面提取 —— 通过 trafilatura 获取完整内容,并提供 Next.js/Nuxt.js SPA 回退方案以及可选的 JS 渲染器。
- 可热重载配置 —— 通过 YAML 添加/移除/重排提供商和代理;更改在下一个请求时生效。
- 可操作的诊断 —— 当一切失败时,你会获得每个提供商的失败原因和建议,而不是笼统的错误。
当某个 API 不可用、被限流、被屏蔽或配额耗尽时,单提供商搜索就会失败。Pivot 会将每个请求路由到已配置的提供商,保留可用的部分结果,并通过 MCP、CLI 和适配器友好的 JSON 暴露相同的行为。
先决条件
- uv —— 自动管理 Python 和依赖项(每个接口都会用到)。
- 至少一个搜索提供商(DDG 无需 API 密钥)。
推荐: 至少配置一个免费 API 密钥 — Tavily(每月 1000 额度,无需信用卡)或 Brave(每月 1000 次查询,需要信用卡)。DDG 是免费的后备方案,但在高负载下可能不可靠。
各主机的设置方法在下面的每个快速开始中都有介绍。
快速开始
Claude Code 插件
第 1 步 — 添加市场(一次性):
claude plugin marketplace add https://github.com/Tannnnhauser/pivot-web-search.git
第 2 步 — 安装:
claude plugin install pivot-web-search
插件会在安装时提示进行配置:
| 设置 | 描述 |
|---|---|
| Tavily API Key | 存储在系统钥匙串中。设置后启用 Tavily(或从 shell 继承 TAVILY_API_KEY)。 |
| Brave Search API Key | 存储在系统钥匙串中。设置后启用 Brave(或继承 BRAVE_API_KEY)。 |
| Gemini API Key | 存储在系统钥匙串中。设置后启用 Gemini(或继承 GEMINI_SEARCH_API_KEY / GOOGLE_STUDIO_API_KEY)。 |
| Proxy URLs | 按顺序尝试的逗号分隔代理。direct 始终作为最终后备追加 — 要禁用该行为,请使用 ~/.pivot-web-search/proxies.yaml。 |
只要你提供了密钥,相应的提供商就会自动启用;DDG 始终开启。路由顺序和超时来自智能默认值 — 你提供密钥的顺序无关紧要。随时可通过 claude plugin configure pivot-web-search 重新配置。
验证: 让 Claude Code 以 status 动作运行 WebSearchConfig — 你应该会看到一份提供商健康报告。
密钥解析与 macOS GUI 注意事项
对于每个提供商密钥,插件会读取 (1) 从 shell 继承的标准环境变量(例如 TAVILY_API_KEY)— 如果已设置则优先 — 然后 (2) /plugin UI 中的值(以 PIVOT_USERCONFIG_TAVILY_API_KEY 注入)。若要改用 UI 中的值,请在 shell 中 unset TAVILY_API_KEY。
macOS: 当 Claude Code 从 Spotlight 或 Dock 启动时,它不会看到 ~/.zshrc 中的导出变量。请从终端启动它,通过 /plugin UI 设置密钥,或将它们添加到 ~/.claude/config.json 的 env 块中。
MCP 主机
任何支持 MCP 的主机(Claude Code、Claude Desktop、Cursor 等)都可以通过 uvx 直接运行服务器 — 无需克隆,无需 venv。添加到你的 .mcp.json:
{
"mcpServers": {
"pivot-web-search": {
"command": "uvx",
"args": [
"git+https://github.com/Tannnnhauser/pivot-web-search.git#subdirectory=plugins/pivot-web-search"
],
"env": {
"TAVILY_API_KEY": "tvly-...",
"BRAVE_API_KEY": "BSA...",
"GEMINI_SEARCH_API_KEY": "AI..."
}
}
}
}
使用 @v1.1.0 固定版本:
git+https://github.com/Tannnnhauser/pivot-web-search.git@v1.1.0#subdirectory=plugins/pivot-web-search
高级提供商/代理配置位于 ~/.pivot-web-search/.yaml(参见配置),并适用于所有启动方式。
CLI
安装的包提供 pivot-web-search,这是一个面向用户的命令,由与 MCP 工具相同的服务提供支持——可在终端、脚本或 CI 中使用,无需经过 AI 宿主。使用 uv 单独安装它:
uv tool install 'git+https://github.com/Tannnnhauser/pivot-web-search.git@v1.1.0#subdirectory=plugins/pivot-web-search'
pivot-web-search search "latest Python release" --format json
pivot-web-search fetch https://example.com --format md
pivot-web-search config status
search 标志:
| 标志 | 默认值 | 描述 |
|---|---|---|
| --max-results | 5 | 结果数量(1–10,使用 --super 时为 1–20) |
| --provider | auto | 按名称强制使用已配置的提供方 |
| --super | 关闭 | 并行查询所有提供方 |
| --news | 关闭 | 搜索新闻而非通用网页 |
| --timelimit | — | d / w / m / y 时效性过滤 |
| --include-answer | 关闭 | 在支持时包含 AI 回答 |
| --search-depth | basic | basic 或 advanced(Tavily) |
| --topic | general | general 或 news(Tavily) |
| --days | — | 将新闻限制为最近 N 天 |
| --include-domains | — | 域名允许列表 |
| --exclude-domains | — | 域名阻止列表 |
| --include-content | 关闭 | 返回预提取的页面内容(Brave LLM Context) |
| --max-content-tokens | 8192 | --include-content 的 token 预算 |
| --region | wt-wt | DDG 区域(仅 CLI;无 MCP 等效项) |
| --format | md | md 或 json |
fetch(别名 extract):--query(用于 JS 渲染器的相关性提示)、--max-chars(每个 URL 的截断)、--format(默认 json,或 md)。
config:位置参数操作,status(默认)或 reload。
DeepSeek Harness
可选的 pivot-web-search-dsh Profile Bundle 通过 DSH 已发布的 Bundle、ctx.web 和 ctx.subprocess API,将 Pivot 注册为 DSH 现有的 web_search 和 web_fetch 提供方。模型仍然看到 DSH 的标准工具——没有第二组 Pivot 专用工具。宿主集成使用公共扩展 API;该适配器不需要 DSH 分支或源代码补丁。
安装运行时和 Bundle:
uv tool install 'git+https://github.com/Tannnnhauser/pivot-web-search.git@v1.1.0#subdirectory=plugins/pivot-web-search'
dsh plugin --profile web add pivot-web-search-dsh
添加 Bundle 后重启 profile。它会选择提供方 pivot 作为 searchProvider/fetchProvider,并启用 DSH 的 tool-web 条目(随附的 web profile 将其禁用)。使用 dsh --profile web --dump-config 验证——你应该看到 searchProvider: pivot、fetchProvider: pivot、已启用的 tool-web 以及 pivot-web-search-provider。
提供方密钥由 cordis.patch.yml 显式转发(TAVILY_API_KEY、BRAVE_API_KEY、GEMINI_SEARCH_API_KEY、GOOGLE_STUDIO_API_KEY,以及 PIVOT_WEB_SEARCH_PROXIES);~/.pivot-web-search/ 下的配置文件会被直接读取。
自定义提供商: 桥接子进程仅接收 cordis.patch.yml 中列出的环境变量——它不会继承父 shell。如果自定义提供商的 api_key_env 指定的密钥不在上述列表中(例如自托管网关令牌),请将该变量添加到 Bundle 的 env 块中,否则它无法到达桥接进程。
开发安装和移除步骤记录在 integrations/deepseek-harness/ 中。
配置
Pivot 默认运行在自动检测模式下——提供 API 密钥(通过 UI 或 shell 环境变量),匹配的提供商便会以智能路由默认值启用。常见场景无需 YAML。
对于高级设置,将 YAML 放入 ~/.pivot-web-search/:
| 文件 | 用途 |
|---|---|
| providers.yaml | 接管提供商配置:SearXNG、自定义 JSON API、LLM 搜索提供商、显式优先级 |
| proxies.yaml | 接管代理配置:SOCKS5、强制代理(无直接回退)、按代理优先级 |
每个文件的优先级是全有或全无: 如果文件存在,该方面的自动检测将被绕过——列出你想要的每个条目(包括 DDG)。模板位于 examples/。
~/.pivot-web-search/providers.yaml
提供商按优先级尝试(数值越小越先尝试)。相同优先级的提供商会进行对冲——以错开的启动时间并发查询,首个高质量结果胜出。如果没有显式 priority,则按类型应用智能默认值。
providers:
- name: tavily
type: tavily
api_key_env: TAVILY_API_KEY
- name: brave
type: brave
api_key_env: BRAVE_API_KEY
- name: gemini
type: gemini
api_key_env: GEMINI_SEARCH_API_KEY
model: gemini-2.5-flash
- name: ddg
type: ddg
Self-hosted SearXNG
- name: searxng-local
type: searxng
endpoint: "http://localhost:8888/search"
Generic JSON API (Serper, Google CSE, etc.) — multiple instances allowed,
each with independent priority, quota tracking, and circuit-breaker state.
- name: serper
type: json_api
endpoint: "https://google.serper.dev/search"
api_key_env: SERPER_API_KEY
method: POST
request_body:
q: "{{query}}"
num: "{{max_results}}"
response_mapping:
results_path: "organic"
title: "title"
url: "link"
snippet: "snippet"
智能默认优先级(当没有显式 priority 时):
| 类型 | 优先级 | 超时 |
|---|---|---|
| llm_search | 10 | 15s |
| tavily / brave / gemini | 20 | 4s / 4s / 20s |
| searxng / json_api | 30 | 6s |
| ddg | 90 | 6s |
注意: 优先级为 10 的 llm_search 提供商会在 Tavily/Brave 之前运行,超时为 15s,因此每次查询可能需要 15 秒以上。如果延迟比答案质量更重要,请将其 priority 提高到 20 以上。
LLM 搜索提供商(type: llm_search)
对于任何具有内置网络搜索基础能力的模型(Perplexity Sonar Pro、带 web_search 的 OpenAI、SAP AI Core 等)。这些模型会返回一个 AI 答案以及引用的 URL。通过 ~/.pivot-web-search/providers.yaml 进行配置(模板位于 examples/providers.yaml)。
chat_completions — 任何与 /chat/completions 兼容且具有内置搜索的端点:
- name: sonar-pro
type: llm_search
api_format: chat_completions
endpoint: "https://api.perplexity.ai/chat/completions"
model: sonar-pro
api_key_env: PERPLEXITY_API_KEY
timeout: 15
响应解析按顺序尝试:search_results(Perplexity/Sonar)、带有 type: url_citation 的 annotations(OpenAI Chat Completions),然后是顶层的 citations。
responses — 使用 web_search 工具的 OpenAI Responses API(/responses):
- name: gpt-web-search
type: llm_search
api_format: responses
endpoint: "https://api.openai.com/v1/responses"
model: gpt-4o
api_key_env: OPENAI_API_KEY
timeout: 45
search_tool: web_search
search_context_size: medium
通用字段:
| 字段 | 是否必需 | 描述 |
|---|---|---|
| api_format | 否 | chat_completions(默认)或 responses |
| endpoint | 是 | API 端点的完整 URL |
| model | 是 | 模型标识符 |
| api_key_env | 是 | 保存 API 密钥的环境变量(作为 Bearer token 发送) |
| max_tokens | 否 | 最大响应 token 数(默认:500 / responses 为 4000) |
| timeout | 否 | 请求超时时间(秒)(默认:30) |
| system_prompt | 否 | 系统提示词(仅限 chat_completions) |
| headers | 否 | 额外的请求头 |
| web_search_options | 否 | 额外的搜索选项(仅限 chat_completions) |
gemini 类型在内部也是 LLM 搜索(Google Search 基础能力),但保留 type: gemini 以保持向后兼容性和双密钥回退。
~/.pivot-web-search/proxies.yaml
当该文件存在时,它会完全接管——安装时的 Proxy URLs 字段会被忽略,并且 direct 不会被自动追加(这是强制代理设置的逃生通道)。
proxies:
- name: direct
url: null # null = direct connection
enabled: true
priority: 1
- name: myproxy1
url: "http://myproxy1.example:8080"
enabled: true
priority: 2
SOCKS5 (requires PySocks: uv pip install pysocks)
- name: ssh-tunnel
url: "socks5://127.0.0.1:1080"
enabled: true
priority: 3
config/fetch.yaml
控制 WebFetch 行为,包括 JS 渲染回退:
js_renderer: none # none (default), "playwright", or "tavily"
max_chars: 100000 # content truncation limit
对于 JavaScript 密集型网站,设置 js_renderer: playwright(需要 uv sync --extra browser)。
MCP 工具参考
通过 MCP,工具带有前缀:mcp__pivot-web-search__WebSearch、mcp__pivot-web-search__WebFetch、mcp__pivot-web-search__WebSearchConfig。
WebSearch
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| query | str | 必填* | 搜索查询 |
| provider | str | "auto" | 强制指定提供商:auto / ddg / tavily / brave / gemini / searxng,或任何已注册的名称 |
| super_mode | bool | false | 并行查询所有提供商 |
| max_results | int | 5 | 1–10(超级模式下为 1–20) |
| allowed_domains | list[str] | null | 仅包含来自这些域名的结果 |
| blocked_domains | list[str] | null | 排除来自这些域名的结果 |
| news | bool | false | 搜索新闻而非网页 |
| timelimit | str | null | d / w / m / y |
| include_answer | bool | false | AI 生成的答案摘要(Tavily) |
| include_content | bool | false | 预提取的页面内容(Brave LLM Context) |
| max_content_tokens | int | 8192 | include_content=true 时的 token 预算(1024–32768) |
| search_depth | str | "basic" | basic 或 advanced — advanced 消耗 2 倍额度(Tavily) |
| topic | str | "general" | general 或 news(Tavily) |
| days | int | null | 将新闻限制为最近 N 天(Tavily) |
WebFetch
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| url | str / list[str] | 必填 | 要提取的 URL。HTTP 自动升级为 HTTPS。支持多 URL 的批量模式。 |
| query | str | null | 用于 JS 回退渲染器的可选相关性查询 |
| max_chars | int | null | 将输出截断为这么多字符(默认:100,000) |
行为: 每 URL 15 分钟缓存 · 二进制内容检测与拒绝 · 跨主机重定向安全(在跟随前阻止) · SPA 回退(__NEXT_DATA__ / RSC payload / __NUXT_DATA__)。
WebSearchConfig
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| action | str | "status" | status — 提供商健康状况、配额、配置来源;reload — 热重载 YAML |
status 返回提供商健康状况、每个提供商的配额,以及配置来源注释,显示每个设置来自何处(环境变量、YAML 路径或内置默认值)。
路由与故障转移的工作原理
Request
│
├─ normal mode: priority-group routing
│ ┌─ Group 1 (priority 10): LLM Search (Perplexity, OpenAI, etc.)
│ ├─ Group 2 (priority 20): Tavily + Brave + Gemini ← hedged (200ms stagger, first quality-gate pass wins)
│ ├─ Group 3 (priority 30): SearXNG / json_api
│ └─ Group 4 (priority 90): DDG (free exhaustion fallback)
│
│ Gates: quota-exhausted → skip | circuit-open → skip | affinity mismatch → skip
│ Quality gate (3-tier): AI answer ≥40 chars? → unique URLs ≥2? → keyword overlap?
│ Circuit breaker: 3 consecutive failures → OPEN (60s cooldown) → HALF_OPEN → probe
│
└─ super mode: Tavily ┐
Brave ┤ parallel (skip exhausted) → dedup → rank by provider count
Gemini ┤
DDG ┘
每个提供方独立尝试所有已配置的代理(直连 → myproxy1 → …),并按主机缓存,持久化到 ~/.cache/pivot-web-search/。
配额管理
使用情况跨会话跟踪,记录在 ~/.cache/pivot-web-search/quota.json 中:
| 提供方 | 跟踪方式 | 免费额度 | 详情 |
|---|---|---|---|
| DuckDuckGo | 不跟踪 | 无限制 | 免费,无需 API 密钥 |
| Tavily | API 同步 | 1000 积分/月 | 启动时调用 GET /usage 获取真实积分数据 |
| Brave | 响应头 | 滚动 30 天窗口 | 解析 X-RateLimit-Remaining / X-RateLimit-Reset |
| Gemini | 本地(每日) | 不定(太平洋时间午夜重置) | 通过 PIVOT_WEB_SEARCH_GEMINI_QUOTA 设置限额 |
配额感知调度会在使用率达到 100% 时跳过相应提供方;在日历翻页时重置。
架构
三个接口构建在一组共享服务之上:
MCP server ─┐
CLI ────────┼─→ search / fetch / config services ─→ provider registry ─→ providers
JSON bridge ┘ (DDG/Tavily/Brave/Gemini/SearXNG/json_api/llm_search)
- server.py — FastMCP 适配器(3 个 MCP 工具)· cli.py — CLI 适配器 · machine_bridge.py — 主机中立的 JSON 适配器
- search_service.py / fetch_service.py / config_service.py — 权威编排 · presentation.py — Markdown/JSON 投影
- routing.py / quality_gate.py — 优先级分组路由、对冲、熔断器 · backends.py / extraction.py / http_client.py — 提供方 I/O、提取、代理故障转移
- providers/ — 适配器基类、6 个内置提供方、mtime 热重载注册表 · quota.py / config.py — 跨会话配额、YAML 热重载
Claude Code 插件载荷位于 plugins/pivot-web-search/ 下;DSH 适配器位于 integrations/deepseek-harness/ 下(绝不修改 DSH 源码);YAML 模板位于 examples/ 下。
测试
uv sync # install workspace + dev deps
uv run pytest -m "not integration" -q # 358 offline tests
uv run pytest -m integration -vv # 7 live network/API tests
uv run pytest # all 365 Python tests
npm --prefix integrations/deepseek-harness test
npm --prefix integrations/deepseek-harness pack --dry-run
用于本地 Claude Code 开发:claude --plugin-dir /path/to/pivot-web-search/。
故障排除
启用调试日志 — 设置 PIVOT_WEB_SEARCH_DEBUG=1;带时间戳的日志会写入 ~/.cache/pivot-web-search/server.log。
所有提供方均无结果 — 运行 WebSearchConfig 的 status 操作(或 pivot-web-search config status)以检查提供方健康状况和当前生效的配置来源。确保至少有一个提供方拥有有效密钥(或 DDG 可访问)。
macOS 上的 SSL 证书错误 — 该插件使用 certifi;如果错误持续存在:uv sync --upgrade-package certifi。
DuckDuckGo 速率限制(403) — 在连续失败后,断路器会绕过 DDG 60 秒,然后进行探测以恢复。配置一个由 API 支持的提供商以提高可靠性。
trafilatura 提取返回空结果 — 一些重度依赖 JS 的网站需要渲染器。在 config/fetch.yaml 中设置 js_renderer: playwright,然后运行 uv sync --extra browser && playwright install chromium。
替代方案对比
| 功能 | Pivot Web Search | 单提供商 MCP 工具 | 内置 WebSearch |
|---|---|---|---|
| 多提供商故障转移 | 4+ 个提供商,自动回退 | 单点故障 | Bedrock 上不可用 |
| 配额管理 | 跨会话跟踪 | 无 | 不适用 |
| 超级模式(并行) | 同时使用所有提供商 | 不可能 | 不适用 |
| 本地内容提取 | trafilatura + SPA 回退 | 通常是 Tavily Extract | Anthropic 托管 |
| 接口 | MCP + CLI + JSON 桥接 | 仅 MCP | 仅内置 |
| 可在 Bedrock 上运行 | 是 | 是 | 否 |
| 自托管 | 是 | 因情况而异 | 否 |
许可证
Apache-2.0扫码进群