Repository navigation
Workspaces
Name your workspace, and the browser that belongs to that name is yours.
Two words, two things:
- A workspace is what you name: the box that lasts. It holds your flows,
your files, your saved site data, where you have been, and the settings your
browser opens with. It is never deleted, only forgotten after it goes unused
for
WORKSPACE_TTL. - A session is the live browser open in a workspace — at most one at a time.
open_sessionstarts it;end_browser, an operator's End, or the Grid reaping an idle browser ends it. A workspace with no session open is an ordinary state.
There is no session id anywhere in this API. No tool takes one, no endpoint takes one, no result carries one. You say who you are and the server hands you the browser that name is holding.
| How to name it | Looks like | Use it when |
|---|---|---|
| a URL parameter | …/mcp?workspace=research-bot |
the usual case — one credential, each caller named in its own URL |
| a header | X-Workspace: research-bot |
an operator pins one workspace to one credential, or a client may only send approved headers (Claude.ai custom connectors) |
| stdio | nothing to do | one process serves one client, and it is named stdio
|
The old names are refused. ?session= and X-Session-Key are a 400 that
names the new spelling — even beside a new name — so a client wired the old way
finds out on its first call.
Sending both is a 400. Not a precedence one of them wins: a request carrying two names has two ideas about who is calling, and quietly picking one hides that from whoever wired it up. A repeated name with two values is refused the same way.
Sending neither is a 400 on anything touching a browser, with a message
saying how to fix it. The one exception is the flow library, which falls back to
the shared global library — which everyone may read and run, and nobody may
write.
The name has to be usable as a directory name, because it is one: it is where
your flows, your screenshots and your Files live — see Files. Letters,
digits, dots, dashes and underscores, starting with a letter or digit, 64
characters at most. stdio and global are reserved.
n8n opens a new MCP transport for every tool call, so nothing the transport negotiates is ever the same twice. Name the workspace in the URL and it simply works. See Installing.
A workspace name is an address, not a secret. The bearer token (or a JWT from your identity provider) is the credential; anyone holding one who knows your workspace's name can drive your browser. Sharing a workspace is deliberate and by name; doing it by accident is easy, which is worth knowing.
Nothing opens a browser implicitly. That is deliberate: open_session is the
only place a window size and the timeouts can be chosen, and hiding the call
hid the settings with it.
Call it again later with the same name — after a reconnect, a client restart, a week — and you are back on the same browser at the same page.
workspace://current reports the workspace name, which browser it is running,
the page it is on, whether a session is open at all (live), whether you are
inside a frame, and the window size. Reading it never opens a browser.
A client whose model cannot read MCP resources reads it with
read_resource(uri="workspace://current"). Over HTTP it is GET /browser.
A session:// URI from before the rename is refused with its workspace://
spelling, so a saved flow that names one says how to fix it.
The Grid reaps idle browsers on its own timeout, so a remembered id can name one that is already gone. The next call notices, reopens, and returns to the page it was last on with the same settings — the refresh is invisible.
"The same settings" includes which browser it was. That is why the choice is
stored as a setting rather than beside them: a Firefox session that came back as
Chrome would be exactly the silent change of shape the stored settings exist to
prevent. workspace://current reports it as browser.
The workspace outlives the sessions it holds. live is false when no session is
open — after the Grid reaps one, or an operator ends one from the admin UI — and
that is an ordinary state.
What survives is the context: the browser choice, the window, the last page. So the recovery is always the same one call:
open_session() # same browser, same window, back where you were
Which is also why you are never told "your browser was taken". You are told no session is open, which is the branch you already handle.
Workspaces themselves expire on WORKSPACE_TTL, slid forward on every use — a
day by default. Nothing else removes one.
There is one distinction that matters here, because getting it wrong strands browsers. A browser that fails to answer is not necessarily gone:
| The Grid says | Means |
|---|---|
200 |
healthy |
500 unexpected alert open |
alive, and blocked by a dialog — answer it with dialog
|
404 invalid session id |
genuinely reaped |
Only the last one counts as gone. Anything else, including a Grid that cannot be reached right now, is assumed alive: a wrong "alive" surfaces as a real error on the next call, while a wrong "dead" silently abandons a working browser and leaks its slot.
| Who owns it | Typical | |
|---|---|---|
| how long a session's browser lives idle | the Grid — SE_NODE_SESSION_TIMEOUT
|
300s idle |
| how long a workspace is remembered | WORKSPACE_TTL |
86400s, slid forward on every call |
| where that is remembered | WORKSPACE_STORE |
memory, or redis to share it |
Nothing runs a cleanup loop, and nothing should — the Grid expires browsers, the store expires its own keys.
end_browser frees the slot, and slots are the scarce
resource: the Grid runs a handful of browsers in total and an abandoned one holds
its place until it is reaped. Close on failure paths too. It ends the session,
never the workspace.
If you are mid-task and the caller may come back, leaving it open is the right call — just know you are holding capacity while you do.
The action pages are generated from openapi.yaml, which is itself generated from the live MCP tool schemas — so they describe the server that shipped, not the one someone remembered. Prose belongs in wiki-notes/<tool>.md in the repo.
selenium-flow · MIT
Start here
Guides
Lifecycle
Going places
Doing things
Getting things out
Site data
Console and network