tmwd-bridge-mcp
by Shitsuki4
README.md
# tmwd-browser-mcp
**让 AI agent 直接操作你真实的浏览器。** 一个 MCP server + 一个极小的浏览器扩展,把
**你自己在用的 Microsoft Edge / Google Chrome** 交给 agent —— 同一个 profile、同一批
cookie、同一份登录态。
不用 Selenium,不用 Playwright,不开 `--remote-debugging-port`,也不启动任何额外浏览器。
**English:** [README.en.md](README.en.md)
```
┌──────────────┐ MCP (stdio) ┌────────────────────┐ WebSocket ┌──────────────────┐
│ AI agent / │ ◄─────────────► │ tmwd-bridge-mcp │ ◄───────────── │ 你的 Edge / │
│ MCP client │ browser_* │ (本项目的 server) │ 127.0.0.1: │ Chrome + │
└──────────────┘ 工具 │ + WebSocket 主端 │ 18765 │ 这个扩展 │
└────────────────────┘ └──────────────────┘
chrome.debugger
(标签页级 CDP)
```
扩展是**主动外连**到 server 的,所以本机没有任何调试端口在监听,浏览器也不会跑在一个
"自动化专用 profile" 里。
## 为什么不用调试端口?
因为 **Chromium 已经把它在默认 profile 上禁掉了**。当浏览器用的是正常用户目录时,
`--remote-debugging-port` 会被直接忽略 —— 这是官方为防 cookie 窃取刻意做的限制。想用它,
就只能另开一个一次性 profile,代价是**丢掉所有登录态**。
本项目走另一条路:一个带 `debugger` 权限的扩展,在**你本来就在用的 profile 里**拿到
标签页级的 CDP。已在 Edge 154 上端到端验证。
## 安装
### 1. 装扩展
- **Edge:** `edge://extensions`
- **Chrome:** `chrome://extensions`
打开**开发者模式** → **加载解压缩的扩展** → 选 `assets/tmwd_cdp_bridge/`。
装好后每个页面右下角会出现一个小徽章:绿色 = 已连上 server,橙色 = 重连中,红色 = 断开。
### 2. 注册 MCP server
```json
{
"mcpServers": {
"tmwd": {
"type": "stdio",
"command": "node",
"args": ["/改成绝对路径/tmwd-browser-mcp/mcp/tmwd-bridge-mcp.mjs"]
}
}
}
```
改完**要重启 MCP 客户端** —— server 是启动时发现的。server 会占用 `127.0.0.1:18765`,
并且对普通 `GET /` 返回 200(扩展就是靠这个探活的)。
扩展自己会重试(`chrome.alarms` 每 ~5 秒探一次,每 ~24 秒发一次保活让 MV3 service worker
不被挂起),所以**谁先启动都无所谓**。
## 工具
| 工具 | 作用 |
|---|---|
| `browser_status` | 连接状态、已知标签页、当前解析到的活动标签页 |
| `browser_tabs` | 列出可脚本化的标签页(仅 http/https) |
| `browser_cookies` | 读取 cookie(含 partitioned),按标签页或 URL |
| `browser_eval` | 在页面里跑 JS(world=MAIN;CSP 拦 eval 时自动回落 CDP) |
| `browser_cdp` | 通过 `chrome.debugger` 发原始 CDP 命令(protocol 1.3) |
| `browser_batch` | 一次往返跑多条命令,懒 attach,支持 `$N.path` 引用 |
| `browser_screenshot` | `Page.captureScreenshot` 存成 PNG(后台标签页也能截) |
| `browser_click` | 完整鼠标生命周期 + 首次 attach 的坐标预热 |
| `browser_type` | `Input.insertText` |
| `browser_upload` | DataTransfer 上传文件(不依赖 CDP) |
| `browser_content_settings` | 例如 `automaticDownloads` → `allow` |
每个工具的 `tabId` 都是**可选的** —— 不传就落到当前活动标签页。
## 这个项目真正编码进去的坑
价值大半不在管道,而在失败模式。有几条我直接写进了工具实现里:
- **`browser_click` 一定会先发 `mouseMoved` 再按下去** —— 漏掉它,所有依赖 hover 的组件
(MUI Tooltip、Ant Design Dropdown)会静默失效。
- **首次 attach 的信息栏偏移:** 第一次 `chrome.debugger.attach` 会弹出一条约 20px 高的
"正在受自动化控制" 提示栏,把页面内容往下推。**attach 之前**量的坐标会整体偏掉这么多。
`browser_click` 首次使用时会先用 `mouseMoved(0,0)` 预热。这条正是上游一次下拉框点歪的
真实根因。
- **`browser_eval` 里用了 `await` 却不写 `return` 会拿到 `null`** —— 代码被包在 async IIFE 里。
- **导航和后续操作必须拆成两次调用** —— 写在同一段 JS 里会报
`Inspected target navigated or closed`。
- **只有标签页级的 CDP 域可用。** `Browser.*`(`getVersion`、`setDownloadBehavior`)和
`Target.getTargets` / `Target.attachToTarget` 都不可用 —— debugger 会话是按标签页的。
命令报 "wasn't found" 时,**先怀疑域,别怀疑浏览器**。
- **`browser_batch`: 前面一条失败,后面所有 `$N` 引用会静默变成 `undefined`。**
必须逐条看 `results` 里的 `ok`,不能只看外层 `ok`。
- **上传走 DataTransfer** —— 因为这个桥里 `DOM.setFileInputFiles` 的 nodeId 跨调用会失效。
- **跨域 iframe:** `Page.getFrameTree` → `Page.createIsolatedWorld` →
用返回的 `executionContextId` 调 `Runtime.evaluate`。
- **autofill 的值只在前台标签页释放** —— 先 `Page.bringToFront`。
完整清单(batch 链式引用、穿透 Shadow DOM、验证码截图、多文件下载对话框绕法)在
[`SKILL.md`](SKILL.md)。
## 当作 Claude Code skill 用
`SKILL.md` 就是按 Claude Code skill 格式写的:把仓库放到 `~/.claude/skills/tmwd-browser/`,
agent 就会按触发词自动认出来(`用我的 Chrome`、`保留登录态`、`browser automation` …)。
## 配置
| 环境变量 | 默认 | 含义 |
|---|---|---|
| `TMWD_PORT` | `18765` | WebSocket + HTTP 端口。**必须**和扩展里的 `WS_URL` 一致。 |
| `TMWD_HOST` | `127.0.0.1` | 绑定地址。 |
| `TMWD_TIMEOUT_MS` | `60000` | 单条命令超时。 |
改端口要同时改 `assets/tmwd_cdp_bridge/background.js` 里**两处**硬编码:`WS_URL` 和
`isServerAlive()` 里的 fetch。
## 环境要求
- Node.js ≥ 18(server **零 npm 依赖** —— WebSocket 服务端和 MCP stdio 传输都是手写的,
裸 `node` 就能跑)
- Microsoft Edge 或 Google Chrome,且能开开发者模式
- 扩展需要 `debugger` 权限,这会导致每个标签页**首次 attach** 时出现一条"正在受自动化控制"
的信息栏。这是预期行为,也正是坐标必须在 attach **之后**测量的原因。
## 致谢
浏览器扩展,以及蒸馏进 `SKILL.md` 的操作知识,来自
[`lsdefine/GenericAgent`](https://github.com/lsdefine/GenericAgent)(MIT):
`assets/tmwd_cdp_bridge/` 和 `memory/tmwebdriver_sop.md`。扩展是**逐字再分发**并保留其
原始许可;MCP server、工具层和文档属于本项目。
上游有一处矛盾值得知道:SOP 里写主端监听 **18766**,而扩展代码里是 **18765**。
本 server **以代码为准**。
## 许可证
MIT —— 见 [LICENSE](LICENSE)。其中再分发的扩展为 MIT © 2025 lsdefine
([其原始许可](assets/tmwd_cdp_bridge/LICENSE))。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues