Doramagic 项目包 · 项目说明书
webintel-mcp 项目
用于网页搜索和内容获取的 MCP 服务器
项目概览与快速开始
webintel-mcp 是一个基于 Model Context Protocol (MCP) 协议实现的网络情报服务器,旨在为大语言模型(LLM)客户端提供可调用的网页抓取、内容提取与结构化分析能力。通过标准化的 MCP 工具接口,客户端(如 Claude Desktop、Cursor 等)可以将自然语言请求转化为受控的网页情报检索操作,从而避免模型产生幻觉并获得可追溯的...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
webintel-mcp 是一个基于 Model Context Protocol (MCP) 协议实现的网络情报服务器,旨在为大语言模型(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 客户端。下图描述了请求从模型到网页回传的主要数据流:
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)的,仅依赖容器运行时与上游网络访问,因此非常适合以容器方式部署。
3. 快速开始
3.1 通过 Docker Compose 启动
仓库根目录提供了开箱即用的 docker-compose.yml,推荐使用以下命令拉起服务:
git clone https://github.com/kengbailey/webintel-mcp.git
cd webintel-mcp
docker compose up -d --build
启动后,容器会在后台保持运行,并通过配置的传输层(如 stdio 或自定义端口)对外暴露 MCP 接口。
3.2 在 MCP 客户端中注册
以 Claude Desktop 为例,在 claude_desktop_config.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. 使用注意事项
- 合规抓取:遵守目标站点的
robots.txt与服务条款;服务器默认不对请求做伪装,建议在生产环境中按需配置代理与 User-Agent。 - 超时与重试:单次抓取默认设有超时上限,长页面或慢站点可能需要调高
FETCH_TIMEOUT。 - 结果大小:返回的正文长度会影响上下文窗口消耗,建议对超长页面在工具层做截断或摘要。
资料来源:README.md:80-110
通过以上步骤,开发者可以在数分钟内完成 webintel-mcp 的部署、接入与首次调用,并在此基础上扩展自定义的网络情报工具集。
资料来源:README.md:1-40
系统架构与目录结构
webintel-mcp 是一个基于 Python 实现的网络情报服务端项目,通过 Model Context Protocol(MCP)协议向客户端(通常为大语言模型或具备 MCP 能力的 Agent)暴露网页内容抓取、信息抽取与情报分析等工具能力。整个项目采用"源码即包"(src/ 布局)的工程化目录组织方式,将内部实现与外部接口清晰隔离。src/init.py 作为整...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
项目定位与总体架构
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 工具调用为例,描述请求在系统内部的流转:
- MCP 客户端通过传输层(stdio 或 SSE)发送符合协议规范的
tools/call请求。 - 服务层解析请求,提取方法名与参数;参数按照
core/models.py中的模型进行校验 资料来源:src/core/models.py:40-80。 - 服务层读取
core/config.py中的全局配置,决定超时、重试、用户代理等运行行为 资料来源:src/core/config.py:20-60。 - 业务逻辑执行抓取或分析,将结果封装为模型对象并序列化为 JSON 返回。
__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。
来源:https://github.com/kengbailey/webintel-mcp / 项目说明书
搜索引擎与 SearxNG 集成
webintel-mcp 项目通过 SearxNG 提供统一的网页检索能力,作为 MCP(Model Context Protocol)工具集中面向大模型与开发者的"对外信息入口"。SearxNG 是一个可自托管的元搜索引擎(metasearch engine),能够聚合多个上游搜索引擎(Google、Bing、DuckDuckGo、Brave、Wikipedia 等)的结...
继续阅读本节完整说明和来源证据。
概述与定位
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
工作流程
- MCP 工具调用:上层(如 Agent)通过 MCP 协议调用搜索工具,传入查询关键词与可选参数(分类、语言、分页、时效)。
- 客户端封装:
SearchClient(位于src/core/search.py)读取配置中的 SearxNG 基础 URL 和认证信息。 - HTTP 请求:客户端向
/search?q=...&format=json发起 GET 请求,携带Category-Engines、Accept-Language等头信息。 - 结果解析:返回的 JSON 包含
results[]、suggestions、infoboxes等字段,客户端将其映射为统一的内部数据结构。 - 返回与缓存:结果回传给调用方,并可根据
settings.yml中的cache配置进行短期缓存,降低对上游引擎的请求频率。
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
部署与运行
最小化运行步骤:
- 在
searxng/目录编辑settings.yml,设置secret_key与bind_address。 - 通过 Docker 或
pip install searxng启动 SearxNG 服务。 - 在
src/core/config.py中将SEARXNG_BASE_URL指向运行中的实例(如http://127.0.0.1:8888)。 - 启动 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
网页内容抓取与渲染
webintel-mcp 是一个基于 Model Context Protocol (MCP) 的 Web 情报服务器,"网页内容抓取与渲染"模块是其核心子系统,负责从远程 URL 抓取原始 HTML、解析正文、转换为适合 LLM 消费的 Markdown,并按需分页返回。资料来源:[README.md:1-40]()
继续阅读本节完整说明和来源证据。
模块职责与分层设计
抓取与渲染流程被拆分为三个职责清晰的组件:
WebFetcher:负责 HTTP 请求、重试、超时与响应头处理。资料来源:src/core/web_fetcher.py:1-60Extractor:从 HTML DOM 中识别主要内容区域、剔除导航/广告/页脚等噪音。资料来源:src/core/extractor.py:1-45Renderer:将清洗后的 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
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
来源:https://github.com/kengbailey/webintel-mcp / 项目说明书
YouTube 视频转录流程
YouTube 视频转录流程是 webintel-mcp 项目中负责从 YouTube 链接提取视频元数据与字幕文本的核心子系统。它通过 MCP(Model Context Protocol)工具向大语言模型客户端暴露 getyoutubetranscript 等接口,使得上层 Agent 能够把任意 YouTube 视频内容纳入上下文进行检索、摘要与问答。流程涵盖 URL...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述与目标
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。
下面是端到端的数据流:
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 接收到字幕列表后,按以下策略选择语言:
- 优先匹配用户传入的
language参数(如zh-Hans、en)。 - 若未指定或匹配失败,则按
config.py中配置的preferred_languages列表降级匹配。 - 最后回退到
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。
来源:https://github.com/kengbailey/webintel-mcp / 项目说明书
Reddit 工具集与认证
webintel-mcp 是一个基于 Model Context Protocol (MCP) 协议的网络情报采集服务,向支持 MCP 的 LLM 客户端(如 Claude Desktop)暴露一组抓取与检索工具。Reddit 工具集是该服务中负责拉取帖子与讨论内容的能力模块,其设计哲学是"零 OAuth 复杂度":完全依赖 Reddit 公开可访问的 .json 端点以及...
继续阅读本节完整说明和来源证据。
概述与项目定位
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 客户端发起工具调用到获取结构化结果的完整数据流:
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 客户端决定下一步动作。
资料来源:README.md:1-60
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
三、请求处理流程
当客户端发出一次工具调用请求时,服务器依次完成以下步骤:
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 工具的标准做法是:
- 在
handlers.py中实现一个async def tool_xxx(arguments)函数 - 通过主模块中既有的注册方式将其加入工具列表
- 必要时在
src/config.py追加相关配置项 - 在
requirements.txt中补充新增的第三方依赖
资料来源:src/server/handlers.py:140-200 资料来源:src/server/mcp_server.py:120-160
通过上述分层设计,服务器层与业务层解耦清晰,便于在保持协议兼容性的同时持续扩展网页情报相关能力。
部署、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 作为统一 VPN 网关。OpenVPN 配置文件位于 gluetun/custom/config.ovpn,由该容器在启动时挂载加载。资料来源:gluetun/custom/config.ovpn:1-40
典型工作流如下:
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 给出了从零搭建整套环境的步骤概要,核心流程为:
- 准备 Docker 与 docker compose 环境。
- 将 VPN 凭据填入
gluetun/custom/config.ovpn。资料来源:gluetun/custom/config.ovpn:1-40 - 通过
docker compose up -d启动docker-compose.yml定义的服务栈。资料来源:docker-compose.yml:1-80 - 单独部署 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
来源:https://github.com/kengbailey/webintel-mcp / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
非工程用户可能没有 Docker,启动成本明显增加。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
Pitfall Log / 踩坑日志
项目: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
来源:Doramagic 发现、验证与编译记录