使用说明
隐形浏览器MCP服务器
一种使用双浏览器引擎提供隐形网页浏览功能的模型上下文协议(MCP)服务器-- Patchright (铬)和 迷彩 (Firefox)-具有自动机器人检测旁路。
专为配合使用而设计 克劳德代码 以及其他MCP兼容的AI代理。
特性
- 双引擎架构 --Patchright(Chromium)作为主要引擎,Camoufox(Firefox)作为后备,具有更强的抗指纹识别能力
- 自动机器人块检测 --检测Cloudflare、验证码和其他机器人保护;在以下情况下自动重试Firefox
engine: auto - 通过Xvfb实现头部模式 --运行真实的浏览器窗口(非无头)以击败指纹检测
- 18个MCP工具 --浏览、交互、提取、抓取、爬行、结构化数据提取、会话管理、持久配置文件状态保存/加载/列表/删除、X/Twitter搜索提取助手、启发式主题研究摘要、线程阅读器、深度主题研究和保存的报告包
- 三层内容提取 --trafilatura→ 可读性→ innertext回退链
- SSRF硬化 --DNS解析验证阻止本地主机、私有IP、云元数据、,
file:// - 会话池 --每个引擎最多5个独立的BrowserContext会话,空闲时间为10分钟
- 智能截断 --段落边界截断为50K个字符的大页面
- 验证码检测 --检测Cloudflare旋转栅门、reCAPTCHA、hCaptcha;结构化报告
captcha_detected旗帜 - 自动清理 --空闲会话在10分钟后被驱逐,崩溃的浏览器自动重启
工具
browse
导航到一个URL,并将页面内容作为干净的标记返回。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | yes | 要导航到的URL(仅限http/https) |
session_id |
string | no | 重用现有会话。如果省略,则创建一个新的 |
wait_for |
string | no | 提取前要等待的CSS选择器 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: url, title, content, session_id, truncated, captcha_detected, extraction_method, timing_ms, status_code, engine
interact
在会话中与当前页面交互。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
session_id |
string | yes | 以前的会话 browse 呼叫 |
action |
string | yes | 以下之一: click, type, select, hover, scroll |
selector |
string | yes | 目标元素的CSS选择器 |
value |
string | 否 | 必填 type 和 select.为 scroll,像素量 |
退货: success, session_id, action_performed, page_url, timing_ms
extract
在不重新导航的情况下从当前页面重新提取内容。用这个代替 browse 当你已经在页面上的时候。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
session_id |
string | yes | 要提取的会话 |
mode |
string | 否 | auto (默认), article,或 text (原始内文本) |
退货: content, session_id, url, extraction_method, truncated
close_session
关闭浏览器会话并释放其资源。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
session_id |
string | yes | 要关闭的会话 |
退货: status, session_id
save_session_state
将活动会话的Cookie和本地存储保存到指定的配置文件中。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
session_id |
string | yes | 要持久的会话 |
profile_name |
string | yes | 要保存的安全配置文件名 |
退货: status, session_id, profile_name, storage_state_path, meta
load_session_state
从以前保存的配置文件创建新会话。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
profile_name |
string | yes | 已保存的配置文件名称 |
session_id |
string | no | 可选自定义会话ID |
engine |
string | 否 | chromium (默认)或 firefox |
退货: status, session_id, profile_name, engine, meta
list_saved_profiles
列出磁盘上保存的持久配置文件。
退货: profiles, count
delete_saved_profile
从磁盘中删除已保存的配置文件。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
profile_name |
string | yes | 已保存的配置文件名称 |
退货: status, profile_name
search_x
打开X搜索结果页面进行查询,并返回结构化推文卡片。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query |
string | yes | 搜索查询 |
mode |
string | 否 | latest (默认)或 top |
max_items |
int | no | 要提取的最大推文数(1-50,默认值20) |
scroll_rounds |
int | no | 其他滚动/收集轮次(0-10,默认为0) |
session_id |
string | no | 重用现有会话 |
profile_name |
string | no | 将持久登录配置文件加载到新会话中 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: query, mode, search_url, session_id, tweets, extracted_count, scroll_rounds_completed, captcha_detected, engine
extract_x_search_results
从现有X搜索会话的当前页面中提取结构化推文卡。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
session_id |
string | yes | X搜索页面上已存在活动会话 |
max_items |
int | no | 要提取的最大推文数(1-50,默认值20) |
退货: session_id, tweets, extracted_count, page_url, page_title
research_x_topic
运行X搜索,并从提取的推文中生成一个轻量级的启发式主题摘要。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query |
string | yes | 搜索查询 |
mode |
string | 否 | latest (默认)或 top |
max_items |
int | no | 要提取的最大推文数(1-50,默认值20) |
scroll_rounds |
int | no | 其他滚动/收集轮次(0-10,默认为0) |
session_id |
string | no | 重用现有会话 |
profile_name |
string | no | 将持久登录配置文件加载到新会话中 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: 一切从 search_x 加 research, normalized,以及 report_markdown
read_x_thread
打开推文/线程URL,从详细页面中提取可见的主推文和回复。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | yes | X推特/线程URL |
max_items |
int | no | 要提取的最大可见推文数(1-50,默认值20) |
session_id |
string | no | 重用现有会话 |
profile_name |
string | no | 将持久登录配置文件加载到新会话中 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: main_tweet, replies, reply_count_extracted,以及页面元数据
research_x_topic_deep
运行X搜索,选择一些高信号推文,加载他们的线程页面,并生成更丰富的深度研究摘要。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query |
string | yes | 搜索查询 |
mode |
string | 否 | latest (默认)或 top |
max_items |
int | no | 要收集的最大搜索推文数 |
scroll_rounds |
int | no | 其他搜索滚动 |
deep_dive_count |
int | no | 要检查的线程URL数(默认值3) |
thread_items |
int | no | 每个线程要提取的最大推文数 |
session_id |
string | no | 重用现有会话 |
profile_name |
string | no | 将持久登录配置文件加载到新会话中 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: deep_dive_candidates, threads, deep_research, normalized,以及 report_markdown 除了基本搜索输出之外
save_x_research_report
运行主题研究(普通或深度)并将JSON+markdown报告包保存到磁盘。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query |
string | yes | 搜索查询 |
deep |
bool | 否 | 如果为真,则使用深度研究工作流程 |
mode |
string | 否 | latest (默认)或 top |
max_items |
int | no | 要收集的最大推文数 |
scroll_rounds |
int | no | 其他搜索滚动 |
deep_dive_count |
int | no | 线程深度挖掘计数 |
thread_items |
int | no | 每个线程的最大推文数 |
session_id |
string | no | 重用现有会话 |
profile_name |
string | no | 将持久登录配置文件加载到新会话中 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
report_name |
string | no | 可选自定义输出名称 |
退货: 研究成果+ saved_report 路径
list_saved_x_reports
从磁盘中列出已保存的研究报告包。
退货: reports, count
scrape_webpage
导航到URL,提取请求格式的内容,并自动关闭会话。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | yes | 要抓取的URL(仅限http/https) |
output_format |
string | 否 | markdown (默认), text, html,或 links |
session_id |
string | no | 重用会话。如果省略,则创建自动关闭的临时会话 |
wait_for |
string | no | 提取前要等待的CSS选择器 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: url, title, content, session_id, status_code, timing_ms, extraction_method, engine
extract_structured_data
从网页中提取结构化DOM数据(元数据、链接、表、JSON-LD等)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | yes | 要提取的URL(仅限http/https) |
session_id |
string | no | 重用会话。如果省略,则创建临时会话 |
include |
列出 | 否 | 要包含的节。默认值:全部。选项: metadata, og_tags, json_ld, headings, links, tables, forms |
wait_for |
string | no | 提取前要等待的CSS选择器 |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: url, title, session_id, timing_ms, engine+请求的数据段
crawl_pages
从URL开始,通过BFS抓取多个页面。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | yes | 起始URL(仅限http/https) |
max_pages |
int | no | 可抓取的最大页面数(1-20,默认值5) |
link_pattern |
string | no | 用于过滤链接href的正则表达式 |
output_format |
string | 否 | markdown (默认), text, html,或 links |
same_domain |
bool | no | 只关注相同的域链接(默认值:true) |
engine |
string | 否 | auto (默认), chromium,或 firefox |
退货: pages (列表 {url, title, content, status_code}), total_pages, total_timing_ms, engine
安装
先决条件
系统库 (Ubuntu/Debian/WSL2):
sudo apt-get install -y libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 \
libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
libpango-1.0-0 libcairo2 libasound2t64 xvfb
Python 3.12+ 和 紫外线 (推荐)或pip。
设置
git clone https://github.com/Axe240-commits/stealth-browser-mcp.git
cd stealth-browser-mcp
chmod +x setup.sh
./setup.sh
或手动:
uv venv
uv pip install -e ".[dev]"
.venv/bin/python -m patchright install chromium
验证
# Run tests
.venv/bin/python -m pytest tests/ -v
# Start server (will wait for MCP stdio input)
.venv/bin/python -m stealth_browser
使用克劳德代码注册
添加 ~/.claude/mcp_servers.json:
{
"stealth-browser": {
"type": "stdio",
"command": "/path/to/stealth-browser-mcp/.venv/bin/python",
"args": ["-m", "stealth_browser"]
}
}
然后在中添加权限 ~/.claude/settings.json:
{
"permissions": {
"allow": [
"mcp__stealth-browser__browse",
"mcp__stealth-browser__interact",
"mcp__stealth-browser__extract",
"mcp__stealth-browser__close_session",
"mcp__stealth-browser__save_session_state",
"mcp__stealth-browser__load_session_state",
"mcp__stealth-browser__list_saved_profiles",
"mcp__stealth-browser__delete_saved_profile",
"mcp__stealth-browser__search_x",
"mcp__stealth-browser__extract_x_search_results",
"mcp__stealth-browser__research_x_topic",
"mcp__stealth-browser__read_x_thread",
"mcp__stealth-browser__research_x_topic_deep",
"mcp__stealth-browser__save_x_research_report",
"mcp__stealth-browser__list_saved_x_reports",
"mcp__stealth-browser__scrape_webpage",
"mcp__stealth-browser__extract_structured_data",
"mcp__stealth-browser__crawl_pages"
]
}
}
重新启动克劳德代码。工具将立即可用。
建筑
┌─────────────────────────────────────────────────┐
│ Claude Code / MCP Client │
│ │
│ browse ─ interact ─ extract ─ close_session │
│ scrape_webpage ─ extract_structured_data │
│ crawl_pages │
└────────────────┬────────────────────────────────┘
│ stdio (JSON-RPC)
┌────────────────▼────────────────────────────────┐
│ server.py — FastMCP Server (7 tools) │
│ ├── security.py — SSRF validation (every URL) │
│ ├── session.py — per-session lock + state │
│ ├── browser_manager.py — dual engine pool │
│ ├── extractor.py — 3-tier content extraction │
│ ├── dom_extractor.py — structured DOM data │
│ └── config.py — configuration │
└───────┬─────────────────┬───────────────────────┘
│ │
┌───────▼──────┐ ┌───────▼──────┐
│ Patchright │ │ Camoufox │
│ (Chromium) │ │ (Firefox) │
│ Primary │ │ Fallback │
└───────┬──────┘ └───────┬──────┘
│ │
┌───────▼─────────────────▼───────────────────────┐
│ Xvfb :99 — 1920x1080 (headed mode) │
└─────────────────────────────────────────────────┘
双引擎和自动回退
随着 engine: auto (默认),每个请求:
- 尝试 修补漆(铬) 首先——快速、低开销
- 检查机器人程序块信号:HTTP 403、标题关键字(“请稍等”、“需要注意”)、空内容
- 如果被阻止,将自动重试 迷彩(Firefox) 具有更强的抗指纹识别能力
对于 crawl_pages,引擎切换发生在第一页,并在爬行的其余部分保持不变。
内容提取管道
trafilatura (best for articles, tables, links)
↓ fallback if < 200 chars
readability-lxml + html2text (complex HTML)
↓ fallback if < 200 chars
page.inner_text('body') (SPAs, JS-rendered content)
会话管理
- 两个持久浏览器 在MCP服务器启动时启动(Chromium+Firefox)
- 每
browse()不打电话session_id创建新BrowserContext(~100ms) - 会话是隔离的(单独的Cookie、存储、状态)
- 马克斯 5个并发会话,如果容量最大,最年长的被驱逐
- 空闲会话在之后被驱逐 10分钟
- 每个会话的所有操作都通过序列化
asyncio.Lock - 每个会话跟踪其引擎类型(
chromium或firefox)
安全(SSRF保护)
每个URL在导航前都经过验证:
- 方案检查 --只有
http和https允许 - DNS解析 --主机名解析为实际IP
- IP验证 --根据专用/保留范围检查所有已解析的IP
- 重定向验证 --在每次跳转时重新验证重定向
此 路 不通:
localhost,127.0.0.1,::1- 私人范围(
10.x,172.16.x,192.168.x) - 云元数据(
169.254.169.254) - 链接本地、多播、保留IP
file://,data://,javascript://,ftp://
AI代理的使用技巧
- 使用
extract重读同一页——不要打电话browse再次 - 使用
browse仅用于实际导航(新URL或页面更改) - 重用
session_id跨相关业务 - 总是打电话
close_session当释放资源时 - 使用
scrape_webpage进行一次刮擦(自动关闭会话) - 使用
crawl_pages从起始URL抓取多个页面 - 默认导航使用
domcontentloaded(快速、可靠)——使用wait_for如果你需要一个特定的元素
项目结构
stealth-browser-mcp/
├── pyproject.toml # Dependencies, build config
├── setup.sh # One-command setup
├── src/stealth_browser/
│ ├── __init__.py
│ ├── __main__.py # Entry: python -m stealth_browser
│ ├── server.py # MCP server, 7 tools, lifespan
│ ├── browser_manager.py # Dual engine lifecycle, context pool
│ ├── session.py # Session state, locking, actions
│ ├── extractor.py # 3-tier content extraction
│ ├── dom_extractor.py # Structured DOM data extraction
│ ├── security.py # SSRF-hardened URL validation
│ ├── config.py # Configuration dataclass
│ └── proxy.py # Stub (Phase 2: Tor)
└── tests/
├── test_security.py # URL/IP validation tests
├── test_extractor.py # Extraction mode/fallback tests
├── test_dom_extractor.py # DOM structured data tests
└── test_server_helpers.py # Server helper function tests
配置
默认值 config.py --不需要配置文件:
| 设置 | 默认值 | 说明 |
|---|---|---|
headless |
False |
头部模式(Xvfb)可实现更好的隐形效果 |
use_xvfb |
True |
自动启动Xvfb用于头部模式 |
max_sessions |
5 |
最大并发浏览器会话数 |
session_timeout_minutes |
10 |
空闲会话驱逐超时 |
navigation_timeout_ms |
30000 |
页面加载超时 |
wait_until |
domcontentloaded |
导航等待策略 |
max_content_length |
50000 |
内容截断限制(字符) |
block_media |
True |
阻止图像/字体/媒体以提高速度 |
camoufox_enabled |
True |
启用Firefox回退引擎 |
crawl_max_pages_limit |
20 |
爬行盖 |
crawl_per_page_max |
10000 |
每个已爬网页面的内容限制 |
依赖项
| 包装 | 用途 |
|---|---|
| 主控程序 | MCP服务器框架(Anthropic) |
| patchright | 隐形剧作家叉子(铬合金) |
| 迷彩 | 防指纹Firefox(回退引擎) |
| 特拉菲拉图拉 | 文章/内容提取 |
| 可读性lxml | 回退HTML提取 |
| html2text | HTML到markdown的转换 |
故障排除
浏览器无法启动: error while loading shared libraries
Chromium需要默认情况下未安装在最小Linux/WSL2上的系统库:
error while loading shared libraries: libnspr4.so: cannot open shared object file
解决方案:
sudo apt-get install -y libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 \
libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
libpango-1.0-0 libcairo2 libasound2t64 xvfb
迷彩服无法启动
迷彩服需要 xvfb 对于头部模式:
sudo apt-get install -y xvfb
如果迷彩仍然失败,它会优雅地回落——仅Chromium模式仍然有效。
克劳德代码中未显示MCP服务器
服务器必须在中注册 ~/.claude/mcp_servers.json:
{
"stealth-browser": {
"type": "stdio",
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "stealth_browser"]
}
}
添加后, 重新启动克劳德代码 --MCP服务器仅在启动时加载。
工具显示“权限被拒绝”
将所有7个工具添加到 ~/.claude/settings.json 权限(请参阅上面的注册部分)。
页面内容为空或太短
- 尝试
extract随着mode="text"适用于SPA/JS密集页面 - 添加
wait_for带有CSS选择器的参数,用于等待动态内容 - 尝试
engine: firefox--一些网站对迷彩效果更好 - 默认
domcontentloaded不等待延迟加载的内容——传递一个在页面完全呈现后出现的选择器
机器人在两个引擎上都被阻塞了
如果 engine: auto 如果网站回退到Firefox并仍被阻止,则可能需要:
- 不同的IP/代理(第2阶段)
- 手动验证码解决
- 特定Cookie/身份验证
未找到会话
在10分钟不活动或达到5个会话限制后,会话将被驱逐。如果你得到 "Session 'xyz' not found",创建一个新的 browse.
第二阶段(计划中)
screenshot工具——用于验证码/同意调试evaluate_js工具——目标DOM查询session_info工具--列出活动会话和状态- 每次工具调用硬超时保护
- 代理/Tor选择加入支持
许可证
麻省理工学院