neu-browser-mcp
Officialneu-browser-mcp
An MCP server that gives an agent a remote browser: create one, get a CDP URL to drive it, hand the user a live view, pick up the files it downloaded, and shut it down.
Why
Lifecycle only. It does not click, type or navigate. The agent drives the browser over CDP with agent-browser, Playwright, or any CDP client.
Same tools on any backend. Prompts and skills stay the same when the browser moves between
nap,kernel,browser-useandhyperbrowser. Each backend is a small adapter behind one interface.Credentials stay on the server. The backend token never enters the agent's context.
Human handoff and downloads. Backends with a live view give you a URL to watch or take over the browser. Files the browser downloads can be listed, linked, or read.
Related MCP server: mcp-browser-kit
Tools
Tool | What it does |
| Starts a browser and returns |
| Lists active browsers with the same connection info, so an agent can reconnect to one it lost track of. |
| Stops a browser. |
| Lists files in the browser's sandbox, the backend's download directory by default. |
| Returns a download URL for one file, or |
| Returns the contents of one file: text as text, anything else as a base64 resource. The server reads with the backend's credentials. Reads are capped at 256 KB. |
Backends
A capability a backend lacks shows up as null or as a missing tool. See Adding a backend.
Backend | Timeout (default / max) | Live view | CDP over HTTP | Metadata | List files | Download link | Read file |
1 hour / 24 hours | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | |
1 hour idle / 72 hours idle | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | |
1 hour / 4 hours | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | |
1 hour / 12 hours | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
More backends are planned.
Run it as a server
Requires Node.js 22 or newer. The server speaks MCP over stdio.
{
"mcpServers": {
"browser": {
"command": "npx",
"args": ["-y", "neu-browser-mcp"],
"env": {
"NEU_BROWSER_BACKEND": "nap",
"NAP_BROWSER_URL": "https://browser.example.com",
"NAP_BROWSER_TOKEN": "<token>"
}
}
}
}NEU_BROWSER_BACKEND picks the backend and defaults to nap. Each backend then reads its own variables.
nap
Variable | Meaning |
| Base URL of the browser service API. Required. |
| Bearer token for the browser service. Required. |
| Base URL used in file download links. Set it when |
kernel
Variable | Meaning |
| Kernel API key. Required. |
browser-use
Variable | Meaning |
| Browser Use Cloud API key. Required. |
hyperbrowser
Variable | Meaning |
| Hyperbrowser API key. Required. |
Use it as a library
To add the tools to an MCP server you already run, register them on it:
import { McpServer } from '@modelcontextprotocol/server'
import { createNapProvider, registerBrowserTools } from 'neu-browser-mcp'
const server = new McpServer({ name: 'my-server', version: '1.0.0' })
registerBrowserTools(server, {
provider: createNapProvider({
baseUrl: 'http://browser.internal:3005',
publicBaseUrl: 'https://browser.example.com',
token: async () => lookUpTokenFor(tenant),
}),
scope: { tenant_id: tenant.id },
})The server can come from either generation of the MCP TypeScript SDK: @modelcontextprotocol/server (v2) or @modelcontextprotocol/sdk (v1).
scope is a set of tags that confines the tools to one tenant. Every browser they create carries the tags, list_browsers returns only browsers that carry them, and a tool given a browser ID refuses it unless that browser carries them. This is what keeps tenants apart when they share the backend's credentials. token can be a string or an async function; a function is called once, on first use.
To pick the backend from the environment, the way the standalone server does, use providerFromEnv(process.env).
Adding a backend
A backend implements BrowserProvider from src/types.ts:
interface BrowserProvider {
readonly name: string
readonly capabilities: ProviderCapabilities
createSession(opts?: CreateSessionOptions): Promise<BrowserSession>
listSessions(opts?: ListSessionsOptions): Promise<BrowserSession[]>
releaseSession(id: string): Promise<void>
readonly files?: BrowserFiles // list, and optionally downloadUrl and read
}
interface ProviderCapabilities {
timeout: { kind: 'absolute' | 'idle'; defaultSeconds: number; maxSeconds: number }
liveView: boolean
httpCdp: boolean
metadata: boolean
}The required part is the session lifecycle plus a CDP WebSocket URL. Everything else is declared, and the tools adapt:
Declaration | Effect when absent |
| Always present. Sets the default and maximum the agent is told about, and whether the timeout counts from creation ( |
|
|
|
|
|
|
| No file tools are registered. |
|
|
|
|
src/providers/nap.ts is the reference implementation.
Development
npm install
npx tsc --noEmit
npx biome check .
npm testSee CONTRIBUTING.md.
License
Available Tools
5 toolscreate_browserCreate BrowserA
Create a headless Chrome browser instance. Returns browser_id plus connection info:
connect_command: a ready-to-run agent-browser command — just run it as-is to start driving the browser.
connect_url: a wss:// URL for "agent-browser connect". Do NOT pass cdp_url here.
cdp_url: an https:// URL for Playwright only, via browser.connectOverCDP(cdp_url).
live_view_url: share with the user so they can watch. The browser auto-expires after the timeout (default 1 hour, max 24 hours).
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_seconds | No | Browser timeout in seconds (default: 3600, max: 86400) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description still discloses the important behavioral facts: the browser is headless, it auto-expires, and it has a default and maximum lifetime. It also carries a useful negative constraint ('Do NOT pass cdp_url here'). It stops short of stating concurrency limits, whether creation is metered, or what a failure looks like, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Action statement is front-loaded, then a tight bullet list where each line maps to a distinct return field and its correct use. No filler sentences, and the expiry caveat sits last where it belongs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description correctly takes on the job of documenting browser_id, connect_command, connect_url, cdp_url, and live_view_url — including the crucial warning not to interchange the URLs. That makes it callable and consumable. It lacks only edge-case behavior such as limits or error conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single timeout_seconds parameter, and the description merely restates the default 1 hour / max 24 hours already written in the schema. Baseline 3 is appropriate — the schema does the work and the description adds no new parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'Create a headless Chrome browser instance.' That is unambiguously distinct from the siblings list_browsers, delete_browser, and file-retrieval tools, so an agent can route correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by naming — create a browser when you need one — and the description gives good downstream guidance on which returned handle to use for which client (agent-browser vs Playwright vs user sharing). However, it never states when to reach for this tool versus an existing browser session, and gives no exclusions or preconditions for creation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_browserDelete BrowserB
Stop and destroy a browser instance.
| Name | Required | Description | Default |
|---|---|---|---|
| browser_id | Yes | ID of the browser to delete |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. 'Destroy' signals a destructive, likely irreversible mutation, which is useful, but nothing is said about whether associated files/artifacts are removed, whether active sessions are terminated, required permissions, or behavior when the ID is invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence, front-loaded with the action and resource, with zero filler. Nothing is redundant or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with full schema coverage, the description is minimally adequate. However, as a destructive operation with no annotations and no output schema, it should disclose irreversibility and side effects on the browser's files or sessions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single browser_id parameter is fully documented in the schema (100% coverage), so the description adds little. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair ('stop and destroy') and a specific resource ('browser instance'), so an agent knows exactly what the tool does. It doesn't explicitly differentiate from siblings like create_browser or list_browsers, though the delete semantics are self-evidently distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this versus alternatives, no prerequisite checks (e.g., confirm the browser exists), and no mention of what to do if the instance is still in use. The agent must infer all usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_browser_file_urlGet Browser File Download URLA
Get a download URL for a file inside the browser sandbox.
Returns the URL alongside the current file state — use ready: true to confirm the file exists. The URL embeds an auth token and can be handed to the user (e.g. as a clickable link in chat) or fetched directly.
Files are only available while the browser is alive.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Full file path (e.g. /tmp/downloads/foo.pdf) | |
| browser_id | Yes | ID of the browser |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses that the URL embeds an auth token (a security-relevant trait), that a file-state object is returned alongside the URL, and the hard lifetime constraint that files only exist while the browser is alive. These are behaviors an agent cannot infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, action stated first, then return shape, then usage, then the lifetime caveat. Every sentence contributes a distinct fact with no repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by explaining the return (URL plus current file state, with `ready` as the existence signal) and the token/lifetime caveats. An agent has everything needed to call it and interpret the result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented in the schema, so the baseline is 3. The description adds no syntax or format detail for `path` or `browser_id` beyond what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence gives a specific verb+resource: 'Get a download URL for a file inside the browser sandbox.' That clearly separates it from list_browser_files, but it never names a sibling or explicitly contrasts scope, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states concrete usage contexts — hand the link to the user (e.g. clickable in chat) or fetch directly — and tells the agent to check `ready: true` before assuming the file exists. It does not state when to prefer list_browser_files instead, so no explicit alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_browser_filesList Browser FilesA
List files inside the browser sandbox.
Defaults to /tmp/downloads — point downloads there first, via CDP Browser.setDownloadBehavior with downloadPath: "/tmp/downloads".
Use after a download completes to discover what was saved. The browser sandbox is ephemeral, so files only exist while the browser is alive.
There can be a brief delay between CDP downloadProgress reporting "completed" and the file being readable; if a file looks truncated, retry after a moment.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Directory path (default: /tmp/downloads) | |
| pattern | No | Optional glob pattern to filter results | |
| browser_id | Yes | ID of the browser |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden, and it discloses several non-obvious traits: the sandbox is ephemeral (files vanish when the browser dies), a CDP download-path prerequisite exists, and there is a race between downloadProgress "completed" and file readability with retry advice. It omits what happens on a nonexistent path or permission errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the operation and default, then prerequisites and the timing caveat. Nearly every sentence earns its place; the redundant restatement of the default path slightly overlaps with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description should hint at the return shape; it says files are discovered but never indicates whether entries are names, paths, or sizes. Everything else an agent needs to call it correctly — location, prerequisite, retry behavior — is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, including the default (/tmp/downloads) for path, so the schema already does the heavy lifting. The description reinforces the default path but says nothing about the glob `pattern` parameter or how results are ordered, adding no meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List files inside the browser sandbox") with the default location, so the operation is immediately identifiable. It does not explicitly contrast with the closest sibling, get_browser_file_url, though the scope difference (listing vs. retrieving a URL) is implied.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear situational guidance: "Use after a download completes to discover what was saved," plus the prerequisite of pointing downloads at /tmp/downloads via CDP Browser.setDownloadBehavior. It does not name an alternative tool or a when-not condition, but the context for invoking it is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_browsersList BrowsersA
List all active browser instances. Each item includes the same connection info as create_browser (cdp_url, live_view_url, plus connect_url/connect_command for running browsers), so this doubles as a reconnect path — pick a running browser and run its connect_command.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden, and it does disclose the return shape: each item carries cdp_url, live_view_url, and connect_url/connect_command for running browsers. It also discloses the filter (only active instances) and the pro tip that connect_command can be executed directly. Missing only minor traits like ordering or whether stopped browsers ever appear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with what it lists, then immediately the payoff (identity with create_browser's connection info) and the actionable conclusion. No sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema and no annotations, so the description must explain returns — it does, describing the per-item fields and the distinction between running browsers and the rest. A note on what identifies each entry (name/id) or ordering would close the remaining gap, but an agent can call this correctly as written.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to explain and the baseline of 4 applies. The description correctly keeps its focus on return values instead of inventing parameter guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List all active browser instances") with a scoping qualifier ("active"). It also names create_browser as the source of the identical connection fields, which lets an agent relate it to a sibling, though it doesn't explicitly contrast with list_browser_files or the delete tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete second use case — as a reconnect path via connect_command — which is real guidance an agent can act on. It stops short of stating when not to call it or naming alternatives to pick instead, so it is clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.2.4- First observed
create_browser - First observed
delete_browser - First observed
get_browser_file_url - First observed
list_browser_files - First observed
list_browsers
TDQS
Scored across 5 tools
Each tool has a distinct role: lifecycle (create/list/delete), file listing, and file URL retrieval. The only mild overlap is that list_browsers re-exposes connection info also returned by create_browser, but that is a documented reconnect convenience rather than a genuine ambiguity.
All five tools follow a consistent snake_case verb_noun pattern (create_browser, list_browsers, delete_browser, list_browser_files, get_browser_file_url). The singular/plural browser vs. browsers variation is trivial and matches the resource semantics.
Five tools is well-scoped for a browser-sandbox lifecycle server: create, list, delete, and two file-access tools. Nothing feels padded or missing to the point of being thin.
Full lifecycle (create/list/delete) plus sandbox file discovery and download URL generation are covered, which is appropriate given that actual browsing is delegated to the external agent-browser/CDP connection. Minor gaps exist, such as no way to extend a browser's timeout or delete sandbox files.
Maintenance
Related MCP Connectors
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Turn any public website into an MCP server for agents to search, read and navigate.
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
MCP server to assist with JxBrowser development.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceA Playwright-based MCP server that exposes a live browser as a traceable, inspectable, debuggable and controllable execution environment for AI agents.5,660 npm57-
- AlicenseNot gradedqualityBmaintenanceAn MCP Server that enables AI assistants to interact with your local browsers.4,054 npm55MIT
- AlicenseBqualityBmaintenanceA headless, agent-controllable real browser as an MCP server that enables AI agents to navigate, click, fill, eval JavaScript, and take screenshots on localhost and allowed hosts, with no GUI required.277MIT
- FlicenseNot gradedqualityBmaintenanceMCP server that wraps agent-browser to let LLMs control a real browser, providing tools for navigation, interaction, reading page content, accessibility snapshots, screenshots, and session management.1-