Prerequisites
- Bun 1.4.0, Docker with Compose v2, Git, and Chrome.
- An MCP client supporting Streamable HTTP with an
Authorization header.
- A separate Chrome profile for testing. Do not start with your primary signed-in profile.
1. Install dependencies and prepare local secrets
From the repository root:
Generate three independent values with openssl rand -hex 32: POSTGRES_PASSWORD, AUTH_SECRET, and SETTINGS_ENCRYPTION_KEY. Put them in your untracked .env using a local editor. Do not paste secrets into issue reports, shell history, or AI conversations.
Set DATABASE_URL to postgresql://browser_mcp:<POSTGRES_PASSWORD>@localhost:5432/browser_mcp, replacing the placeholder. Hex passwords are URL-safe. Keep PUBLIC_URL=http://localhost:3000 for this local example.
2. Start PostgreSQL and migrate
Start the API in one terminal:
Start the frontend in another:
Use the frontend URL printed by Vite. Its development proxy forwards API traffic to the local backend; keep auth flows on the configured upstream origin. For production-like local onboarding without a Vite proxy, use docker compose up --build --wait and open http://localhost:3000 instead. Compose waits for PostgreSQL health and successful migration before starting the server.
The first community account becomes administrator. Complete bootstrap on a private or loopback-only installation before exposing it publicly. Public password signup closes after that account; later users need configured OIDC.
3. Build and load the extension
- In Chrome, open
chrome://extensions and turn on Developer mode.
- Choose Load unpacked and select the repository’s
dist/extension directory.
- Open the extension popup. For community, set the upstream to
http://localhost:3000.
- Start pairing, sign in to your own server, and explicitly approve the device request.
- Return to the extension and confirm it is connected; check the browser entry in the dashboard.
The verification flow expires after ten minutes. Start again if it expires. The device code alone cannot redeem a connection token. See extension setup for release ZIP installation and troubleshooting.
4. Create an MCP credential
In the dashboard, open your browser and create an MCP token with a descriptive name and the shortest useful expiry. Copy both the browser-specific URL and the one-time token into your client’s secret storage.
A common client configuration shape is:
Exact client keys differ. Use its Streamable HTTP transport, not a legacy SSE-only connection. Supply the token in a header, never in a URL. A browser connection token (br_…) will not work as an MCP token (mcp_…).
5. Try a harmless task
Ask your client to list tabs, open https://example.com, take a snapshot, and report the page title. Approve only those actions. Do not start with purchases, inboxes, admin consoles, or unknown JavaScript.
Disconnect in the extension when finished. Revoke the MCP token in the dashboard to remove that client’s access; rotate the connection token if the extension credential may be exposed.
Troubleshooting
- 401 from MCP: check token type, expiry, revocation, and the browser ID in the URL.
- Browser offline: keep Chrome running, finish approval, and reconnect the extension to the same upstream.
- Origin/auth errors: align
PUBLIC_URL, the external origin, OAuth callbacks, and proxy headers. Do not mix localhost and 127.0.0.1 in auth URLs.
- Migration/DB errors: confirm
.env credentials match the existing PostgreSQL volume. Changing POSTGRES_PASSWORD does not change a password already stored in that volume.