# https://github.com/robbyczgw-cla/web-search-plus-mcp 项目说明书

生成时间：2026-07-21 03:24:25 UTC

## 目录

- [项目概述与 v3 合约架构](#page-1)
- [提供商系统与自动路由（含 v1.0 回落修复）](#page-2)
- [提取、有界上下文、语义跨度与缓存](#page-3)
- [配置、SDK、入门与运维（含 v1.0 迁移）](#page-4)

<a id='page-1'></a>

## 项目概述与 v3 合约架构

### 相关页面

相关主题：[提供商系统与自动路由（含 v1.0 回落修复）](#page-2), [提取、有界上下文、语义跨度与缓存](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/README.md)
- [web_search_plus_mcp/server.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/server.py)
- [web_search_plus_mcp/contract_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/contract_v3.py)
- [web_search_plus_mcp/orchestrator_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/orchestrator_v3.py)
- [web_search_plus_mcp/runtime_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/runtime_v3.py)
- [schemas/v3/request.schema.json](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/schemas/v3/request.schema.json)
- [pyproject.toml](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/pyproject.toml)
</details>

# 项目概述与 v3 合约架构

## 1. 项目定位与组件边界

`web-search-plus-mcp` 是一个独立的 MCP (Model Context Protocol) 服务端，它把可移植的 Web Search Plus 引擎能力以稳定的工具面 (`web_search`、`web_extract`) 暴露给 MCP 客户端 资料来源：[README.md:1-40]()。在 v1.0.0 之后，项目主线与源仅发布的 Web Search Plus v3.x 引擎合约保持同步，但服务端的对外 API 表面积仍然限定在 `web_search` 与 `web_extract` 两个工具，避免破坏既有 MCP 客户端集成 资料来源：[README.md:30-60]()。

工程边界由 `pyproject.toml` 锁定的包名 `web-search-plus-mcp` 与入口 `web_search_plus_mcp.server` 共同定义，使其可以通过 `uvx web-search-plus-mcp` 直接拉起 资料来源：[pyproject.toml:1-40]()。运行时不再把 Hermes 私有组件打入 wheel，只保留 portable engine + MCP 适配层。

## 2. v3 合约架构

v3 合约是项目与底层 Web Search Plus v3.x 引擎之间的请求/响应规约，所有调用必须通过这套规范化结构传递，并在响应里以加性方式追加 `evidence`、`provider_attempt`、`routing`、`cache_origin`、`policy` 等维度 资料来源：[web_search_plus_mcp/contract_v3.py:1-80]()。这套结构由 `schemas/v3/request.schema.json` 提供 JSON Schema 描述，确保 MCP → CLI → engine 三层在字段命名与可空性上保持一致 资料来源：[schemas/v3/request.schema.json:1-120]()。

`contract_v3.py` 中的合约模块负责把外部进入的请求对象映射为引擎所需的 v3 字段，并在响应回到 MCP 工具前把引擎输出装配成对外结构 资料来源：[web_search_plus_mcp/contract_v3.py:40-120]()。这样 MCP 工具名 (`web_search`、`web_extract`) 与 v3 路由字段解耦，便于后续 schema 演进而不破坏上层调用方。

## 3. MCP → CLI → v3 请求边界

请求从 MCP 工具入口进入 `server.py`，由 CLI 适配层收齐环境变量、配置文件 (`config.json` 的 `auto_routing` 等) 与命令行参数，然后下发到 v3 合约层 资料来源：[web_search_plus_mcp/server.py:40-120]()。CLI 适配层的作用之一是规范化“显式参数”与“隐式默认”：v1.0.1 修复了一个回归 —— 当 CLI 没有 `--allow-fallback` 标志时，绝不能将其强制成 `allow_fallback: false`，否则在 `provider=auto` 路径下，规划器只会生成一个候选提供者，任何配额/限流都会使整个请求失败 资料来源：[web_search_plus_mcp/server.py:60-140]()。

这条边界同时承担安全/隐私职责：v0.14.0 起，`web_extract` 在下发到 provider 之前会拦截 loopback、RFC1918、CGNAT 等私有目标，避免内部地址泄漏 资料来源：[README.md:120-180]()。

## 4. 多提供者编排与回退

`orchestrator_v3.py` 是 v3 引擎的路由编排核心，负责从可用的 provider 列表中根据策略、能力、冷却状态与配额预算生成候选计划，并按 `allow_fallback` 与显式 provider 选择的不同语义驱动执行 资料来源：[web_search_plus_mcp/orchestrator_v3.py:60-160]()。对于显式指定 provider 的请求，系统保持严格单候选 (strict) 语义；而 `provider=auto` 则期望计划具备多个候选并具备失败回落能力 资料来源：[web_search_plus_mcp/orchestrator_v3.py:120-220]()。

在社区报告的 issue #27 中，v1.0.0 暴露了一个真实退化：在装配了 10 个 provider key 的进程里，`auto` 路由每次只规划出 1 个候选，导致任何单点失败都成为终结错误，证据留在 routing receipts 中 资料来源：[web_search_plus_mcp/orchestrator_v3.py:140-240]()。该问题在 v1.0.1 通过 CLI 边界修正 `allow_fallback` 推断逻辑得以恢复，但提示我们在升级 MCP/CLI/v3 边界时必须重新验证 `auto` 语义 资料来源：[web_search_plus_mcp/server.py:100-180]()。

## 5. 运行时与持久化

`runtime_v3.py` 把编排结果落进 SQLite 状态库，并维护 cache envelope、provider 健康/冷却、host 使用统计等结构 资料来源：[web_search_plus_mcp/runtime_v3.py:40-160]()。v1.1.0 进一步把 schema 升到 v3，并引入 budget preflight、diversity reranking、shadow observations、semantic extraction spans 等能力，使 MCP 端能在不破坏 v3 合约的情况下把这些信号透出 资料来源：[web_search_plus_mcp/runtime_v3.py:120-240]()。

```mermaid
flowchart LR
    A[MCP 客户端] --> B[server.py<br/>web_search / web_extract]
    B --> C[CLI 适配层<br/>allow_fallback 等规整]
    C --> D[contract_v3.py<br/>v3 请求/响应合约]
    D --> E[orchestrator_v3.py<br/>多 provider 候选与回退]
    E --> F[runtime_v3.py<br/>cache + SQLite + 预算]
    F --> G[Web Search Plus v3 引擎]
    G --> F --> E --> D --> C --> B --> A
```

整体而言，v3 合约是项目稳定对外与持续演进的“锚”：上层 MCP 工具面在 v1.0 起就基本冻结，下层引擎则可通过加性字段不断扩展；而 `server.py → contract_v3.py → orchestrator_v3.py → runtime_v3.py` 这条纵深链路正是任何关于“路由退化为单候选”、“allow_fallback 语义漂移”等问题需要追溯的主干。

---

<a id='page-2'></a>

## 提供商系统与自动路由（含 v1.0 回落修复）

### 相关页面

相关主题：[项目概述与 v3 合约架构](#page-1), [提取、有界上下文、语义跨度与缓存](#page-3), [配置、SDK、入门与运维（含 v1.0 迁移）](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [web_search_plus_mcp/providers.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/providers.py)
- [web_search_plus_mcp/provider_registry.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/provider_registry.py)
- [web_search_plus_mcp/provider_dispatch.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/provider_dispatch.py)
- [web_search_plus_mcp/provider_adapter_protocol.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/provider_adapter_protocol.py)
- [web_search_plus_mcp/routing.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/routing.py)
- [web_search_plus_mcp/attempt_engine_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/attempt_engine_v3.py)
</details>

# 提供商系统与自动路由（含 v1.0 回落修复）

## 概述与作用域

`web-search-plus-mcp` 是一个独立的 MCP（Model Context Protocol）服务器，它围绕可插拔的「提供商（provider）」抽象构建统一的 `web_search` 与 `web_extract` 工具表面。提供商系统的职责是：发现可用的搜索/提取后端、维护健康状态与配额冷却、按请求上下文挑选候选链并在失败时回落。自动路由（`provider=auto`）是该系统的核心策略，它允许请求透明地跨多个提供商（如 Serper、Tavily、Exa、Bing、Brave、Keenable、GroktoCrawl 等）进行尝试，而不是把客户端绑定到单一后端。资料来源：[web_search_plus_mcp/providers.py]()

该系统的设计目标包括：稳定的对外工具契约；可观测的尝试链；以及在配额/限流场景下不中断请求的弹性。这三个目标共同催生了 v3 请求/响应模型（`attempt_engine_v3.py`），其中包含 `provider-attempt`、`routing`、`cache-origin` 与 `policy` 等附加证据字段，使每次路由决策都可被审计与回放。

## 架构组件

提供商系统按职责切分为几个相互协作的模块：

- `providers.py`：维护运行期提供商列表与每个提供商的元数据（API key、端点、特性开关、健康状态）。资料来源：[web_search_plus_mcp/providers.py]()
- `provider_registry.py`：负责发现、注册与去重；v1.1.0 起引入 fail-closed `providers.d` 目录机制，未通过一致性检查的提供商不会进入候选链。资料来源：[web_search_plus_mcp/provider_registry.py]()
- `provider_adapter_protocol.py`：定义适配器必须实现的搜索与提取接口（同步/异步、错误码、归一化产出），所有提供商都必须遵守这一协议才能被发现。资料来源：[web_search_plus_mcp/provider_adapter_protocol.py]()
- `provider_dispatch.py`：根据候选链依次调用适配器、累计失败信息、处理配额与冷却，并在所有候选失败时抛出可序列化的错误。资料来源：[web_search_plus_mcp/provider_dispatch.py]()
- `routing.py`：实现 `provider=auto` 的候选构造逻辑（按优先级、特性匹配、`auto_routing.disabled_providers` 过滤），并产出可在响应中暴露的 routing 收据。资料来源：[web_search_plus_mcp/routing.py]()

下面用一张表概述 v1.0 之后请求路径中各字段的语义，这对理解 v1.0.1 的修复尤为关键：

| 字段 | 含义 | 默认行为（v1.0.1+） |
| --- | --- | --- |
| `provider` | 客户端指定的后端名称；`auto` 触发候选链 | 显式名称 → 严格单提供商；`auto` → 多候选回落 |
| `allow_fallback` | 是否允许在首个候选失败时尝试后续候选 | CLI 未传时不强制为 `false` |
| `disabled_providers` | 配置层禁用的提供商列表 | 仅在 auto 路由下生效 |
| `provider-attempt` | 每次尝试的提供商、错误码、耗时 | 全部追加到响应证据中 |

资料来源：[web_search_plus_mcp/attempt_engine_v3.py]()

## 自动路由的工作流

典型的 `provider=auto` 请求经历如下阶段：

1. **入口校验**：MCP 工具层接收请求，按 v3 契约补齐 `policy` 与 `cache-origin` 等字段。
2. **候选构造**：`routing.py` 依据优先级、健康冷却、`disabled_providers` 与特性（如 `freshness`、`country`）筛选可执行候选。资料来源：[web_search_plus_mcp/routing.py]()
3. **串行尝试**：`provider_dispatch.py` 按候选顺序调用 `provider_adapter_protocol` 中定义的适配器；任意一次成功立即终止并返回结果。资料来源：[web_search_plus_mcp/provider_dispatch.py]()
4. **失败聚合**：当所有候选均失败时，聚合错误并附带完整 `provider-attempt` 链返回，便于上层降级或重试。
5. **预算与可观测性**：v1.1.0 引入的预算预检（budget preflight）会在第 2 步前剔除明显超出预算的候选；shadow observations 与 receipt journals 用于离线分析。

```mermaid
flowchart LR
  A[MCP 工具调用] --> B{provider == auto ?}
  B -- 是 --> C[候选构造<br/>routing.py]
  B -- 否 --> D[严格单提供商]
  C --> E[串行尝试<br/>provider_dispatch.py]
  E --> F{任一成功 ?}
  F -- 是 --> G[返回结果 + attempt 链]
  F -- 否 --> H[聚合错误<br/>attempt 证据]
  D --> I[单次调用适配器]
  I --> J[返回或报错]
```

资料来源：[web_search_plus_mcp/routing.py]()、[web_search_plus_mcp/provider_dispatch.py]()

## v1.0 回落回归与 v1.0.1 修复

v1.0.0 引入了 v3 请求/响应契约的完整端口，但社区在 issue #27 中报告：在配置 10 个提供商密钥的环境下运行 PyPI v1.0.0 时，每个请求只规划了一个候选——也就是说，回落链被压扁成了单提供商。任何一次配额耗尽或限流都会成为终结性失败。资料来源：[GitHub Issue #27]()

v1.0.1 修复聚焦在 MCP → CLI → v3 的请求边界上。问题根源是 CLI 缺少 `--allow-fallback` 标志，但默认回填逻辑把它解释为显式 `allow_fallback: false`，于是 `auto` 路由的候选构造退化为仅一个提供商。修复后：

- 普通 `provider=auto` 的 Search 与 Extract 请求恢复了多提供商回落链。
- 客户端未显式传 `allow_fallback` 时，不再被强制为 `false`。
- 显式指定具体提供商的请求保持严格模式（无回落），避免对用户意图的意外覆盖。

资料来源：[web_search_plus_mcp/routing.py]()、[web_search_plus_mcp/attempt_engine_v3.py]()、[web_search_plus_mcp/providers.py]()

后续 v1.1.0 在此基础上又叠加了：budget preflight、diversity reranking、self-hosted profiles，以及面向第三方贡献者的公共 provider SDK 与 fail-closed `providers.d` 发现机制，进一步巩固了回落链的弹性与可观测性。

## 运维要点

部署侧应关注：每个提供商的密钥健康、冷却状态与 `disabled_providers` 配置；自定义提供商时必须实现 `provider_adapter_protocol` 中规定的接口并通过一致性检查；调试时可读取响应中的 `routing` 与 `provider-attempt` 证据来还原回落链上的每一步。当观察到「单次失败即终结」的症状时，应先确认当前运行的版本是否已升级到 v1.0.1 及以上，并核对请求路径上是否有客户端在显式注入 `allow_fallback: false`。资料来源：[web_search_plus_mcp/provider_registry.py]()、[web_search_plus_mcp/routing.py]()

---

<a id='page-3'></a>

## 提取、有界上下文、语义跨度与缓存

### 相关页面

相关主题：[项目概述与 v3 合约架构](#page-1), [提供商系统与自动路由（含 v1.0 回落修复）](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [web_search_plus_mcp/extract.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/extract.py)
- [web_search_plus_mcp/bounded_context_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/bounded_context_v3.py)
- [web_search_plus_mcp/span_extraction_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/span_extraction_v3.py)
- [web_search_plus_mcp/cache_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/cache_v3.py)
- [web_search_plus_mcp/cache_identity_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/cache_identity_v3.py)
- [web_search_plus_mcp/state_store_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/state_store_v3.py)
</details>

# 提取、有界上下文、语义跨度与缓存

本主题覆盖 `web-search-plus-mcp` v3 引擎在网页正文提取、响应裁剪、语义跨度切分与缓存层之间的协同设计。`web_extract` 与 `web_search` 共享 v3 请求/响应契约，但提取链路需要额外处理目标安全校验、跨段落语义化与可重放缓存，因此被拆分到多个模块中。

## 提取链路与目标保护

`web_search_plus_mcp/extract.py` 是网页正文提取的主入口，负责把上游 `web_extract` 请求派发到具体的 provider（如 Tavily、Serper、Keenable），并在派发前对目标 URL 施加安全检查。

- v0.14.0 引入**私有/内网提取目标保护**：在派发前阻断 loopback、RFC1918、CGNAT、IPv6 私有/映射地址等内网段 资料来源：[web_search_plus_mcp/extract.py]()
- 该机制把 MCP 工具从潜在的 SSRF 入口中隔离，仅放行公网可解析的目标
- 域名比对沿用 v0.15.0 强化的 authority-domain 匹配，避免同形异义或子串继承导致的绕过
- v0.16.0 将 `serper` 暴露为 `web_extract` provider 之一，使其与搜索端共用同一套 API key 体系 资料来源：[web_search_plus_mcp/extract.py]()

## 有界上下文与语义跨度

v1.1.0 在 MCP 响应中暴露了**语义提取跨度**（semantic extraction spans），让下游 Agent 可以按"语义单元"消费抓取到的正文，而不是按整页或固定窗口读取。

- `bounded_context_v3.py` 负责按 token 预算与语义边界裁剪响应，生成可在 v3 契约中序列化的有界上下文 资料来源：[web_search_plus_mcp/bounded_context_v3.py]()
- `span_extraction_v3.py` 实现跨度切分逻辑，每个 span 携带文本片段、起止偏移、来源段落与置信度 资料来源：[web_search_plus_mcp/span_extraction_v3.py]()
- 切分结果嵌入到 `extract_plus` 响应中，供模型按需引用

这一设计把"抓到了多少字"与"模型实际能用多少字"解耦：提取层负责召回足够多的 span，有界上下文层负责在预算下选出最优组合并拼装为最终响应。

## 缓存身份与 SQLite 状态

缓存层由三个模块协同实现，彼此职责清晰分离：

| 模块 | 职责 | 关键标识 |
|------|------|---------|
| `cache_v3.py` | envelope 级缓存读写 | 完整 search-cache envelope |
| `cache_identity_v3.py` | 缓存键构造与版本化 | 提取缓存身份 v6 |
| `state_store_v3.py` | 运行态与冷却持久化 | SQLite state schema v3 |

补充说明：

- `cache_v3.py` 自 v0.17.0 起仅管理"完整的 Web Search Plus 搜索缓存 envelope"，不再误吞 provider 健康/host usage 等异构数据 资料来源：[web_search_plus_mcp/cache_v3.py]()
- `cache_identity_v3.py` 在 v1.1.0 引入的 **identity v6** 让 span 粒度的缓存键具备版本化复用条件 资料来源：[web_search_plus_mcp/cache_identity_v3.py]()
- `state_store_v3.py` 使用 **SQLite state schema v3** 持久化冷却时间、命中率与 provider 健康度 资料来源：[web_search_plus_mcp/state_store_v3.py]()

身份版本号提升（如 v5 → v6）通常意味着键的组成因子发生不兼容变更；旧键自然淘汰而非迁移，由幂等的 `clear` 操作回收。

## 失败语义与社区反馈

提取链路的失败语义受上游**自动路由**影响。v1.0.0 曾出现 auto routing 构建**单候选计划**的回归（issue #27），任何 provider 失败都会直接终止而不再回退；v1.0.1 通过恢复多 provider fallback 行为修复了该问题。此外，`extract_plus` 自 v0.12.0 起会读取 `config.json` 中 `auto_routing.disabled_providers`，与搜索端的禁用列表保持一致，避免在已知不可用 provider 上浪费提取预算。

---

<a id='page-4'></a>

## 配置、SDK、入门与运维（含 v1.0 迁移）

### 相关页面

相关主题：[项目概述与 v3 合约架构](#page-1), [提供商系统与自动路由（含 v1.0 回落修复）](#page-2), [提取、有界上下文、语义跨度与缓存](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [web_search_plus_mcp/config.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/config.py)
- [web_search_plus_mcp/env_loader.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/env_loader.py)
- [web_search_plus_mcp/compat_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/compat_v3.py)
- [web_search_plus_mcp/request_gate_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/request_gate_v3.py)
- [web_search_plus_mcp/budget_preflight_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/budget_preflight_v3.py)
- [web_search_plus_mcp/diversity_v3.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/diversity_v3.py)
- [web_search_plus_mcp/server.py](https://github.com/robbyczgw-cla/web-search-plus-mcp/blob/main/web_search_plus_mcp/server.py)
</details>

# 配置、SDK、入门与运维（含 v1.0 迁移）

## 系统定位与组件范围

`web-search-plus-mcp` 是一个独立 MCP（Model Context Protocol）服务器，承载 `web_search` 与 `web_extract` 两个工具入口，并对外提供一致的 v3 请求/响应契约。配置、SDK 与运维围绕以下目标展开：

- **契约对齐**：MCP 层 → CLI 层 → v3 engine 层统一使用 canonical v3 契约，避免"silent schema drift"。资料来源：[web_search_plus_mcp/compat_v3.py:1-120]()
- **多 provider 回退**：`provider=auto` 模式下应构建多候选计划，单一 provider 失败（配额、配额限制、超时）须能回退到链路下一节点。资料来源：[web_search_plus_mcp/compat_v3.py:120-240]()
- **资源预算前置**：v1.1.0 起引入 `budget_preflight` 与 `diversity reranking`，在分发前先做成本/多样性评估。资料来源：[web_search_plus_mcp/budget_preflight_v3.py:1-80]()、[web_search_plus_mcp/diversity_v3.py:1-80]()

## 配置层（环境变量、JSON 配置、v3 契约）

配置加载遵循"环境变量优先 + JSON 兜底 + 严格 schema 校验"的三段式：

| 阶段 | 负责模块 | 关键行为 |
|---|---|---|
| 环境变量加载 | `env_loader.py` | 解析进程 env 中的 provider key（`SERPAPI_API_KEY`、`SERPER_API_KEY`、`TAVILY_API_KEY`、`KEENABLE_API_KEY` 等），缺失键按"未启用"处理而非报错 |
| JSON 配置合并 | `config.py` | 加载 `config.json`，合并 `auto_routing.disabled_providers`、`extract_plus` 优先级、`freshness`/`country`/`language` 等策略 |
| v3 请求规范化 | `compat_v3.py` | 把 MCP 工具入参折叠成 v3 `SearchRequest`/`ExtractRequest`，并补齐 `allow_fallback`、`cache_origin` 等字段 |

```mermaid
flowchart LR
  A[MCP tool call] --> B[compat_v3]
  C[process env] --> D[env_loader]
  E[config.json] --> F[config]
  D --> B
  F --> B
  B --> G[request_gate_v3]
  G --> H[budget_preflight_v3]
  H --> I[diversity_v3]
  I --> J[v3 engine / providers.d]
```

需特别注意：`--allow-fallback` 缺失时不得被解释为显式 `allow_fallback: false`，否则 `auto` 计划会坍缩为单候选（见社区 issue #27，v1.0.1 已修复）。资料来源：[web_search_plus_mcp/compat_v3.py:200-360]()、[web_search_plus_mcp/request_gate_v3.py:1-120]()

## 公共 Provider SDK 与入门

v1.1.0 起 SDK 形态演化为**公共 provider SDK** + **fail-closed `providers.d` 发现机制** + **一致性校验**，典型接入步骤：

1. **声明 provider 目录**：将自定义 provider 实现放入 `providers.d/`，命名遵循 `<name>_provider.py`，暴露 `search()` / `extract()` 同步或异步方法。资料来源：[web_search_plus_mcp/compat_v3.py:360-480]()
2. **配置 API key 与配额**：在 `config.json` 或环境变量中登记，端到端使用 `KEENABLE_API_KEY`（含可选 keyless 公共层，默认关闭）等字段。资料来源：[web_search_plus_mcp/config.py:1-160]()、[web_search_plus_mcp/env_loader.py:1-120]()
3. **跑一致性校验**：SDK 加载时执行 conformance check，缺失必需方法或签名不匹配的 provider 会被直接 fail-closed 拒绝加载。资料来源：[web_search_plus_mcp/compat_v3.py:480-600]()
4. **本地启动**：`uvx web-search-plus-mcp` 拉起独立 MCP 进程；亦可作为 Python 包在 Hermes 客户端中以 `web-search-plus-mcp` 服务器名注册。资料来源：[web_search_plus_mcp/server.py:1-160]()

自托管 profile（self-hosted profiles）、shadow observations（灰度观察）以及 Hermes-only Operator Console 在 v1.1.0 首次公开，用法见各自 README 段落。资料来源：[web_search_plus_mcp/budget_preflight_v3.py:80-200]()、[web_search_plus_mcp/diversity_v3.py:80-200]()

## v1.0 迁移与运维要点

迁移路径以"修复回退 + 收紧契约 + 暴露 SDK"为主线，关键运维动作如下：

- **回退链修复**：从 v1.0.0 升级到 ≥ v1.0.1 后，`provider=auto` 在 MCP → CLI → v3 三层边界之间会重建多候选计划；显式指定 provider 仍保持严格不回退策略。资料来源：[web_search_plus_mcp/compat_v3.py:600-760]()
- **缓存身份与状态 schema 升级**：v1.1.0 引入 extraction cache identity v6 与 SQLite state schema v3，旧缓存不会自动迁移，建议在升级前清理 `~/.cache/web-search-plus-mcp/` 与 SQLite 文件。资料来源：[web_search_plus_mcp/config.py:160-320]()
- **预算预检与多样性重排**：开启 `budget_preflight` 后会消耗少量本地 CPU 做代价估算；`diversity reranking` 会改变返回顺序与 `provider_attempt` 日志字段，需要日志聚合关注。资料来源：[web_search_plus_mcp/budget_preflight_v3.py:200-360]()、[web_search_plus_mcp/diversity_v3.py:200-360]()
- **私密/内网目标防护**：`web_extract` 在分发前会阻断 loopback、RFC1918、CGNAT、IPv6 本地/ULA 等私有地址（自 v0.14.0 起持续强化）。资料来源：[web_search_plus_mcp/request_gate_v3.py:120-260]()
- **运维排障**：当出现"仅一个 provider 被规划"时，检查 `--allow-fallback` 是否被显式置 `false`、env 中是否真的存在多个有效 key、以及 `auto_routing.disabled_providers` 是否误把候选清空。资料来源：[web_search_plus_mcp/compat_v3.py:760-900]()

> 社区提醒：v1.0.0 的单候选回退缺陷已在 v1.0.1 修复，但 v1.0.0 现场用户须显式升级 PyPI 包才能消除症状（参见 issue #27）。

## 常见问题速查

| 现象 | 可能原因 | 处置 |
|---|---|---|
| `auto` 仅规划一个 provider | v1.0.0 缺陷或 `--allow-fallback=false` | 升级到 ≥ v1.0.1，移除显式 `allow_fallback: false` |
| 自定义 provider 不生效 | `providers.d` 一致性校验失败 | 检查方法签名、错误日志中的 conformance 报告 |
| 提取失败但搜索成功 | 命中私有地址黑名单或 extract schema 缺字段 | 检查 `web_extract` 入参并放宽安全策略前先审计目标 |
| SQLite/缓存不兼容 | schema 版本不一致 | 清理缓存目录并让 SDK 重建 schema v3 |

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：robbyczgw-cla/web-search-plus-mcp

摘要：发现 19 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：安装坑 - 失败模式：installation: web-search-plus-mcp v0.11.0。

## 1. 安装坑 · 失败模式：installation: web-search-plus-mcp v0.11.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: web-search-plus-mcp v0.11.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.11.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.11.0 | web-search-plus-mcp v0.11.0

## 2. 安装坑 · 失败模式：installation: web-search-plus-mcp v0.17.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: web-search-plus-mcp v0.17.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.17.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.17.0 | web-search-plus-mcp v0.17.0

## 3. 安装坑 · 失败模式：installation: web-search-plus-mcp v1.0.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: web-search-plus-mcp v1.0.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v1.0.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v1.0.0 | web-search-plus-mcp v1.0.0

## 4. 安装坑 · 失败模式：installation: web-search-plus-mcp v1.1.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: web-search-plus-mcp v1.1.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v1.1.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v1.1.0 | web-search-plus-mcp v1.1.0

## 5. 安装坑 · 来源证据：v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/robbyczgw-cla/web-search-plus-mcp/issues/27 | 来源类型 github_issue 暴露的待验证使用条件。

## 6. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/robbyczgw-cla/web-search-plus-mcp | host_targets=mcp_host, claude, cursor

## 7. 配置坑 · 失败模式：configuration: v0.12.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: v0.12.0
- 对用户的影响：Upgrade or migration may change expected behavior: v0.12.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.12.0 | v0.12.0

## 8. 配置坑 · 失败模式：configuration: v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit
- 证据：failure_mode_cluster:github_issue | https://github.com/robbyczgw-cla/web-search-plus-mcp/issues/27 | v1.0.0: auto routing builds single-candidate plans — no fallback on quota/rate-limit

## 9. 配置坑 · 失败模式：configuration: web-search-plus-mcp v0.13.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: web-search-plus-mcp v0.13.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.13.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.13.0 | web-search-plus-mcp v0.13.0

## 10. 配置坑 · 失败模式：configuration: web-search-plus-mcp v0.14.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: web-search-plus-mcp v0.14.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.14.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.14.0 | web-search-plus-mcp v0.14.0

## 11. 配置坑 · 失败模式：configuration: web-search-plus-mcp v0.15.0

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: web-search-plus-mcp v0.15.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.15.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.15.0 | web-search-plus-mcp v0.15.0

## 12. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/robbyczgw-cla/web-search-plus-mcp | README/documentation is current enough for a first validation pass.

## 13. 维护坑 · 失败模式：migration: web-search-plus-mcp v1.0.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this migration risk before relying on the project: web-search-plus-mcp v1.0.1
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v1.0.1
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v1.0.1 | web-search-plus-mcp v1.0.1

## 14. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/robbyczgw-cla/web-search-plus-mcp | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/robbyczgw-cla/web-search-plus-mcp | no_demo; severity=medium

## 16. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/robbyczgw-cla/web-search-plus-mcp | no_demo; severity=medium

## 17. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/robbyczgw-cla/web-search-plus-mcp | issue_or_pr_quality=unknown

## 18. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/robbyczgw-cla/web-search-plus-mcp | release_recency=unknown

## 19. 维护坑 · 失败模式：maintenance: web-search-plus-mcp v0.16.0

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: web-search-plus-mcp v0.16.0
- 对用户的影响：Upgrade or migration may change expected behavior: web-search-plus-mcp v0.16.0
- 证据：failure_mode_cluster:github_release | https://github.com/robbyczgw-cla/web-search-plus-mcp/releases/tag/v0.16.0 | web-search-plus-mcp v0.16.0

<!-- canonical_name: robbyczgw-cla/web-search-plus-mcp; human_manual_source: deepwiki_human_wiki -->
