Metadata-Version: 2.4
Name: nexus-browser-mcp
Version: 0.1.0
Summary: 事件驱动确定性快照的浏览器操控 MCP 服务器 (Playwright + Accessibility Tree)
Author: pai
License: MIT
Project-URL: Homepage, https://github.com/paipaipai666/nexus-broswer-mcp
Project-URL: Repository, https://github.com/paipaipai666/nexus-broswer-mcp
Project-URL: Issues, https://github.com/paipaipai666/nexus-broswer-mcp/issues
Keywords: mcp,browser,playwright,llm,agent,automation,accessibility-tree
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp>=1.0
Requires-Dist: playwright>=1.59
Requires-Dist: pydantic<3,>=2.10
Requires-Dist: pydantic-settings>=2
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: pytest-mock>=3; extra == "dev"
Requires-Dist: ruff>=0.3; extra == "dev"
Dynamic: license-file

# nexus-browser-mcp

**事件驱动确定性快照的浏览器操控 MCP 服务器。**

基于 Playwright,通过 Accessibility Tree(无障碍树)让 LLM 驱动浏览器——导航、点击、输入、读取、表单、多标签。与市面同类产品(Playwright MCP 等)的核心差异:

1. **确定性快照**:不靠固定间隔 `sleep` 硬等,而是注入 `MutationObserver` 记录最后一次 DOM 变异,由浏览器自身的 `requestAnimationFrame` 循环判定"页面已静默 `STABLE_WINDOW_MS`(默认 800ms)"后才提取快照。杜绝"快照抓在动画/加载中"的竞态。
2. **内嵌治理门**:HITL 规则(如点击"支付/确认"需人工)、`browser_evaluate` 默认禁用+无条件确认、JSONL 审计(含敏感参数脱敏)。
3. **多 task 隔离**:一个 MCP 连接(session)内可建多个独立 `task_id`,各自独立 BrowserContext(登录态互不污染),TTL 空闲回收、回收后再次使用时自动重建并恢复上次页面。
4. **死亡可观测 + 自愈**:标签页/浏览器被外部关闭或崩溃后,下次调用自动重建(持久化 profile 登录态不丢),并在工具返回前置 `[状态变更]` 通知,明确告知"恢复了什么、丢了什么",不再泄漏 Playwright 底层异常。

## 安装

```bash
pip install nexus-browser-mcp
# 或
uvx nexus-browser-mcp
```

安装后提供 `nexus-browser-mcp` / `nexus-browser` 两个可执行入口;兜底启动方式(一定可用):`python -m nexus_browser.server`。

依赖 `playwright` 及其浏览器内核:

```bash
pip install playwright && playwright install chromium
```

## 接入(任意 MCP 客户端)

**opencode**(`~/.config/opencode/opencode.json`):

```json
{
  "mcp": {
    "browser": {
      "type": "local",
      "command": ["uvx", "nexus-browser-mcp"],
      "enabled": true
    }
  }
}
```

**Claude Code**(`.mcp.json`,项目根):

```json
{
  "mcpServers": {
    "browser": {
      "type": "stdio",
      "command": "uvx",
      "args": ["nexus-browser-mcp"]
    }
  }
}
```

**Pi Coding Agent**:读取标准 MCP 配置 —— 项目 `.mcp.json` 或用户全局 `~/.config/mcp/mcp.json`,stdio 默认 transport:

```json
{
  "mcpServers": {
    "browser": {
      "command": "uvx",
      "args": ["nexus-browser-mcp"]
    }
  }
}
```

详细见 `docs/INTEGRATE.md`。

## 使用你自己的浏览器(带登录态)

默认 `isolated` 模式启动 Playwright 内置 Chromium,**不带你的 cookie/登录态**。要用你自己的浏览器,二选一:

**方式 A — 直接加载你的浏览器 profile(推荐,最省事)**

用系统 Chrome 加载你平时的用户数据目录(Cookie/登录态/书签都在):

```
BROWSER_CHANNEL=chrome
BROWSER_USER_DATA_DIR="C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data"
```

> 注意:用自己的 User Data 时,进程会占用浏览器,期间你自己开 Chrome 会冲突。建议复制一份 profile 或用独立的 `--user-data-dir` 指向一个专用目录。

**推荐做法:工具专用 profile(不与日常浏览器冲突)**

用 `BROWSER_CHANNEL=chrome` + 指向一个专用 user data 目录(如 `C:\Users\<你>\.nexus-browser\chrome-profile`):

```
BROWSER_CHANNEL=chrome
BROWSER_USER_DATA_DIR="C:\Users\你的用户名\.nexus-browser\chrome-profile"
```

首次使用需要在 agent 调浏览器工具时弹出的专用 Chrome 里**登录一次**目标网站,之后 cookie 永久保存在该 profile,agent 从此自带登录态;且与你日常浏览器完全隔离,互不干扰。

**方式 B — CDP 连接运行中的 Chrome**

先启动: `chrome --remote-debugging-port=9222`,然后 `BROWSER_MODE=cdp`。

> 若 CDP 连接失败,服务器现在会**明确报错**(不再静默启动全新浏览器),提示你先启动调试端口浏览器。

## 配置(环境变量)

所有可选项通过 `BROWSER_` 前缀环境变量覆盖:

| 变量 | 默认 | 说明 |
|---|---|---|
| `BROWSER_MODE` | `isolated` | `isolated`(隔离新浏览器) / `cdp`(连你的 Chrome) |
| `BROWSER_CDP_ENDPOINT` | `http://localhost:9222` | CDP 地址 |
| `BROWSER_CHANNEL` | `""` | 系统浏览器通道: `chrome`/`msedge` 等(空=Playwright 内置 Chromium) |
| `BROWSER_USER_DATA_DIR` | `""` | 用户数据目录(带登录态)。设置后为共享登录态的 persistent context, 多 task 共享。空=全新 profile |
| `BROWSER_HEADLESS` | `false` | 无头模式(仅 isolated) |
| `BROWSER_DEFAULT_TIMEOUT_MS` | `30000` | Playwright 单次操作超时(导航等) |
| `BROWSER_TOOL_TIMEOUT_MS` | `60000` | 单次工具调用的外层超时护栏(超时返回 ERROR, 不挂死) |
| `BROWSER_STABLE_WINDOW_MS` | `800` | DOM 静默窗口: 无变异持续多久判"稳定" |
| `BROWSER_STABLE_REQUIRED` | `2` | 稳定后连拍确认快照数(防纯动画/非 DOM 变化) |
| `BROWSER_STABLE_TIMEOUT_MS` | `3000` | 稳定性等待总超时, 超时优雅降级 |
| `BROWSER_SNAPSHOT_MAX_NODES` | `100` | 快照最大节点数 |
| `BROWSER_CONTEXT_TTL_SEC` | `600` | 空闲 task 自动回收(秒) |
| `BROWSER_STREAM_CHAR_CAP` | `16000` | 单条流式缓冲最大字符数(溢出丢最旧,保留丢弃标记) |
| `BROWSER_STREAM_PAGE_CAP` | `64000` | 单页面全部流的总字符上限 |
| `BROWSER_ALLOW_JS_EXECUTION` | `false` | 是否允许 `browser_evaluate`(开启后无条件 HITL) |
| `BROWSER_HITL_RULES` | `[]` | JSON 数组: HITL 规则, 如 `[{"action":"click","name_pattern":"支付|确认"}]` |
| `BROWSER_AUDIT_PATH` | `~/.nexus-browser/audit.jsonl` | 审计日志路径 |

## 工具

20 个工具:`browser_navigate`、`browser_snapshot`、`browser_click`、`browser_type`、`browser_read`、`browser_screenshot`、`browser_evaluate`、`browser_wait`、`browser_wait_stable`、`browser_wait_ms`、`browser_scroll`、`browser_scroll_to`、`browser_wait_navigation`、`browser_dismiss_popup`、`browser_list_pages`、`browser_switch_page` 及 4 个生命周期工具 `browser_tasks`、`browser_close_task`、`browser_list_sessions`、`browser_close_session`。

流式内容(AI 回复等):`browser_read(wait_stable=true)` 等 DOM 静默后一次读全;`browser_read(selector=..., follow=true)` 增量跟踪,每次只回新增部分,`full=true` 取缓冲全文。`browser_wait_stable` / `browser_wait_ms` 提供事件驱动等待与纯等待两种原语。

多数工具接受可选 `task_id`(不传则用默认 task)。见 `docs/` 中的用法指南。

## 开发

```bash
uv venv
uv pip install -e ".[dev]"
python -m pytest tests -q
ruff check src tests
python -m smokes.test_e2e           # 真实浏览器冒烟
python -m smokes.test_e2e_interact  # 表单 + 多 task 冒烟
```

## License

MIT
