BLOG
Browser MCP Cursor: Wiring Cursor to a Real Browser
Browser MCP Cursor setups connect the Cursor IDE to a real Chromium session. Here is how the pieces fit, what breaks, and how to run it in production.

A browser MCP Cursor setup means giving the Cursor IDE a Model Context Protocol server that exposes browser control as tools, so the model inside Cursor can navigate pages, click elements, read the DOM, and pull back results without you copy-pasting anything. The intent behind the search is usually concrete: you want Cursor to research a page, reproduce a bug, or drive a workflow against a live site, and you want it to do that against a real browser rather than a text fetch. This guide covers how the pieces fit, where local MCP browser servers fall short, and how to point Cursor at a hosted Chromium session that behaves the same on your laptop and in CI.
What "browser MCP Cursor" actually refers to
Three components are in play, and people conflate them:
- Cursor is the client. It hosts the model and speaks MCP to whatever servers you configure.
- An MCP browser server is the adapter. It exposes tools like
navigate,click,snapshot,evaluate, andscreenshotover MCP, and translates each call into browser actions. - A browser is the thing being driven. It can be a local Chrome instance, a headless Chromium launched by the server, or a remote session reachable over the Chrome DevTools Protocol (CDP).
The confusion is that "browser MCP" is used for both the adapter and the browser. They are separate decisions. You can run the same MCP server against a local browser or a remote one, and that choice matters far more for reliability than which MCP server you pick.
The most common adapters today are chrome-devtools-mcp, which drives Chrome through CDP and exposes DevTools-style tools, and playwright-mcp, which wraps Playwright's automation surface. Both are legitimate. Both assume a browser exists somewhere. The question this article answers is where that browser should live.
Why local browser MCP breaks down
Running the MCP server and the browser on the same machine is the fastest path to a demo. It is also the path that produces the most support threads. The failure modes are consistent:
- Session state leaks. A local Chrome profile accumulates cookies, extensions, and cached auth. Two agent runs against the same profile interfere with each other, and a stale login silently changes what the agent sees.
- The browser is not reproducible. Your laptop has a specific Chrome version, a specific set of extensions, and a specific network. CI has none of that. A workflow that passes locally fails in the pipeline for reasons that have nothing to do with the code.
- Long-running tasks die with the process. If Cursor restarts, the terminal closes, or the machine sleeps, the browser session is gone. Agents that need to hold a session across minutes or hours cannot rely on a local process.
- No isolation between tasks. Parallel agent runs against one local browser collide on tabs, focus, and storage. You end up serializing work you wanted to parallelize.
- Debugging is opaque. When a step fails, you get a stack trace and maybe a screenshot. You cannot watch the session live or replay it.
None of these are MCP problems. They are runtime problems. The MCP layer is fine; the browser underneath it is not built for agent workloads.
The architecture that holds up
The pattern that survives production separates three concerns:
- The MCP server stays thin. It translates MCP tool calls into CDP commands or Playwright actions.
- The browser runs as a hosted Chromium session with its own lifecycle, isolated from other sessions, reachable over a WebSocket CDP endpoint.
- The client (Cursor) connects to the MCP server, which connects to the remote browser.
In practice this means the MCP server runs locally inside Cursor's MCP configuration, but it is configured to attach to a remote browser rather than launch one. That keeps the ergonomics of Cursor — you still get tool calls in the chat pane — while moving the fragile part (the browser) to infrastructure that is designed for it.
Remote Browser provides exactly this: hosted Chromium sessions with CDP access, Playwright/Puppeteer/Selenium compatibility, a live viewer, persistent profiles, configurable browser settings including proxy options, and per-session isolation. You create a session, get a CDP endpoint, and point your MCP server at it. The documentation covers the session API and the connection details.
Comparison: local browser vs hosted Chromium for Cursor MCP
| Criterion | Local browser (MCP launches Chrome) | Hosted Chromium (MCP attaches over CDP) |
|---|---|---|
| Setup time | Minutes | Minutes, plus a session API call |
| Reproducibility across machines | Low — depends on local Chrome version and profile | High — same image, same settings every run |
| Session isolation | None by default; shared profile | Per-session isolation |
| Survives Cursor restart | No | Yes, session persists until stopped |
| Parallel agent runs | Collide on tabs and storage | Independent sessions |
| Live debugging | Screenshot at best | Live viewer plus CDP |
| Persistent logins | Manual profile management | Persistent profiles via API |
| Cost model | Your machine | Metered per browser-hour; see pricing |
| Best for | One-off exploration | Repeated workflows, CI, multi-step research |
The table is not an argument that local is bad. It is an argument that local is a different tool. If you are asking Cursor to look at one page once, launch Chrome locally and move on. If you are asking it to run a workflow you will run again tomorrow, the hosted path pays for itself in debugging time alone.
Wiring Cursor to a remote browser over CDP
The mechanics are straightforward once you separate the MCP server from the browser. Two approaches work.
Approach 1: MCP server that accepts a CDP endpoint
Most MCP browser servers accept either a launch configuration or a connection endpoint. For chrome-devtools-mcp, the relevant flag is a browser URL; for playwright-mcp, it is a CDP endpoint. The exact flag names change between versions, so check the server's README rather than trusting a blog post — including this one.
The pattern is:
- Create a hosted session via the Remote Browser API. You get back a session ID and a CDP WebSocket URL.
- Add the MCP server to Cursor's
mcp.jsonwith the CDP URL as an argument or environment variable. - Restart Cursor so it picks up the new server.
- Ask Cursor to navigate somewhere and confirm the tool call appears in the chat.
Approach 2: A thin MCP server you control
If you need behavior the off-the-shelf servers do not provide — custom tool names, session lifecycle management, per-task profiles — write a small MCP server that wraps Playwright and connects over CDP. This is more work but gives you full control over what the model can do, which matters for safety and for token efficiency.
Here is a minimal Playwright connection over CDP, which is the core of either approach:
import { chromium, Browser, Page } from "playwright";
interface SessionInfo {
cdpUrl: string;
sessionId: string;
}
async function connectToHostedBrowser(session: SessionInfo): Promise<{
browser: Browser;
page: Page;
}> {
// Connect to the hosted Chromium session over CDP.
// The endpoint is a WebSocket URL returned by the session API.
const browser = await chromium.connectOverCDP(session.cdpUrl, {
timeout: 30_000,
});
// Reuse the existing context if the session already has one,
// otherwise create a fresh context. Hosted sessions typically
// come with a default context you should attach to.
const contexts = browser.contexts();
const context = contexts.length > 0 ? contexts[0] : await browser.newContext();
const pages = context.pages();
const page = pages.length > 0 ? pages[0] : await context.newPage();
return { browser, page };
}
async function runTask(session: SessionInfo) {
const { browser, page } = await connectToHostedBrowser(session);
try {
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
const title = await page.title();
console.log("Title:", title);
} finally {
// Disconnect without closing the remote browser.
// The session lifecycle is managed by the API, not by this client.
await browser.close();
}
}Two details matter here. First, connectOverCDP attaches to an existing browser; it does not launch one. Second, browser.close() on a CDP connection disconnects the client — it does not necessarily terminate the remote session. That distinction is what lets you reconnect from a different process, or from a different machine, without losing state. The Playwright CDP documentation is the authoritative reference for the connection semantics.
For the MCP server itself, the tool surface should be small. A model with twenty browser tools will pick the wrong one. Five or six well-named tools — navigate, snapshot, click, type, evaluate, screenshot — cover most research and debugging tasks and keep the context window manageable.
What Cursor is actually good at with a browser
Once the wiring is in place, the useful patterns are narrower than the marketing suggests. In practice, Cursor plus a browser MCP server is strong at:
- Reproducing bugs against a live site. Point the agent at a URL, describe the symptom, and let it step through the flow while you watch the live viewer.
- Reading documentation that resists static fetching. Pages behind tabs, accordions, or client-side rendering are exactly where a text fetch fails and a real browser succeeds.
- Extracting structured data from a page you can see. The agent navigates, snapshots the DOM, and returns JSON. This is a web research tool use case, not a general scraping platform.
- Verifying that a change works. After editing code, ask Cursor to load the local dev server in the hosted browser and confirm the behavior.
It is weaker at long-horizon tasks with many branches, at anything requiring CAPTCHA solving without configuration, and at workflows where the site changes between runs. Those are runtime and site problems, not MCP problems, and they are the reason hosted sessions with persistent profiles and configurable browser settings exist.
Production criteria before you commit
If you are evaluating this setup for a team rather than a single developer, the checklist is short but unforgiving:
- Session lifecycle. Can you create, inspect, and stop sessions programmatically? Can a session outlive the client that created it?
- Isolation. Does each session get its own storage, cookies, and network identity, or do they share?
- Observability. Can you watch a session live and replay what happened? The remote control browser post covers why this matters more than raw speed.
- Profile management. Can you persist logins across sessions without leaking them between tasks?
- Network configuration. Can you set proxies and other browser settings per session?
- Cost model. Is it metered per browser-hour, per session, or per request? The pricing page has current details; do not plan capacity from a blog post.
- Compatibility. Does it speak CDP in a way Playwright, Puppeteer, and Selenium all understand, or does it require a proprietary client?
Remote Browser is built around these criteria: hosted Chromium, CDP access, Playwright/Puppeteer/Selenium compatibility, a live viewer, persistent profiles, session isolation, and usage controls. It is not the only option, and the remote browser for AI agents post compares the runtime layer more broadly.
Common mistakes
A few patterns show up repeatedly in broken setups:
- Launching a browser inside the MCP server when you meant to attach. If the server launches Chrome, you are back to local semantics regardless of where the server runs.
- Closing the browser at the end of every tool call. This destroys the session and forces a fresh login on the next call. Disconnect the client; do not terminate the session.
- Giving the model too many tools. Every tool is a token cost and a chance to pick wrong. Start with five.
- Skipping the live viewer. Debugging an agent without watching it is guesswork. The viewer is the difference between "it failed" and "it clicked the wrong button because the page had not finished rendering."
- Assuming the local profile is the production profile. It is not. Persistent profiles on the hosted side are how you make logins reproducible.
Where this fits in a larger stack
Cursor is one client among several. The same hosted session that Cursor drives can be driven by a CI job, a scheduled agent, or a second developer's IDE, because the browser is not tied to any one process. That is the practical argument for the hosted path: the browser becomes infrastructure, and clients become interchangeable. The remote browser online post covers the broader case for running Chromium without managing it locally.
If you are starting today, the shortest path is: create a session, copy the CDP URL, add your MCP server to Cursor with that URL, and ask Cursor to load a page. If the tool call appears and the page loads, the wiring is correct. Everything after that is a question of which tools you expose and how you manage session lifecycle — and those are decisions worth making deliberately rather than inheriting from a default config.