Chrome Browser Control
Enables controlling a local Chrome browser via MCP tools, using a Chrome extension and WebSocket broker for browser automation.
README
Chrome Browser Control
Local Chrome-profile control for stdio MCP hosts.
This project exposes browser-control MCP tools through a Manifest V3 Chrome extension connected to a loopback WebSocket broker. Configure your MCP host to launch the stdio adapter with the same pairing token you enter in the extension.
Repository: https://github.com/vkongv/chrome-browser-control
Prerequisites
- Node.js 18+
- Google Chrome
Install and Setup
-
Clone the repository:
git clone https://github.com/vkongv/chrome-browser-control.git cd chrome-browser-control -
Install dependencies and run setup:
npm install npm run setupnpm run setupwrites.env.localwithCHROME_BROWSER_CONTROL_TOKENandCHROME_BROWSER_CONTROL_PORT, prints the extension folder path, and shows copy-paste MCP config snippets. That file is gitignored — do not commit it. -
Continue with Load The Extension, then add MCP config and verify the connection.
To generate a pairing token manually instead of npm run setup:
node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
Environment Variables
CHROME_BROWSER_CONTROL_TOKEN— Required. High-entropy pairing token shared by the broker, MCP adapter, and extension popup.CHROME_BROWSER_CONTROL_PORT— WebSocket broker port (default8765).CHROME_BROWSER_CONTROL_HOST— Loopback host for the broker (default127.0.0.1).CHROME_BROWSER_CONTROL_EXTENSION_ID— Optional. Pins the broker to one installed extension ID.CHROME_BROWSER_CONTROL_DISABLE_LOCAL_ENV— Optional. Set to1to skip loading.env.local.
For manual operation outside an MCP host:
CHROME_BROWSER_CONTROL_TOKEN='<generated-token>' npm run broker
CHROME_BROWSER_CONTROL_TOKEN='<generated-token>' npm run mcp
npm start is an alias for npm run mcp.
Load The Extension
- Open Chrome with the profile you want the MCP tools to control.
- Go to
chrome://extensions. - Enable Developer mode.
- Click "Load unpacked".
- Select
/path/to/chrome-browser-control/extension. - Open the Chrome Browser Control extension popup.
- Keep the bridge URL at
ws://127.0.0.1:8765unless you changed the local port. - Paste the generated pairing token.
- Add allowed origins such as
https://example.com,http://localhost:3000, or*for all normalhttp://andhttps://pages. - Click "Save and reconnect".
The extension may ask for host permission for the allowed origins. Denying that request prevents page actions for those origins.
Using * is convenient for local development, but it exposes every normal web page in the current Chrome profile to MCP tools. Prefer explicit origins when you only need a few sites.
MCP Host Configuration
Paste a snippet from npm run setup into Cursor, Claude Desktop, Codex, or another stdio MCP host. To print host-specific config again later:
npm run --silent mcp-config -- --host cursor
npm run --silent mcp-config -- --host claude
npm run --silent mcp-config -- --host codex
npm run --silent mcp-config -- --host yaml
Use absolute paths because many MCP hosts do not apply a per-server working directory. The exact key names vary by host, but Claude Desktop, Codex, Cursor, and similar MCP hosts generally need a command, args, and env block for a stdio MCP server. This project should work with any stdio MCP host; verify host-specific config syntax in that host's documentation.
YAML-style example:
mcp_servers:
chrome_browser_control:
command: "/path/to/chrome-browser-control/node_modules/.bin/tsx"
args: ["/path/to/chrome-browser-control/server/index.ts"]
env:
CHROME_BROWSER_CONTROL_TOKEN: "<generated-token>"
CHROME_BROWSER_CONTROL_PORT: "8765"
timeout: 60
connect_timeout: 30
JSON-style example:
{
"mcpServers": {
"chrome_browser_control": {
"command": "/path/to/chrome-browser-control/node_modules/.bin/tsx",
"args": ["/path/to/chrome-browser-control/server/index.ts"],
"env": {
"CHROME_BROWSER_CONTROL_TOKEN": "<generated-token>",
"CHROME_BROWSER_CONTROL_PORT": "8765"
}
}
}
}
If your MCP host uses a config file, keep it private and outside the repository.
Verify
Run the setup checker:
npm run doctor
Then confirm from your MCP host by calling the browser_status tool. When ready, extension.status and ping.status should reflect a live bridge connection, and extension.allowedOrigins should show your configured scope.
Tools
browser_status: checks whether the MCP adapter can reach the broker and whether the Chrome extension answersping. When ready,extension.statusandping.statusreflect the live bridge connection (not a stale disconnected default),extension.allowedOriginsshows the configured scope (including* (all http/https web origins)when wildcard mode is enabled), andprotocolVersion/featuresconfirm the loaded unpacked extension code.list_tabs: lists tabs whose URL origin is allowed in the extension popup. When every open tab is filtered out, returns{ tabs: [], detail, hiddenTabCount, allowedOrigins? }instead of a bare[]. Wildcard mode is labeled clearly inallowedOrigins.snapshot: returns a simplified DOM snapshot for an allowed tab. By default this is a compact automation snapshot that includes concise actionable elements, a text preview (500 chars), omitted counts, and region summaries. Passmode: "full"for verbose element metadata and atextfield (4000 chars by default). PasstextLimit(up to100000) when you need more page body text — checktextBytesOmittedto see if content was truncated.navigate: navigates the active tab or a specifiedtabIdto an allowed URL, then waits for the tab to finish loading when possible. If loading times out, the result includespending: trueand awarning.click: clicks an element by snapshot ref on an allowed tab.type: types into an element by snapshot ref on an allowed tab. Password-like fields are blocked unlessforce=true.scroll: scrolls an allowed tab bydeltaXanddeltaY. Scrolling does not paginate snapshot text — snapshots use fulldocument.bodyinnerText. RaisetextLimitonsnapshotinstead of scroll-stitching unless the page lazy-loads content.
Snapshot Modes And Refs
Default compact snapshots are designed to reduce model-context usage while preserving browser automation. A compact snapshot looks like:
{
"title": "Example Domain",
"url": "https://example.com/",
"mode": "compact",
"elements": [{ "ref": "h1", "role": "link", "label": "Learn more" }],
"omittedElements": 0,
"textPreview": "Example Domain ...",
"textBytesOmitted": 0,
"regions": []
}
Use full mode only when you need the legacy verbose element metadata:
{ "mode": "full", "tabId": 123 }
To read long page content (for example API docs), raise textLimit instead of using broker scripts or CDP workarounds:
{ "mode": "full", "textLimit": 100000, "tabId": 123 }
Compact mode honors textLimit too; body text is returned in textPreview (there is no text field in compact mode). When textBytesOmitted is greater than zero, increase textLimit or scroll the page and snapshot again only if content is lazy-loaded below the fold.
Refs are per-document in-memory IDs (h...) assigned from element identity, not output order. They remain stable across DOM insertion/reorder in the same document, and click / type resolve through the content script's ref store. Navigating to a different page loads a new document, so old refs are expected to fail cleanly; take a fresh snapshot after navigation or major page changes. The ref store prunes disconnected, expired, and over-cap entries, and removes stale data-cbc-ref attributes so pruned refs cannot be reused accidentally.
Development Checks
npm test
npm run build
npm run doctor
npm run benchmark:compact-snapshots
npm audit
npm run benchmark:snapshots is an alias for the same compact-vs-full benchmark. The benchmark prints compact bytes, full bytes, and reduction percentage; compact mode should stay at least 50% smaller on the dense fixture.
After editing files under extension/, reload the unpacked extension on chrome://extensions before running browser e2e checks. A stale loaded background service worker can keep serving older behavior; browser_status should show the current protocolVersion and features marker when Chrome has loaded the latest extension code.
Limitations
- This is a prototype with a shared local token, not multi-user authentication.
- Browser tool calls are serialized globally at the broker.
- Content scripts use DOM snapshots, not the full Chrome accessibility tree.
- Refs are document-scoped in-memory handles. Run
snapshotagain after navigation, reloads, major DOM changes, or stale-ref errors. - Browser history, bookmark, download, and cookie tools are intentionally not exposed.
server/cdp.tsremains only as an unused development reference and is not wired into the MCP adapter.
Security
- No default token is accepted. Set
CHROME_BROWSER_CONTROL_TOKENto a high-entropy URL-safe value for both the broker and MCP adapter, then paste the same value into the extension popup. - The broker binds only to loopback hosts:
127.0.0.1,localhost, or::1. - The extension only connects to
ws://127.0.0.1,ws://localhost, orws://[::1]with an optional port. - Page access is limited by allowed origins configured in the popup. Use explicit entries such as
https://example.com, or enter*to allow all normalhttp://andhttps://web pages. Tabs and page actions outside the configured scope are blocked. - Optional
CHROME_BROWSER_CONTROL_EXTENSION_IDpins the broker to one installed extension ID. - CDP fallback is not supported by the MCP adapter because it bypasses extension pairing.
Never bind the broker to a non-loopback interface or commit tokens, local config files, logs, or personal setup notes.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。