关于 webshift
WebShift 是 Rust 库和 MCP 服务,可将网页转换为干净且有长度限制的文本,供 Agent 和 LLM 工作流使用。它整合可配置搜索、抓取、清理与重排,并可选提供 LLM 功能及保留标记结构的 HTML 文本改写。
主要功能
- 01通过八种可配置后端搜索
- 02抓取并清理静态 HTML 页面
- 03使用 BM25 重排结果
- 04限制单页和总文本预算
- 05可选使用 LLM 扩展查询和生成摘要
- 06保留标记结构改写 HTML 文本
适用场景
- 01为 Agent 提供简洁的网页搜索结果
- 02抓取页面并避免传递原始 HTML
- 03将网页内容控制在上下文长度限制内
- 04在不改变结构的情况下翻译或简化 HTML 文本
MCP 相关
MCP 服务通过 stdio 提供 `webshift_query`、`webshift_fetch` 和 `webshift_onboarding`,分别用于搜索与重排、抓取并清理单页,以及获取入门指南。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
WebShift
什么是 WebShift
WebShift 是一个 Rust 库和 MCP 服务,可将杂乱的网页转换为简洁、大小合适的文本,供大模型使用。
原始 HTML 大多是无用内容:脚本、广告、导航菜单、Cookie 横幅、跟踪像素。直接将其输入大模型,会让上下文窗口被数万个无用词元塞满,留不出推理空间。WebShift 会剔除所有这些噪声、净化文本,并严格限制内容大小,确保模型只接收重要内容。
你将获得
根据启用的功能,WebShift 可以有以下四种用途:
| 用例 | Crate | 功能标志 | 功能说明 |
|---|---|---|---|
| HTML 降噪器 | webshift | default-features = false | clean() — 纯 Rust HTML 转文本处理流程。剔除噪声元素、净化 Unicode/BiDi 字符、合并空白字符。无需联网,无需配置。可用于任何处理大模型网页内容的 Rust 项目。 |
| HTML 文本改写器 | webshift | features = ["text-map"] | extract_text_nodes() + replace_text_nodes() — 从 HTML 中提取独立文本节点,对其进行处理(翻译、改写、简化),并在保留结构的同时重建 HTML。不会触及标签、属性和链接。 |
| 网页内容客户端 | webshift | default 或 features = ["llm"] | fetch() + query() — 支持流式传输且带有大小上限的 HTTP 抓取器、8 种搜索后端、BM25 重排序,以及可选的大模型查询扩展和摘要。从搜索查询到结构化结果的完整处理流程。 |
| MCP 服务 | webshift-mcp | 所有功能 | 原生二进制文件(mcp-webshift),通过 MCP stdio 提供 webshift_query、webshift_fetch 和 webshift_onboarding。单个静态二进制文件,无运行时依赖。 |
适用场景
- 你正在构建需要网页搜索的 AI Agent,并且想要简洁、受预算控制的文本,而非原始 HTML。
- 你正在 Rust 处理流程中处理网页,需要一个可靠的 HTML 转文本清理器,能够剔除噪声而不丢失真实内容。
- 你需要大模型翻译、改写或简化 HTML 中的文本,同时不破坏标记;text-map 可为你提供安全的往返处理。
- 你想要一个以单个二进制文件运行的 MCP 网页搜索服务——无需 Python、pip、venv 或 Docker(除非你想用)。
- 你需要对输出大小作出硬性保证:单页上限、总预算上限、流式下载限制。
不适用场景
- 你需要一个能渲染 JavaScript 密集型单页应用的无头浏览器。WebShift 解析静态 HTML,不会执行 JS。
- 你需要渲染页面或截取屏幕截图,同时保留页面的视觉布局。WebShift 处理 HTML 结构,但不会渲染 CSS 或计算布局。(注意:
text-map确实会为文本改写场景保留 DOM 结构。) - 你正在构建需要跨页面导航、填写表单或处理身份验证流程的网页抓取器。
工作原理
Question
|
+- (optional) LLM query expansion -> multiple search variants
|
+- Search via backend (SearXNG, Brave, Tavily, Exa, SerpAPI, Google, Bing, HTTP)
|
+- Deduplicate + filter binary URLs
|
+- Streaming fetch with per-page size cap
|
+- HTML cleaning -> plain text (noise elements, scripts, nav removed)
|
+- Unicode/BiDi sterilization
|
+- BM25 deterministic reranking
| +- (optional) LLM-assisted tier-2 reranking
|
+- Budget-aware truncation across all sources
|
+- (optional) LLM Markdown summary with inline citations
|
+- Structured JSON output
如需详细了解各个流水线阶段、BM25 参数、自适应预算分配和实际压缩指标,请参阅幕后原理。如需完整的配置参考(TOML、环境变量、CLI 参数),请参阅配置。如需可直接使用的示例,请参阅使用场景。
安装
二进制文件(MCP 服务)
cargo install webshift-mcp
二进制文件名为 mcp-webshift。
从源码安装
cargo install --path crates/webshift-mcp
作为库使用
# Full pipeline (search + fetch + clean + rerank)
webshift = "0.2"
# Cleaner + fetcher only (no search backends)
webshift = { version = "0.2", default-features = false }
# Text-map only (extract/replace text nodes in HTML)
webshift = { version = "0.2", default-features = false, features = ["text-map"] }
# Everything including LLM features
webshift = { version = "0.2", features = ["llm"] }
快速入门
1. 设置搜索后端
最简单的选择是 SearXNG——免费、可自托管且无需 API 密钥:
docker run -d -p 8080:8080 searxng/searxng
没有 Docker?可以使用云端后端——请参阅搜索后端。
2. 配置 MCP 客户端
{
"mcpServers": {
"webshift": {
"command": "mcp-webshift",
"args": ["--default-backend", "searxng"]
}
}
}
就这么简单。现在,Agent 可以使用 webshift_query、webshift_fetch 和 webshift_onboarding。
客户端专属的设置方法请参阅 docs/integrations/。
MCP 工具
| 工具 | 描述 |
|---|---|
webshift_query | 完整的搜索流水线:搜索 + 抓取 + 清理 + 重新排序 +(可选)摘要 |
webshift_fetch | 抓取并清理单个页面 |
webshift_onboarding | 为 Agent 返回 JSON 指南(预算、后端、提示) |
webshift_query 参数
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
queries | 字符串或列表 | 必填 | 搜索查询或查询列表 |
num_results_per_query | 整数 | 5 | 每个查询的结果数 |
lang | 字符串 | 无 | 语言筛选条件(例如 "en") |
backend | 字符串 | 配置默认值 | 覆盖搜索后端 |
配置
解析优先级(从高到低):
- CLI 参数 —
--default-backend、--brave-api-key等。 - 环境变量 —
WEBSHIFT_*前缀 - 配置文件 —
webshift.toml(当前目录,然后是~/webshift.toml) - 内置默认值
配置文件
[server]
max_query_budget = 32000 # total char budget across all sources
max_result_length = 8000 # per-page char cap
max_total_results = 20 # hard cap on results per call
max_download_mb = 1 # streaming cap per page (MB)
search_timeout = 8 # seconds
results_per_query = 5
oversampling_factor = 2
adaptive_budget = "auto" # "auto" | "on" | "off" — budget allocation mode
[backends]
default = "searxng"
[backends.searxng]
url = "http://localhost:8080"
[backends.brave]
api_key = "BSA-..."
[backends.tavily]
api_key = "tvly-..."
[backends.exa]
api_key = "..."
[backends.serpapi]
api_key = "..."
engine = "google" # google | bing | duckduckgo | yandex
[backends.google]
api_key = "..."
cx = "..." # Custom Search Engine ID
[backends.bing]
api_key = "..."
market = "en-US"
[backends.http]
url = "https://my-search.example.com/api/search"
query_param = "q"
count_param = "limit"
results_path = "data.items" # dot-path to results array in JSON response
title_field = "title"
url_field = "link"
snippet_field = "description"
[backends.http.headers]
"Authorization" = "Bearer my-token"
[llm]
enabled = false
base_url = "http://localhost:11434/v1" # OpenAI-compatible
api_key = ""
model = "gemma3:27b"
timeout = 60
expansion_enabled = true
summarization_enabled = true
llm_rerank_enabled = false
如需查看每项设置的三种配置方式(TOML、环境变量、CLI 参数)以及通俗易懂的说明,请参阅完整的配置参考。
可直接使用的配置示例请参阅使用场景和 examples/。
关键环境变量
WEBSHIFT_DEFAULT_BACKEND=searxng
WEBSHIFT_SEARXNG_URL=http://localhost:8080
WEBSHIFT_BRAVE_API_KEY=BSA-xxx
WEBSHIFT_GOOGLE_API_KEY=xxx
WEBSHIFT_GOOGLE_CX=xxx
WEBSHIFT_BING_API_KEY=xxx
WEBSHIFT_LLM_ENABLED=true
WEBSHIFT_LLM_BASE_URL=http://localhost:11434/v1
WEBSHIFT_LLM_MODEL=gemma3:27b
搜索后端
| 后端 | 身份验证 | 备注 |
|---|---|---|
| SearXNG | 无 | 可自托管、免费。默认值:http://localhost:8080 |
| Brave | API 密钥 | 免费套餐。brave.com/search/api |
| Tavily | API 密钥 | 面向 AI。tavily.com |
| Exa | API 密钥 | 神经搜索。exa.ai |
| SerpAPI | API 密钥 | 多引擎代理(Google、Bing、DDG 等)。serpapi.com |
| API 密钥 + CX | 自定义搜索。免费:每天 100 次请求。programmablesearchengine.google.com | |
| Bing | API 密钥 | Web 搜索 API。免费:每月 1,000 次请求。Microsoft Azure |
| HTTP | 可配置 | 通用 REST 后端——无需编写代码,仅需 TOML 配置 |
大模型功能(可选)
均为主动选择启用——默认禁用,除非启用,否则不会有任何数据离开你的设备。
| 功能 | 作用 |
|---|---|
| 查询扩展 | 单个查询 -> N 个互补的搜索变体 |
| 摘要 | Markdown 报告,包含行内 [1] [2] 引用 |
| 大模型重排 | 在确定性 BM25 之上进行第二层重排 |
跨语言规范化(额外功能): 当 BM25 重排结果中出现外语页面(例如中文、日文、阿拉伯文)时,大模型摘要器仍会使用提示词所用的语言生成最终报告。无论来源页面包含哪些语言,Agent 都能收到简洁易读的输出。
适用于任何兼容 OpenAI 的 API(OpenAI、Ollama、vLLM、LM Studio 等):
[llm]
enabled = true
base_url = "http://localhost:11434/v1"
model = "gemma3:27b"
防洪保护
始终启用——这是核心价值主张:
| 保护措施 | 描述 |
|---|---|
max_download_mb | 流式上限——绝不缓冲完整响应 |
max_result_length | 对每个清理后页面的字符数设置硬上限 |
max_query_budget | 所有来源的总字符预算 |
max_total_results | 对每次调用的结果数设置硬上限 |
| 二进制文件过滤 | .pdf、.zip、.exe 等会在发出任何网络请求之前过滤 |
| Unicode 清理 | 移除 BiDi 控制字符和零宽字符 |
库的用法
use webshift::{Config, clean, fetch, query};
// Clean raw HTML — cap output at 8000 chars
let result = clean("<html><body><p>Hello world</p></body></html>", 8000);
println!("{}", result.text);
// Pass 0 to disable the per-page cap entirely (no truncation)
let full = clean("<html><body><p>Hello world</p></body></html>", 0);
assert!(!full.truncated);
// Fetch and clean a single page
let config = Config::default();
let page = fetch("https://example.com", &config).await?;
// Full search pipeline
let results = query(&["rust async programming"], &config).await?;
for source in &results.sources {
println!("[{}] {} — {} chars", source.id, source.title, source.content.len());
}
// Backend partial failures (CAPTCHA, rate-limits, engine outages) are surfaced
// in `warnings` rather than as Err. Empty sources + non-empty warnings means
// "all backends blocked" — distinct from a legitimate "no matches found".
if results.sources.is_empty() && !results.warnings.is_empty() {
eprintln!("all backends failed: {:?}", results.warnings);
}
文本映射:重写 HTML 内容而不破坏标记
提取文本节点,对其进行处理(翻译、改写、简化),然后在保留结构、属性和链接的情况下重建 HTML。
use webshift::{extract_text_nodes, replace_text_nodes, TextReplacement};
let html = r#"<p>Hello <a href="https://example.com">world</a></p>"#;
let map = extract_text_nodes(html);
// map.nodes = [(0, "Hello"), (1, "world")]
let replacements = vec![
TextReplacement { id: 0, text: "Ciao".into() },
TextReplacement { id: 1, text: "mondo".into() },
];
let result = replace_text_nodes(html, &replacements).unwrap();
// → <p>Ciao <a href="https://example.com">mondo</a></p>
// href untouched, tags intact, only text changed.
需要 features = ["text-map"]。完整的翻译示例请参阅 使用案例 #11。
功能标志
| 功能 | 默认状态 | 启用内容 |
|---|---|---|
backends | 开启 | 所有搜索后端 + 查询流水线 |
llm | 关闭 | 大模型客户端、扩展器、摘要器、大模型重排 |
text-map | 关闭 | extract_text_nodes() + replace_text_nodes() — 用于重写内容的 DOM 往返处理 |
集成
| 平台 | 指南 |
|---|---|
| Claude Desktop、Claude Code、Cursor、Windsurf、VS Code | IDE 集成 |
| Zed — 原生扩展,支持自动下载和 Configure Server 模态窗口 | Zed 扩展 |
| Gemini CLI、Claude CLI、自定义 Agent | Agent 集成 |
Beta 状态
WebShift 目前处于 Beta 阶段。核心功能稳定,且服务每天都在使用,但在 1.0 版本发布前,API 接口仍可能发生变化。
非常欢迎反馈。 如果有任何功能未按预期运行、表现异常,或你有尚未涵盖的使用场景:
Bug 报告、配置问题和功能请求都有助于规划路线图。
贡献
欢迎贡献!详细指南请参阅 CONTRIBUTING.md,内容包括:
- 开发环境设置和工作流
- 代码风格和约定
- 测试要求
- 文档规范
- Pull Request 流程
许可证
MIT 许可证——详情请参阅 LICENSE。
链接
- GitHub 仓库 — 源代码和问题反馈
- Docs.rs — API 文档
- MCP Registry — Model Context Protocol Registry 上的 WebShift
- MCP Protocol — Model Context Protocol 规范
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。