Skip to main content
Glama
README.md
# Agent Chrome Bridge

[English](README.md) | [简体中文](README.zh-CN.md)

Let local AI agents work with the Chrome browser you already use, including your existing signed-in sessions. A Manifest V3 extension connects Chrome to a local, dependency-free MCP server through Native Messaging.

**Status:** v0.1.0 / MVP. Tested on macOS with real Chrome. Linux registration is implemented but has not been verified; Windows is not supported. This is an independent project, not an official product of Google, OpenAI, or any agent provider.

## What it does

- Lists accessible tabs, reads page text and actionable elements, and enumerates frames.
- Clicks, fills ordinary inputs, selects options, scrolls, opens pages, and navigates tabs.
- Captures the visible viewport and returns images through MCP.
- Uses the browser's existing login state without exporting cookies.
- Reconnects automatically and coordinates multiple clients with per-tab leases.
- Provides persistent pause and write-action controls in the extension popup.

Site access is requested when the extension is installed. There is no additional per-site allowlist or repeated debugger-attachment prompt. Chrome's own site-access restrictions and the agent client's approval policies still apply.

## Architecture

```text
Local agent / MCP client
        │ MCP stdio (JSON-RPC)
        ▼
src/mcp.mjs
        │ Unix socket (0700 directory / 0600 socket)
        ▼
src/native-host.mjs
        │ Chrome Native Messaging
        ▼
Manifest V3 extension
        │ tabs / scripting / ISOLATED DOM operations
        ▼
Your existing HTTP(S) pages
```

No `debugger` permission, remote debugging port, or public network listener is used by the bridge. The optional test fixture server listens only on loopback.

## Quick start (macOS)

Requirements: **Node.js 20+**, **Google Chrome 120+**, and Git. The project has **zero npm dependencies**; `npm install` is not required.

### 1. Clone and register the native host

```sh
git clone https://github.com/FUTUREWORKER/agent-chrome-bridge.git
cd agent-chrome-bridge
npm run prepare:extension
npm run install:host -- --register
```

Keep this checkout in a stable location: Chrome runs the native host from it. `prepare:extension` prints the absolute extension directory. The installer generates `.runtime/mcp-config.json`, a native-host launcher, and a manifest using your actual Node executable and checkout paths. `--register` also installs the manifest into Chrome's per-user Native Messaging directory. Without `--register`, the command only generates local files.

### 2. Load the Chrome extension

1. Open `chrome://extensions` and enable **Developer mode**.
2. Choose **Load unpacked** and select this checkout's `extension` directory.
3. Open the extension popup. The current popup is in Chinese; **已连接 · 可供 Agent 使用** means “Connected · Ready for agents”.
4. For access across websites, set Chrome's extension **Site access** to **On all sites**. You can restrict this later in Chrome.

The bundled public key keeps the unpacked extension ID stable: `ghpncnhckadomkikpdngadhmjcckcdbi`. It is a public identifier, not a secret or signing private key. If the ID differs, verify the loaded directory and rerun the installer.

The bridge starts with connection and write actions enabled. **暂停连接** pauses the connection; **允许点击、输入和导航** controls clicks, input, and navigation. These settings persist. Disabling write actions still allows reads, scrolling, and screenshots; screenshots may focus a tab when explicitly requested.

### 3. Connect your agent

Merge the `agent-chrome` entry from **`.runtime/mcp-config.json`** into your client's MCP settings, preserving its other servers. The client must support launching a **local stdio MCP process**. Restart or reload its MCP configuration as needed.

Illustrative configuration only—use the generated file's real absolute paths:

```json
{
  "mcpServers": {
    "agent-chrome": {
      "command": "/absolute/path/to/node",
      "args": ["/absolute/path/to/agent-chrome-bridge/src/mcp.mjs"]
    }
  }
}
```

A cloud-only agent cannot reach your Mac by using its own `localhost`. Remote HTTP MCP access and per-agent authentication are not implemented. Compatibility with any specific third-party agent client, including Grok Bot, has not been verified.

### 4. Check the connection

```sh
npm run doctor
node src/cli.mjs status
node src/cli.mjs tabs
```

`doctor` checks host registration, the socket, directory permissions, and live bridge status. It exits unsuccessfully if the bridge cannot be reached.

## Tools and usage

| Tool | Purpose |
| --- | --- |
| `bridge_status` | Connection state, version, and site permissions |
| `browser_tabs` | Accessible HTTP(S) tabs |
| `browser_snapshot` | Page text and element references |
| `browser_frames` | Accessible frame IDs |
| `browser_click` | Click an element reference |
| `browser_fill` | Replace ordinary input or editable text |
| `browser_select` | Select a standard dropdown option by value |
| `browser_scroll` | Scroll a page or frame |
| `browser_open` | Open a new tab |
| `browser_navigate` | Navigate an existing tab |
| `browser_screenshot` | Capture the visible viewport |
| `browser_release` | Release this connection's tab lease |

Recommended sequence: `browser_tabs` → `browser_snapshot` → act using returned `ref` values → read again to verify → `browser_release`.

References are bound to a page/frame and its latest snapshot. Do not guess references or reuse them after a new snapshot, navigation, or element replacement. For frames, call `browser_frames`, then pass the returned `frameId` to snapshot and element tools.

CLI examples (replace `123` and `REF_FROM_SNAPSHOT` with actual returned values):

```sh
node src/cli.mjs snapshot '{"tabId":123}'
node src/cli.mjs fill '{"tabId":123,"ref":"REF_FROM_SNAPSHOT","text":"Hello"}'
node src/cli.mjs browser_select '{"tabId":123,"ref":"REF_FROM_SNAPSHOT","value":"b"}'
```

Each CLI invocation disconnects on completion, so tab leases do not persist across CLI commands. Prefer a persistent MCP connection for multi-agent work. A tab can be leased by one connection at a time; release it explicitly or disconnect. Browser actions are serialized across clients, including actions on different tabs.

## Security and privacy

- Installing the extension grants broad ongoing site access. Only connect agents and local software you trust.
- **Any process running as the same OS user can use the local bridge.** Socket permissions isolate other OS users; they do not authenticate individual agents.
- Page text, tab titles/URLs, and screenshots are returned to the calling client. Whether that client forwards them to a cloud model depends on its configuration.
- Password input values are omitted. Automatic filling rejects password/file inputs and fields marked with autocomplete values for one-time codes, card numbers, or card security codes. This is **not general-purpose secret detection**; text and screenshots can contain sensitive information.
- Web content is untrusted input. The calling agent must handle prompt injection and obtain any necessary approval for submissions, payments, or destructive actions. The bridge does not enforce per-action human approval.
- Automatic reconnection does **not** replay business commands. After a timeout or disconnect, inspect the page before retrying: the action may already have occurred.

See [SECURITY.md](SECURITY.md) for the security model and reporting guidance.

## Limitations

- Ordinary HTTP(S) pages only. Chrome internal pages, extension pages, file URLs, and incognito windows are unsupported. Protected pages such as the Chrome Web Store may reject injection.
- Uses DOM events. Sites requiring trusted native input may not work. No native keyboard/mouse control, coordinate-based Canvas clicks, drag-and-drop, file uploads, browser-dialog handling, or full Playwright API.
- Supports open shadow roots; closed roots are inaccessible. Frames remain subject to Chrome permissions, sandboxing, and URL restrictions.
- A snapshot returns at most 300 actionable elements and 50,000 text characters (18,000 by default). It is not a full-site crawler.
- Screenshots capture only the viewport. The target must be active; `activate: true` switches tabs and focuses the window. Chrome applies capture rate limits.
- One Chrome profile per OS user can own the bridge at a time. Pause the other profile before switching.

## Development and verification

```sh
npm test
# Optional: requires the installed, connected extension with write actions enabled.
node scripts/e2e.mjs
# Optional: open the printed local URL and click “运行 DOM 验证”.
node scripts/fixture-server.mjs
```

The Node tests use isolated temporary state and simulated extension responses; they do not require a running browser. The live end-to-end test opens a new local fixture tab, manipulates only that page, activates it for a screenshot, and writes local artifacts under `docs/`. These generated artifacts are gitignored. The fixture tab can be closed after testing.

The initial macOS validation recorded 12 Node tests, 8 live DOM checks, and 9 live MCP checks passing, plus automatic reconnection. See [verification notes](docs/verification.md) for scope and remaining gaps. These results are not a guarantee of compatibility with every website or agent.

Contributions are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md).

## Troubleshooting

| Symptom | Action |
| --- | --- |
| `Specified native messaging host not found` | Run `npm run install:host -- --register`; check the extension ID and checkout location. |
| `Another Chrome profile already owns the bridge` | Pause this extension in the other Chrome profile. |
| Node or the checkout moved | Rerun the installer, then pause and re-enable the connection. |
| Site access denied | Check Chrome's extension Site access settings; protected pages may remain inaccessible. |
| Agent timeout | Inspect the actual page before repeating any action. |
| GUI client cannot find Node | Use the absolute executable path in the generated MCP configuration. |

## Uninstall

Pause the connection in the popup, remove the extension from Chrome, remove `agent-chrome` from your MCP client configuration, then run from this checkout:

```sh
node scripts/uninstall.mjs --confirm
```

The script removes only the Native Messaging registration that points to this checkout. It does not delete the source, generated files, or other extensions. You can remove this checkout separately when it is no longer needed.

## License

[MIT License](LICENSE). Copyright (c) 2026 FUTUREWORKER and contributors.

## References

- [Chrome Native Messaging](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)
- [Chrome scripting API](https://developer.chrome.com/docs/extensions/reference/api/scripting)
- [Chrome screenshot API](https://developer.chrome.com/docs/extensions/reference/api/tabs#method-captureVisibleTab)
- [MCP stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)