browser-use-mcp-server: Giving an MCP Client a Real Browser
Browse the web, directly from Cursor etc.
At a glance
- What is it?
- This MCP server wraps browser-use and Playwright so an assistant such as Cursor can drive a Chromium instance and report back. It is a thin transport layer with a real dependency cost, and the README leaves several operational questions open.
- Who is it for?
- Adopt it if you already accept browser-use and an OpenAI key as part of your agent stack and want that capability reachable from Cursor or another MCP client without writing your own transport. Skip it if you need a deterministic, LLM-free scraper or cannot send page content to an external API.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 118 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap between an MCP client and an actual page
An assistant running inside Cursor or Claude Desktop can read files and run shell commands, but it has no eyes on a live page. The README frames the project as an MCP server that lets AI agents control browsers using browser-use, which is the upstream library doing the reasoning. The server's job is narrower: translate MCP tool calls into browser actions and expose the result back to the client. The example prompt in the README is the whole pitch in one line, asking the assistant to open news.ycombinator.com and return the top ranked article. Anyone who has tried to get that answer by pasting HTML into a chat window knows why a real browser session matters. Dynamic pages, cookie banners and JavaScript-rendered lists all defeat a static fetch. The target user is a developer already working inside an MCP-capable editor who wants the assistant to reach the open web without leaving the editor. It is not aimed at data engineers building scheduled scrapers, and nothing in the README suggests it wants to be.
What sits between the MCP client and Chromium
Three layers are visible in the material. At the bottom is Playwright, installed separately with uv run playwright install --with-deps --no-shell chromium. Above it sits browser-use, the library that turns a natural-language task into browser actions. On top is this project, which the README describes as an MCP server with dual transport, SSE and stdio. The SSE path runs the server directly and the client connects to http://localhost:8000/sse. The stdio path is more involved: the README states that mcp-proxy is required for stdio mode, and the client config passes --stdio together with --proxy-port 9000, which implies the server still binds a port internally while the proxy carries traffic over standard input and output. That is an unusual shape, and the README does not explain why the port remains necessary in stdio mode. The features list also mentions VNC streaming and async tasks, and the Docker section maps port 5900 for VNC, so the browser session can be watched while it runs. The async task flag appears in the environment as PATIENT, described as controlling whether API calls wait for task completion. That is the only hint about how long-running browser work is scheduled.
Installing it: uv, Playwright, mcp-proxy, then the wheel
The README assumes uv as the package manager and gives a three-step prerequisite block: install uv via the astral.sh script, then uv tool install mcp-proxy, then uv tool update-shell. From a source checkout the sequence is uv sync, uv pip install playwright, and uv run playwright install --with-deps --no-shell chromium. Note the --no-shell flag, which skips the bundled shell browser. To run from source in SSE mode, the command is uv run server --port 8000. For stdio, the README builds a wheel with uv build, uninstalls any previous global tool, installs the wheel from dist, and then runs browser-use-mcp-server run server --port 8000 --stdio --proxy-port 9000. Environment variables live in a .env file: OPENAI_API_KEY, an optional CHROME_PATH, and PATIENT defaulting to false. The client configuration differs by transport. SSE mode needs only a url entry pointing at the local SSE endpoint. stdio mode needs command, args and an env block carrying the OpenAI key. The README lists config paths for Cursor, Windsurf and both Claude desktop variants, which is the most practically useful table in the document.
The OpenAI key is the design decision you have to accept
OPENAI_API_KEY is a required environment variable, not an optional one. That means every browsing task is interpreted by a hosted model, and the content the browser reads is sent to that API. For a public news page this is unremarkable. For an internal dashboard, a staging environment behind a login, or anything covered by a data processing agreement, it is the constraint that decides the question. The README does not discuss redaction, local model support, or a way to keep inference on your own hardware. It also does not state what happens when the key is missing or the API returns an error, so the failure mode is undocumented. A second, quieter cost is the Playwright browser download with system dependencies, which the install command pulls in via --with-deps. On a locked-down machine that step is often the one that fails, and the README offers no fallback beyond the optional CHROME_PATH variable. Anyone evaluating this should treat the OpenAI dependency as the primary architectural fact rather than a configuration detail.
Docker, VNC and the default password
The Docker path is documented more carefully than the source path. The image builds with docker build -t browser-use-mcp-server . and runs with ports 8000 and 5900 published. The README states the default VNC password is browser-use unless overridden, and shows the override as a file mounted read-only at /run/secrets/vnc_password. A noVNC checkout is suggested for viewing, launched with ./utils/novnc_proxy --vnc localhost:5900. Watching the automation is genuinely useful when a task fails halfway and you want to know whether the page changed or the model chose the wrong element. The trade-off is that a VNC server with a documented default password is now listening on your machine. The README notes the :ro mount flag for the password file but says nothing about binding the ports to localhost only, and the example uses the default Docker port mapping, which publishes on all interfaces. If you run this on a shared network, that detail deserves attention before the first container starts.
When a plain HTTP client is the better tool
The obvious alternative for many tasks is not another MCP server but a scripted HTTP client: requests plus BeautifulSoup, or Playwright used directly without an LLM in the loop. The difference in approach is where the decision-making lives. Here, browser-use asks a model to decide which element to click and when the task is done, which handles pages you have never seen and selectors you cannot predict. A scripted client does the opposite: you write the selector once and it either matches or raises an error you can read. For a nightly job against a stable endpoint, the scripted version is faster, cheaper, and reproducible, and it fails loudly instead of hallucinating a plausible answer. The MCP server earns its place when the target is unknown at authoring time, when a human is sitting in the editor iterating on a question, or when the page structure changes often enough that maintaining selectors is the real cost. Choosing this project for a fixed, high-volume extraction task would be a mismatch, and the README's own framing around agents and vibe browsing supports that reading.
Maintenance, versioning and the MIT licence
The repository is MIT licensed, which permits commercial use and modification provided the copyright notice and permission text are retained. That is the whole of the licence implication here, and it is not legal advice. On maintenance, the release history shows three patches, v1.0.1 through v1.0.3, all dated 2025-04-15, and the last push to the default branch is 2026-05-20, so the project has been touched since the last tagged release without a corresponding version bump. That pattern means the wheel you install from PyPI may lag the source tree. The build-and-reinstall loop in the README, uv build followed by uv tool uninstall and uv tool install, is the workflow the maintainers expect for local changes. Upgrade cost is concentrated in two places: Playwright's Chromium version, which moves independently, and the browser-use library, which is the component actually driving the model. Neither is pinned in the material shown, so a fresh uv sync months from now may resolve different versions than the README was written against. Pinning both in your own lockfile is the practical mitigation.
Verify these four things before you commit
First, confirm the Python and Playwright version constraints, since the README does not state them and the install command pulls system dependencies. Second, test the PATIENT flag both ways on a task that takes more than a few seconds, because the README describes it only as controlling whether API calls wait for completion and does not say what the client sees while waiting. Third, check whether CHROME_PATH actually overrides the bundled Chromium in your environment, since the README marks it optional without describing the fallback. Fourth, decide whether port 5900 needs to be published at all; if you do not need to watch the session, leaving VNC closed removes the default-password question entirely. None of these are blockers, but each is a place where the documentation stops short of the behaviour you will depend on.
Editorial conclusion
Adopt it if you already accept browser-use and an OpenAI key as part of your agent stack and want that capability reachable from Cursor or another MCP client without writing your own transport. Skip it if you need a deterministic, LLM-free scraper or cannot send page content to an external API. Before installing, confirm which Python and Playwright versions the wheel pins, whether CHROME_PATH and PATIENT behave as documented, and whether the VNC port needs to be exposed on your network at all.
Community notes