🚀 dev-browser-mcp
dev-browser-mcp 是一個 MCP(模型上下文協議)服務器,它允許 OpenCode(以及其他 MCP 客戶端)通過發送 Chrome 開發者工具協議 (CDP) 命令,在本地驅動真實的 Chrome/Chromium 標籤頁,而無需使用 --remote-debugging-port 啟動 Chrome。
它解決了這樣的問題:“我希望一個代理能夠對現有的本地瀏覽器會話進行點擊、輸入、導航和截圖操作”,藉助輕量級擴展橋接器和本地中繼實現。
🚀 快速開始
本項目通過 標準輸入輸出 運行一個 MCP 服務器。在底層,它與一個本地 中繼 進行通信,該中繼連接到 Chrome/Chromium 擴展程序。
✨ 主要特性
擴展模式中繼 + 端點
中繼暴露以下端點:
ws://HOST:PORT/extension
瀏覽器擴展程序連接到此端點(一次只能有一個連接)。
ws://HOST:PORT/cdp
一個 類似 CDP 的 WebSocket 端點。MCP 服務器連接到此端點併發送 CDP JSON 消息。
像 dev_browser_goto、dev_browser_click 等工具最終會通過 /cdp 發送 CDP 命令(例如 Page.navigate、Runtime.evaluate、Page.captureScreenshot)。中繼會將這些命令轉發到擴展程序,並將 CDP 事件轉發回連接的客戶端。
📦 安裝指南
前提條件
- Node.js >= 18
- 安裝了 dev-browser 擴展程序 的 Chrome/Chromium(擴展程序必須運行並能夠連接到
ws://HOST:PORT/extension)
- 安裝並配置好 OpenCode 以運行 MCP 服務器
安裝步驟
npm install
npm run build
這將生成 dist/ 目錄和一個可運行的入口點。
📚 詳細文檔
OpenCode 配置
OpenCode 支持 全局 配置和 項目 配置。在兩種情況下,都需要添加一個名為 dev_browser 的 MCP 服務器條目。
全局配置:~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dev_browser": {
"type": "local",
"command": ["node", "/Users/<you>/Code/devtools/dev-browser-mcp/dist/index.js"],
"enabled": true,
"environment": {
"HOST": "127.0.0.1",
"PORT": "9222",
"RELAY_MODE": "auto"
}
}
}
}
項目配置:./opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dev_browser": {
"type": "local",
"command": ["node", "./dist/index.js"],
"enabled": true,
"environment": {
"HOST": "127.0.0.1",
"PORT": "9222",
"RELAY_MODE": "auto"
}
}
}
}
注意:
- 不需要任何機密信息或令牌。
- MCP 服務器通過標準輸入輸出進行通信;OpenCode 將通過
command 數組啟動它。
環境變量
HOST(默認值:127.0.0.1)
中繼 HTTP/WS 服務器的主機。
PORT(默認值:9222)
中繼 HTTP/WS 服務器的端口。
RELAY_MODE(默認值:auto)
控制 MCP 服務器是啟動還是連接到中繼:
auto:首先探測 http://HOST:PORT/;如果中繼已經在運行,則連接。否則啟動一箇中繼。
- 如果啟動中繼時出現
EADDRINUSE 錯誤,它會再次探測 http://HOST:PORT/(更長的超時時間)。如果中繼可達,則連接;否則重新拋出原始錯誤。
start:始終啟動自己的中繼(端口衝突時會失敗)。
connect:從不啟動;要求在 http://HOST:PORT/ 處有一個現有的中繼(如果不可達則拋出錯誤)。
💻 使用示例
典型流程
確保擴展程序已連接 → 打開/選擇一個標籤頁 → 導航 → 交互 → 快照/截圖。
1) 等待擴展程序連接
{
"tool": "dev_browser_ensure_extension_connected",
"input": { "timeoutMs": 30000, "pollIntervalMs": 250 }
}
2) 打開(或重用)一個命名標籤頁
{
"tool": "dev_browser_page_open",
"input": { "name": "my-tab" }
}
3) 導航
{
"tool": "dev_browser_goto",
"input": {
"url": "https://example.com",
"waitUntil": "load",
"timeoutMs": 30000
}
}
4) 快照(AI 友好的 DOM 大綱)
{
"tool": "dev_browser_snapshot",
"input": {}
}
快照包含 snapshotRef 標識符,可用於點擊或輸入操作。
5) 點擊 / 輸入
通過 CSS 選擇器點擊
{
"tool": "dev_browser_click",
"input": { "selector": "button[type='submit']" }
}
通過 snapshotRef 點擊(來自 dev_browser_snapshot 的輸出)
{
"tool": "dev_browser_click",
"input": { "snapshotRef": "e123" }
}
通過 CSS 選擇器輸入
{
"tool": "dev_browser_type",
"input": { "selector": "input[name='q']", "text": "hello", "clearFirst": true }
}
通過 snapshotRef 輸入
{
"tool": "dev_browser_type",
"input": { "snapshotRef": "e456", "text": "hello", "clearFirst": true }
}
6) 截圖
{
"tool": "dev_browser_screenshot",
"input": { "fullPage": false, "saveToFile": true }
}
如果 saveToFile=true(默認值),它將在以下位置寫入一個 PNG 文件:
./.opencode/dev_browser/
並返回 文件路徑(以及圖像內容)。
工具列表
dev_browser_relay_status — 獲取中繼狀態(wsEndpoint、extensionConnected、mode);在 auto 模式下,它將啟動或連接。
dev_browser_ensure_extension_connected — 等待直到 extensionConnected=true(輪詢中繼 /)。
dev_browser_pages_list — 列出中繼中註冊的命名頁面。
dev_browser_page_open — 通過中繼獲取或創建一個命名標籤頁,並選擇它以進行後續操作。
dev_browser_page_delete_mapping — 刪除中繼中的命名頁面映射。
dev_browser_goto — 將選定的標籤頁導航到指定 URL。
dev_browser_click — 通過 CSS 選擇器或 snapshotRef(來自 dev_browser_snapshot)點擊元素。
dev_browser_type — 通過 CSS 選擇器或 snapshotRef(來自 dev_browser_snapshot)在輸入框中輸入內容。
dev_browser_wait_for_selector — 等待選定標籤頁上的選擇器出現。
dev_browser_evaluate — 在選定標籤頁的上下文中執行 JavaScript 代碼。
dev_browser_screenshot — 拍攝 PNG 截圖;保存到 ./.opencode/dev_browser 並返回文件路徑。
dev_browser_snapshot — 返回選定標籤頁的 AI 友好快照(類似 YAML)。
與 dev-browser (SawyerHood/dev-browser) 的關係
本項目旨在將與 SawyerHood/dev-browser 相同的核心思想暴露給 MCP 客戶端(OpenCode):驅動具有持久狀態的真實瀏覽器 並提供 對大語言模型友好的 DOM 快照。
複用/對齊的部分
- 擴展模式 CDP 中繼概念:dev-browser 有一個“擴展模式”,其中本地中繼在擴展程序(
chrome.debugger)和自動化客戶端之間橋接 CDP 消息。
- 命名頁面:兩個系統都提供了
POST /pages 抽象,用於創建/激活命名標籤頁並返回 targetId。
- 快照引用:dev-browser 的快照方法使用注入的腳本返回一個帶有穩定
[ref=eN] 標記的類似 YAML 的大綱。
不同之處
- 協議表面:dev-browser 作為 Claude Code 插件/技能分發;本倉庫是一個專為 OpenCode 設計的獨立 MCP 服務器。
- 控制路徑:本項目不提供“技能客戶端” API,而是暴露離散的 MCP 工具(
dev_browser_goto、dev_browser_click 等)來發送 CDP 命令。
- 多 OpenCode 中繼所有權:此 MCP 支持
RELAY_MODE=auto,因此多個 OpenCode 實例可以連接到單箇中繼進程,而不會因 EADDRINUSE 錯誤而崩潰。
- 確定性標籤頁目標:操作通過
targetId + Target.attachToTarget 會話作用於特定的 Chrome 標籤頁,因此不同的 OpenCode 實例可以可靠地控制不同的命名標籤頁。
🔧 技術細節
故障排除
extensionConnected=false
- 確保 Chrome/Chromium 正在運行,並且 dev-browser 擴展程序已安裝並啟用。
- 擴展程序必須能夠連接到
ws://HOST:PORT/extension。
- 運行
dev_browser_relay_status 以確認中繼是否可達,並查看 extensionConnected 狀態。
EADDRINUSE / 端口衝突
PORT=9222 通常被其他工具使用(包括 Chrome 遠程調試)。
- 通過選擇不同的端口來解決:
- 設置
PORT(並確保中繼和擴展程序的端口一致)
- 或者,如果您有意在其他地方運行中繼並希望連接,請設置
RELAY_MODE=connect。
多個 OpenCode 實例 / 標籤頁命名
- 建議通過
dev_browser_page_open 使用明確、唯一的標籤頁名稱(例如 "myproject-admin"、"myproject-patient")。
- 如果不向工具傳遞
pageName,它們將在“最後選擇”的頁面上操作;為避免衝突,請始終為每個工作區/代理打開/選擇一個命名頁面。
截圖保存位置
- 默認情況下,截圖保存到:
- 如果看不到文件,請確認您的當前工作目錄(OpenCode 項目根目錄),並確保
saveToFile=true。