@krakerxyz/browser-mcp
v1.5.0
Published
MCP server package for remote browser automation.
Readme
@krakerxyz/browser-mcp
MCP server package for remote browser automation.
@krakerxyz/browser-mcp is the MCP-facing bridge your AI tool runs locally.
It is designed to be launched by an MCP host (for example from .mcp.json) and connects that host to a Browser MCP backend over WebSocket.
What it is used for
- Give MCP-compatible assistants access to a real Chromium browser session
- Support browser actions such as opening pages, navigation, DOM reads, JS execution, clicks, and screenshots
- Create and manage isolated browser sessions, each with its own timezone, locale, and geolocation
- Reach local/dev-only services through optional tunnel ports
Session model
A session is an isolated browser instance (browser context) on the server.
- The agent creates sessions explicitly with
browser_create_session, which returns asessionId - Every page and cookie tool takes that
sessionId(just like pages are addressed bypageId), so one connection can drive several sessions at once - Each session keeps its own pages, cookies, and state isolated from other sessions
- A session can fix its
timezone,locale, andgeolocationat creation time — useful for rendering dates, formatting numbers, and testing location-aware pages - Sessions live until closed with
browser_close_sessionor until they sit idle past the server's session timeout; they are not tied to the connection, so they survive reconnects (usebrowser_list_sessionsto rediscover them)
How it works
- Your MCP host starts this package over stdio.
- This package connects to a Browser MCP server (
ws://.../ws/client). - On connect, it discovers tools from the server and registers them dynamically.
- MCP tool calls are forwarded to the remote browser backend.
- Results are returned to your MCP host over stdio.
This means new server tools can be added without requiring a matching MCP package release.
MCP host configuration (.mcp.json)
Minimal example:
{
"mcpServers": {
"browser": {
"command": "npx",
"args": [
"-y",
"@krakerxyz/browser-mcp",
"--server",
"ws://localhost:3100",
"--api-key",
"change-me"
]
}
}
}Configuration options
--server <ws-url>(required): Browser MCP server URL, for examplews://localhost:3100--api-key <key>(optional): Required when the server hasAPI_KEYenabled--name <client-name>(optional): Identifies this client in the server dashboard — sessions it creates are grouped under this name. It does not create or name a session; the agent creates sessions viabrowser_create_session--tunnel-port <port>(optional, repeatable): Enables localhost tunneling for specific ports
Locale, timezone, and geolocation
browser_create_session accepts optional timezone, locale, and geolocation so the remote browser renders content for a specific place and language:
timezone— IANA id likeAmerica/New_York; controls howDateandIntlrender dates and timeslocale— BCP 47 tag likede-DE; controls date/number/currency formatting,navigator.language, and theAccept-Languageheadergeolocation—{ latitude, longitude, accuracy? }reported to the page's geolocation API (permission is granted automatically)
These are fixed for the life of the session. To use different values (for example to compare how a page renders in two timezones), create another session and drive both side by side.
Tunnel ports
Tunnel ports let the remote browser reach services that are only accessible from the MCP host machine (for example local dev servers).
Example: with --tunnel-port 3000, browsing to http://localhost:3000 in the remote browser is tunneled to port 3000 on the MCP host.
Multiple tunnel ports are supported by repeating --tunnel-port.
Tunnel .mcp.json example:
{
"mcpServers": {
"browser": {
"command": "npx",
"args": [
"-y",
"@krakerxyz/browser-mcp",
"--server",
"ws://localhost:3100",
"--api-key",
"change-me",
"--tunnel-port",
"3000",
"--tunnel-port",
"5173"
]
}
}
}Tunnel troubleshooting
If navigating to a tunneled URL fails with ERR_SOCKS_CONNECTION_FAILED, the SOCKS bridge reached the
server fine, but the client could not open a TCP connection to your local service. The server logs the
real reason on a [tunnel] line, e.g. client could not reach localhost:5174: connect ECONNREFUSED. An
agent can read the same thing without server-log access by calling the browser_get_connection_diagnostics
tool, which returns the recent tunnel results (the failing host:port and error) for clients started with
--name.
The most common cause is that the @krakerxyz/browser-mcp process and your dev server are in different
network namespaces (for example the MCP host runs in a separate container from the dev server). A working
curl localhost:5174 from your shell does not prove the mcp client can reach it. Verify from the same
environment the mcp client runs in:
node -e "require('net').connect(5174,'127.0.0.1').on('connect',()=>console.log('reachable')).on('error',e=>console.log('UNREACHABLE',e.code))"If that prints UNREACHABLE, run the mcp client where it can reach the dev server (same container/network
namespace), or bind the dev server to an interface the mcp client can reach. If only localhost fails but
127.0.0.1 works, it's an IPv6 (::1) mismatch — navigate to 127.0.0.1 instead.
Available tools
Tools are discovered dynamically from the server on connect. Start by creating a session with browser_create_session; every page and cookie tool then takes the returned sessionId. The current set of tools provided by the server:
| Tool | Description |
|------|-------------|
| browser_create_session | Create an isolated browser session and return its sessionId. Optionally set timezone, locale, and geolocation. Call this before opening pages. |
| browser_list_sessions | List active sessions with their ids, labels, page counts, and locale settings. |
| browser_close_session | Close a session, destroying its browser context and all of its pages. |
| browser_get_connection_diagnostics | Get recent tunnel results for this client (which localhost ports the browser reached, and the real error when a tunnel failed). Use after ERR_SOCKS_CONNECTION_FAILED. Retained per --name. |
| browser_open_page | Open a new page in a session and navigate to a URL. Optionally accepts a viewport size for responsive layout testing. |
| browser_close_page | Close a browser page |
| browser_list_pages | List all open pages in a session |
| browser_navigate | Navigate an existing page to a new URL |
| browser_execute_js | Execute JavaScript in a page context. Expression must return a JSON-serializable value. |
| browser_get_dom | Get DOM HTML content. Returns full page HTML or matching elements for a CSS selector. |
| browser_capture_screenshot | Capture a screenshot of a page. Returns both an inline image and a downloadable URL. |
| browser_click | Click on an element by CSS selector or coordinates |
| browser_fill | Clear an input and set its value, dispatching a real input event so SPAs receive the change. Use for <input>, <textarea>, and contenteditable. |
| browser_type | Type text one character at a time, dispatching real keydown/input/keyup events. Use when the page reacts to individual keystrokes (autocomplete, masks); prefer browser_fill otherwise. |
| browser_press_key | Press a single key or chord (e.g. Enter, Tab, Control+A), optionally focusing a selector first. |
| browser_select_option | Select an option in a native <select> by value, label, or index, dispatching real input/change events. |
| browser_set_viewport | Set the viewport (screen) size of a page for responsive layout testing. Accepts width/height or a Playwright device preset name. |
| browser_set_cookies | Set one or more cookies in a session's browser context. Supports HttpOnly/Secure cookies. |
| browser_get_cookies | Get cookies from a session's browser context. |
| browser_get_console_logs | Get captured console log entries from a page (buffers last 50). |
| browser_get_network_requests | Get captured network request entries from a page (buffers last 20). |
| browser_get_performance_report | Collect performance metrics (web vitals-style, CPU sample, long tasks, resources) with optional auto CPU profiling on high usage. |
| browser_start_performance_profile | Start a manual CPU sampling profile for a page. |
| browser_stop_performance_profile | Stop a manual CPU sampling profile and return top function/file hotspots. |
Because tools are registered dynamically from the server, new tools added to the server become available to the MCP host without requiring a new release of this package.
Server setup (Docker Compose)
services:
browser-mcp:
image: joshkrak/browser-mcp:latest
container_name: browser-mcp
restart: unless-stopped
ports:
- "3100:3100"
environment:
API_KEY: "${BROWSER_MCP_API_KEY}"
volumes:
- browser-mcp-data:/data
volumes:
browser-mcp-data:First start downloads the Chromium browser (~640MB) into the /data volume — it is not baked into the image. Keep /data on a persistent volume (as above) so this happens only once; later starts reuse it. The first container therefore takes longer to report healthy.
If your MCP host is not on the same machine as Docker, replace ws://localhost:3100 with your reachable server URL.
