Selenium MCP
Allows driving a real browser through Selenium Grid, providing tools for session management, navigation, clicking, typing, pressing keys, extracting element content, executing JavaScript, and taking screenshots.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Selenium MCPOpen example.com, search for 'MCP', and screenshot the results."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
๐ Selenium Flow
One browser, many calls. Drive a real Chrome or Firefox on Selenium Grid from an agent over MCP โ or from anything else over plain HTTP. Same actions, same server, one browser that stays exactly where you left it. ๐งญ
The whole idea, in one breath
Open a browser once. It stays alive โ same page, same cookies, same scroll position โ while an agent works a task one call at a time, or an n8n workflow steps node to node. Nothing relaunches, nothing logs in twice.
agent โโโโ MCP /mcp โโโโโโถ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ selenium-flow โ โโโโโโถ โ Selenium Grid โ โโโถ ๐
workflow โโโโ HTTP /browser โโโถ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
stateless the browser
lives hereThis server holds no browser. The session lives on the Grid, so the server can restart, scale to zero, or run several replicas without anyone losing a tab. ๐ช
Related MCP server: monkeysee
๐ Two surfaces, one implementation
Surface | For | Path |
MCP over Streamable HTTP | agents and MCP clients |
|
JSON over HTTP | n8n HTTP nodes, curl, scripts, anything |
|
Every action is a tool and an endpoint, one to one, and a test fails the build if that stops being true. They differ in one place: screenshot hands MCP an image block a vision model can see, and HTTP a base64 payload.
GET /health and GET /openapi.yaml need no credentials.
๐งฐ Every action, both ways
Fourteen actions, each a tool and an endpoint with identical parameters. All endpoints are POST with a JSON body.
The one difference: over HTTP
session_idis always required; over MCP it depends on the mode, and the advertised schema says which. See Sessions.
Action | Endpoint | |
| Start a browser โ | |
| Go to a URL ๐งญ | |
| Click, double-click, right-click, hover, scroll to ๐ฑ๏ธ | |
| Type into a field โจ๏ธ | |
| Press a named key โ | |
| Read text and HTML off the page ๐ | |
| Capture a PNG, viewport or full page ๐ธ | |
| Print the page with the browser's print engine ๐ | |
| Run JavaScript โ the escape hatch ๐งช | |
| Enter and leave an iframe ๐ผ๏ธ | |
| Answer a native alert, confirm or prompt ๐ฌ | |
| Change the window at any time ๐ | |
| Attach a file to a file input ๐ | |
| Give the slot back, keep the session ๐งน |
Every parameter, every return field and the traps worth knowing are one page per action in the wiki โ generated from openapi.yaml, which is itself generated from the live tool schemas, so it cannot drift from the server. The same schemas are served at GET /openapi.yaml.
๐ฆ Chrome or Firefox
open_session(browser="firefox") and you are on Firefox; leave it out and you are on Chrome. Every other action behaves identically on both โ both are plain W3C WebDriver, so only session creation differs.
๐ง A session is not a browser
The session outlives the browsers it holds. When the Grid reaps an idle one, or an operator ends one, the session keeps the browser choice, the window and the page it was on โ so recovery is one call with no arguments:
open_session() # same browser, same window, back where you wereSessions expire on SESSION_TTL, slid forward on every use. Nothing else removes one. More in the wiki.
๐งญ About that url parameter
click, write, press_key, extract, screenshot and execute_script all take an optional url, and it is not an assertion. If the browser is elsewhere it goes there first, so you can jump straight to a page instead of clicking a path to it.
๐ช Sessions
Over HTTP it is session in, session out, always โ so an n8n workflow owns its session and can pass it between nodes.
open_session always comes first. Nothing opens a browser implicitly, because that is the only place its browser, window size and timeouts can be chosen.
After that there are two modes, and they are exclusive. session://current reports which one applies and links the reference that explains it:
Mode | When | The rule |
saved | the server can identify you | never pass |
stateless | it cannot, or you are on |
|
It works out who is calling from the first of these it finds and never invents one โ a caller it cannot identify is stateless, not quietly handed a browser:
Key | How it's set | How stable |
A name you choose |
| Survives a client restart or reconnect |
The MCP transport session | the negotiated | Lasts the connection; a reconnect is a new key |
stdio | one process, one client | Lasts the process |
Prefer the query parameter: one credential shared across callers, each naming itself in its URL. The header wins over it, so an admin can pin one browser per credential.
โ ๏ธ n8n opens a new MCP transport per tool call, so the negotiated id is never the same twice. Name the session in the URL or saved mode cannot work there.
Browser lifetime is the Grid's (SE_NODE_SESSION_TIMEOUT, 300s here); how long we remember a caller is SESSION_TTL, slid forward on every call. Nothing runs a cleanup loop.
๐ Where am I?
session://current reports the mode, the session this client holds and which browser it is running, whether the Grid still has it, whether you are inside a frame, and a link to the reference that applies. Reading it never opens a browser.
The same status is also a current_session tool, hidden unless a client declares ?resources=off or X-MCP-Resources: off โ resources being the least implemented corner of MCP.
๐ It teaches you how to use it
The server ships an Agent Skill: the strategic half tool descriptions cannot
hold โ which session mode you are in, why extract beats screenshot by orders
of magnitude, how to reach a page in one call, and what a timeout usually means.
SKILL.md is a thin index; each reference is its own resource, so an agent loads
only what its task needs:
Resource | Holds |
| the index: session mode, the three rules, where next |
| you own the session id |
| the server holds your browser |
| extract vs script vs screenshot, and durable XPath |
| forms, clicks, keys, scrolling, waiting |
| timeouts, dead sessions, blank captures |
| setting the server up, which env var to change |
| the file listing, with sizes and hashes |
The two session references are mutually exclusive: session://current tells you
which one applies.
Those URIs are FastMCP's convention, served by its own SkillProvider, so
list_skills and download_skill work here with no special casing.
Same fallback as the session status: clients that cannot read resources get a
selenium_flow_skill tool instead, hidden otherwise. SKILL_ENABLED=false turns
both shapes off.
๐ What a session leaves behind
Everything a session downloads is kept by the Grid, in a per-session store beside the browser โ created with the session, deleted with it. Two kinds of file land there, undistinguished: whatever the site served to a download, and whatever you kept with screenshot(save=true) or save_pdf.
Read it as | URI / path |
a resource |
|
a resource |
|
a tool |
|
a link |
|
That last one travels: signed over path and expiry, because an <img> tag cannot send an Authorization header.
๐ฅ Admin UI
GET /admin โ your sessions and what each downloaded, marked with the browser each is running. Click a file to view it in place; click a session for a header of its context. End quits a stale browser and gives its Grid slot back, rather than waiting out the Grid's idle timeout โ the session itself is kept.
Flow sessions, not Grid sessions: browsers somebody else put on the Grid are not listed. Nothing on the MCP surface lists sessions at all โ a client sees its own and nothing else. More in the wiki.
The list pushes its own updates over Server-Sent Events โ no refresh button, and no polling per tab: one loop serves every page. Rows carry the name their caller claimed; a browser this server has no record of is labelled as somebody else's rather than passed off as ours.
There are no accounts: the sign-in box asks for the server's token, since anyone holding it can already drive every browser through the API. It is kept in sessionStorage, so it does not outlive the tab.
The Grid's own console is a second tab, framed same-origin. Put both behind one host โ the Grid at /, this server under a path โ and its live view works with no cross-origin exception.
๐งฉ MCP Apps
Hosts implementing the MCP Apps extension โ Claude, ChatGPT, VS Code, Goose โ render a tool result as UI rather than JSON. session_files and browser_sessions each declare one, so a listing arrives as thumbnails.
The components are shared with the admin UI, not copied, so the two cannot drift. Degradation is the point: one server, the client's capabilities pick the rendering.
The client can | It gets |
render apps | the component, inline |
read resources |
|
neither | the tool's JSON, with links anything can open |
Apps get a deny-by-default CSP with no network, so PUBLIC_BASE_URL is also what admits this server's images to the frame. APPS_ENABLED=false turns it off.
โ๏ธ Configuration
Every flag has an environment fallback: containers are configured with env vars, developers reach for flags.
Env | Flag | Default | Notes |
|
| the in-cluster Grid Service | Selenium Grid hub |
|
| unset | Bearer token for both surfaces. Unset disables auth |
|
|
| Path prefix for the HTTP endpoints |
|
|
| Let MCP callers omit |
| โ |
|
|
| โ |
| Seconds a caller's mapping is kept |
| โ | unset | Connection for |
| โ |
| Key namespace, so sharing a database is safe |
|
|
| Serve the embedded skill as a resource, and as a tool where there are none |
|
|
| Offer the MCP Apps components to hosts that render them |
| โ | unset | Externally reachable root, e.g. |
| โ |
| Where the admin UI frames the Grid console from |
| โ |
|
|
| โ | node default | Default window size for new sessions |
| โ | unbounded | Seconds a navigation may take. Worth setting โ a hung page holds a Grid slot |
| โ | driver default | Seconds |
|
|
| Drop MCP transport sessions. Required for >1 replica |
|
|
|
|
|
|
| |
|
|
|
|
Session defaults cascade
The browser, the window size and the two timeouts resolve in order of increasing specificity:
server default (env) < client default (?width= / X-Window-Width) < open_session argumentA bad default is ignored and logged; an explicit browser fails loudly. The browser is stored with the session, so a reaped one reopens as the same browser.
๐ Auth
Setting MCP_AUTH_TOKEN turns on auth for both surfaces at once. Clients send it the usual way:
Authorization: Bearer <token>The HTTP endpoints also accept the bare token as the Authorization value, for clients that can't express a scheme. /health is always open.
It is also the signing key for file links and the event stream, so rotating it revokes those too. In the cluster it is generated by External Secrets โ no value is authored anywhere.
๐ Running it
docker compose up --buildThat starts the server and a standalone Grid for it to drive, with auth off:
curl -X POST localhost:8000/browser/open \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com","width":1280,"height":800}'Point an MCP client at http://localhost:8000/mcp, open localhost:8000/admin โ and watch the browser work live at localhost:7900, the Grid's noVNC view. ๐
๐ Contributing
Setup, tests, how the OpenAPI spec is generated and how the embedded skill is packaged: CONTRIBUTING.md. Design rules worth reading before changing behaviour: AGENTS.md.
๐ References
๐ Licence
MIT. See LICENSE.
Not affiliated with, endorsed by, or sponsored by the Selenium project. "Selenium" is a trademark of the Software Freedom Conservancy, used here only to identify the software this server drives.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Run multi-step tasks in a real Chrome browser: persistent environments, live view, human takeover.
Automate cloud Chromeโnavigate, click, type, screenshot, run code, record screen video
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables browser automation using the Selenium WebDriver through MCP, supporting browser management, element location, and both basic and advanced user interactions.542427MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive a real, logged-in Chrome browser for web automation tasks like navigation, clicking, typing, and screenshotting.41MIT
- FlicenseNot gradedqualityCmaintenanceEnables MCP clients to control a real local browser window for web automation tasks such as clicking, typing, scrolling, and taking screenshots.51-
- AlicenseAqualityCmaintenanceEnables AI agents and MCP clients to automate web browsers via Selenium WebDriver, supporting Chrome, Firefox, and Edge in headless or visible mode with tools for navigation, interaction, content extraction, screenshots, and scripting.2113MIT