-
Notifications
You must be signed in to change notification settings - Fork 0
Sessions
Whether you pass session_id, and what happens when you get it wrong.
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.
| Mode | When | The rule |
|---|---|---|
| saved | the server can identify you |
never pass session_id — it is not even advertised |
| stateless | it cannot, or you are on /browser/*
|
session_id is required on every call |
Using the wrong one fails every call the same way, so do not guess: read
session://current, which reports the mode and links the reference that
applies. Reading it never opens a browser — a null session_id means nothing is
held yet.
If your client cannot read MCP resources, the current_session tool returns the
same object. Add ?resources=off to make it visible.
Over the HTTP surface it is always session in, session out. That is its whole contract, so a workflow owns its session outright and can pass the id between steps.
It takes the first of these it finds, and never invents one — a caller it cannot identify is stateless, not quietly handed somebody's browser.
| Key | How it is set | How stable |
|---|---|---|
| a name you choose |
X-Session-Key header, else ?session=<name> on the MCP URL |
survives a client restart or reconnect |
| the MCP transport session | the negotiated Mcp-Session-Id
|
lasts the connection; a reconnect is a new key |
| stdio | one process, one client | lasts the process |
The header wins over the query parameter. That ordering is a permission boundary, not a preference: the header is set inside a credential, which an administrator controls, while the query parameter is written by whoever wires up the call. Leaving the header unset delegates the choice to the implementor.
n8n opens a new MCP transport for every tool call, so the negotiated id is never the same twice and a saved session keyed on it can never be found. Name the session in the URL. See Installing.
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. session://current reports it as browser.
There is one distinction that matters here, because getting it wrong strands browsers. A session 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 browser lives | the Grid — SE_NODE_SESSION_TIMEOUT
|
300s idle |
| how long a caller is remembered | SESSION_TTL |
3600s, slid forward on every call |
| where that is remembered | SESSION_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.
close_session 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.
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