Limitations
Listed here rather than buried. Two of these are inherent to sharing one browser process and no amount of guarding removes them — you are trading isolation for a shared session, and it is worth knowing the price.
Inherent to sharing
Storage is one bucket
Cookies, localStorage and IndexedDB are shared across every instance attached to the browser. Two instances on the same origin will clobber each other's state. This was measured, not assumed:
Unrelated domains are unaffected in practice — the clash needs the same origin. But same-origin concurrency is genuinely unsafe, and no guard arbitrates storage writes.
The profile has real credentials
Every attached instance can act as you: read mail, send as your account, authenticate anywhere you are signed in. This is the point of the tool and also its risk.
- Use a dedicated profile, not your daily browser profile.
- Be deliberate about which repos get an agent with browser access. An agent running untrusted code is an agent holding your credentials.
- Remember the same applies to any tool with network or shell access.
Guard limitations
A blank tab mid-navigation is closable
about:blank is treated as inert, because the browser always keeps one seed blank tab that no session claims — counting it as foreign would deny every close permanently, which would make the guard useless.
The cost: if another instance is mid-navigation, its tab can briefly read asabout:blank and become closable. The window is narrow, but it is real, and the guard cannot distinguish "seed tab" from "navigating tab".
Same-URL tabs are indistinguishable
Ownership is tracked by URL, not by target id. Two tabs on the identical URL cannot be told apart, so a same-site instance could have its tab closed. In practice this needs two agents on the exact same page at once.
Closes are denied while any foreign tab exists
This is the guard working as intended, but it is also a real limit on convenience: if another instance is active, you cannot close anything at all, including your own tabs. Tidy up when you are alone.
Operational
One browser, one process
If the shared browser is not running, every attached instance fails with a connection error until it is back. The wrapper starts it automatically on the next MCP spawn, but opencode does not retry an MCP that failed during startup — a restart is needed for the tools to reappear.
Linux and macOS only
The launcher shells out to POSIX tools and passes--no-sandbox, which is not something to ship to untrusted desktops. It is intended for your own machine.
Browser cache coupling
The launcher resolves the newest full Chromium in~/.cache/ms-playwright at launch. Upgrading Playwright can therefore change which binary runs. If the MCP's own bundled revision differs from what is in the cache, pass --executable-path explicitly.