BLOG
Chrome CDP MCP: Wiring Agents to Remote Chromium
Learn how Chrome CDP MCP connects AI agents to remote Chromium, what the protocol layers actually do, and how to run it in production.
# Chrome CDP MCP: Wiring Agents to Remote Chromium
"Chrome CDP MCP" is really three things stacked together: Chrome as the browser, the Chrome DevTools Protocol (CDP) as the control channel, and the Model Context Protocol (MCP) as the interface an AI agent calls. Each layer has a different job, and conflating them is where most setup guides go wrong. This post separates them, shows how a Chrome CDP MCP stack actually connects to a remote browser, and covers the production criteria that matter once you move past a local demo.
If you are searching for how to get an agent driving a real Chrome instance over CDP through an MCP server, the short answer is: run an MCP server that exposes browser tools, have it attach to a Chromium instance over a CDP WebSocket endpoint, and point that endpoint at a hosted session rather than a local --remote-debugging-port. The rest of this guide explains why, and how to do it without the usual breakage.
What each layer in Chrome CDP MCP actually does
Before you wire anything, it helps to know which layer owns which responsibility.
Chrome (or Chromium) is the execution environment. It renders pages, runs JavaScript, holds cookies and storage, and exposes a debugging interface. Whether it runs on your laptop or in a data center does not change what the protocol can do — only how you reach it.
CDP is the wire protocol. It is a JSON-based protocol over WebSocket that lets a client send commands (Page.navigate, Runtime.evaluate, Network.enable) and receive events (Page.loadEventFired, Network.responseReceived). Playwright, Puppeteer, and Selenium's Chrome driver all speak CDP under the hood, either directly or through a translation layer. The Chrome DevTools Protocol documentation is the authoritative reference for domains and commands.
MCP is the agent-facing interface. An MCP server exposes tools — navigate, click, screenshot, extract_text — that a model can call with structured arguments. The MCP server is the component that translates a tool call into one or more CDP commands (often via Playwright) and returns a result the model can reason about.
The practical consequence: MCP does not replace CDP. It sits on top of it. When someone says "Chrome CDP MCP," they usually mean an MCP server that drives Chrome over CDP. That server is the piece you configure, and the CDP endpoint is the piece you point somewhere useful.
| Layer | Role | Who configures it |
|---|---|---|
| Chrome / Chromium | Renders pages, holds session state | Runtime or hosting provider |
| CDP | Command and event channel over WebSocket | Connection string / endpoint |
| MCP server | Exposes browser tools to the model | You (or a framework) |
| Agent / model | Decides which tools to call | Your application |
Why the CDP endpoint is the part that matters
Most Chrome CDP MCP tutorials assume a local browser started with --remote-debugging-port=9222. That works for a demo. It falls apart in production for predictable reasons:
- The browser lives on the same machine as the agent. If your agent runs in a container, a serverless function, or a queue worker, there is no local Chrome to attach to.
- State does not survive. A local Chrome dies with the process. Cookies, logins, and in-progress flows vanish.
- You cannot watch or debug. When a tool call fails, you have no live view and no recording.
- Concurrency is manual. Running twenty agents means managing twenty Chrome processes, ports, and profiles yourself.
The fix is to decouple the browser from the agent. The MCP server keeps its tool interface; only the CDP endpoint changes — from ws://localhost:9222 to a remote WebSocket URL. That single substitution is what makes a Chrome CDP MCP stack production-viable. Remote Browser provides hosted Chromium sessions with CDP access, so the endpoint is a managed URL rather than a process you babysit. The remote browser for AI agents post covers the runtime model in more depth.
Connecting an MCP-driven agent to remote Chromium
The most common pattern is an MCP server built on Playwright. Playwright's chromium.connectOverCDP() attaches to an existing browser over CDP instead of launching one. That is exactly the hook you need.
Here is a TypeScript example of an MCP tool handler that attaches to a hosted Chromium session and runs a navigation plus extraction step. The endpoint and session ID come from your provider's session API; treat them as secrets.
import { chromium, type Browser, type BrowserContext } from "playwright";
// Provided by your runtime: a CDP WebSocket endpoint for a live session.
const CDP_ENDPOINT = process.env.REMOTE_CDP_ENDPOINT!;
let browser: Browser | null = null;
let context: BrowserContext | null = null;
async function getContext(): Promise<BrowserContext> {
if (context) return context;
// connectOverCDP attaches to an already-running Chromium.
browser = await chromium.connectOverCDP(CDP_ENDPOINT, {
timeout: 30_000,
});
// A hosted session usually exposes one default context.
const contexts = browser.contexts();
context = contexts[0] ?? (await browser.newContext());
return context;
}
// Example MCP tool handler: navigate and return visible text.
export async function navigateAndRead(args: {
url: string;
selector?: string;
}): Promise<{ title: string; text: string }> {
const ctx = await getContext();
const page = await ctx.newPage();
try {
await page.goto(args.url, {
waitUntil: "domcontentloaded",
timeout: 45_000,
});
const title = await page.title();
const target = args.selector ? page.locator(args.selector) : page.locator("body");
const text = (await target.innerText()).slice(0, 8_000);
return { title, text };
} finally {
// Close the page, not the browser: the session stays alive for reuse.
await page.close();
}
}
// Call once at shutdown so the session can be released cleanly.
export async function disconnect(): Promise<void> {
if (browser) await browser.close();
browser = null;
context = null;
}A few details that matter in practice:
- Close pages, not the browser, between tool calls. Closing the browser tears down the session. Closing the page keeps the context, cookies, and storage intact for the next call.
- Set explicit timeouts. Remote endpoints add latency; the default 30-second navigation timeout is often too tight for heavy pages.
- Reuse the context. Reconnecting over CDP on every tool call adds round trips and can leak sessions. Cache the connection per session ID.
- Handle disconnects. Remote sessions can expire. Wrap tool handlers so a dropped CDP connection triggers a reconnect or a clean error the model can act on.
If you are comparing this to a fully managed agent runtime, the remote browser online guide walks through the trade-offs between running your own MCP server and using a hosted agent loop.
Production criteria for a Chrome CDP MCP stack
Once the connection works, the questions shift from "does it run" to "does it hold up." These are the criteria worth evaluating before you commit.
Session lifecycle and isolation
Each agent task should get its own browser session, or a deliberately shared one. Isolation prevents one agent's cookies or navigation state from leaking into another's. Look for explicit session creation and teardown APIs, not a shared pool you cannot reason about. Remote Browser sessions are isolated by default and can be released explicitly.
Persistent profiles
Many real tasks need a logged-in state across multiple runs — a dashboard, an internal tool, a checkout flow. Persistent profiles let a session resume with cookies and storage intact. Without them, every run starts cold and your agent burns tool calls re-authenticating. See the remote web browser post for how profile persistence interacts with session reuse.
Live viewer and recordings
When an MCP tool call returns an unexpected result, you need to see what the browser saw. A live viewer lets you watch the session in real time; recordings let you replay a failed run. Both are debugging infrastructure, not features — they cut the time to diagnose a bad tool call from hours to minutes.
Proxy and browser settings
Some workloads need a specific egress region or configurable browser settings. Remote Browser exposes proxy and browser configuration at the session level. Be precise about what you need: region selection and proxy routing are common; anything beyond that should be verified against current documentation rather than assumed.
Usage controls and cost visibility
Browser time is metered. A runaway agent that leaves sessions open will burn budget silently. Look for per-session time limits, concurrency controls, and usage reporting. Current plan details and metering are on the pricing page; check it directly rather than relying on secondhand numbers.
Protocol compatibility
CDP is not perfectly uniform across browser versions. Playwright's connectOverCDP works with Chromium-based browsers; Firefox and WebKit do not expose a compatible CDP surface. If your stack assumes Chrome CDP MCP, stay on Chromium and pin your Playwright version against the browser build your provider runs.
| Criterion | Local Chrome + MCP | Hosted Chromium + MCP |
|---|---|---|
| Endpoint | ws://localhost:9222 | Managed CDP WebSocket URL |
| Session isolation | Manual (one process per agent) | Per-session by default |
| Persistent profiles | You manage the user-data dir | Provider-managed |
| Live debugging | DevTools on localhost | Live viewer + recordings |
| Concurrency | Port and process management | API-driven session creation |
| Cost model | Your compute | Metered browser time |
Common failure modes and how to avoid them
A few problems show up repeatedly when teams move a Chrome CDP MCP setup from local to remote.
Attaching to the wrong context. connectOverCDP returns a browser with existing contexts. If you call newContext() when one already exists, you can end up with a blank context that has none of the session's cookies. Read browser.contexts() first.
Leaking sessions. Every connectOverCDP call that is never closed leaves a session running. Track session IDs and release them in a finally block or a shutdown hook.
Assuming tool calls are atomic. An MCP tool that navigates and extracts in one call is convenient but hides intermediate state. For complex flows, split into smaller tools so the model can inspect results and recover from partial failures.
Ignoring event streams. CDP events (Network.*, Page.*) carry information that a single tool response cannot. If your MCP server subscribes to events, you can surface network failures or console errors back to the model instead of returning a silent empty result.
Hardcoding the endpoint. Session endpoints rotate. Read them from environment or a session API at runtime, never from a committed constant.
When to run your own MCP server vs. use a managed runtime
You have two reasonable paths.
Run your own MCP server. You control the tool schema, the retry logic, and the model integration. You attach it to a hosted Chromium session over CDP. This is the right choice when your agent logic is bespoke, when you need custom tools beyond navigation and extraction, or when you want full control over what the model can do. The remote control browser post covers the control-plane side of this setup.
Use a managed agent runtime. If your task is a standard web workflow, a managed runtime that bundles the browser, the agent loop, and the tool surface may get you to production faster. You trade some control for less infrastructure. The trade-off is real: managed runtimes constrain what your agent can do, but they also remove the session-management and debugging burden.
Either way, the CDP layer is the constant. Whether you write the MCP server or a provider ships one, the browser is reached over CDP, and the quality of that connection — isolation, persistence, observability — determines whether the stack holds up. Start with the documentation to see the session and CDP endpoints available, then build the smallest MCP server that proves your workflow before scaling concurrency.
The Chrome CDP MCP stack is not complicated once you separate the layers. Chrome executes, CDP transports, MCP exposes. Get the endpoint right, manage the session lifecycle, and instrument the failures — that is most of the work.