@selenium/mcp is the official Model Context Protocol server from the Selenium
project. It lets a coding agent drive a real browser through Selenium: the agent reads the page as an accessibility
snapshot with element refs, and acts on those refs. It never has to write or guess a selector.
It is the Selenium bindings exposed as tools, not a test runner. Selenium Manager comes with the bindings, so there is no driver to install.
Status: v1 in progress. Chrome, headless by default, over stdio, one browser per server. See What it covers.
You need Node.js ^22.23.4 || ^24.22.1 || >= 26.12.1 and Chrome. Then add the server to your agent:
Claude Code
claude mcp add selenium -- npx @selenium/mcp@latestCodex
codex mcp add selenium -- npx @selenium/mcp@latestCursor: add to .cursor/mcp.json (or ~/.cursor/mcp.json):
{ "mcpServers": { "selenium": { "command": "npx", "args": ["@selenium/mcp@latest"] } } }VS Code: add to .vscode/mcp.json:
{ "servers": { "selenium": { "command": "npx", "args": ["@selenium/mcp@latest"] } } }Any other MCP client: run npx @selenium/mcp@latest as a stdio server.
| Flag | Meaning |
|---|---|
--browser <name> |
chrome (default). edge and firefox start but are not yet tested. |
--headless / --headed |
Run headless (the default) or show the window. |
--grid <url> |
Run the browser on a Selenium Grid instead of locally. |
--allowed-origins <list> |
Semicolon-separated origins or hosts (*.example.com) the browser may navigate to. |
--blocked-origins <list> |
Semicolon-separated origins or hosts it may not navigate to. |
--allow-unrestricted-file-access |
Let browser_navigate open file:// URLs, and browser_file_upload send files from outside the working directory (both blocked by default). |
--allow-evaluate |
Offer browser_evaluate, which runs JavaScript the agent writes in the page. |
--log-level <level> |
Log to stderr: severe, warning (default), info, fine, all. all includes raw WebDriver traffic, so typed text such as passwords. |
Flag names match @playwright/mcp wherever they mean the same thing.
Tool names and arguments match @playwright/mcp wherever the operation is the same, so habits and skills files carry
over.
| Tool | What it does |
|---|---|
browser_snapshot |
The page as an accessibility tree with refs. all: true adds text and structure. |
browser_navigate |
Go to a URL. |
browser_navigate_back |
Go back. |
browser_click |
Click a ref (optionally double or right click). |
browser_type |
Replace the text in a ref, optionally pressing Enter. |
browser_fill_form |
Fill several textboxes, checkboxes, radios and selects at once. |
browser_select_option |
Choose options in a <select> by value or label. |
browser_press_key |
Press a key or chord (Enter, Control+a). |
browser_hover |
Move the mouse over a ref. |
browser_drag |
Drag one ref and drop it on another. |
browser_file_upload |
Choose files for a file input, or for the button that opens a hidden one. |
browser_wait_for |
Wait for text to appear or go, or for some seconds. |
browser_handle_dialog |
Accept or dismiss an alert, confirm or prompt. |
browser_take_screenshot |
PNG of the viewport or of one ref. |
browser_console_messages |
Console messages and uncaught errors, collected over WebDriver BiDi. |
browser_network_requests |
Requests since the page loaded, with status, over WebDriver BiDi. |
browser_resize |
Resize the browser window. |
browser_tabs |
List, open, select or close tabs. |
browser_close |
Close the browser; the next call starts a new one. |
browser_install |
Have Selenium Manager install the browser and driver. |
browser_evaluate |
Run a JavaScript function on the page or a ref. Only with --allow-evaluate. |
Every action returns the page's URL, title and a fresh snapshot, so the agent rarely needs to ask for one.
[e1] heading "Login" [level=1]
[e2] textbox "Username"
[e3] textbox "Password"
[e4] button "Login"
[e5] iframe "Help"
[f5e1] link "Forgot password?"
- Roles, names and states come from the bindings'
getAccessibilitySnapshot(), which computes them in the page following WAI-ARIA, html-aam and accname, in a sandbox that page scripts cannot reach. Open shadow roots are included. - By default a snapshot lists interactive elements, headings, live regions (
alert,status) and frames.browser_snapshotwithall: trueadds the rest of the visible content. - A ref stays the same for the same element across snapshots;
browser_navigatestarts over. - Content inside an iframe gets refs prefixed with the frame's own ref (
f5e1), and tools act on them directly. - Password values are never shown.
Chrome, headless, stdio, and the tools above. Not yet: Firefox and Edge under test, the opt-in tool groups behind
--caps (request interception, storage, coordinates, PDF), HTTP transport, more than one session, and the
selenium_* tools (Grid status, selenium_doctor). Those come in later releases.
- No tool runs JavaScript the agent writes unless the server is started with
--allow-evaluate. browser_file_uploadsends only files inside the server's working directory unless started with--allow-unrestricted-file-access, since an upload hands the file to whatever page is open.browser_navigateopens only http(s),about:blankanddata:URLs;file://needs--allow-unrestricted-file-access, anddata:is refused when--allowed-originsis set.--allowed-originsand--blocked-originsrestrict wherebrowser_navigatecan go. They do not stop links, redirects or scripts on a page from going elsewhere, so they are not a browser-wide security boundary.- Snapshots, screenshots, console messages and request URLs and statuses are the only page data returned by default.
The server depends on getAccessibilitySnapshot(), which first ships in selenium-webdriver 4.53.0. Until that is on
npm, the dependency points at the nightly build in GitHub Packages, so installing needs a GitHub token with
read:packages:
NODE_AUTH_TOKEN=<token> npm install
npm run test:unit # unit tests, no browser
npm run test:e2e # every tool against real Chrome
npm run lint # eslint and prettierSee AGENTS.md for conventions and CONTRIBUTING.md for how to send a change.
The community Python Selenium MCP server is the reference this design grew from, and its command coverage is the checklist for v1.