浏览器 MCP 服务器( S)@browsermcp/mcp(中文(简体) )
MCP 服务器 AI 应用程序运行(npx @browsermcp/mcp@latest) (中文(简体) ). 它通过浏览器MCP扩展来驱动用户的Chrome,其中有一个 browser 工具.
快开始
浏览器 MCP 允许诸如 Claude 代码, Cursor 和 VS 代码等 AI 应用程序使用您的浏览器, 在您所在的地方登录, 在自己的标签中 。 你需要Chrome(或Edge或Brave)和Node.js 20或后期.
-
安装 浏览器 MCP 扩展 把它接入工具栏.
-
将服务器添加到您的 AI 应用程序中, 然后重新启动该应用程序 。 在克洛德代码中:
claude mcp add --scope user browsermcp -- npx @browsermcp/mcp@latest。大多数其他应用程序,如 Cursor 和 Claude Desktop , 都使用此软件( VS 代码的格式不同; 参见下面的文件):{ "mcpServers": { "browsermcp": { "command": "npx", "args": ["@browsermcp/mcp@latest"] } } } -
请代理打开一页 。 第一次,它让你点击 允许 在扩展名的弹出: 检查弹出名的六位数代码是否匹配代理, 点击 允许,请代理再次尝试.
每个AI应用程序的步骤和故障排除: 浏览器mcp.io/docs。其余部分用于开发服务器.
建筑
AI app ──stdio──▶ thin process (dist/index.js, one per AI app) src/thin/
│ starts the daemon if needed; forwards tools/list and tools/call
▼ ws://127.0.0.1:<port>/client?token=… (token from ~/.browsermcp/daemon.json)
daemon (dist/daemon.js, one per user) src/daemon/
├─ command engine: the browser tool src/commands/, src/tools/
│ └─ BrowserBackend (src/contracts.ts): public tab IDs src/relay/backend.ts
└─ a slot per browser (Chrome profile), up to 8 src/relay/browser-slot.ts
├─ Playwright connectOverCDP
│ ▼ ws://127.0.0.1:<port>/cdp?token=…&browser=<slot id>
├─ CDP bridge: fakes Browser.* / Target.* src/relay/bridge.ts
└─ extension connection src/relay/extension-connection.ts
▲ ws://127.0.0.1:<port>/extension
MV3 service worker ── chrome.debugger (one per profile)
- 端口 : 守护进程将第一个9010、9011和9012的自由港绑起(
RELAY_PORTS),跳过端口其他程序控件. 一个端口算作我们的守护进程( 所以一个新的守护进程退出, 薄的流程使用它)daemon.json命名其端口和/browsermcp/status报告,其符号打开/client; 另一个程序回答/status作为browsermcp和任何其他人一样跳过 我们没有使用9009,其中0.1.x服务器杀死任何听觉.--port <n>(在薄的流程上,传递给守护进程)使用一个端口,与daemon-<n>.json财务报告和审定财务报表daemon-<n>.log。 。 。 . ~/.browsermcp/(0700; (中文(简体) );BROWSER_MCP_HOME覆盖它 :daemon.json(口号,pid,版本,代号;0600),identity.json(对接密钥; 6: 00, 贯穿重启; 写入临时文件并硬链接到位置, 因此守护进程同时商定一个密钥),daemon.starting.json(由启动或取而代之的瘦进程所写,其版本)和daemon.log(1 MB, 1 旋转).- 中继 (单位:千美元)
src/relay/server.ts:只有回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回.GET /browsermcp/status(CORS为chrome-extension://, (中文(简体) ),WS /extension(ORGIN: Chrome Web Store ID,自建扩展的ID或BROWSER_MCP_EXTENSION_IDS,逗号分隔,加上每个细进程发出的IDhello中,守护进程在运行时允许使用,而ID则输入~/.browsermcp/dev-extension-ids,当未知扩展连接时读取;src/relay/extension-ids.ts, (中文(简体) ),WS /cdp财务报告和审定财务报表WS /client(token, 无浏览器来源) 和POST /shutdown(声). - 配对 : 扩展名
hello提出挑战;welcome携带守护进程公用钥匙,承诺为此连接提供新的非ce,并签名挑战、承诺和端口 分机拨号(pairingPayload(), (中文(简体) ),src/daemon/identity.ts),因此另一个端口的程序无法将挑战传递给守护进程. 对于它没有配对的密钥,扩展会发出它自己的一个非单数(pairingNonce),守护进程显示其非ce (pairingReveal, (中文(简体) ),src/relay/extension-connection.ts),两者计算相同的六位数代码(pairingCode(); 见“对等”@browsermcp/protocol为什么命令让它安全。 直到用户点击 允许,工具调用答案"Click允许在浏览器MCP扩展的弹出. 代码为482 913"(在扩展的"nice"到来之前暂无代码). - 桥 只宣布要求的标签为目标(
BrowserBackend.page()索赔;release()脱口而出。 它坚持着Runtime.enable直至Page.getFrameTree回答、通过儿童会话、在除canceled_by_user, (中文(简体) ),paused财务报告和审定财务报表not_allowed,并计数域允许每个会话如此原始cdp会话无法禁用 Playwright 。 后端按目标ID查找每个标签的页. - 隐藏标签 (单位:千美元)
src/commands/hidden-tabs.ts从spikes/hidden-tabs/RESULTS.md:代理标签是背景标签,Chrome不渲染. Playwright 连接到noDefaults: true,所以它的覆盖 远离用户的标签,引擎打开Emulation.setFocusEmulationEnabled对于它声称的每个分页。 在鼠标和键盘输入和截图检查前document.visibilityState,在需要时再次打开仿真,否则失败:输入发送到隐藏的标签挂起后着陆,其截图为空白. - 正在重新连接 : 在守护进程启动或浏览器断开( 服务员重新启动) 后, 调用最多可等待 10 s 才能返回( 调用另一个浏览器的分页不等待) , 会话同时保留它们的分页 .
- 若干浏览器 (单位:千美元)
src/relay/backend.ts, (中文(简体) ),browser-slot.ts:守护进程连接到MAX_BROWSERS(8) 浏览器(Chrome profile)同时拒绝使用anotherBrowser。每个都得到了自己的一个插槽:它的扩展连接,它的CDP桥(一个桥的状态被Chrome的标签ID所键入,浏览器级的CDP命令通过它的一个标签,所以一个桥为一个浏览器服务)及其Playwright连接(/cdp?browser=<slot id>) (中文(简体) ). 一个插槽超过它的连接:一个浏览器,它可以重新连接它旧的,从另一个角度讲hello.browserId(通过用户代理和窗口ID,随机识别每个配置文件的扩展保存)或从发送无(22)的扩展中:这种连接占用了浏览器的插槽,就像它最后留下的一样,它的首对state证实这一点,或者移动到它报告的窗口的槽上. 一个旧的连接仍然打开的浏览器,只有在该浏览器不回答一个ping时才能返回它的槽;一个是这样的(一个复制的配置文件,内容相同)browserId)取而取之,而新来者被拒. 守护进程记起多达16个浏览器,忘记了最远的浏览器. Chrome的Tab ID只指一个浏览器内部的东西(分离的Chrome进程从1开始编号),所以后端会发布ID代理商所看到的: 一个Tab 保存了Chrome的ID,除非另一个浏览器的标签有这个号码,当它得到一个超过100000的备用的标签,并保存在它的浏览器的再连接上,除非该标签在浏览器返回时比它离开时显示另一个URL: Chrome nuts在重启时会重新发布,所以旧的ID已经退役(它作为已关闭的标签失败)而不是命名另一个标签. 离去的浏览器的ID会以"已断开"失败,从不给另一个浏览器的分页命名. 每个浏览器由用户在弹出时给出的标签来命名( P)state.label,仅发送给一个对齐的守护进程),否则Chrome, (中文(简体) ),Chrome 2...由守护进程。 对等、停止、活动和发布是每个浏览器:一个等待 允许 不停止特工使用另一个unavailableReason()只有在没有可用时才说话。 在标签页的浏览器中新建打开的标签, 或它选择的标签browser use因为,否则其窗口最后聚焦的可使用浏览器(state.lastFocusedAt换句话说,是最后一个连接的;tab new --browser <label|id>在别处打开一个。 在一个浏览器连接后,代理商看不到任何这样的内容:输出和工具的定义是一样的,以及browser未列出help数个,tab list命名每个标签的浏览器( 结尾有行browser list),关于一个浏览器的错误从它的标签开始. - 超时 : 30s的请求
cdp5分,由于Playwright乘以这些本身,RPC介于瘦进程和守护进程30 s之间tools/call守护进程为 5 分( 稀薄进程再等 30 s; 稀薄进程再等 10 s)welcome。 。 。 . - 版本数 : 较守护进程要求它退出的更细的流程(
POST /shutdown,一旦没有电话在飞行中就应答),开始自己的;一个更老的,使用更新的守护进程,同时daemon.starting.json而不是自己开始。 守护进程在最后一个会话离开10分钟后退出;细进程在他们的下个呼叫中开始一个新的进程. - 文件 : 守护进程要求瘦进程阅读上传并写入截图. 机器上的任何路径都可以工作,但需要运行AI应用程序的用户的许可:
~是主目录,并且相对路径解析了AI应用程序的第一个MCP根(当客户端没有时它的工作目录). 没有限制文件输入的代理文件可以上传, 或是哪些文件screenshot --path可以覆盖,所以将允许代理浏览的页面视为可以读取用户能够读取的任何文件,并覆盖用户能够所写的任何文件.
发展
pnpm build正在建设dist/index.js(单位:千美元)bin和dist/daemon.js· ;pnpm watch在变化中重建.- 手动运行 :
node dist/index.js --port 9333在MCP客户端(或下面的检查员)中,扩展端口设为9333.node dist/daemon.js --port 9333 --stderr在前景中运行守护进程 。 使用BROWSER_MCP_HOME=$(mktemp -d)远离真正的守护者. - Dev 扩展名的构建有它自己的 ID 每一次检出: 将 ID 设置在一条
~/.browsermcp/dev-extension-ids(单位:千美元)#启动注释; 当未知扩展连接时, 守护进程会读取文件, 因此不需要重新启动), 或设置BROWSER_MCP_EXTENSION_IDS=<id>在AI app的 MCP 配置中重新连接到 MCP 服务器(薄进程发送到运行中的守护进程). 当守护进程拒绝扩展时,工具会调用它的ID和这个变量的名称. 对于一个守护进程,您从手开始设定变量.
检查员
- 客户端 UI 在端口 9001 上运行( 默认的 5173 与扩展的 Vite 服务器相冲突)
- MCP 代理服务器运行于端口 9002(3000的默认值与
marketing应用)
- 运行
pnpm build或者说pnpm watch用于建设dist/ - 运行
pnpm inspector开始检查 - 导航到
http://localhost:9001?proxyPort=9002打开检查器UI - 点击
Connect要运行的按钮dist/index.js启动 MCP 服务器
测试
pnpm test (声入地. 测试从不使用端口 9009-9012 或 ~/.browsermcp:它们使用随机端口和一个临时 BROWSER_MCP_HOME,只停止它们开始的守护进程.
src/relay/server.test.ts, (中文(简体) ),bridge.test.ts:端口和检查,并有内存扩展和CDP客户端的桥.src/relay/backend.test.ts, (中文(简体) ),integration.test.ts:真正的"Playwright"通过桥面,真正的"无头"Chrimium为扩展站入(pairing,数个浏览器一次,iframes,放出并重取,一个生的CDP会话,停止并取消,断开).src/daemon/daemon.test.ts, (中文(简体) ),src/thin/*.test.ts:进程内守护进程和作为真实进程(按要求启动,同时启动两个稀疏进程,版本替换,闲置退出,一个被杀死的守护进程,其他程序持有的端口,相对文件路径和MCP根).- 结束到结束, 以真正的扩展 :
pnpm --filter @browsermcp/extension smoke(单位:千美元)@browsermcp/extension是因为scripts/smoke-browser-control.ts),用于构建此软件包并运行dist/index.js超乎寻常.
帮助者 src/testing/ 其他测试:
FakeChromium.launch()财务报告和审定财务报表FakeExtension.connect({ port, chromium, pairing? })(单位:千美元)fake-extension.ts: 无头铬被驱动过一个生的 CDP 套接字, 说扩展协议(attach, (中文(简体) ),cdp儿童会议,createTab, (中文(简体) ),groupTab... ;事件,状态,tabOpened),加上用户的动作:openTab(), (中文(简体) ),allow(), (中文(简体) ),pause(), (中文(简体) ),cancel(), (中文(简体) ),assign(), (中文(简体) ),disconnect()。 。 。 .verifyWelcome()对照它拨打的端口检查守护进程与 WebCrypto 的签名(port) (中文(简体) ). 与pairing: "pending"它与守护进程和设定交换非切code,弹出会显示的代码(pairingNonce: false不留一个;exchangePairingNonces()等会再说.userAgent, (中文(简体) ),windowId财务报告和审定财务报表browserId将假浏览器区分开( 启动 a)FakeChromium每个浏览器用于相撞的分页ID,如单独的Chrome进程,label财务报告和审定财务报表setLabel()编号 :focus()发送弹出点的标签和焦点answering = false像一个被卡住的服务员一样,它忽略了电话和请求.startTestBackend()(单位:千美元)test-backend.ts: 中继器和RelayBackend随机端口, aBrowserBackend发动机测试.startFixtureServer(pages)(单位:千美元)fixture-server.ts: 测试页面127.0.0.1而且,对于跨地点的架子,localhost。 。 。 .createStubEngine和脚踏车守护进程stub-engine.ts, (中文(简体) ),stub-daemon.ts,由global-setup.ts并且通过测试inject("stubDaemon")) (中文(简体) ).
释放
浏览器 MCP 维护者释放 @browsermcp/mcp {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}请说 要运行一个你自己的建筑取而代之,参见"自己建造"在寄存器的README中.