web-shooter 发布 MCP 网页读取器,只返回相关段落而非整页
MCP web reader that returns only the relevant passages instead of whole pages
web-shooter 发布一个基于 MCP 的网页读取与聚焦爬取工具,只返回与提问匹配的段落或页面,而非整页内容。
一个快速、低 token 的网页阅读器和专注爬虫,供 AI 助手使用,通过 MCP 提供服务。它不会把整个页面交给助手,而是只返回与助手所请求内容匹配的段落或页面。
工作原理:docs/how-it-works.md。
在我们的测试集上,它回答的中位时间为 405 毫秒,约 1,100 个 token,而 Firecrawl 和 Jina Reader 每页返回约 16,000 个 token(详情见 Benchmark)。
示例:向一个 Rust Book 页面提问“rust 中的所有权规则是什么”,返回的是这个,而不是整个章节:
[1] https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html · What is Ownership? - The Rust Programming Language
§ The Rust Programming Language > What Is Ownership? > Ownership Rules · 1.00
First, let’s take a look at the ownership rules. Keep these rules in mind as we
work through the examples that illustrate them:
* Each value in Rust has an *owner*.
* There can only be one owner at a time.
* When the owner goes out of scope, the value will be dropped.
- 内部没有 LLM。 由助手决定读什么;web-shooter 负责抓取、清理、排序和裁剪。排序在 CPU 上本地运行,只需几毫秒。
- 本地运行。 你的机器上只有一个 Rust 二进制文件,由你的 MCP 客户端通过 stdio 启动。
- 不保留任何内容。 页面仅在单次工具调用期间存在于内存中;不会写入磁盘。
工具
| 工具 | 使用场景 | 返回内容 |
|---|---|---|
fetch(urls, query?, keywords?, max_tokens?, precise?) |
你有 URL,想要获取其内容 | 带查询时:最佳段落,按页面分组。不带查询时:整页裁剪至 max_tokens(默认 2,000) |
links(url, query?, keywords?, max_links?) |
你想选择接下来读哪个页面 | 该页面的链接,如果提供了查询则按查询排序 |
crawl(url, query, keywords?, max_pages?, max_depth?, other_sites?, max_results?) |
你有一个起始页面和一个目标,但没有 URL | 找到的最相关页面,以 URL 形式返回,每个附带一行摘要 |
fetch 还能读取 JSON API 响应(每条记录一个 section)以及 JavaScript 渲染页面中嵌入的数据。precise: true 增加了一个较慢的交叉编码器重排序器(多约 300 毫秒,token 减少约三分之一)。crawl 遵守 robots.txt,默认停留在起始站点,一次抓取 4 个页面,默认在 30 个页面或 30 秒后停止。
安装
1. 安装
任选一种。每种都会给你一个 web-shooter 二进制文件。
预编译二进制文件(macOS 适用于 Apple Silicon,Linux x86_64 和 ARM64,Windows x86_64),来自 最新发布版:
# macOS / Linux curl --proto '=https' --tlsv1.2 -LsSf https://github.com/heyyviv/web-shooter/releases/latest/download/web-shooter-installer.sh | sh
# Windows powershell -ExecutionPolicy Bypass -c "irm https://github.com/heyyviv/web-shooter/releases/latest/download/web-shooter-installer.ps1 | iex"
这会把 web-shooter 放到 ~/.cargo/bin。如果你愿意,可以先阅读安装脚本;它只会从发布页面下载匹配的归档文件。
从源码构建(需要 Rust 1.88 或更高版本;Intel Mac 必须使用此方式,因为没有为它们提供预编译二进制文件):
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # if you don't have Rust cargo install --git https://github.com/heyyviv/web-shooter
首次构建会下载依赖项,包括用于可选重排序器的 ONNX Runtime,需要几分钟。
2. 将其注册到你的 MCP 客户端
Claude Code(在你的所有项目中可用):
claude mcp add --scope user web-shooter -- web-shooter
然后启动一个新会话,或运行 /mcp 进行连接。用 claude mcp list 检查;它应该显示 web-shooter … ✔ Connected。如果你的 shell 找不到 web-shooter,请使用绝对路径($(which web-shooter))。
Claude Desktop、Cursor 和其他 MCP 客户端:在客户端的 MCP 配置中添加一个 stdio 服务器,使用二进制文件的绝对路径:
{
"mcpServers": {
"web-shooter": {
"command": "/absolute/path/to/web-shooter"
}
}
}3. 首次运行
首次查询会将嵌入模型(minishlab/potion-retrieval-32M,约 130 MB,大约 30 秒)下载到 Hugging Face 缓存中,~/.cache/huggingface。之后加载约需 50 毫秒。重排序器(约 1.1 GB)仅在首次调用 precise: true 时下载。如果模型无法下载,例如离线时,排序会回退到关键词匹配,而不是失败。
更新
再次运行安装命令,或者如果你是从源码构建的,运行 cargo install --git https://github.com/heyyviv/web-shooter --force。
正在运行的会话会保留旧二进制文件:在 Claude Code 中用 /mcp 重新连接,或重启你的客户端。
卸载
claude mcp remove --scope user web-shooter
这只会取消注册。要同时释放磁盘空间,请删除二进制文件(rm ~/.cargo/bin/web-shooter)和缓存的模型:
rm -rf ~/.cache/huggingface/hub/models--minishlab--potion-retrieval-32M \ ~/.cache/huggingface/hub/models--jinaai--jina-reranker-v2-base-multilingual
用法
让你的助手按名称使用它。例如:
- “对 https://blog.rust-lang.org 使用 web-shooter
crawl,查询为 'security vulnerabilities in cargo'。” - "对这 5 个职位发布 URL 使用 web-shooter
fetch,查询词为 'visa sponsorship, location, years of experience'。" - "对这个招聘页面使用 web-shooter
links,查询词为 'machine learning roles',然后获取前 3 条结果。"
提示:
- 向一次
fetch调用传入多个 URL;它们会并行抓取。 - 当答案可能与问题不共享词汇时(城市名、产品代码),用精确术语或同义词添加
keywords。 crawl返回 URL 和摘要,而非页面文本。对你想要的页面继续用fetch。
配置
| 环境变量 | 作用 |
|---|---|
WEB_SHOOTER_EMBED_MODEL |
另一个 model2vec 嵌入模型(Hugging Face 仓库 ID 或本地文件夹) |
WEB_SHOOTER_RERANK_MODEL |
用于 precise 的另一个重排序器:bge-base、bge-m3 或 jina-turbo |
HF_HOME |
模型缓存位置(默认 ~/.cache/huggingface) |
它目前还读不了什么
web-shooter 不运行 JavaScript。页面到达后从单独 API 加载内容的页面会返回空:Oracle HCM 招聘网站、许多搜索结果页面,以及 Cloudflare 等有机器人检查的网站。如果你知道该网站的 JSON API URL,把它传给 fetch;否则使用浏览器工具。计划加入无头 Chrome 回退方案。目前也不支持 PDF。
基准测试
单次运行,实时网络(examples/bench.rs),在用于调优排序的 15 个问题上:
| 工具 | 中位延迟 | 平均返回 token 数 | 答案存在 |
|---|---|---|---|
带查询的 web-shooter fetch |
405 毫秒 | 1,138 | 14/15 |
| Jina Reader | 625 毫秒 | 15,692 | 15/15 |
| Firecrawl,允许缓存 | 1,214 毫秒 | 16,513 | 15/15 |
| Firecrawl,全新抓取 | 3,341 毫秒 | 16,523 | 15/15 |
留出检查
eval/heldout.json 有 8 个问题,其页面在调优时未使用(Rust Book、MDN、PEP 8、Wikipedia、Effective Go、SQLite、Paul Graham、Docker 文档)。用 -- --heldout 运行。
| 结果 | |
|---|---|
| 输出中存在答案 | 8/8 |
| 最高分段落包含答案 | 6/8 |
| 平均返回 token 数 | 1,134(Jina Reader:约 13,700) |
| 中位延迟,3 次实时运行 | 434、438 和 658 毫秒(Jina Reader:688、697 和 2,110 毫秒) |
两次未命中(一篇 Paul Graham 文章和 Docker 最佳实践页面)的输出中仍有答案,但不在最高分段落中。这些案例未运行 Firecrawl。延迟在运行之间波动很大,因此与 Jina 的速度差异应视为大致相当到略快,而非固定倍数。
注意事项:Firecrawl 和 Jina 返回整个页面,因此它们总是包含答案。最初的 15 个问题用于调优,因此留出数字更诚实,但 8 个案例样本很小。这些页面都不需要 JavaScript,而这正是 Firecrawl 和 Jina 最强的地方。
开发
cargo test # unit tests cargo run --release --example eval # ranking test set (eval/cases.json) cargo run --release --example eval -- --heldout # cases kept out of tuning (eval/heldout.json) cargo run --release --example probe -- <url> final # markdown extracted from one page cargo run --release --example probe -- <url> rank "<query>" # top passages with scores FIRECRAWL_API_KEY=… cargo run --release --example bench # benchmark (uses Firecrawl credits)
docs/how-it-works.md 更深入地解释了流水线、爬取、排序和数据处理。CLAUDE.md 记录了设计决策及其背后的原因。
许可证
根据 Apache License 2.0 或 MIT license 任选其一授权。
来源:Hacker News · github.com