BLOG
Chrome MCP: Wiring AI Agents to a Real Browser
Chrome MCP connects AI agents to a real browser. Learn how the protocol works, where it breaks, and how to run it on hosted Chromium.

Chrome MCP is the pattern of exposing a real Chrome or Chromium instance to an AI agent through the Model Context Protocol. The agent calls tools like "navigate," "click," or "read the page," and an MCP server translates those calls into Chrome DevTools Protocol (CDP) commands against a live browser. It is the shortest path from a language model to a page it can actually see and operate.
The catch is that most Chrome MCP setups assume the browser lives on the same machine as the agent. That works for a demo and falls apart in production, where sessions need isolation, persistence, and a way to watch what the agent is doing. This guide covers how Chrome MCP works, where the local model breaks, and how to run the same tool interface against hosted Chromium.
What Chrome MCP actually is
MCP is a protocol for exposing tools and resources to a model in a structured way. A "Chrome MCP" server is an MCP server whose tools map to browser actions. Under the hood, almost every implementation drives the browser over CDP, the same protocol Playwright and Puppeteer use. The MCP layer is a translation and safety layer; CDP does the work.
That distinction matters. When you evaluate a Chrome MCP server, you are really evaluating two things:
- The tool surface — what actions the agent can take (navigate, click, type, screenshot, extract text, run JS) and how results are returned.
- The browser transport — whether it launches a local Chrome, attaches to an existing instance, or connects to a remote endpoint.
Most public discussion focuses on the first. Production problems come from the second.
The two common topologies
| Topology | How it works | Best for | Main limitation |
|---|---|---|---|
| Local launch | MCP server spawns Chrome on the same host | Prototyping, single-user dev | No isolation, no scale, dies with the process |
| Attach to existing | MCP server connects to a running Chrome via CDP | Debugging a live session | Fragile; one browser shared by everything |
| Remote endpoint | MCP server connects to hosted Chromium over CDP/WebSocket | Production, multi-tenant agents | Requires a runtime that exposes CDP |
The third row is where Chrome MCP becomes infrastructure rather than a dev convenience.
Why the local model breaks in production
A local Chrome MCP server is fine when one developer runs one agent against one browser. It stops being fine the moment any of the following is true:
- You run more than one agent at a time. Two agents sharing one Chrome instance will fight over tabs, cookies, and focus. You need session isolation.
- The agent needs to stay logged in. Local Chrome profiles are tied to a machine. If the worker restarts or moves, the session is gone. You need persistent profiles that survive across workers.
- You need to see what happened. When an agent fails at step 14, a screenshot at the end is not enough. You need a live viewer and a replayable session.
- You need to run headless at scale. Launching Chrome per task on your own boxes means managing memory, zombie processes, and version drift. That is a runtime problem, not an MCP problem.
- You need egress control. Configurable proxy settings and per-session browser configuration are runtime features. A local MCP server does not give you them.
None of these are solved by a better tool schema. They are solved by moving the browser off the agent's host and connecting the MCP server to a remote endpoint instead.
How Chrome MCP maps to CDP
Every Chrome MCP tool is a thin wrapper over CDP domains. Understanding the mapping helps you debug when an agent does something unexpected.
| MCP tool (typical) | CDP domain | Notes |
|---|---|---|
| navigate | Page.navigate | Returns a frame ID; wait for Page.loadEventFired |
| click / type | Input.dispatchMouseEvent, Input.dispatchKeyEvent | Coordinates or selectors, depending on server |
| read page | Runtime.evaluate or DOM.getDocument | Text extraction is server-defined |
| screenshot | Page.captureScreenshot | Format and quality are server options |
| wait for selector | Runtime.evaluate polling | Often the flakiest tool |
| run JS | Runtime.evaluate | Powerful and dangerous; scope it |
If you want the authoritative reference, the Chrome DevTools Protocol documentation lists every domain and event. The MCP server is not magic; it is a curated subset.
The connection layer
A remote-capable Chrome MCP server connects to a browser endpoint rather than launching one. With Playwright, that is chromium.connectOverCDP(). The endpoint is a WebSocket URL that a hosted runtime exposes per session. The MCP server does not care whether the browser is on localhost or in a data center; it just needs a valid CDP endpoint.
That is the key insight: Chrome MCP and hosted Chromium are complementary, not competing. The MCP server stays on your side; the browser moves to a runtime that handles isolation, profiles, and scale.
Running Chrome MCP against hosted Chromium
The setup has three parts: a hosted session that exposes a CDP endpoint, an MCP server configured to attach to it, and an agent that calls the MCP tools. Here is the connection step in TypeScript, using Playwright's CDP attach, which is what most remote-capable MCP servers do internally.
import { chromium, type Browser, type Page } from "playwright";
// The hosted runtime returns a CDP WebSocket endpoint per session.
// Treat this URL as a secret; it grants full control of the browser.
const cdpEndpoint = process.env.REMOTE_BROWSER_CDP_URL!;
async function attach(): Promise<{ browser: Browser; page: Page }> {
const browser = await chromium.connectOverCDP(cdpEndpoint, {
timeout: 30_000,
});
// Reuse the existing context so persistent profile state is preserved.
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = context.pages()[0] ?? (await context.newPage());
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
return { browser, page };
}
async function main() {
const { browser, page } = await attach();
try {
const title = await page.title();
console.log("attached to:", title);
// Hand `page` to your MCP tool handlers here.
} finally {
// Close the CDP connection, not the remote browser, unless you own it.
await browser.close();
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});Two details matter in production. First, browser.close() on a CDP connection detaches; whether it terminates the remote session depends on the runtime, so check your provider's semantics before relying on it. Second, reusing contexts()[0] preserves cookies and storage from a persistent profile, which is usually what you want for logged-in workflows.
For the full runtime model — sessions, profiles, proxies, and live debugging — see Remote Browser for AI agents. For a lighter walkthrough of running Chromium without a local install, see remote browser online.
Chrome MCP vs the alternatives
Chrome MCP is one option among several for giving agents browser control. The right choice depends on whether you want a tool interface, a code interface, or a full agent framework.
| Approach | Interface | Control | Best fit |
|---|---|---|---|
| Chrome MCP | MCP tools | Model-driven, schema-bound | Agents that need a small, safe action set |
| Playwright directly | Code | Full, deterministic | Scripted automation and test harnesses |
| browser-use style agents | Natural language | High-level, model-driven | Open-ended tasks |
| Raw CDP | Protocol | Maximum, low-level | Custom runtimes and debugging |
The trade-off is control versus safety. MCP tools constrain what the agent can do, which reduces blast radius but also limits flexibility. Raw Playwright gives you everything but requires you to write the logic. Most production systems end up hybrid: MCP for exploratory steps, Playwright for the deterministic parts.
If you are comparing agent frameworks specifically, browser use vs Playwright covers where each fits. If you need to drive a session from outside the agent loop — for debugging or human handoff — see remote control browser.
Production criteria for a Chrome MCP runtime
If you are moving Chrome MCP off localhost, evaluate the runtime on these axes. They matter more than the tool schema.
- CDP endpoint stability. The runtime must expose a WebSocket endpoint that survives reconnects and does not change mid-session.
- Session isolation. Each agent gets its own browser process and profile. No shared cookies, no tab collisions.
- Persistent profiles. Logins and storage should survive across sessions and workers, with a clear way to reset them.
- Live viewer. A human should be able to watch a session in real time and take over when the agent stalls.
- Configurable browser settings. Proxy selection, user agent, locale, and timezone should be settable per session. Be precise about what "stealth" means; ask for the specific settings, not the marketing term.
- Usage controls. You need per-session limits and a clear billing model. See /pricing for current rates and metering.
- Observability. Session logs, network captures, and recordings make failures debuggable.
A runtime that checks all seven lets you keep your Chrome MCP server thin and put the hard problems where they belong.
Common failure modes
A few issues show up repeatedly when teams move Chrome MCP to production.
Stale CDP connections. Long-running agents hold a WebSocket open for minutes. If the network drops, the MCP server may not notice. Add a heartbeat and reconnect logic, and treat a failed Runtime.evaluate as a signal to re-attach.
Selector drift. MCP tools that click by selector break when the page changes. Prefer tools that return a page snapshot the model can reason over, or combine MCP with a deterministic Playwright step for critical actions.
Profile leakage. If two sessions share a profile, one agent's login can leak into another's. Verify that the runtime scopes profiles per session unless you explicitly opt into sharing.
Unbounded JS execution. A run JS tool is a remote code execution primitive. Scope it, log it, and consider disabling it for untrusted agents.
Silent timeouts. A tool that waits for a selector with no timeout will hang the agent loop. Set explicit timeouts on every browser action and surface them to the model as errors it can react to.
When Chrome MCP is the right call
Chrome MCP is a good fit when:
- Your agent needs a bounded action set rather than arbitrary code execution.
- You want to swap models without rewriting browser logic, since the tool schema is stable.
- You are building on an MCP-native client and want browser tools to sit alongside other tools.
- You need a human-in-the-loop path where a person can watch and intervene.
It is a weaker fit when you need deterministic, high-throughput automation with no model in the loop. In that case, drive Playwright directly against a hosted endpoint and skip the MCP layer.
Getting started
The practical path is short:
- Pick a Chrome MCP server that supports attaching to a remote CDP endpoint, not just launching local Chrome.
- Provision a hosted Chromium session and capture its CDP WebSocket URL.
- Point the MCP server at that URL and verify with a single
navigatecall. - Add session isolation, persistent profiles, and a live viewer before you scale past one agent.
- Instrument every tool call so failures are debuggable.
The documentation covers session creation, CDP endpoints, and profile management in detail. The protocol layer is the easy part; the runtime is where Chrome MCP either holds up or does not.