Cursor's agent can edit code and run your terminal. A browser MCP server adds a different kind of reach: it lets the agent open pages, click, type and read what is on screen. This guide sets up MCP Browser Extension as a Cursor browser MCP server. It is an MCP server (@mehmoodqureshi/chrome-mcp on npm) plus a Chrome extension, and it drives the Chrome you already have open, with your logins. You get the exact mcp.json, the extension and pairing steps, three practical use cases, a note for Windsurf, and an honest list of limits.
What a browser MCP server adds to Cursor
An MCP server is a local process that exposes tools to the agent. Cursor reads MCP servers from a JSON config and lists their tools to the model. A browser server gives the agent tools such as navigate, snapshot, click, type and get_text.
There are two broad designs. Most browser servers launch their own browser, so every site sees a stranger and anything behind a login needs scripting. MCP Browser Extension does the opposite. A Manifest V3 extension in your normal Chrome connects to the server over a localhost WebSocket and runs each call through Chrome's extension APIs. The agent sees your Chrome profile, signed in as you. The logged-in Chrome page explains the model.
It is not the only server that works this way. hangwin/mcp-chrome and Browser MCP also reuse your existing browser and its logins. What this one adds is a set of defaults: a domain allowlist that starts empty, reads gated as well as clicks, password values never returned, optional redaction and a per-call audit log.
Cursor already has a browser. Do you need this?
Maybe not. Cursor ships its own browser tool. It runs as a web view in a pane inside Cursor. Its cookies and storage persist per workspace, and each workspace's browser is isolated from the others. For pages behind a login, Cursor's help says to tell the agent how to sign in.
That built-in browser is a good default for checking a local dev server. You do not need to install anything. Reach for a Chrome-based MCP server when:
- The page needs a login you have already done in Chrome, with 2FA, SSO or a hardware key you do not want to script.
- You want the same setup in Cursor, Claude Code and Windsurf.
- You want an explicit allowlist and an audit trail of every URL the agent touched.
Configure Cursor
Cursor reads MCP servers from .cursor/mcp.json in your project, or from ~/.cursor/mcp.json in your home directory for every project. Add this:
{
"mcpServers": {
"chrome-mcp": {
"command": "npx",
"args": [
"-y",
"@mehmoodqureshi/chrome-mcp",
"--allow-domain",
"example.com",
"--enable-mutations",
"--persist-token"
]
}
}
}What the flags do:
--allow-domain example.comis the allowlist. Replace it with your real sites, one--allow-domainper host.*.example.comcovers a domain and its subdomains.--enable-mutationslets the agent navigate, open tabs, click and type. Leave it out for a read-only setup.--persist-tokenkeeps the pairing across restarts.
Node 18 or newer and Chrome 116 or newer are required. Cursor asks for approval before running MCP tools by default. If the server does not come up, open the Output panel and pick MCP Logs to see why.
Windows
On Windows, npx is a batch shim that MCP hosts cannot start directly. Use cmd as the command:
{
"mcpServers": {
"chrome-mcp": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@mehmoodqureshi/chrome-mcp",
"--allow-domain",
"example.com",
"--enable-mutations",
"--persist-token"
]
}
}
}Windsurf browser MCP
Windsurf takes the same mcpServers block in its mcp_config.json. The arguments, the extension and the pairing are identical. The quickstart has every host side by side.
Install the extension and pair it
The server can do nothing without the extension. Install MCP Browser Extension from the Chrome Web Store, or load the copy bundled in the npm package. Every time the server boots it copies the extension to ~/chrome-mcp-extension (or %USERPROFILE%\chrome-mcp-extension on Windows). Print the path with:
npx -y @mehmoodqureshi/chrome-mcp --extension-pathThen go to chrome://extensions, turn on Developer mode, click Load unpacked, and choose that folder. The Web Store build is reviewed per release and can trail npm by a version. The bundled folder always matches what you installed.
Pairing is usually automatic. The server writes a pairing.json file (mode 0600) into the extension folder on each boot, and the extension reads it and connects. Pin the extension from the puzzle-piece menu and watch its badge: a green dot means paired and connected, a grey circle means no server has run yet. If it stays grey, run npx -y @mehmoodqureshi/chrome-mcp --print-pairing and paste the port and token from ~/.chrome-mcp/handshake.json into the extension's Options page.
If you would rather let the agent do this, paste the setup prompt from the agent setup page into Cursor's chat. It follows the same steps and stops for the two that must happen inside Chrome.
To verify, ask Cursor's agent:
Call chrome_status and tabs_list, then tell me which tabs you can see.Then ask it to open a site that is not on your allowlist. It should be refused with a message starting Blocked:. That is the deny-all policy working.
Use case: check a local dev server
Allow localhost. Ports are stripped when matching, so one entry covers localhost:3000 and localhost:5173. 127.0.0.1 is a separate host and needs its own entry.
"args": [
"-y", "@mehmoodqureshi/chrome-mcp",
"--allow-domain", "localhost",
"--enable-mutations", "--enable-observers", "--persist-token"
]--enable-observers turns on console_logs, network_log and dialogs. It is off by default because it patches console, fetch and XMLHttpRequest on allowlisted pages. With it on, a prompt like this gives the agent the real error instead of a guess:
Open localhost:3000/settings, click Save, then show me any console
errors and failed network requests.snapshot { "diff": true } returns only what changed between snapshots, which keeps the snapshot, click, snapshot loop cheap.
Use case: read a logged-in dashboard
Many analytics, billing and admin screens have no API, or one you never set up. Allow just that host:
"args": [
"-y", "@mehmoodqureshi/chrome-mcp",
"--allow-domain", "dashboard.example.com",
"--redact", "--persist-token"
]This setup leaves out --enable-mutations, so the agent cannot navigate, open tabs or click. It can only read pages on that host that are already open in your Chrome. Open the dashboard yourself, then ask Cursor to read it with get_text or read_as_markdown. --redact scrubs JWTs, cloud keys and bearer tokens from reads. If the session has expired, auth_check reports [AUTH_REQUIRED] so the agent stops and asks you to sign in again. The server never signs in for you.
To read several pages at once, the batch tool runs many calls in one request. Open pages with active: false so they load in the background and do not take over the tab you are using.
Use case: browser testing a form in Cursor
With --enable-mutations, the agent can fill and submit a form on an allowed domain:
On localhost:3000/signup, fill the form with an invalid email,
submit it, and tell me which validation messages appear.Useful details:
fill_formfills several fields in one call.- Actions accept role and name instead of CSS selectors, for example
click { "role": "button", "name": "Sign up" }. clickandtypeaccepttrusted: truefor real OS-level input, which works on React and Vue controlled inputs.- Elements inside iframes, such as payment widgets, are reachable with
allFrames: true, and each frame is checked against the allowlist by its own URL.
The tools reference lists all 40 tools, and the guides cover these patterns in depth.
Limits
Be clear about what this does not do:
- It does not launch a browser. The extension is required.
- It drives a real, visible Chrome window. There is no headless mode.
- Chrome only. No Firefox, Safari or WebKit.
- It cannot reach what Chrome blocks extensions from, such as
chrome://pages and other extensions' pages. - It shares your Chrome with you. Two agents driving the same tab at once will collide, so give each its own tabs.
- Every tool definition costs context on each turn. Use
--toolsto advertise only the tools a run needs.
If you are writing end-to-end tests, or need Firefox or WebKit, Playwright MCP is the better choice. If you only check public pages or a local server, Cursor's built-in browser may be all you need. The compare page covers the trade-offs, and the security page covers the allowlist, redaction and audit log. For the same setup in Claude Code, see Claude Code browser access.
FAQ
How do I add a browser MCP server to Cursor?
Add a chrome-mcp entry under mcpServers in .cursor/mcp.json or ~/.cursor/mcp.json, with npx as the command and -y @mehmoodqureshi/chrome-mcp plus your flags as arguments. Then install the Chrome extension and check that its badge turns green.
Can Cursor use my logged-in Chrome sessions?
Yes, through this server. The extension runs inside your normal Chrome, so sites you are signed into are signed in for the agent, on the domains you allow.
Why does every call say Blocked?
The server is deny-all by default. Add --allow-domain for each host, and add --enable-mutations if the agent needs to navigate, open tabs, click or type.
Does it work with Windsurf?
Yes. Windsurf takes the same mcpServers block in its mcp_config.json, and the extension and pairing steps are identical.
Should I use this or Cursor's built-in browser?
For a local dev server or public pages, the built-in browser is simpler. Use a Chrome-based MCP server when you need your existing logins, an explicit domain allowlist, or the same setup across several MCP hosts.
Set it up in a few minutes