关于 crawlio-browser
Crawlio Browser 通过扩展和 MCP 服务将 AI Agent 接入实时 Chrome,面向动态页面和需登录页面,并结合框架感知检查、证据追踪与会话录制。
主要功能
- 01控制实时 Chrome 会话
- 02检查框架专属页面数据
- 03采集结构化证据并追踪置信度
- 04录制并回放浏览器交互
- 05跨多个标签页操作
- 06审查 SEO、无障碍和性能
适用场景
- 01操作已登录的 Web 应用
- 02检查 JavaScript 渲染的页面
- 03录制可重复的浏览器工作流
- 04分析页面证据与覆盖情况
MCP 相关
MCP 服务通过 WebSocket 连接 Chrome 扩展,扩展则通过 CDP 控制 Chrome。客户端可经 stdio 或 Portal HTTP/SSE 接入,并选择 code 或 full 模式使用工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | number | 否 | 最大结果数(默认:10) |
| query | string | 是 | 搜索关键字(例如:'screenshot'、'cookie'、'network'、'navigate') |
详细介绍
Crawlio Browser
文档 | API 参考 | Chrome 扩展
通过 CDP 让 AI 完全控制实时 Chrome 浏览器的 MCP 服务。提供 150 个工具,具备框架感知智能、类型化证据基础设施、跟踪像素分析、技术特征指纹识别、SEO 审核和带置信度跟踪的发现结果——能够捕获静态爬虫无法看到的内容。
何时使用 Crawlio Browser
当 AI 需要与真实浏览器交互时,请使用 Crawlio Browser——适用于 SPA、需身份验证的页面、动态内容和 JS 渲染的框架。与无头浏览器工具不同,Crawlio Browser 通过轻量级扩展连接到你实际使用的 Chrome,让 AI 能够访问你的登录会话、Cookie 和完整浏览器状态。
**Crawlio Browser 与无头浏览器工具的比较:**无头工具会启动单独的浏览器进程。Crawlio Browser 则连接到你现有的 Chrome——无需单独启动浏览器,无需登录流程,并可完全访问你的标签页和会话。
警告
这里的权衡直截了当:连接你自己的 Chrome 正是这项功能的核心,这也意味着 AI Agent 可以代表你操作你已登录的所有网站。它会将 Chrome 调试器附加到你连接的 标签页,因此可以读取该会话的 Cookie、存储数据和页面内容。
请仔细检查你连接的对象。建议使用专用的 Chrome 配置文件来执行 Agent 任务。在你连接标签页之前, 不会捕获任何内容;你也可以在配置任何内容之前,运行
npx crawlio-browser tools查看 所有可用工具。网站可以通过<meta name="crawlio-agent" content="disable">选择退出,扩展会遵守此设置。
快速开始
- 安装 Chrome 扩展
- 运行初始化向导:
npx crawlio-browser init
就是这么简单。它会自动检测并配置 14 个 MCP 客户端:Claude Code、Cursor、VS Code、Codex、Gemini CLI、Claude Desktop、ChatGPT Desktop、Windsurf、Cline、Zed、Goose、OpenCode、MCPorter 和 Cline CLI。
初始化向导选项
npx crawlio-browser init # Default: code mode, stdio transport
npx crawlio-browser init --full # Full mode (every tool exposed individually)
npx crawlio-browser init --portal # Portal mode (persistent HTTP server)
npx crawlio-browser init --cloudflare # Add Cloudflare MCP (89 tools, no wrangler)
npx crawlio-browser init --dry-run # Show what would happen
npx crawlio-browser init --yes # Skip prompts (CI / scripted installs)
npx crawlio-browser init -a claude # Target specific MCP client
作为 Agent 插件使用
该软件包也是符合 Agent Plugins v1 规范的插件,因此符合规范的客户端
可以直接加载它,无需运行向导——根目录中的 plugin.json、skills/ 下的十一个技能,
以及在 mcp.json 中声明的 MCP 服务。
面向产品的 crawlio-* 工作流已整合到随附的十一个技能中。agents/ 中名称相似的定义仍是仓库本地的开发测试文件:它们会导入 src/evidence/*
和 loops/*,这两者都不属于 npm 运行时。我们通过 package.json 排除了这些定义,
而不是将它们宣传为另一套无法执行的产品功能。
将客户端指向已安装的软件包:
node_modules/crawlio-browser # after `npm install crawlio-browser`
mcp.json 通过 ${PLUGIN_ROOT}/dist/mcp-server/index.js 解析服务,因此该插件必须是已安装的软件包,而不能是解压后的 tarball——服务会在运行时导入其依赖项,所以直接解压后启动会因无法响应而终止。
查看其提供的功能
npx crawlio-browser tools # What code mode exposes (the default)
npx crawlio-browser tools --full # Every tool, individually
npx crawlio-browser tools --json # Machine-readable, for diffing across versions
npx crawlio-browser doctor # Bridge, portal, native host, client configs
npx crawlio-browser --help # All commands and options
npx crawlio-browser --version # Version only
这两种方式都是只读的,无需浏览器、扩展或网络连接即可运行——你可以在配置客户端之前查看完整功能。显示的数字来自服务注册时使用的同一组构建器,因此与客户端收到的内容完全一致。
传输模式
| 模式 | 命令 / URL | 协议 | 适用场景 |
|---|---|---|---|
| stdio | npx crawlio-browser | 基于 stdin/stdout 的 JSON-RPC | Claude Desktop、Cursor、Windsurf——客户端管理进程生命周期 |
| Portal(HTTP) | POST http://127.0.0.1:3001/mcp | MCP Streamable HTTP | Claude Code、ChatGPT Desktop——服务可在会话重启后继续运行 |
| Portal(SSE) | GET /sse + POST /message | Server-Sent Events | 需要 SSE 传输的旧版客户端 |
推荐 Claude Code 使用 Portal 模式——服务会在上下文压缩和会话重启后继续运行。在 macOS 上,--portal 会安装一个 launchd 代理,以便在登录时自动启动。
手动设置(适用于任何客户端)
各客户端的手动配置
Claude Desktop——添加到 claude_desktop_config.json:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Claude Code(Portal 模式)——启动 npx crawlio-browser --portal,然后添加到 .mcp.json:
{ "mcpServers": { "crawlio-browser": { "type": "http", "url": "http://127.0.0.1:3001/mcp" } } }
Claude Code(stdio):
claude mcp add crawlio-browser -- npx -y crawlio-browser
Cursor——添加到 .cursor/mcp.json:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Windsurf——添加到 Windsurf 设置 > MCP:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Cline(VS Code)——添加到 settings.json:
{ "cline.mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
ChatGPT Desktop——设置 > 集成 > MCP:
URL:http://127.0.0.1:3001/mcp | 类型:Streamable HTTP
工作原理
AI Client (stdio/http) --> MCP Server (Node.js) --> Chrome Extension (MV3)
crawlio-browser WebSocket -> CDP
MCP 服务通过 WebSocket 与 Chrome 扩展通信。扩展通过 Chrome DevTools Protocol (CDP) 控制浏览器。
功能
框架感知智能
每次调用 execute 时,都会探测浏览器的框架特征,并注入一个能够动态适配的 smart 对象,提供框架原生访问器。React 状态、Vue 响应性、Next.js 路由、Shopify 购物车数据——涵盖 4 个层级的 17 个框架命名空间,可在运行时检测,并在每次导航时重新构建。AI 不会查询通用 DOM,而是查询框架自身的数据结构。
基于证据的分析
Method Mode 在 Code Mode 的基础上增加了高阶方法和类型化证据系统。smart.extractPage() 可在单次调用中运行 7 项并行操作——页面捕获、性能指标、安全状态、字体检测、元数据提取、无障碍审计和移动端就绪度检查。操作失败时会生成类型化的 CoverageGap 记录,而不是静默返回 null。使用 smart.finding() 创建的发现会在支持数据缺失时自动调整置信度。最终结果是结构化、可审计的研究输出,并带有缺口跟踪和置信度传递机制。
会话录制与回放
将浏览器交互录制为结构化数据,然后将其编译为可复用的 SKILL.md 自动化流程。录制期间会自动拦截 12 种交互工具——点击、输入、导航、滚动——并分别捕获参数、结果、计时信息和页面 URL。调用一次 compileRecording() 即可将会话转换为确定性自动化脚本。
机器人训练
将人工引导的浏览器演示采集为可重放的机器人训练包。默认模式
observe 生命周期会在扩展程序中启动事件驱动的记录器;即使 MCP 进程断开连接或重启,采集仍会继续。
重新连接后,training_stop 会导出保留的运行记录,并生成完整的 13 个文件的 RecordingBundle,供重放和 API 合成使用。
完整模式会保留现有的 robot_training_* 名称作为兼容别名。
页面监控也以同样的方式常驻:即使没有 MCP 服务,扩展程序拥有的后台标签页和 Chrome 闹钟也会采集有界的 ARIA 快照。训练和监控历史共用 25 MiB 的本地空间预算,并设有数量上限:20 次已完成的训练运行、50 个监控任务、总计 200 个快照,以及每个监控最多 50 个快照。系统会优先清除较早的已完成数据;绝不会静默清除进行中的工作。只有通过明确的 MCP 生命周期操作才会启动工作;这些操作还会报告状态、停止采集、清除监控快照,并且只有在提供准确的 ID 和明确确认后,才会从 Chrome 中删除已停止的训练/录制记录,同时保留其已生成的文件。扩展程序弹出窗口仍用于显示连接和浏览器访问状态。 除非调用方明确选择加入,否则存储值仅包含键。监控快照会有意在本地保留精简的 ARIA 页面文本;因此,启动监控应视为同意保留该 URL 的可见内容,直到将其清除为止。
自动等待稳定与可操作性
每个会修改页面的操作(click、type、navigate、select_option)都会在执行前进行可操作性检查,包括轮询可见性、尺寸、启用状态和遮罩层检测。操作完成后,会通过渐进式退避等待([0, 20, 100, 100, 500]ms)等待 DOM 变更趋于稳定。AI 无需在操作之间手动调用 sleep()。
同时操作多个标签页
任何作用于页面的命令都可以从 list_tabs 接收可选的 tabId。省略该参数时,命令会像以前一样在已连接的标签页上运行;提供该参数时,则会在指定标签页上运行,且所有命令都可在每个标签页上使用。命令可以并行执行,因此可以同时操作两个标签页:
const [checkout, search] = await Promise.all([
bridge.send({ type: "browser_snapshot", tabId: 42 }),
bridge.send({ type: "browser_snapshot", tabId: 57 }),
]);
指定标签页不会改变 connect_tab 指向的标签页,因此,同时操作多个标签页的 Agent 无法重新指定人类正在查看的标签页。框架选择、覆盖率会话和框架检测均按标签页分别处理。网络捕获是个例外——它一次只记录一个标签页,并会指出当前记录的是哪个标签页,而不会交错记录两个标签页。
Chrome 配置文件
扩展程序实例仅限于自身的 Chrome 配置文件,无法查看其他配置文件。因此,如果在多个配置文件中启用了 Crawlio,命令会发送到最先连接的配置文件。list_profiles 会显示已连接的配置文件以及当前正在操作的配置文件;switch_profile 可将连接切换到另一个配置文件。一次只能操作一个配置文件——已释放的扩展程序会在后台重新连接,因此切换回来时无需等待。
配置文件会使用写入各自扩展程序存储空间的 UUID 来标识自身。这个 UUID 可区分配置文件,但不会描述配置文件:不包含账户、电子邮件、路径,也不需要额外权限。
选择配置文件可避免相互协作的扩展程序彼此干扰,但这并非安全边界,因为该 ID 由扩展程序声明,而非经过验证。桥接器现有的保护措施保持不变:一次只允许一个扩展程序,并且每个扩展程序都必须证明服务器持有真实的桥接令牌,操作才能执行。
架构
分层执行架构中,每一层都会吸收一类原本需要由模型处理的复杂性。模型看到的是四个主要工具和一个简洁的 SDK。这个表面之下的一切,都由运行时负责吸收现实中的复杂情况。
值得了解的是会自行组装的那一层。首次使用时,系统会针对实时页面进行检测,并构建与页面实际情况相符的 smart 对象——只有在页面使用 React 时,才会存在 smart.react.*。启动时不会预先了解目标,因此系统会针对每个标签页动态组装接口,而不是预先声明。
┌───────────────────────────────────┐
│ AI Model (LLM) │
│ Writes code, reads errors, loops │
└───────────────┬───────────────────┘
│ search, execute, observe, connect_tab (+ 3 job tools)
▼
┌─────────────────────────────────────────────────────────────────┐
│ Crawlio Browser runtime │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ METHOD MODE │ │
│ │ Behavioral protocol + higher-order methods │ │
│ │ scrollCapture · waitForIdle · extractPage · comparePages │ │
│ │ detectTables · extractTable · waitForNetworkIdle · │ │
│ │ extractData │ │
│ │ │ │
│ │ ↳ Absorbs: behavioral variance, ad-hoc composition, │ │
│ │ inconsistent output shapes, data extraction patterns │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ POLYMORPHIC CONTEXT │ │
│ │ 17 framework namespaces, injected Just-In-Time │ │
│ │ react · vue · angular · nextjs · shopify · ... │ │
│ │ │ │
│ │ ↳ Absorbs: framework opacity, minified code, │ │
│ │ devtools hook complexity │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ ACTIONABILITY ENGINE │ │
│ │ 7 core smart methods with built-in resilience │ │
│ │ click · type · navigate · waitFor · evaluate · │ │
│ │ snapshot · rebuild │ │
│ │ │ │
│ │ ↳ Absorbs: DOM timing, hydration delays, CSS animations, │ │
│ │ disabled states, overlapping elements │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ TETHERED IPC BRIDGE │ │
│ │ WebSocket ↔ Chrome extension, message queue, │ │
│ │ heartbeat, auto-reconnect, stale detection │ │
│ │ │ │
│ │ ↳ Absorbs: connection drops, tab refreshes, │ │
│ │ port conflicts, extension lifecycle │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ COMMAND CHANNEL │ │
│ │ bridge.send → CDP browser control via the extension │ │
│ │ crawlio.* → Crawlio HTTP endpoints │ │
│ │ Live searchable catalog: browser + Crawlio HTTP │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────┐
│ Live Chrome Browser │
│ Persistent session, real DOM, │
│ framework runtime, user state │
└───────────────────────────────────┘
各层吸收的复杂性
| 层 | 没有它 | 有了它 |
|---|---|---|
| Tethered IPC Bridge | 标签页刷新会导致脚本崩溃,重连时待处理命令丢失,启动时发生端口冲突 | 具备消息队列(容量为 100 条消息)、心跳陈旧检测(间隔 15 秒)和自动重连并排空队列的弹性 WebSocket |
| Actionability Engine | click('#btn') 会在按钮渲染前、CSS 过渡期间,或按钮被遮罩层覆盖时触发 | 采用渐进式轮询(存在 → 具有尺寸 → 可见 → 未禁用 → 未被遮挡),并使用 [0, 20, 100, 100, 500]ms 退避间隔 |
| Polymorphic Context | 模型看到的是经过压缩的 <div> 元素;要读取 React 状态,必须知道精确的 Hook 路径、渲染器映射和 fiber 根 API | 运行时探测实时 JavaScript 环境,识别 64 种框架,并附加最多 17 个匹配的命名空间(smart.react.getVersion()、smart.nextjs.getData()) |
| Method Mode | 模型临时组合基础操作,导致滚动循环不一致、遗漏边界情况、返回值形式不一 | 18 个经过测试的方法编码了正确模式;行为协议约束了工作流 |
执行生命周期
- 发现 — 模型调用
search("page capture performance"),获取相关命令的文档 - 框架检测 — 运行时探测实时 DOM,检测活跃框架,并构建包含相应命名空间的多态
smart对象 - 作用域组装 — 模型的代码会被编译为异步函数,并注入以下参数:
bridge(浏览器命令通道)、crawlio(HTTP 客户端)、sleep、TIMEOUTS、smart(7 个核心方法 + 18 个高阶方法 + 最多 17 个框架命名空间)、compileRecording - 执行 — Method Mode 方法组合底层各层的功能:
extractPage()并行触发 7 次bridge.send()调用;click()运行可操作性引擎;react.getVersion()执行框架专属表达式 - 错误恢复(Agentic REPL) — 发生故障时,浏览器会保持在产生错误时的确切状态。模型读取结构化错误,进行调整,然后再次调用
execute。框架缓存会保留;除非 URL 发生变化,否则不会重新检测
设计原则
- 向下吸收复杂性 — 每类难点(连接管理、DOM 时序、框架检测、多步骤组合)都由最适合处理它的层负责。模型只需面对顶层的简洁接口。
- 让 SDK 适配目标 — 多态上下文系统会检测页面类型,并相应调整可用方法。模型针对稳定的接口编写代码;底层由运行时负责适配。
- 跨周期保留状态 — 系留式架构让模型能够在同一个实时环境中失败、学习并重试,从而将错误处理从“从头重启”转变为“调整后继续”。
对比
Code Mode 是 Cloudflare 提出的一个好想法:将工具呈现为类型化 API,并让模型针对它编写代码,因为模型接触过的代码远多于工具调用。Crawlio Browser 将这一模式应用于一个它原本并非为之构建的目标——一个保持着你会话状态的实时浏览器。这是一个 MCP 服务,而非 MCP 的替代方案。
| 维度 | 标准 MCP | Cloudflare Code Mode | Crawlio Browser |
|---|---|---|---|
| 上下文中的工具 | 50-100+ 个架构 | 2 个(search、execute) | 7 个(4 个主要工具 + 3 个异步任务工具) |
| 执行环境 | 不适用(工具调用) | V8 isolate(无状态) | 本地异步沙盒,与实时浏览器绑定 |
| DOM 访问 | 通过单独的工具调用 | 无 | 实时、持久、具备框架感知能力 |
| 框架感知能力 | 无 | 无 | 最多 17 个命名空间,按页面附加 |
| 操作韧性 | 模型必须处理时序问题 | 不适用(无 DOM) | 内置可操作性轮询 + 稳定等待延迟 |
| 错误恢复 | 重新调用单个工具 | 重新创建 isolate | 针对产生错误的状态重新运行 |
| 多步模式 | 模型自行发挥 | 模型编写循环 | 18 种经过测试的高阶方法 + 行为协议 |
关键在于错误恢复。isolate 的设计目的就是可随时销毁——这正是运行不可信代码时保障安全的原因,也意味着失败会丢弃导致失败的状态。这里的执行与真实标签页绑定,因此代码失败时,浏览器仍停留在导致问题的确切情境中:相同的滚动位置、相同的模态窗口、相同的半填表单。模型读取错误后,就能基于该状态再次运行。两种方式没有普遍意义上的优劣;它们是针对不同问题的解决方案,而 Cloudflare 通过 V8 isolate 获得的沙盒保障确实比本地异步沙盒提供的更强。
两种模式
Code Mode(4 个主要工具)——默认模式
将 150 个工具合并为四个高阶工具,另加用于异步执行的 get_job_result、
list_jobs 和 cancel_job,因此 tools/list 会报告
7 个工具。
这样,tools/list 的负载会缩小 85%。该数据是通过序列化各模式实际返回的结果得出的,而非根据工具数量估算。Code
Mode 并非没有代价:execute 和 search 都带有较长的描述,因此实际测得的缩减幅度小于简单按工具数量计算的比例。你可以自行验证——npx crawlio-browser tools --json 会在不连接任何内容的情况下打印两种模式的工具列表。
| 工具 | 描述 |
|---|---|
search | 按关键字查找可用命令 |
execute | 在作用域中包含 bridge、crawlio、smart、sleep 和 compileRecording 的情况下运行异步 JS |
observe | 启动/查询/停止扩展驻留式训练、录制和页面监控 |
connect_tab | 连接到浏览器标签页 |
// Navigate and screenshot
await bridge.send({ type: 'browser_navigate', url: 'https://example.com' }, 30000);
await sleep(2000);
const screenshot = await bridge.send({ type: 'take_screenshot' }, 10000);
return screenshot;
Full Mode(150 个工具)
将每个工具直接暴露给大模型。使用 --full 启用:
npx crawlio-browser init --full
Smart Object
在 Code Mode 中,smart 对象提供具备框架感知能力的辅助方法,并支持自动等待和可操作性检查。
核心方法
| 方法 | 描述 |
|---|---|
smart.evaluate(expression) | 通过 CDP 在页面中执行 JS |
smart.click(selector, opts?) | 自动等待后点击,并稳定等待 500ms |
smart.type(selector, text, opts?) | 自动等待后输入,并稳定等待 300ms |
smart.navigate(url, opts?) | 导航,并稳定等待 1000ms |
smart.waitFor(selector, timeout?) | 轮询,直到元素可操作 |
smart.snapshot() | 无障碍树快照 |
smart.rebuild() | 重新检测框架,并为当前页面重新附加命名空间 |
高阶方法
| 方法 | 描述 |
|---|---|
smart.scrollCapture(opts?) | 滚动到底部,并在每个位置捕获屏幕截图。可处理滚动卡住检测、底部检测、分段上限和滚动重置。 |
smart.waitForIdle(timeout?) | 基于 MutationObserver 的空闲检测——等待 500ms 的静默窗口。超时时间硬性限制为 15s。用于替代盲目调用 sleep()。 |
smart.extractPage(opts?) | 一次调用执行 7 项并行操作——页面捕获、性能、安全、字体、元数据、无障碍功能和移动设备就绪度。返回类型化的 PageEvidence,其中包含所有失败项的 CoverageGap[]。 |
smart.comparePages(urlA, urlB) | 导航到两个 URL,分别运行 extractPage(),并返回一个 ComparisonScaffold,包含 11 个维度、共享/缺失字段以及可比较的指标。 |
类型化证据
用于结构化分析结果并传播置信度的方法:
| 方法 | 描述 |
|---|---|
smart.finding(data) | 创建经过验证的 Finding,包含声明、证据、sourceUrl、置信度和方法。输入格式错误时会返回具体错误。 |
smart.findings() | 获取会话中累积的所有发现(返回副本) |
smart.clearFindings() | 重置会话发现和覆盖缺口 |
当发现项的 dimension 与有效覆盖缺口匹配时,置信度会自动设上限:
| 输入置信度 | 有效缺口 | 输出 |
|---|---|---|
high | reducesConfidence: true | medium + confidenceCapped: true |
medium | reducesConfidence: true | low + confidenceCapped: true |
low | 任意 | low(下限) |
| 任意 | 无匹配缺口 | 不变 |
框架命名空间
检测到框架后,智能对象会公开该框架专用的辅助方法:
React — smart.react
| 方法 | 返回值 |
|---|---|
getVersion() | 版本字符串和打包类型 |
getRootCount() | React 根组件的数量 |
hasProfiler() | 是否提供性能分析器 |
isHookInstalled() | 是否已安装 DevTools hook |
Vue.js — smart.vue
| 方法 | 返回值 |
|---|---|
getVersion() | Vue 版本字符串 |
getAppCount() | Vue 应用实例的数量 |
getConfig() | 应用配置对象 |
isDevMode() | 是否启用了 DevTools |
Angular — smart.angular
| 方法 | 返回值 |
|---|---|
getVersion() | ng-version 属性值 |
isDebugMode() | 是否提供调试 API |
isIvy() | 是否启用了 Ivy 编译器 |
getRootCount() | Angular 根元素的数量 |
getState() | 完整状态对象 |
Svelte — smart.svelte
| 方法 | 返回值 |
|---|---|
getVersion() | Svelte 版本字符串 |
getMeta() | Svelte 元数据对象 |
isDetected() | 是否检测到 Svelte |
Redux — smart.redux
| 方法 | 返回值 |
|---|---|
isInstalled() | 是否已安装 Redux DevTools |
getStoreState() | 完整存储状态 |
Alpine.js — smart.alpine
| 方法 | 返回值 |
|---|---|
getVersion() | Alpine 版本字符串 |
getStoreKeys() | 存储对象键 |
getComponentCount() | [x-data] 组件的数量 |
Next.js — smart.nextjs
| 方法 | 返回值 |
|---|---|
getData() | __NEXT_DATA__ 对象 |
getRouter() | 路由器状态(pathname、query、asPath) |
getSSRMode() | SSR 模式(hybrid、app-router、static) |
getRouteManifest() | 当前页面数据 |
Nuxt — smart.nuxt
| 方法 | 返回值 |
|---|---|
getData() | __NUXT__ 对象 |
getConfig() | 应用配置 |
isSSR() | 是否由服务器渲染 |
Remix — smart.remix
| 方法 | 返回值 |
|---|---|
getContext() | __remixContext 对象 |
getRouteData() | 状态中的 Loader 数据 |
Shopify — smart.shopify
| 方法 | 返回值 |
|---|---|
getShop() | 商店元数据(主题、区域设置、货币) |
getCart() | 购物车对象 |
WordPress — smart.wordpress
| 方法 | 返回值 |
|---|---|
isWP() | 是否存在 WordPress |
getRestUrl() | REST API 端点 |
getPlugins() | 已启用插件列表 |
更多框架 — Gatsby、WooCommerce、Laravel、Django、Drupal、jQuery
| 命名空间 | 方法 |
|---|---|
smart.gatsby | getData()、getPageData() |
smart.woocommerce | getParams() |
smart.laravel | getCSRF() |
smart.django | getCSRF() |
smart.drupal | getSettings() |
smart.jquery | getVersion() |
代码模式让模型编写代码。方法模式则为这些代码提供经过测试的方法词汇: 18 种高阶方法,编码了模型原本需要自行摸索的多步骤模式。
await smart.extractTable(selector) // not a hand-rolled scrape loop
await smart.scrollCapture() // not a guessed scroll cadence
它是代码模式之上的领域层,而非替代方案:工具接口不会改变,
模型仍然可以看到相同的四个主要工具,底层也仍是相同的 182 条命令
目录。改变的是 execute 内部发生的事情。
接口会按页面组装。检测功能可识别 64 种
框架,并附加最多 17 个匹配的命名空间,因此 smart.react.*
只会在使用 React 的页面上存在——模型无需询问页面采用了什么技术构建,也不必猜测钩子路径和 fiber 内部结构来查明这一点。
此外,由于执行绑定到一个实时标签页,而不是一次性隔离环境,失败后浏览器会保持在导致失败的确切状态。模型读取结构化错误后, 会基于该状态再次运行,而不是从头重建情境。
成熟度阶梯
| 层级 | 优化目标 | 行为差异 | 证据质量 |
|---|---|---|---|
| 原始 MCP(150 个工具) | 完整性 | 高——扁平的工具列表,没有组合指导 | 无——非结构化文本 |
| 代码模式(7 个工具) | 令牌效率 | 中——原语合适,组合方式临时决定 | 无——由模型定义形状 |
| 方法模式(+ 18 种方法 + 协议) | 一致性 | 低——采用恰当的方法和协议约束 | 惯例——{ finding, evidence, url } |
| + 类型化证据(缺口 + 置信度) | 正确性 | 极低——采用类型化架构,发现项由工具强制执行 | 结构化——类型化记录、缺口跟踪、置信度传递 |
架构
┌────────────────────────────────────────────────────────────┐
│ execute sandbox │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Behavioral Protocol (web-research skill) │ │
│ │ Acquire → Normalize → Analyze │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Evidence Infrastructure │ │
│ │ finding() · findings() · clearFindings() │ │
│ │ Typed records · Coverage gaps · Confidence prop. │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Higher-Order Methods [18] │ │
│ │ scrollCapture · waitForIdle · extractPage · │ │
│ │ comparePages · detectTables · extractTable · │ │
│ │ waitForNetworkIdle · extractData · detectSections · │ │
│ │ detectTechnologies · parseTrackingPixels · ... │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Smart Core [7 methods] │ │
│ │ evaluate · click · type · navigate · waitFor · │ │
│ │ snapshot · rebuild │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Framework Namespaces [up to 17, attached per page] │ │
│ │ react · vue · angular · nextjs · shopify · ... │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ bridge.send() — the browser command channel │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
每往上一层,编码的领域知识就更多。bridge.send({ type: "capture_page" }) 会捕获页面。smart.extractPage() 不仅会捕获页面,还会并行运行性能指标、安全状态、字体检测、无障碍分析和移动设备适配检查——七项操作,一次调用;补充数据获取失败时可优雅降级,并为任何失败项记录类型化缺口。
证据基础设施
覆盖缺口——当 extractPage() 中的补充操作失败时,不会悄无声息地返回 null。系统会记录一个类型化缺口,其中包含维度、原因、影响,以及该缺口是否会降低相关发现项的置信度:
// Example gap from a failed performance metrics call
{ dimension: "performance", reason: "CDP domain disabled", impact: "method-failed", reducesConfidence: true }
由工具强制执行的发现项——smart.finding() 会在工具层面验证每个字段。模型必须满足架构要求才能生成发现项——否则会返回有效的 Finding,否则会收到明确错误。在一个会话中,发现项会在多次 execute 调用间累积,并可通过 smart.findings() 获取。
会话聚合——发现项和覆盖缺口会在多次 execute 调用间保留。模型可以通过多次调用生成发现项,然后使用 smart.findings() 获取完整集合。使用 smart.clearFindings() 重置。
端到端示例:竞争对手审查
// 1. Extract and compare both sites (scaffold + gaps included)
const comparison = await smart.comparePages(
'https://acme.com',
'https://rival.com'
);
// 2. Make findings — confidence auto-adjusts based on data availability
smart.finding({
claim: 'Rival loads 2.3x faster on Largest Contentful Paint',
evidence: [
`Acme LCP: ${comparison.siteA.performance?.webVitals?.lcp}ms`,
`Rival LCP: ${comparison.siteB.performance?.webVitals?.lcp}ms`,
],
sourceUrl: 'https://acme.com',
confidence: 'high',
method: 'comparePages + extractPage performance metrics',
dimension: 'performance', // if perf data failed, confidence caps to "medium"
});
smart.finding({
claim: 'Acme has 12 images without alt text; Rival has 0',
evidence: [
`Acme imagesWithoutAlt: ${comparison.siteA.accessibility?.imagesWithoutAlt}`,
`Rival imagesWithoutAlt: ${comparison.siteB.accessibility?.imagesWithoutAlt}`,
],
sourceUrl: 'https://acme.com',
confidence: 'high',
method: 'comparePages + extractPage accessibility summary',
dimension: 'accessibility',
});
// 3. Capture visual evidence
await smart.navigate('https://acme.com');
await smart.waitForIdle();
const acmeVisuals = await smart.scrollCapture({ maxSections: 5 });
// 4. Return accumulated session findings + visual evidence
return {
findings: smart.findings(),
scaffold: comparison.scaffold,
gaps: { acme: comparison.siteA.gaps, rival: comparison.siteB.gaps },
visualEvidence: { acme: acmeVisuals.sectionCount + ' sections captured' },
};
示例
导航、提取与分析
// Connect to active tab, extract structured page evidence
const page = await smart.extractPage();
const finding = smart.finding({
claim: `Site uses ${page.capture.framework?.name || 'no detected framework'}`,
evidence: [`Framework: ${JSON.stringify(page.capture.framework)}`],
sourceUrl: page.meta?.canonical || 'active tab',
confidence: 'high',
method: 'extractPage framework detection',
});
return { page: page.meta, finding };
移动设备模拟 + 截图
// Emulate iPhone and capture
await bridge.send({ type: 'emulate_device', device: 'iPhone 14' }, 10000);
await smart.navigate('https://example.com');
await smart.waitForIdle();
const screenshot = await bridge.send({ type: 'take_screenshot' }, 10000);
return screenshot;
记录并编译自动化
// Record a browser session, then compile to reusable skill
await bridge.send({ type: 'start_recording' }, 10000);
await smart.navigate('https://example.com');
await smart.click('button.submit');
await smart.type('#email', '[email protected]');
const session = await bridge.send({ type: 'stop_recording' }, 10000);
return compileRecording(session.session, 'signup-flow');
拦截并模拟网络
// Block analytics, mock API response
await bridge.send({
type: 'browser_intercept',
pattern: '*analytics*',
action: 'block'
}, 10000);
await bridge.send({
type: 'browser_intercept',
pattern: '*/api/user',
action: 'mock',
body: JSON.stringify({ name: 'Test User' }),
statusCode: 200
}, 10000);
await smart.navigate('https://example.com');
return await smart.snapshot();
会话录制
将浏览器会话录制为结构化数据,然后将其编译成可复用的自动化技能。录制期间会自动拦截 12 种交互工具(点击、输入、导航、滚动等),并捕获参数、结果、时间信息和页面 URL。
// In code mode: record, interact, compile
await bridge.send({ type: 'start_recording' }, 10000);
// ... interact with the page ...
const session = await bridge.send({ type: 'stop_recording' }, 10000);
const skill = compileRecording(session.session, 'my-automation');
return skill;
在完整模式下,录制功能以 4 个独立工具的形式提供:start_recording、stop_recording、get_recording_status 和 compile_recording。
自动稳定
修改页面的工具(browser_click、browser_type、browser_navigate、browser_select_option)会执行可操作性检查:
- 执行前检查:在操作前轮询元素的可见性、稳定性和启用状态
- 执行操作:分发 CDP 命令
- 操作后稳定:以逐步退避的间隔
[0, 20, 100, 100, 500]ms等待 DOM 变更停止
这意味着 AI 无需在操作之间手动添加 sleep() 或 waitFor() 调用——这些工具会自动处理 SPA 渲染延迟。
框架检测
通过全局变量、DOM 标记、meta 标签、HTTP 标头和脚本 URL,在 4 个层级中检测 64 种技术:
| 层级 | 框架 | 信号强度 |
|---|---|---|
| 元框架 | Next.js、Nuxt、SvelteKit、Remix、Gatsby | 独有全局变量 + 父级检测 |
| 核心 | React、Vue.js、Angular、Svelte、Astro、Qwik、SolidJS、Lit、Preact | 全局变量 + DOM 标记 |
| CMS 和平台 | WordPress、Shopify、Webflow、Squarespace、Wix、Drupal、Magento、Ghost、Bubble | Meta 标签 + 全局变量 |
| 库和工具 | jQuery、Bootstrap、Tailwind CSS、Alpine.js、HTMX、Turbo、Stencil、Redux、Ember.js、Backbone.js | DOM + 全局变量 |
多框架检测会返回一个主要框架(元框架优先),并通过 subFrameworks 数组提供完整技术栈。
工具参考
下表是常用工具的手写指南,并非完整列表。如需查看完整的最新工具集——全部 150 个工具,可从服务本身读取——
请运行 npx crawlio-browser tools --full。
工具参考 — 连接、捕获、导航、网络、存储、模拟、跟踪、SEO 等
连接与状态
| 工具 | 描述 |
|---|---|
connect_tab | 通过 URL、标签页 ID 或活动标签页连接到浏览器标签页 |
disconnect_tab | 断开与当前标签页的连接 |
list_tabs | 列出所有打开的标签页及其 ID 和 URL |
get_connection_status | 检查 CDP 连接状态 |
reconnect_tab | 强制重新连接,以修复失效的连接 |
get_capabilities | 按标签页、CDP 域和权限状态报告浏览器桥接的实时可用性 |
页面捕获
| 工具 | 描述 |
|---|---|
capture_page | 完整捕获:框架 + 网络 + 控制台 + DOM |
detect_framework | 检测 JS 框架和版本 |
start_network_capture | 开始录制网络请求 |
stop_network_capture | 停止录制并返回捕获的请求 |
get_console_logs | 获取控制台日志(错误、警告、信息) |
get_cookies | 获取 Cookie(敏感值会被隐藏) |
get_dom_snapshot | 简化的 DOM 树,支持 Shadow DOM 和 iframe |
take_screenshot | 查看视口、整页或元素图像(默认 JPEG,按需提供 PNG) |
get_response_body | 获取已捕获网络请求的响应正文 |
导航与交互
| 工具 | 描述 |
|---|---|
browser_navigate | 导航到 URL(自动等待稳定) |
browser_click | 按 CSS 选择器点击元素(自动等待稳定,支持左键/右键/中键及修饰键) |
browser_double_click | 双击元素 |
browser_type | 在元素中输入文本(自动等待稳定) |
browser_press_key | 按下键盘按键(Enter、Tab、Escape、快捷键) |
browser_hover | 将鼠标悬停在元素上 |
browser_select_option | 按值选择 <option>(自动等待稳定) |
browser_scroll | 滚动页面或元素 |
browser_drag | 将一个元素拖到另一个元素上 |
browser_file_upload | 将文件上传到 <input type="file"> |
browser_wait | 等待 N 毫秒 |
browser_wait_for | 等待元素状态(可见、隐藏、已附加、已分离) |
| 工具 | 描述 |
|---|---|
browser_intercept | 阻止、修改标头或模拟符合 URL 模式的响应 |
emulate_network | 限制网络速度(离线、3G、4G、WiFi 预设) |
set_cache_disabled | 禁用/启用浏览器缓存 |
set_extra_headers | 为所有请求添加自定义标头 |
get_websocket_connections | 列出活跃的 WebSocket 连接 |
get_websocket_messages | 获取 WebSocket 消息历史记录 |
框架与标签页
| 工具 | 描述 |
|---|---|
get_frame_tree | 获取框架层级结构(主框架 + iframe) |
switch_to_frame | 将执行上下文切换到 iframe |
switch_to_main_frame | 切回主框架 |
create_tab | 创建带有 URL 的新标签页 |
close_tab | 按 ID 关闭标签页 |
switch_tab | 按 ID 聚焦标签页 |
Cookie 与存储
| 工具 | 描述 |
|---|---|
set_cookie | 设置 Cookie(通过 CDP 支持 httpOnly) |
delete_cookies | 按名称/域名/路径删除 Cookie |
get_storage | 读取 localStorage 或 sessionStorage |
set_storage | 写入存储项 |
clear_storage | 清除所有存储项 |
get_databases | 列出 IndexedDB 数据库 |
query_object_store | 查询 IndexedDB 对象存储 |
clear_database | 清除或删除 IndexedDB 数据库 |
对话框
| 工具 | 描述 |
|---|---|
get_dialog | 获取待处理的 JS 对话框(alert/confirm/prompt) |
handle_dialog | 接受或关闭对话框 |
模拟
| 工具 | 描述 |
|---|---|
set_viewport | 设置视口尺寸 |
set_user_agent | 覆盖 User-Agent 字符串 |
emulate_device | 模拟设备(iPhone、iPad、Pixel、Galaxy、Desktop) |
set_geolocation | 覆盖地理位置坐标 |
set_stealth_mode | 反检测模式(可选启用,会修补 webdriver 指纹) |
安全
| 工具 | 描述 |
|---|---|
get_security_state | TLS 证书详情、协议和密码套件 |
ignore_certificate_errors | 忽略预发布环境中的证书错误 |
Service Worker
| 工具 | 描述 |
|---|---|
list_service_workers | 列出所有 Service Worker 注册项 |
stop_service_worker | 停止/注销 Service Worker |
bypass_service_worker | 对网络请求绕过 Service Worker |
DOM 操作
| 工具 | 描述 |
|---|---|
set_outer_html | 替换元素的 HTML |
set_attribute | 设置元素属性 |
remove_attribute | 移除元素属性 |
remove_node | 从 DOM 中移除元素 |
CSS 与 JS 覆盖率
| 工具 | 描述 |
|---|---|
start_css_coverage / stop_css_coverage | 跟踪使用了哪些 CSS 规则 |
start_js_coverage / stop_js_coverage | 跟踪执行了哪些 JS 代码 |
get_computed_style | 获取元素解析后的 CSS 属性 |
force_pseudo_state | 强制 :hover、:focus、:active 状态 |
性能与内存
| 工具 | 描述 |
|---|---|
get_performance_metrics | Chrome 指标 + Web Vitals(LCP、CLS、FID) |
get_dom_counters | 统计 DOM 节点、文档和事件监听器的数量 |
force_gc | 强制垃圾回收 |
take_heap_snapshot | 获取 V8 堆快照摘要 |
PDF 与无障碍功能
| 工具 | 描述 |
|---|---|
print_to_pdf | 生成 PDF(自定义纸张、页边距和方向) |
get_accessibility_tree | 获取无障碍树,用于屏幕阅读器审查 |
目标与上下文
| 工具 | 描述 |
|---|---|
get_targets | 列出所有 Chrome 目标(页面、工作线程、扩展程序) |
attach_to_target | 将 CDP 会话附加到任意目标 |
create_browser_context | 创建隔离上下文(类似隐身模式) |
可视化调试
| 工具 | 描述 |
|---|---|
highlight_element | 使用彩色叠加层突出显示元素 |
show_layout_shifts | 可视化 CLS 区域 |
show_paint_rects | 可视化绘制/重绘区域 |
会话录制
| 工具 | 描述 |
|---|---|
start_recording | 开始录制浏览器会话 |
stop_recording | 停止录制并返回会话数据 |
get_recording_status | 检查录制状态 |
compile_recording | 将会话编译为 SKILL.md 自动化 |
机器人训练
| 工具 | 描述 |
|---|---|
robot_training_start | 开始一次全新的受监控演示运行 |
robot_training_status | 查询扩展程序保留的运行记录和录制状态 |
robot_training_stop | 停止/导出驻留运行并保存所有捆绑文件 |
robot_training_clear | 确认删除一条已停止、由扩展程序保留的运行记录;保留文件 |
robot_training_artifacts | 列出机器人训练文件目录中的文件 |
monitor_page | 启动/查询/停止由扩展程序驻留的定期页面监控 |
Crawlio App 集成
可选 — 需要在本地运行 Crawlio.app。
ControlServer 身份验证会自动进行,且仅在本地执行:MCP 会读取明确设置的 CRAWLIO_MCP_TOKEN,否则读取 Crawlio.app 的 mode-0600 ~/Library/Logs/Crawlio/mcp.token,并且只将其发送到发现的 127.0.0.1 ControlServer。此值不会在 MCP 结果中返回,也不会写入日志。
| 工具 | 描述 |
|---|---|
extract_site | 启动对当前标签页 URL 的 Crawlio 爬取 |
get_crawl_status | 获取爬取进度和状态 |
get_enrichment | 获取浏览器增强数据 |
get_crawled_urls | 分页获取带状态的已爬取 URL |
enrich_url | 一次调用即可完成导航、捕获并提交增强数据 |
要求
- Node.js >= 18
- 安装了 Crawlio for Chrome 扩展程序 的 Chrome(或 Chromium)
- Crawlio.app(可选)— 用于网站爬取和数据增强
最低权限
生产版扩展程序不会持续访问任何主机。它需要的权限为 debugger
(CDP 控制平面)、storage(桥接/会话设置和持久驻留元数据),以及
alarms(重新连接、空闲释放和驻留监控唤醒)。专用引导页面会一次性请求当前构建版本声明的所有可选功能权限。生产版中,这些权限为 tabs、
nativeMessaging 和 http://127.0.0.1/*,用于发现/接管标签页、提供经过身份验证的本地令牌,以及发现环回桥接服务。
引导流程是唯一能够打开 Chrome 权限提示的界面。扩展程序弹出窗口和 MCP 工具只会报告缺少的权限,并引导用户返回引导页面。即使 tabs 元数据权限被拒绝,connect_tab({url})、
由 Agent 创建的标签页、机器人训练和驻留监控仍可创建并控制自己的标签页。Crawlio 不会请求 <all_urls>、activeTab、
tabGroups 或 unlimitedStorage。
从源代码构建
git clone https://github.com/Crawlio-app/crawlio-browser.git
cd crawlio-browser
npm install
npm run build # selectors → semantic-grounding → MCP server → extension
构建输出位于 dist/mcp-server/(ESM 捆绑包)和 dist/extension/(未打包的 MV3 扩展程序)中。
若要使用扩展程序进行开发,请构建开发版本并以未打包方式加载:
npm run build:dev # → dist/extension-dev, with __DEV__ logging enabled
然后打开 chrome://extensions,启用开发者模式,选择 Load unpacked,
并选择 dist/extension-dev。每次重新构建后,都要在此处重新加载扩展程序。
npm test # vitest
npm run typecheck # server + extension TypeScript projects
资源
贡献
欢迎贡献 — 有关构建和开发流程,请参阅 CONTRIBUTING.md;有关社区规范,请参阅 CODE_OF_CONDUCT.md。请通过 SECURITY.md 私下报告安全漏洞,不要在公开议题中报告。
许可证
Apache-2.0 — 请参阅 LICENSE。
packages/selectors 中的选择器内核采用 MIT 许可证:其中包含从 Selector Forge(MIT)和 Chromium DevTools(BSD-3-Clause)移植的代码。完整归属信息请参阅 packages/selectors/LICENSE 和 THIRD_PARTY_NOTICES.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。