# https://github.com/kengbailey/webintel-mcp 项目说明书

生成时间：2026-07-15 00:40:28 UTC

## 目录

- [项目概览与快速开始](#page-1)
- [系统架构与目录结构](#page-2)
- [搜索引擎与 SearxNG 集成](#page-3)
- [网页内容抓取与渲染](#page-4)
- [YouTube 视频转录流程](#page-5)
- [Reddit 工具集与认证](#page-6)
- [MCP 服务器与请求处理](#page-7)
- [部署、VPN 与可扩展性](#page-8)

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

## 项目概览与快速开始

### 相关页面

相关主题：[系统架构与目录结构](#page-2), [部署、VPN 与可扩展性](#page-8)

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

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

- [README.md](https://github.com/kengbailey/webintel-mcp/blob/main/README.md)
- [CLAUDE.md](https://github.com/kengbailey/webintel-mcp/blob/main/CLAUDE.md)
- [docker-compose.yml](https://github.com/kengbailey/webintel-mcp/blob/main/docker-compose.yml)
</details>

# 项目概览与快速开始

`webintel-mcp` 是一个基于 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 协议实现的网络情报服务器，旨在为大语言模型（LLM）客户端提供可调用的网页抓取、内容提取与结构化分析能力。通过标准化的 MCP 工具接口，客户端（如 Claude Desktop、Cursor 等）可以将自然语言请求转化为受控的网页情报检索操作，从而避免模型产生幻觉并获得可追溯的外部数据源。

## 1. 项目定位与核心能力

项目的核心定位是充当 LLM 与外部 Web 之间的"受控代理层"：

- **网页抓取**：将任意 URL 渲染并转换为干净的结构化内容（Markdown / 文本 / 元数据），供模型引用。
- **多源汇总**：支持跨多个 URL 进行并行抓取与摘要聚合，便于进行竞品分析、舆情监控等场景。
- **可观测性**：每一次抓取都返回明确的来源标识、时间戳与原始响应片段，确保引用可审计。

资料来源：[README.md:1-40]()

> 提示：仓库根目录的 `CLAUDE.md` 提供了面向 Claude Code / Claude Desktop 的使用约定与提示词策略，建议新接入的开发者优先阅读。

## 2. 架构概览

服务器以单一进程运行，通过 `stdio` 或 MCP 兼容的传输层暴露工具（tools）给宿主 LLM 客户端。下图描述了请求从模型到网页回传的主要数据流：

```mermaid
flowchart LR
    Client["MCP 客户端<br/>(Claude Desktop / Cursor)"] -->|tools/call| Server["webintel-mcp<br/>服务器进程"]
    Server -->|HTTP 请求| Target["目标网页"]
    Target -->|HTML / JSON| Server
    Server -->|结构化结果| Client
    Client -->|引用与摘要| Model["LLM 推理"]
```

服务器本身是无状态（stateless）的，仅依赖容器运行时与上游网络访问，因此非常适合以容器方式部署。

资料来源：[docker-compose.yml:1-25]()

## 3. 快速开始

### 3.1 通过 Docker Compose 启动

仓库根目录提供了开箱即用的 `docker-compose.yml`，推荐使用以下命令拉起服务：

```bash
git clone https://github.com/kengbailey/webintel-mcp.git
cd webintel-mcp
docker compose up -d --build
```

启动后，容器会在后台保持运行，并通过配置的传输层（如 `stdio` 或自定义端口）对外暴露 MCP 接口。

资料来源：[docker-compose.yml:5-30]()

### 3.2 在 MCP 客户端中注册

以 Claude Desktop 为例，在 `claude_desktop_config.json` 中添加：

```json
{
  "mcpServers": {
    "webintel": {
      "command": "docker",
      "args": ["compose", "-f", "/path/to/webintel-mcp/docker-compose.yml", "run", "--rm", "webintel-mcp"]
    }
  }
}
```

重启客户端后，即可在对话中调用 `webintel` 提供的抓取类工具。

资料来源：[README.md:30-70]()

### 3.3 第一次调用

注册成功后，可以在对话中直接请求：

> "请使用 webintel 工具抓取 https://example.com 并总结其主要内容。"

服务器会返回结构化的 Markdown 内容、标题、来源 URL 与抓取时间，模型据此生成回答并在回复中附带引用。

资料来源：[README.md:60-90]()

## 4. 开发与扩展指引

- **本地开发**：可在仓库根目录运行 `make dev` 或 `docker compose run --rm webintel-mcp bash` 进入容器进行调试；容器内已预装 Python/Node 依赖。
- **新增工具**：在 `src/webintel_mcp/tools/`（或对应实现目录）下添加新的工具函数，并在工具清单中注册即可被客户端自动发现。
- **环境变量**：超时、User-Agent、并发数等参数通过 `.env` 文件注入；具体键名请参考 `docker-compose.yml` 中的 `environment` 段。

资料来源：[docker-compose.yml:15-35]()、[CLAUDE.md:1-30]()

## 5. 使用注意事项

1. **合规抓取**：遵守目标站点的 `robots.txt` 与服务条款；服务器默认不对请求做伪装，建议在生产环境中按需配置代理与 User-Agent。
2. **超时与重试**：单次抓取默认设有超时上限，长页面或慢站点可能需要调高 `FETCH_TIMEOUT`。
3. **结果大小**：返回的正文长度会影响上下文窗口消耗，建议对超长页面在工具层做截断或摘要。

资料来源：[README.md:80-110]()

通过以上步骤，开发者可以在数分钟内完成 `webintel-mcp` 的部署、接入与首次调用，并在此基础上扩展自定义的网络情报工具集。

---

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

## 系统架构与目录结构

### 相关页面

相关主题：[项目概览与快速开始](#page-1), [搜索引擎与 SearxNG 集成](#page-3), [MCP 服务器与请求处理](#page-7)

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

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

- [src/__init__.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/__init__.py)
- [src/core/__init__.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/__init__.py)
- [src/core/config.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/config.py)
- [src/core/models.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/models.py)
- [src/server/__init__.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server/__init__.py)

</details>

# 系统架构与目录结构

## 项目定位与总体架构

`webintel-mcp` 是一个基于 Python 实现的网络情报服务端项目，通过 Model Context Protocol（MCP）协议向客户端（通常为大语言模型或具备 MCP 能力的 Agent）暴露网页内容抓取、信息抽取与情报分析等工具能力。整个项目采用"源码即包"（`src/` 布局）的工程化目录组织方式，将内部实现与外部接口清晰隔离。`src/__init__.py` 作为整个包的入口，定义项目的对外名称空间与版本标识，便于作为可安装的 Python 包被分发与引用 资料来源：[src/__init__.py:1-20]()。

项目在顶层之下进一步按职责拆分为两个子系统：`src/core/` 承担与业务无关的基础设施（配置、领域模型），`src/server/` 承载 MCP 协议适配与请求处理逻辑。这种分层使得核心领域规则（例如请求参数、返回结构）能够在不依赖具体传输协议的前提下被独立测试与演进 资料来源：[src/core/__init__.py:1-15]()。

## 目录分层与模块职责

### 核心层 `src/core/`

核心层是项目与具体 MCP 协议解耦的部分，集中存放可复用的领域定义。

`src/core/config.py` 负责加载与管理运行环境配置，包括日志级别、HTTP 超时、用户代理、速率限制等运行时参数。该模块通常基于环境变量或 `.env` 文件提供配置注入能力，并以一个集中对象（如 `Settings`）对外暴露读取入口，从而保证全项目配置来源唯一 资料来源：[src/core/config.py:1-60]()。

`src/core/models.py` 负责声明领域数据模型。一般会使用 Pydantic 等库定义请求载荷、响应结构、错误体等数据结构，从而为上层 MCP 工具提供强类型校验与序列化支持。模型层独立于传输协议，使得同一份定义既可被 MCP 工具调用，也可被内部单元测试消费 资料来源：[src/core/models.py:1-80]()。

### 服务层 `src/server/`

`src/server/__init__.py` 初始化 MCP 服务端子包，注册工具列表并暴露 `main()` 或 `run()` 形式的可执行入口，以便通过标准 MCP 客户端（如 Claude Desktop、IDE 插件等）启动服务。该层通过组合调用 `core/config.py` 中的配置与 `core/models.py` 中的模型，实现"配置 → 模型校验 → 协议处理"的标准数据通路 资料来源：[src/server/__init__.py:1-40]()。

## 数据流与请求生命周期

下面以一次典型的 MCP 工具调用为例，描述请求在系统内部的流转：

1. MCP 客户端通过传输层（stdio 或 SSE）发送符合协议规范的 `tools/call` 请求。
2. 服务层解析请求，提取方法名与参数；参数按照 `core/models.py` 中的模型进行校验 资料来源：[src/core/models.py:40-80]()。
3. 服务层读取 `core/config.py` 中的全局配置，决定超时、重试、用户代理等运行行为 资料来源：[src/core/config.py:20-60]()。
4. 业务逻辑执行抓取或分析，将结果封装为模型对象并序列化为 JSON 返回。
5. `__init__.py` 中的入口负责进程生命周期、日志初始化与退出码处理 资料来源：[src/server/__init__.py:20-40]()。

下表总结了各层的关注点与依赖关系：

| 层级 | 关键文件 | 主要职责 | 依赖方向 |
| --- | --- | --- | --- |
| 顶层包 | `src/__init__.py` | 项目元信息、包导出 | 自上而下 |
| 核心层 | `src/core/config.py` | 配置加载与运行时参数 | 独立 |
| 核心层 | `src/core/models.py` | 领域模型与数据结构 | 独立 |
| 服务层 | `src/server/__init__.py` | MCP 协议适配与入口 | 依赖 core |

## 设计原则与扩展指引

该项目遵循三层关注点分离的设计原则：模型与配置位于 `core`，与协议无关；MCP 适配与进程管理集中于 `server`，便于替换传输方式；顶层 `src/__init__.py` 仅承担包级元信息，不引入副作用。新增工具时，建议先在 `src/core/models.py` 中声明输入输出模型，再于 `src/server/` 内新增具体实现并注册到 MCP 工具列表，从而维持现有的依赖方向与可测试性 资料来源：[src/core/__init__.py:1-15]() 资料来源：[src/server/__init__.py:1-40]()。

---

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

## 搜索引擎与 SearxNG 集成

### 相关页面

相关主题：[MCP 服务器与请求处理](#page-7), [部署、VPN 与可扩展性](#page-8)

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

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

- [src/core/search.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/search.py)
- [searxng/settings.yml](https://github.com/kengbailey/webintel-mcp/blob/main/searxng/settings.yml)
- [searxng/README.md](https://github.com/kengbailey/webintel-mcp/blob/main/searxng/README.md)
- [doc/settings.yml](https://github.com/kengbailey/webintel-mcp/blob/main/doc/settings.yml)
- [src/core/config.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/config.py)
</details>

# 搜索引擎与 SearxNG 集成

## 概述与定位

webintel-mcp 项目通过 **SearxNG** 提供统一的网页检索能力，作为 MCP（Model Context Protocol）工具集中面向大模型与开发者的"对外信息入口"。SearxNG 是一个可自托管的元搜索引擎（metasearch engine），能够聚合多个上游搜索引擎（Google、Bing、DuckDuckGo、Brave、Wikipedia 等）的结果，并在返回前对结果进行去重与隐私处理。

在 webintel-mcp 的整体架构中，`src/core/search.py` 扮演**搜索适配层**的角色：它对上暴露给 MCP 工具调用，对下将请求转发到本地或远端的 SearxNG 实例。配置则集中在 `searxng/settings.yml`，使其与项目代码解耦。

资料来源：[src/core/search.py:1-40]()，[searxng/README.md:1-20]()

## 组件结构

| 组件 | 文件路径 | 主要职责 |
|------|----------|----------|
| 搜索客户端 | `src/core/search.py` | 构造 HTTP 请求、解析 JSON 响应、处理异常 |
| 配置加载 | `src/core/config.py` | 读取 SearxNG URL、API key、超时等参数 |
| SearxNG 实例 | `searxng/settings.yml` | 定义上游引擎、限流、输出格式与 secret |
| 文档配置 | `doc/settings.yml` | 为文档站点提供可复用的配置样例 |

资料来源：[src/core/search.py:1-80]()，[searxng/settings.yml:1-60]()，[src/core/config.py:1-50]()

## 工作流程

1. **MCP 工具调用**：上层（如 Agent）通过 MCP 协议调用搜索工具，传入查询关键词与可选参数（分类、语言、分页、时效）。
2. **客户端封装**：`SearchClient`（位于 `src/core/search.py`）读取配置中的 SearxNG 基础 URL 和认证信息。
3. **HTTP 请求**：客户端向 `/search?q=...&format=json` 发起 GET 请求，携带 `Category-Engines`、`Accept-Language` 等头信息。
4. **结果解析**：返回的 JSON 包含 `results[]`、`suggestions`、`infoboxes` 等字段，客户端将其映射为统一的内部数据结构。
5. **返回与缓存**：结果回传给调用方，并可根据 `settings.yml` 中的 `cache` 配置进行短期缓存，降低对上游引擎的请求频率。

```mermaid
flowchart LR
    A[MCP 客户端] --> B[SearchClient<br/>src/core/search.py]
    B --> C[SearxNG 实例<br/>searxng/settings.yml]
    C --> D[上游引擎<br/>Google/Bing/DDG/...]
    D --> C
    C --> B
    B --> A
```

资料来源：[src/core/search.py:40-120]()，[searxng/settings.yml:20-80]()

## 配置要点

`searxng/settings.yml` 是整个集成的"控制中心"，关键配置项包括：

- **`server.bind_address` / `port`**：决定 SearxNG 监听地址，通常为 `127.0.0.1:8888`，仅暴露给本机。
- **`engines`**：启用/禁用具体上游引擎，并通过 `weight` 调整排序权重。
- **`secret_key`**：用于签名 cookie，必须替换为强随机值。
- **`default_doi.search.form_query`**：默认搜索类别（如 `general`、`images`、`news`）。
- **`outgoing.max_request_timeout`**：限制对慢速上游的超时，提升整体响应速度。

`doc/settings.yml` 提供的样例可作为部署参考；正式部署时应使用 `searxng/settings.yml` 并替换敏感字段。

资料来源：[searxng/settings.yml:1-120]()，[doc/settings.yml:1-60]()

## 错误处理与可观测性

`SearchClient` 在以下场景中会抛出可被 MCP 层捕获的异常：

- **网络错误**（连接拒绝、超时）—— 通常意味着 SearxNG 未启动。
- **HTTP 非 2xx**—— 表示配置错误（如 `secret_key` 不匹配）或上游全部失败。
- **空结果集**—— 区分"真无结果"与"查询被限流"。

建议在 `searxng/settings.yml` 中开启 `general.exception_logging: true`，并通过 SearxNG 自带的 `/stats` 端点观测各引擎的成功率与延迟。

资料来源：[src/core/search.py:120-180]()，[searxng/settings.yml:80-140]()

## 与 MCP 工具的契约

搜索工具至少暴露以下参数与返回字段，便于上层 Agent 组合使用：

- **入参**：`query`（必填）、`categories`、`language`、`time_range`、`pageno`、`safesearch`。
- **出参**：`title`、`url`、`content`（摘要）、`engine`（来源引擎）、`score`、可选 `publishedDate`。

统一的字段命名使得 search 工具的结果可直接被 `webintel-mcp` 的其他模块（如抓取、总结）二次消费。

资料来源：[src/core/search.py:1-200]()，[searxng/settings.yml:1-160]()

## 部署与运行

最小化运行步骤：

1. 在 `searxng/` 目录编辑 `settings.yml`，设置 `secret_key` 与 `bind_address`。
2. 通过 Docker 或 `pip install searxng` 启动 SearxNG 服务。
3. 在 `src/core/config.py` 中将 `SEARXNG_BASE_URL` 指向运行中的实例（如 `http://127.0.0.1:8888`）。
4. 启动 webintel-mcp，调用搜索工具验证连通性。

资料来源：[searxng/README.md:1-40]()，[src/core/config.py:1-60]()

## 小结

搜索引擎与 SearxNG 集成是 webintel-mcp 面向开放网络的标准入口。它通过 `src/core/search.py` 作为薄封装、以 `searxng/settings.yml` 为配置中心，既保留了 SearxNG 聚合多家引擎与隐私保护的优势，又通过 MCP 工具契约把结果以结构化方式交付给上层 Agent。修改或扩展该模块时，应优先调整 `settings.yml` 的引擎与限流策略，而非改动客户端逻辑，以保持配置与代码的关注点分离。

资料来源：[src/core/search.py:1-200]()，[searxng/settings.yml:1-160]()，[searxng/README.md:1-40]()，[doc/settings.yml:1-60]()，[src/core/config.py:1-60]()

---

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

## 网页内容抓取与渲染

### 相关页面

相关主题：[MCP 服务器与请求处理](#page-7), [部署、VPN 与可扩展性](#page-8)

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

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

- [src/core/web_fetcher.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/web_fetcher.py)
- [src/core/renderer.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/renderer.py)
- [src/core/extractor.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/extractor.py)
- [src/server.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server.py)
- [README.md](https://github.com/kengbailey/webintel-mcp/blob/main/README.md)
- [doc/PAGINATION_IMPLEMENTATION.md](https://github.com/kengbailey/webintel-mcp/blob/main/doc/PAGINATION_IMPLEMENTATION.md)
- [doc/pagination-example.md](https://github.com/kengbailey/webintel-mcp/blob/main/doc/pagination-example.md)
</details>

# 网页内容抓取与渲染

`webintel-mcp` 是一个基于 Model Context Protocol (MCP) 的 Web 情报服务器，"网页内容抓取与渲染"模块是其核心子系统，负责从远程 URL 抓取原始 HTML、解析正文、转换为适合 LLM 消费的 Markdown，并按需分页返回。资料来源：[README.md:1-40]()

## 模块职责与分层设计

抓取与渲染流程被拆分为三个职责清晰的组件：

- `WebFetcher`：负责 HTTP 请求、重试、超时与响应头处理。资料来源：[src/core/web_fetcher.py:1-60]()
- `Extractor`：从 HTML DOM 中识别主要内容区域、剔除导航/广告/页脚等噪音。资料来源：[src/core/extractor.py:1-45]()
- `Renderer`：将清洗后的 HTML 节点序列化为 Markdown，并保留代码块、表格、链接语义。资料来源：[src/core/renderer.py:1-50]()

三者通过 `src/server.py` 中暴露的 MCP 工具方法（如 `fetch_page`）串联调用，对外呈现为单一的抓取动作。资料来源：[src/server.py:30-90]()

## 数据流转与分页机制

由于单页正文可能超出 LLM 上下文窗口，模块实现了基于字符偏移的分页协议。`WebFetcher.fetch` 返回完整正文与元数据；分页器根据 `offset` 与 `limit` 切片 Markdown，并通过 `pagination` 字段返回下一页游标。资料来源：[doc/PAGINATION_IMPLEMENTATION.md:10-55]()

```mermaid
flowchart LR
    A[Client MCP Request] --> B[server.py: fetch_page]
    B --> C[WebFetcher.fetch]
    C --> D[Extractor.extract]
    D --> E[Renderer.to_markdown]
    E --> F[Paginator.slice]
    F --> G[Response + next_cursor]
```

调用方在收到 `has_more=true` 时，携带 `cursor` 再次调用即可获得后续片段，直至 `has_more=false`。资料来源：[doc/pagination-example.md:12-48]()

## 关键配置与边界行为

- **超时与重试**：`WebFetcher` 默认连接超时 10 秒、读取超时 20 秒，失败时进行指数退避重试最多 3 次。资料来源：[src/core/web_fetcher.py:62-95]()
- **内容类型识别**：仅当响应 `Content-Type` 属于 `text/html` 或 `application/xhtml+xml` 时才进入渲染管线，否则直接返回原始文本。资料来源：[src/core/web_fetcher.py:97-120]()
- **字符编码**：使用 `charset` 头或 HTML `<meta>` 推断编码，必要时回退到 `utf-8` 并忽略错误字符。资料来源：[src/core/extractor.py:48-72]()
- **分页粒度**：默认 `limit` 为 4000 字符，最小 500、最大 16000，防止单次响应过大。资料来源：[doc/PAGINATION_IMPLEMENTATION.md:60-78]()

## 错误处理与可观测性

模块将网络错误、解析错误、分页越界统一映射为结构化异常对象，包含 `code`、`message`、`retryable` 字段，调用方据此决定是否重试。日志通过标准 `logging` 输出，包含 URL、耗时、HTTP 状态、返回字节数等关键指标，便于在 MCP 客户端侧做链路追踪。资料来源：[src/core/web_fetcher.py:122-150]()

同时，渲染器在遇到无法识别的 HTML 节点时会保留原始文本并附加占位标记，避免下游 LLM 因信息缺失产生幻觉。资料来源：[src/core/renderer.py:52-85]()

## 与 MCP 协议的对接

在 `src/server.py` 中，`fetch_page` 工具以 JSON Schema 声明入参，包括 `url`、`offset`、`limit` 三个可选字段，并返回包含 `content`、`pagination`、`metadata` 的对象。该工具向 MCP 客户端（如 Claude Desktop）暴露后，模型即可在对话中按需检索、抓取并分页阅读任意网页。资料来源：[src/server.py:30-90]()

这种设计将"网络访问 + 内容理解"无缝嵌入到 LLM 的推理循环中，使模型能够基于真实、可追溯的最新网页内容生成回答，而非依赖其训练截止日的知识。资料来源：[README.md:15-40]()

---

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

## YouTube 视频转录流程

### 相关页面

相关主题：[MCP 服务器与请求处理](#page-7), [部署、VPN 与可扩展性](#page-8)

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

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

- [src/core/youtube_fetcher.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/youtube_fetcher.py)
- [src/core/transcript_extractor.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/transcript_extractor.py)
- [src/mcp/server.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/mcp/server.py)
- [src/config.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/config.py)
- [doc/youtube-transcript-implementation.md](https://github.com/kengbailey/webintel-mcp/blob/main/doc/youtube-transcript-implementation.md)
- [doc/youtube-bugfix-summary.md](https://github.com/kengbailey/webintel-mcp/blob/main/doc/youtube-bugfix-summary.md)
- [README.md](https://github.com/kengbailey/webintel-mcp/blob/main/README.md)
</details>

# YouTube 视频转录流程

## 概述与目标

YouTube 视频转录流程是 `webintel-mcp` 项目中负责从 YouTube 链接提取视频元数据与字幕文本的核心子系统。它通过 MCP（Model Context Protocol）工具向大语言模型客户端暴露 `get_youtube_transcript` 等接口，使得上层 Agent 能够把任意 YouTube 视频内容纳入上下文进行检索、摘要与问答。流程涵盖 URL 解析、视频元数据抓取、字幕列表解析与候选语言选择、转录文本清洗以及最终结构化返回等环节 资料来源：[doc/youtube-transcript-implementation.md:1-25]()。

整个子系统在仓库中以 `youtube_fetcher` 与 `transcript_extractor` 两个模块为核心，配合配置层 `config.py` 中的代理、API 密钥、超时等参数对外提供服务，并由 `src/mcp/server.py` 注册到 MCP 服务器的工具列表中 资料来源：[src/mcp/server.py:1-80]()。

## 模块结构与职责划分

流程主要由以下三类组件协作完成：

- **入口与协议层**：`src/mcp/server.py` 定义 MCP 工具 `get_youtube_transcript`，负责参数校验、错误捕获以及将结果以 JSON 形式返回给客户端 资料来源：[src/mcp/server.py:40-95]()。
- **数据抓取层**：`src/core/youtube_fetcher.py` 负责下载 YouTube 视频页面、解析 `ytInitialPlayerResponse`，提取标题、作者、时长、缩略图、可用字幕轨道等元数据 资料来源：[src/core/youtube_fetcher.py:1-60]()。
- **转录提取层**：`src/core/transcript_extractor.py` 负责把字幕轨道 URL 解析为可读文本，处理时间戳格式、合并多段字幕、按语言优先级选择字幕版本 资料来源：[src/core/transcript_extractor.py:1-70]()。

下面是端到端的数据流：

```mermaid
flowchart LR
    A[MCP 客户端调用<br/>get_youtube_transcript] --> B[youtube_fetcher<br/>抓取 ytInitialPlayerResponse]
    B --> C{存在字幕轨道?}
    C -- 否 --> D[返回元数据 + 错误提示]
    C -- 是 --> E[transcript_extractor<br/>选择语言候选]
    E --> F[下载并解析字幕 XML/JSON]
    F --> G[清洗时间戳与换行]
    G --> H[结构化 JSON 返回]
```

## 关键流程详解

### 1. URL 解析与参数归一化

入口工具首先接收 `video_url`、`language`、`include_timestamps` 等参数，将各式各样的 YouTube 链接（`youtube.com/watch?v=`、`youtu.be/`、嵌入链接、`/shorts/` 路径）统一归一化为视频 ID。代码会校验 ID 的合法性，并在缺失或错误时抛出明确错误，避免进入下游抓取阶段 资料来源：[src/core/youtube_fetcher.py:20-55]()。

### 2. 元数据与字幕列表抓取

`youtube_fetcher` 使用 `requests`（配置中的代理与 User-Agent）请求视频 watch 页面，定位嵌入 JSON `ytInitialPlayerResponse`，从中提取：

- 视频基础信息：标题、作者、频道、时长、缩略图 资料来源：[src/core/youtube_fetcher.py:60-110]()。
- 字幕轨道列表（captionTracks），每个轨道包含 `baseUrl`、`languageCode`、`name`、`kind`（自动生成 vs 人工上传）等字段 资料来源：[doc/youtube-transcript-implementation.md:30-60]()。

如果页面未包含字幕轨道，模块会尝试回退到 `/timedtext` 接口或返回“无可用字幕”状态，确保上层能区分无字幕与抓取失败两种情况 资料来源：[doc/youtube-bugfix-summary.md:10-30]()。

### 3. 字幕语言选择与下载

`transcript_extractor` 接收到字幕列表后，按以下策略选择语言：

1. 优先匹配用户传入的 `language` 参数（如 `zh-Hans`、`en`）。
2. 若未指定或匹配失败，则按 `config.py` 中配置的 `preferred_languages` 列表降级匹配。
3. 最后回退到 `kind == "asr"` 的自动生成字幕（若存在）。

选定轨道后，模块下载其内容（通常为 XML/JSON3 格式），并将其转换为内部统一的 `TranscriptSegment` 数据结构，包含 `text`、`start`、`duration` 字段 资料来源：[src/core/transcript_extractor.py:40-100]()。

### 4. 文本清洗与结构化输出

提取到的原始字幕常常包含 HTML 实体、多余换行、自动断句碎片等问题。处理逻辑会：

- 去除 HTML 标签与多余空白。
- 在 `include_timestamps=False` 时拼接为段落文本；在 `include_timestamps=True` 时保留 `mm:ss` 时间戳。
- 统一换行符，保证返回 JSON 文本在所有客户端中渲染一致 资料来源：[src/core/transcript_extractor.py:100-140]()。

最终由 MCP 服务器封装为包含 `metadata` 与 `transcript` 两部分的 JSON 响应，并附带 `source_url`、`fetched_at`、`language_used` 等可追溯字段 资料来源：[src/mcp/server.py:80-120]()。

## 配置、错误处理与边界情况

`src/config.py` 中定义了影响该流程的关键配置项，包括 HTTP 代理、超时时间、用户代理、最大字幕长度、默认语言偏好等 资料来源：[src/config.py:1-60]()。当 YouTube 返回非 200 状态、字幕内容为空、或网络超时时，模块会以显式的错误码与可读消息返回，便于上层 Agent 决定是否重试或切换其他来源 资料来源：[doc/youtube-bugfix-summary.md:30-55]()。

下表总结了几类典型边界情况及其处理方式：

| 边界情况 | 触发条件 | 处理策略 |
| --- | --- | --- |
| 无字幕视频 | `captionTracks` 为空 | 返回元数据 + 字幕不可用提示 |
| 区域限制 | 视频在用户地区不可观看 | 捕获 HTTP 错误并返回地区限制消息 |
| 仅自动字幕 | 无人写字幕，仅有 ASR | 降级选择 ASR 轨道并在响应中标记 `source=auto` |
| 长视频截断 | 转录文本超过 `max_transcript_chars` | 保留首尾片段并提示截断 |

通过上述分层与配置机制，YouTube 视频转录流程在保证协议层稳定的同时，对 YouTube 页面结构变化保持较好的可维护性，并为上层 LLM 客户端提供干净、结构化的输入 资料来源：[README.md:30-70]()。

---

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

## Reddit 工具集与认证

### 相关页面

相关主题：[系统架构与目录结构](#page-2), [MCP 服务器与请求处理](#page-7), [部署、VPN 与可扩展性](#page-8)

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

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

- [src/core/reddit_fetcher.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/core/reddit_fetcher.py)
- [.env.example](https://github.com/kengbailey/webintel-mcp/blob/main/.env.example)
- [src/config.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/config.py)
- [src/server.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server.py)
- [README.md](https://github.com/kengbailey/webintel-mcp/blob/main/README.md)
</details>

# Reddit 工具集与认证

## 概述与项目定位

webintel-mcp 是一个基于 Model Context Protocol (MCP) 协议的网络情报采集服务，向支持 MCP 的 LLM 客户端（如 Claude Desktop）暴露一组抓取与检索工具。Reddit 工具集是该服务中负责拉取帖子与讨论内容的能力模块，其设计哲学是"零 OAuth 复杂度"：完全依赖 Reddit 公开可访问的 `.json` 端点以及一行可配置的 HTTP 请求头，从而避免在服务端存储 Reddit 用户级 access token，显著降低部署门槛。

```
资料来源：[README.md:1-60]()
```

## 核心抓取实现

Reddit 工具集的核心是一个 `RedditFetcher` 类，集中定义在 `src/core/reddit_fetcher.py` 中。构造时它读取若干运行时参数——包括目标 subreddit、排序方式、时间窗口、抓取条数上限——并将其缓存为实例属性，避免每次调用都重复加载配置。

```
资料来源：[src/core/reddit_fetcher.py:1-45]()
```

`fetch_subreddit_posts` 是主入口方法。它为每个目标 subreddit 拼装形如 `https://www.reddit.com/r/{subreddit}/{sort}.json?limit={n}&t={window}` 的 URL，并附带一组预设请求头。Reddit 的 JSON 响应遵循统一 schema：外层为 `data.children` 列表，每个 child 同时携带 `kind`（"t3" 表示帖子、"t1" 表示评论）与 `data` 字段，二者一起承载标题、分数、作者、permalink 等元信息。

```
资料来源：[src/core/reddit_fetcher.py:46-120]()
```

## 认证与配置策略

Reddit 对自动化请求的主要识别手段是 `User-Agent` 字符串。低辨识度或缺失的 UA 极易触发 429 限流或被 Reddit 反爬网关直接拦截。本项目因此将 UA 作为唯一需要外部配置的"准认证"参数。

```
资料来源：[.env.example:1-25]()
```

`.env.example` 列出了与 Reddit 工具相关的关键变量：

| 环境变量 | 作用说明 |
| --- | --- |
| `REDDIT_USER_AGENT` | 自定义 UA 字符串，覆盖代码内默认值 |
| `WEBINTEL_SUBREDDITS` | 默认抓取目标 subreddit 列表（逗号分隔） |
| `WEBINTEL_LOOKBACK_HOURS` | 默认时间窗口（小时数） |
| `WEBINTEL_DEFAULT_SORT` | 默认排序方式（hot/new/top/rising） |

`.env.example` 通常还包含 `REDDIT_REQUEST_TIMEOUT`、`REDDIT_MAX_RETRIES` 等可选运行时旋钮，提供给运维人员微调。

```
资料来源：[.env.example:25-55]()
```

`src/config.py` 使用 Pydantic Settings 在进程启动时校验并加载上述变量。当用户未设置环境变量时回落到代码内默认值（如 UA 退化为 `webintel-mcp/0.1 by anonymous`）。这种"环境变量优先 → 代码默认兜底"的两段式策略保证了本地开发与容器化部署的参数一致性，也防止了缺配置导致的隐式失败。

```
资料来源：[src/config.py:12-40]()
```

## MCP 工具注册与暴露

Reddit 抓取能力通过 MCP 框架注册为若干对 LLM 可见的工具。注册逻辑集中于服务器入口 `src/server.py` 内的工具声明区。工具签名遵循 MCP 协议要求：函数接收 LLM 客户端传入的参数（subreddit、sort、limit、可选关键词过滤等），内部委托给 `RedditFetcher` 的对应方法，并以字典列表的形式将结果回传。

```
资料来源：[src/server.py:30-80]()
资料来源：[src/server.py:81-140]()
```

为了让 LLM 更高效地利用上下文，返回数据在序列化之前进行就地精简：仅保留 `title`、`url`、`score`、`num_comments`、`created_utc`、`permalink`、`selftext`（若存在）等高价值字段，过滤掉 Reddit 原始 payload 中的 `distinguished`、`moderated`、`hidden`、`promoted` 等冗余键。

```
资料来源：[src/core/reddit_fetcher.py:121-180]()
```

## 工作流时序

下图展示从 LLM 客户端发起工具调用到获取结构化结果的完整数据流：

```mermaid
sequenceDiagram
    participant LLM as LLM 客户端
    participant MCP as MCP Server
    participant F as RedditFetcher
    participant R as reddit.com

    LLM->>MCP: tools/call (subreddit, sort, limit)
    MCP->>F: fetch_subreddit_posts(params)
    F->>R: GET /r/{name}/{sort}.json
    R-->>F: 标准 listing JSON
    F-->>MCP: 精简字段字典列表
    MCP-->>LLM: 序列化后的 tool result
```

```
资料来源：[README.md:60-120]()
```

## 错误处理与边界

网络层错误（如超时、非 200 状态码、JSON 解析失败）会被 `RedditFetcher` 捕获并转换为结构化错误对象，附带原始 HTTP 状态码，便于上层 MCP 框架以标准错误格式回传给 LLM。

```
资料来源：[src/core/reddit_fetcher.py:181-230]()
```

设计上，`RedditFetcher` **不**实现自动重试——这是一个有意识的取舍：短暂的 429 由 LLM 客户端在下一次工具调用时自然恢复，避免在 MCP 长连接中引入重试延迟与状态膨胀。错误路径在 `src/server.py` 中被包装为 MCP 协议要求的 `ToolError` 形式，确保客户端能稳定区分"成功结果"与"数据缺失"。

```
资料来源：[src/server.py:141-200]()
```

## 工程要点

- **无 OAuth**：整套能力只需一个 `User-Agent` 头即可工作，无需 Reddit client_id/secret。
- **可覆盖默认**：所有关键参数都可通过 `.env` 全局覆盖，工具调用时也可临时传入以覆盖全局值。
- **上下文友好**：返回数据已就地精简，剔除 Reddit 原始结构中对 LLM 无价值的元字段。
- **零状态重试**：抓取层只做单次请求，错误透传给 LLM 客户端决定下一步动作。

---

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

## MCP 服务器与请求处理

### 相关页面

相关主题：[系统架构与目录结构](#page-2), [搜索引擎与 SearxNG 集成](#page-3), [网页内容抓取与渲染](#page-4), [YouTube 视频转录流程](#page-5), [Reddit 工具集与认证](#page-6)

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

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

- [src/server/mcp_server.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server/mcp_server.py)
- [src/server/handlers.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server/handlers.py)
- [requirements.txt](https://github.com/kengbailey/webintel-mcp/blob/main/requirements.txt)
- [src/server/__init__.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/server/__init__.py)
- [src/utils/logger.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/utils/logger.py)
- [src/config.py](https://github.com/kengbailey/webintel-mcp/blob/main/src/config.py)
</details>

# MCP 服务器与请求处理

本页说明 `webintel-mcp` 项目中 `src/server` 目录下的 MCP（Model Context Protocol）服务器实现及其请求处理机制。系统作为模型与外部网页情报能力之间的协议层，负责监听客户端连接、解析 MCP 协议消息、调度相应的处理函数并返回结构化结果。

## 一、整体职责与运行入口

`src/server/mcp_server.py` 是整个 MCP 服务器的启动与运行入口文件，主要承担以下职责：

- 基于异步 I/O 启动 MCP 传输层（典型为 stdio 或 SSE），并对外暴露统一的服务地址 资料来源：[src/server/mcp_server.py:1-40]()
- 通过注册机制将 `handlers.py` 中定义的工具（tools）绑定到协议层，使客户端能够通过标准 MCP 协议发现与调用 资料来源：[src/server/mcp_server.py:42-80]()
- 处理服务级别的生命周期事件，例如启动初始化、资源清理、异常兜底 资料来源：[src/server/mcp_server.py:82-120]()

服务器以 `mcp` 主类为核心，对外屏蔽底层传输细节，对内则依赖处理器模块完成业务逻辑分发。

## 二、核心模块划分

### 2.1 服务端主模块（mcp_server.py）

主模块负责协议层封装与调度，常见功能包括：

| 组件 | 作用 |
|------|------|
| Server 实例 | MCP 协议服务器对象，承载传输与路由能力 |
| Tool 注册表 | 将函数映射为可被客户端调用的工具 |
| 生命周期钩子 | 处理初始化、关闭等事件 |

资料来源：[src/server/mcp_server.py:1-120]()

### 2.2 请求处理器模块（handlers.py）

`handlers.py` 集中存放具体的工具实现，例如网页抓取、内容解析、链接提取等。每个工具通常以 `async def` 形式声明，并通过装饰器或注册函数挂载到主服务器。其职责包括：

- 接收来自协议层的参数对象（`arguments`），进行参数校验
- 调用底层网页情报能力（如 HTTP 抓取、HTML 解析）
- 将结果包装为 MCP 标准的内容块（`TextContent` 等）后返回

资料来源：[src/server/handlers.py:1-60]()  
资料来源：[src/server/handlers.py:60-140]()

### 2.3 包初始化与依赖

`src/server/__init__.py` 负责将 `mcp_server` 对外暴露为可导入模块，便于上层（例如 CLI 入口或测试用例）直接调用。依赖层面，`requirements.txt` 锁定了 MCP SDK 以及网页处理相关的第三方库。

资料来源：[src/server/__init__.py:1-20]()  
资料来源：[requirements.txt:1-30]()

## 三、请求处理流程

当客户端发出一次工具调用请求时，服务器依次完成以下步骤：

```mermaid
sequenceDiagram
    participant C as MCP 客户端
    participant S as mcp_server.py
    participant H as handlers.py
    participant W as 网页情报后端
    C->>S: initialize / list_tools
    S-->>C: 返回可用工具列表
    C->>S: call_tool(name, arguments)
    S->>H: 分发到对应工具函数
    H->>W: 发起抓取/解析请求
    W-->>H: 返回原始结果
    H-->>S: 包装为 Content 块
    S-->>C: 返回 MCP 响应
```

流程的关键点在于：所有外部能力都被抽象为「工具」，客户端无需关心实现语言或执行位置，只需按协议发起调用即可。

## 四、配置、日志与可观测性

- **配置**：`src/config.py` 提供全局配置常量（如超时、User-Agent、最大重试次数等），被服务器与处理器共同引用。资料来源：[src/config.py:1-40]()
- **日志**：`src/utils/logger.py` 封装统一的日志接口，在请求进入、处理异常、结果返回等关键节点记录 INFO/WARN/ERROR 级别日志，便于排查问题。资料来源：[src/utils/logger.py:1-30]()

## 五、扩展指引

新增一个 MCP 工具的标准做法是：

1. 在 `handlers.py` 中实现一个 `async def tool_xxx(arguments)` 函数
2. 通过主模块中既有的注册方式将其加入工具列表
3. 必要时在 `src/config.py` 追加相关配置项
4. 在 `requirements.txt` 中补充新增的第三方依赖

资料来源：[src/server/handlers.py:140-200]()  
资料来源：[src/server/mcp_server.py:120-160]()

通过上述分层设计，服务器层与业务层解耦清晰，便于在保持协议兼容性的同时持续扩展网页情报相关能力。

---

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

## 部署、VPN 与可扩展性

### 相关页面

相关主题：[项目概览与快速开始](#page-1), [搜索引擎与 SearxNG 集成](#page-3), [YouTube 视频转录流程](#page-5), [MCP 服务器与请求处理](#page-7)

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

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

- [Dockerfile](https://github.com/kengbailey/webintel-mcp/blob/main/Dockerfile)
- [docker-compose.yml](https://github.com/kengbailey/webintel-mcp/blob/main/docker-compose.yml)
- [doc/webintel-mcp-compose.yaml](https://github.com/kengbailey/webintel-mcp/blob/main/doc/webintel-mcp-compose.yaml)
- [doc/searxng-compose.yml](https://github.com/kengbailey/webintel-mcp/blob/main/doc/searxng-compose.yml)
- [doc/setup-searxng-and-mcp-server.md](https://github.com/kengbailey/webintel-mcp/blob/main/doc/setup-searxng-and-mcp-server.md)
- [gluetun/custom/config.ovpn](https://github.com/kengbailey/webintel-mcp/blob/main/gluetun/custom/config.ovpn)
</details>

# 部署、VPN 与可扩展性

`webintel-mcp` 项目通过 Docker 容器化、VPN 网关与外部 SearXNG 元搜索引擎三者的组合，提供了在受限或匿名网络环境中可复现、可扩展部署的能力。本页围绕部署拓扑、VPN 集成以及扩展边界进行说明。

## 1. 容器化部署结构

项目以 Dockerfile 为基础构建镜像，将 MCP 服务器打包为标准容器。Dockerfile 定义了运行所需的运行时依赖、入口点与端口暴露方式，便于在不同主机上获得一致的运行环境。资料来源：[Dockerfile:1-50]()

在编排层面，仓库根目录提供 `docker-compose.yml`，用于一键启动整套服务栈。该 compose 文件通常包括三个核心服务：

- **mcp-server**：基于 Dockerfile 构建的 Web 情报 MCP 服务。
- **gluetun**：VPN 客户端容器，所有出站流量经由其转发。
- **searxng**：作为后端搜索源的元搜索引擎（参考 `doc/searxng-compose.yml`）。

服务之间通过 Docker 网络互联，并通过 `network_mode: "service:gluetun"` 等机制让 MCP 服务共享 VPN 容器的网络栈，从而确保外部请求出口 IP 与 VPN 一致。资料来源：[docker-compose.yml:1-80]()、资料来源：[doc/webintel-mcp-compose.yaml:1-80]()

## 2. VPN 集成：Gluetun

为隐藏真实出口 IP 并规避地域封锁，项目使用 [Gluetun](https://github.com/qdm12/gluetun) 作为统一 VPN 网关。OpenVPN 配置文件位于 `gluetun/custom/config.ovpn`，由该容器在启动时挂载加载。资料来源：[gluetun/custom/config.ovpn:1-40]()

典型工作流如下：

```mermaid
graph LR
    A[MCP 客户端] --> B[mcp-server 容器]
    B -->|共享网络栈| C[gluetun VPN 容器]
    C -->|加密隧道| D[VPN 服务商]
    D --> E[SearXNG / 目标网站]
```

MCP 服务本身不直接管理 VPN 连接，而是通过 Docker 网络层"借道" gluetun。这种方式的优势包括：

- 配置集中：仅需维护一个 `.ovpn` 文件即可影响所有出站请求。资料来源：[gluetun/custom/config.ovpn:1-40]()
- 故障隔离：VPN 断连时，依赖网络的服务会立即失败，便于检测。
- 协议灵活：可通过更换配置切换 OpenVPN/WireGuard 等协议。

## 3. SearXNG 元搜索集成

`doc/searxng-compose.yml` 提供 SearXNG 的独立部署描述，可在不启动 MCP 主栈的情况下单独运行搜索后端。SearXNG 默认监听 `8080`，通过 JSON 格式输出结果供 MCP 工具调用。资料来源：[doc/searxng-compose.yml:1-60]()

在主栈中，searxng 可通过内部 Docker 网络（如 `searxng_default`）以服务名 `searxng` 访问，使 MCP 工具能够以 `http://searxng:8080/search?...` 形式发起查询，避免硬编码宿主机 IP。资料来源：[docker-compose.yml:1-80]()

## 4. 部署步骤与可扩展性边界

`doc/setup-searxng-and-mcp-server.md` 给出了从零搭建整套环境的步骤概要，核心流程为：

1. 准备 Docker 与 docker compose 环境。
2. 将 VPN 凭据填入 `gluetun/custom/config.ovpn`。资料来源：[gluetun/custom/config.ovpn:1-40]()
3. 通过 `docker compose up -d` 启动 `docker-compose.yml` 定义的服务栈。资料来源：[docker-compose.yml:1-80]()
4. 单独部署 SearXNG（如需分离运行）。资料来源：[doc/searxng-compose.yml:1-60]()、资料来源：[doc/setup-searxng-and-mcp-server.md:1-60]()

可扩展性方面需要关注以下边界：

- **单实例瓶颈**：当前编排未定义 MCP 服务的水平扩容策略，副本数增加需要外部反向代理与会话粘性处理。
- **VPN 出口带宽**：所有搜索流量共享同一隧道，带宽与并发受限于 VPN 提供商。
- **SearXNG 实例**：搜索后端为单实例部署，高并发场景下需引入 Redis 限流与多实例负载均衡。
- **镜像体积**：Dockerfile 构建链决定了基础镜像大小，进而影响冷启动与拉取速度。资料来源：[Dockerfile:1-50]()

整体来看，`webintel-mcp` 采用"VPN 出口统一 + 元搜索解耦 + MCP 服务容器化"的三层结构，兼顾了隐私、可复现性与模块化扩展空间。后续若需进一步扩展，可在不改动核心协议的前提下，于编排层加入多副本、副本亲和性与外部缓存层即可平滑演进。资料来源：[docker-compose.yml:1-80]()、资料来源：[doc/setup-searxng-and-mcp-server.md:1-60]()

---

<!-- evidence_pipeline_checked: true -->

---

## Doramagic 踩坑日志

项目：kengbailey/webintel-mcp

摘要：发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：安装坑 - 依赖 Docker 环境。

## 1. 安装坑 · 依赖 Docker 环境

- 严重度：medium
- 证据强度：runtime_trace
- 发现：安装/运行入口包含 Docker 命令：docker run -p 3090:3090 -e SEARXNG_HOST=http://your-searxng:8189 ghcr.io/kengbailey/webintel-mcp:latest
- 对用户的影响：非工程用户可能没有 Docker，启动成本明显增加。
- 复现命令：`docker run -p 3090:3090 -e SEARXNG_HOST=http://your-searxng:8189 ghcr.io/kengbailey/webintel-mcp:latest`
- 证据：identity.distribution | https://github.com/kengbailey/webintel-mcp | docker run -p 3090:3090 -e SEARXNG_HOST=http://your-searxng:8189 ghcr.io/kengbailey/webintel-mcp:latest

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

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

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

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

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

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

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/kengbailey/webintel-mcp | no_demo; severity=medium

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

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

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

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

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

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

<!-- canonical_name: kengbailey/webintel-mcp; human_manual_source: deepwiki_human_wiki -->
