PhantomHand
PhantomHand 是一个面向 AI 智能体的浏览器控制引擎。它通过 Chrome DevTools Protocol 以 Model Context Protocol (MCP) 标准把浏览器的感知与操控能力暴露给大语言模型,让智能体能像人一样视觉理解网页,并真实地点击、输入、采集信息。
所有命令默认作用于浏览器的当前激活标签页,也可通过显式
tabId参数指定任意标签页。
---
核心特性
- 复用已登录的真实浏览器:直接在你的日常 Chrome 上操作,保留登录态、插件、书签——无需另开隔离 profile。
- 真视觉感知:Set-of-Mark 标注截图,能识别 canvas、视频、复杂 CSS 渲染的内容(纯无障碍树看不到的)。
- 稳定 ref 引用:每个可交互元素分配稳定的
ref,操控时解析其当前坐标,页面轻微重排也不会失效。 - 拟人与反检测:贝塞尔鼠标轨迹、人类化打字节奏、点击前瞄准停顿;基于
chrome.debugger而非 WebDriver,并自动在页面主世界抹除自动化指纹。 - 信息密度优先:文本快照、批量结构化提取、页面智能摘要、页面身份 API 请求;大体积产物默认存盘或摘要,不回流上下文。
- 可观测性:console、网络请求、性能指标、Web Storage 全量回流。
---
快速使用
在你的 AI Agent(Claude Desktop、Cursor、Windsurf、Antigravity 等)的 MCP 配置中注册 phantom-hand。两种部署方式任选其一。
A. 从 npm 安装(已发布)
{
"mcpServers": {
"phantom-hand": {
"command": "npx",
"args": ["-y", "phantom-hand-mcp"]
}
}
}
B. 从本地源码运行(开发 / 未发布)
克隆仓库后先构建,再用产物的绝对路径注册:
npm install && npm run build
{
"mcpServers": {
"phantom-hand": {
"command": "node",
"args": ["<项目根目录的绝对路径>/dist/index.cjs"]
}
}
}
各 Agent 的配置文件位置
| Agent | 配置文件 | |---|---| | Claude Desktop(Windows) | %APPDATA%\Claude\claude_desktop_config.json | | Claude Desktop(macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json | | Cursor | 工作区 .cursor/mcp.json,或设置中的 MCP GUI | | Windsurf | ~/.codeium/windsurf/mcp_config.json | | Antigravity | ~/.gemini/config/mcp_config.json |
保存并重启 Agent,服务会在后台启动并监听 ws://localhost:37210。
---
安装浏览器扩展(必需)
PhantomHand 通过一个浏览器扩展与 Chrome 通信,需手动加载一次:
- 让你的 AI 助手调用
get_extension_info工具,获取本机扩展目录的绝对路径(位于~/.npm/_npx/.../extension)。 - 打开
chrome://extensions/,开启右上角「开发者模式」,点击「加载已解压的扩展程序」,选中上一步的目录。 - 点击浏览器工具栏的 PhantomHand 图标,URL 保持默认
ws://localhost:37210,点击「Connect to Agent Server」,指示灯变绿即连接成功。
---
工具清单
| 分类 | 工具 | |---|---| | 元信息 | get_extension_info | | 感知 | browser_scan、browser_snapshot(文本快照,无图)、browser_screenshot、browser_get_page_info、browser_query_ref(按 selector 精确取 ref) | | 鼠标 | browser_click、browser_click_ref、browser_double_click、browser_triple_click、browser_right_click、browser_hover、browser_drag | | 键盘 / 剪贴板 | browser_type、browser_type_ref、browser_press_key、browser_keyboard_shortcut、browser_select_all、browser_clipboard_set、browser_clipboard_get | | 滚动 | browser_scroll、browser_scroll_to_element | | DOM / JS | browser_eval_js、browser_get_html、browser_extract_text、browser_get_attributes、browser_extract_structured(批量 → JSON)、browser_read_page(主内容智能摘要) | | 表单 | browser_set_value、browser_clear_value、browser_select_option、browser_check、browser_focus、browser_upload_file | | 标签页 / 导航 | browser_navigate、browser_go_back、browser_go_forward、browser_reload、browser_tab_new、browser_tab_close、browser_tab_list、browser_tab_switch | | 可观测性 · debug | browser_list_console_messages | | 可观测性 · network | browser_list_network_requests、browser_get_network_request、browser_fetch(以页面身份请求 API)、browser_mock_request、browser_clear_mocks | | 可观测性 · performance | browser_performance_start_trace、browser_performance_stop_trace | | 存储 | browser_storage_get、browser_storage_set、browser_storage_remove | | 捕获 / 模拟 | browser_print_to_pdf、browser_set_viewport、browser_clear_viewport、browser_screencast_start、browser_screencast_stop | | 会话 | browser_session_export、browser_session_import | | 时序 | browser_wait、browser_wait_for_element(精确等待元素出现/消失)、browser_fast_forward、browser_wait_for_download |
---
核心范式
ref 引用(推荐的元素操控方式)
browser_scan / browser_snapshot 为每个可交互元素分配稳定 ref(如 [ref: 3])。优先用 browser_click_ref / browser_type_ref 按 ref 操控——它会解析元素当前的坐标,即使页面发生轻微重排也能正确命中。若已知目标的选择器,可直接用 browser_query_ref 获取 ref,跳过全页扫描。
穿透同源 iframe
感知会递归进入 shadow DOM 与同源 iframe:iframe 内的元素同样分配 ref,坐标已折算到主页面视口,可直接用 ref 操控,无需关心 iframe 边界与坐标偏移。跨域 iframe(如第三方验证码)的 DOM 不可访问,不会出现在感知结果中。
信息密度
为避免上下文膨胀,大体积产物默认存盘或摘要:
browser_print_to_pdf把 PDF 写入下载目录,仅返回路径;browser_storage_get不传 key 时只返回键名列表;browser_screencast_start/browser_screencast_stop只统计帧数,不回传画面;browser_scan在长页面上提示「视口内 X / 共 Y 个元素」,告知还有多少未展示。
需要采集成片内容时,优先用高密度工具:browser_extract_structured(批量结构化)、browser_read_page(页面摘要)、browser_fetch(直连站点 API)。
自动等待
导航与点击/输入默认启用 auto-wait:导航等待页面 complete,交互等待网络空闲(networkIdle)。对 SPA 中延迟渲染的元素,用 browser_wait_for_element 精确等待其出现、附着或消失。
反检测
PhantomHand 基于 chrome.debugger(CDP)操控浏览器,不携带 WebDriver 指纹。每次连接一个标签页后,会自动向页面的主世界注入轻量补丁(经 Page.addScriptToEvaluateOnNewDocument,在任何站点脚本之前生效),抹除剩余自动化痕迹:
navigator.webdriver→undefined- 补全
window.chrome.runtime - 规整
navigator.languages/navigator.plugins - 修正
permissions.query对notifications的泄漏
注入逐标签页幂等,标签页关闭时自动清理,默认开启、无需配置。鼠标移动采用贝塞尔曲线加随机抖动,打字按字符类型差异化停顿(句末标点长停顿、逗号中停顿),点击前有短暂瞄准停顿。
---
配置
所有配置通过环境变量驱动(详见 .env.example):
| 变量 | 默认 | 说明 | |---|---|---| | PORT | 37210 | WebSocket 端口 | | PHANTOM_HAND_TOKEN | (空) | WebSocket 鉴权 token | | PHANTOM_HAND_SCREENSHOT_FORMAT | jpeg | 截图重编码格式(jpeg/webp/png,需安装 sharp) | | PHANTOM_HAND_SCREENSHOT_QUALITY | 75 | 截图质量 1-100 | | PHANTOM_HAND_SCREENSHOT_MAX_WIDTH / _HEIGHT | 0(不限) | 截图最大尺寸,超出则等比缩小 | | PHANTOM_HAND_AUTO_WAIT_TIMEOUT | 3000 | auto-wait 等待上限(ms),0 关闭 | | PHANTOM_HAND_DOMAIN_ALLOWLIST | (空) | 域名白名单(逗号分隔),设置后仅允许这些域名 | | PHANTOM_HAND_DOMAIN_BLOCKLIST | (空) | 域名黑名单(逗号分隔) | | PHANTOM_HAND_CATEGORY_DEBUG / _NETWORK / _PERFORMANCE / _STORAGE | true | 设为 false 隐藏整类工具,缩小 agent 选择面 |
截图压缩(可选):默认极轻量。安装 npm i sharp 后,截图会按上述参数重编码(webp/jpeg 显著小于 png),降低上下文占用;未安装时返回原图,功能不受影响。
---
安全
- 服务默认监听
ws://localhost,仅本机可连。不要将服务暴露到公网或不受信任的远程地址——browser_eval_js等工具等同于本机浏览器的远程代码执行权限。 - 启用鉴权:设置
PHANTOM_HAND_TOKEN=<密钥>,并在扩展弹窗 URL 中追加?token=<密钥>。服务会拒绝未携带正确 token 的连接。 - 除非完全控制远端主机,否则不要在扩展弹窗填写
wss://远程地址。
---
多 Agent 并发(Proxy Broker)
多个宿主 Agent(如同时运行 Cursor 与 Claude Desktop,各自启动 phantom-hand)可共享同一个浏览器扩展:
- 第一个进程占用
37210端口,成为 Master,承载 WebSocket 服务并与扩展通信。 - 后续进程发现端口被占用,自动作为 Proxy 连接到 Master,转发命令。
每条请求/响应通过唯一 requestId 路由,并发调用互不串扰。若希望多个 Agent 各自控制独立标签页,可在工具调用中传入显式 tabId(通过 browser_tab_list 获取)。
---
开发
npm install # 安装依赖
npm run build # esbuild 打包到 dist/index.cjs
npm run dev # 以 tsx 直接运行 src/index.ts
npm start # 运行编译产物
npm test # 单元测试
npm run lint # tsc --noEmit 类型检查
端到端功能验证见 test/smoke-test.md。
---
常见问题
- 发送指令后浏览器无反应?
Chrome 禁止扩展在系统保护页(chrome://newtab、chrome://settings、chrome://extensions、Web Store 等)执行调试 API。请确保当前聚焦一个常规网页。
- 端口被占用?
若 37210 被占用,服务不会结束占用进程,而是自动以 Proxy 模式继续工作(见上节)。如需换端口:设置 PORT=xxxx,并在扩展弹窗填入对应端口。
- 浏览器一直显示「正在调试此浏览器」黄条?
这是 CDP 调试的正常表现。扩展会在标签页关闭时自动 detach 调试器;如需立即清除,关闭对应标签页。
- 剪贴板读取偶尔失败?
现代浏览器要求剪贴板读取有用户手势。无手势上下文中 browser_clipboard_get 可能失败——这是浏览器安全策略。
- 按 ref 操作时报「ref not found」?
ref 不跨扫描保活。重新 browser_scan / browser_snapshot / browser_query_ref 获取新 ref 后再操作。











