Skip to main content
Glama

简体中文

Web Bridge — Browser Automation MCP Server (dsh plugin)

Web Bridge is an automation MCP server that uses a real browser. It gives agents a browser's eyes and hands: open web pages, read page structure, click, fill forms, take screenshots, and execute scripts. Its core mechanism is the accessibility-tree snapshot — rendering the page into a structured text tree with numbered interactive elements, so agents can interact with pages precisely without a vision model.

  • Language: TypeScript (Node.js ≥ 20), communicating over the MCP protocol (stdio transport)

  • Browser engines: Chromium / Firefox / WebKit (Chromium by default)

  • Tool count: 22, all named with the web_ prefix

Features

  • Snapshot driven: web_snapshot produces an accessibility tree with reference numbers (ref), so elements can be clicked/filled precisely without guessing selectors

  • Real interactions: click, double-click, right-click, key combos, form filling, dropdown selection, hover, scroll, keyboard input

  • Visual capabilities: viewport / full-page / element screenshots (PNG/JPEG), returned to the caller or saved locally

  • Script execution: run JS in the page context; results are sanitized (circular references, BigInt, NaN, etc. safely converted)

  • Multi-tab: create, list, switch, and close tabs; popups are captured automatically

  • Fine-grained waiting: wait by load state / element state / URL match / fixed duration

  • Session management: lazy browser startup, web_shutdown releases resources, automatic cleanup on disconnect

Related MCP server: mcp-server-agent-browser

Installation

npm install          # install dependencies
npm run build        # compile to dist/
npx playwright install chromium   # install browser engine (required on first use)

Firefox / WebKit engines are also supported: npx playwright install firefox, switchable via configuration.

Quick Start

Option A: generic MCP client (stdio)

{
  "mcpServers": {
    "web-bridge": {
      "command": "node",
      "args": ["D:/path/to/browser-automation/dist/index.js"]
    }
  }
}

Option B: command line verification

node dist/index.js --help        # view usage
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}' | node dist/index.js

Option C: load as a dsh plugin (see next section)

Installing in DSH

dsh plugin --profile demo add github:JohnXu22786/browser-automation

Adds this plugin to the dsh demo profile from github:JohnXu22786/browser-automation. See the next section for authorization, loading, and lifecycle details.

Cordis bundle (dsh.bundle)

As an alternative to the dsh-plugin.json MCP-server manifest, the repo ships a Cordis bundle for hosts that consume dsh.bundle manifests: package.json declares dsh.bundle.patch → cordis.patch.yml, and index.js is the bridge a dsh profile loads. The bridge spawns the built MCP server (node dist/index.js) over stdio, performs the MCP handshake, and re-exposes the 22 web_* tools to the harness — the server itself is untouched.

In a source checkout dist/ is gitignored, so the bridge runs npm run build once on first load; installed npm packages ship dist/ in their files list and need no build step. Profile-level settings map to the same WEB_BRIDGE_* environment variables described below.

dsh Plugin Integration

This plugin follows the dsh "everything is a plugin" convention and describes itself via the dsh-plugin.json manifest in the root directory:

Field

Value

Meaning

id

dsh.web-bridge

Unique plugin identifier

kind

mcp-server

Plugin type: provides an MCP tool set

entry

dist/index.js

Entry file (run with node dist/index.js)

transport

stdio

Transport: MCP clients communicate with the plugin via stdin/stdout

config.envPrefix

WEB_BRIDGE_

Plugin config is injected via environment variables with this prefix

tools

22 items

Tool list exposed by the plugin (name + title)

Harness loading flow (the dsh runtime integrates the plugin as follows):

  1. Scan the plugin directory, read dsh-plugin.json, validate kind / entry / runtime;

  2. Check that the Node version satisfies runtime.minVersion;

  3. Spawn the plugin process with spawn('node', [entry]), connecting stdin/stdout to the MCP protocol (JSON-RPC 2.0, line-delimited);

  4. Map harness config to environment variables injected into the child process according to config.envPrefix (e.g. actionTimeout → WEB_BRIDGE_ACTION_TIMEOUT);

  5. After the MCP client handshake (initialize / notifications/initialized / tools/list), the tools in the tools list enter the agent's tool set automatically; each tool's schema and permission description are provided by the plugin in the tools/list response;

  6. When the session ends or the process exits, the harness closes stdin and the plugin recycles the browser and exits automatically (see "Lifecycle").

Any standard MCP client (that does not support manifest) can also connect directly as in Option A.

Configuration

Priority: defaults < config file (--config or WEB_BRIDGE_CONFIG) < environment variables.

Environment variables (prefix WEB_BRIDGE_)

Variable

Default

Description

WEB_BRIDGE_BROWSER

chromium

Engine: chromium / firefox / webkit

WEB_BRIDGE_HEADLESS

true

Headless mode

WEB_BRIDGE_VIEWPORT

1280x720

Viewport size, e.g. 1440x900

WEB_BRIDGE_EXECUTABLE

—

Custom browser executable path

WEB_BRIDGE_USER_DATA_DIR

—

User data directory (persistent context; login state survives across sessions)

WEB_BRIDGE_PROXY

—

Proxy address, e.g. http://proxy:3128

WEB_BRIDGE_LOCALE / WEB_BRIDGE_TIMEZONE

—

Locale and browser timezone

WEB_BRIDGE_USER_AGENT

—

Custom User-Agent

WEB_BRIDGE_IGNORE_HTTPS_ERRORS

false

Ignore certificate errors (debug only)

WEB_BRIDGE_SANDBOX

true

Browser sandbox; set to false when no sandbox in container

WEB_BRIDGE_PERMISSIONS

—

Permissions granted to the context, comma-separated (e.g. geolocation,clipboard-read)

WEB_BRIDGE_ACTION_TIMEOUT

10000

Per-action timeout (ms, 0 = unlimited)

WEB_BRIDGE_NAV_TIMEOUT

60000

Navigation timeout (ms, 0 = unlimited)

WEB_BRIDGE_SETTLE_MS

500

Wait for async tasks to settle after an action (ms)

WEB_BRIDGE_STORAGE_STATE

—

Session restore file path (non-persistent mode only)

WEB_BRIDGE_TEST_ID_ATTR

data-testid

Attribute name used by the testid= selector

WEB_BRIDGE_CONFIG

—

Config file path

Config file

{
  "browser": { "name": "chromium", "headless": true, "viewport": { "width": 1280, "height": 720 } },
  "context": { "ignoreHTTPSErrors": false, "permissions": ["geolocation"] },
  "timeouts": { "action": 10000, "navigation": 60000, "settle": 500 },
  "sandbox": true,
  "testIdAttribute": "data-testid"
}

Start: node dist/index.js --config web-bridge.config.json.

Tool List

Full tool descriptions and permission notes are returned by MCP tools/list; key points are listed here.

Navigation

Tool

Description

Permission impact

web_open

Open a URL (supports http/https/file/data), optional wait strategy

Makes real network requests and renders the page

web_back / web_forward

History back / forward

Triggers navigation, may reload the page

web_refresh

Refresh current page

Re-requests all page resources

Interaction

Tool

Description

Permission impact

web_click

Click (ref/selector; supports button, double-click, modifier keys)

Dispatches mouse events, may trigger navigation/submit/scripts

web_fill

Clear and fill an input/textarea

Modifies form data, may trigger validation

web_type

Type keystrokes into the focused element

Sends keyboard events

web_press

Press keys (Enter, Control+a, etc.)

Sends keyboard events

web_select

Dropdown selection (by value or label)

Modifies form data

web_hover

Hover (triggers menus/tooltips)

Dispatches mouse-move events

web_scroll

Scroll page/element (up/down/left/right/top/bottom/into_view)

Only changes scroll position

Observation

Tool

Description

Permission impact

web_snapshot

Generate an accessibility-tree snapshot (ref numbers + state annotations)

Read-only, no network requests

web_screenshot

Screenshot (PNG/JPEG, viewport/full-page/element, can save locally)

Read-only page; save_to writes to caller-specified path

web_status

Session status: running state, tabs, current page

Read-only

Scripting and viewport

Tool

Description

Permission impact

web_evaluate

Run JS in the page context, returns sanitized result

High risk: can read/write page data, cookies, login state; can make network requests

web_resize

Resize the viewport

Only changes the rendered viewport

Tabs and session

Tool

Description

Permission impact

web_tab_new

Create a new tab (optional URL, optional activation)

Creates a tab; may make network requests

web_tab_list

List all tabs

Read-only

web_tab_switch

Switch the active tab

Read-only

web_tab_close

Close a tab (current by default)

Closes the tab; unsaved data is lost

web_wait

Wait: load / networkidle / selector / url / sleep

Read-only

web_shutdown

Close the browser and clean up the session

Closes the browser process; login state is lost

Snapshot and ref Mechanism

web_snapshot renders the page as an indented structured text, for example:

title: Demo Home
url: http://localhost:8080/index.html
tree:
  banner
    navigation
      [1] link "首页"
      [2] link "文档"
  main
    heading "欢迎来到演示站点" (level: 1)
    form
      [3] textbox "用户名" (placeholder: "请输入用户名")
      [4] checkbox "记住我" (unchecked)
      [5] button "提交表单"
  • [n] is a reference number (ref), assigned only to interactive elements (buttons/links/inputs/dropdowns/checkboxes, etc.);

  • Subsequent web_click / web_fill / web_select calls can locate elements by ref (ref: 3), or by selector (selector: "#username", text=keyword, testid=value);

  • The snapshot shows states: (checked/unchecked), (disabled), (selected), (expanded/collapsed), (password), (value: ...), (placeholder: ...);

  • The value of password boxes is never shown;

  • The selector parameter snapshots only a subtree, max_depth limits depth, and max_nodes limits the total node count (protects against token bombs).

ref is a positional path (determined by the DOM structure): after navigation, old refs automatically become invalid (reporting an error and asking for a re-snapshot); if the page script adds/removes DOM without navigation, old refs may resolve to other elements — re-snapshot if an operation fails.

Wait Strategies

web_open's wait_until: commit (request sent) → domcontentloaded (DOM ready) → load (resources loaded) → networkidle (network idle). Default is load.

Actions wait for settleMs (500ms) by default so async tasks (navigation, requests) settle.

Permissions and Security Notes

  • This plugin is not a security boundary. web_evaluate can run arbitrary scripts, web_open can access any site, and save_to can write to any path — only use it in trusted environments, and configure per-tool permissions at the harness layer.

  • Prefer least privilege: use web_snapshot for routine observation (zero network requests, zero side effects), web_screenshot when visual confirmation is needed, and only consider web_evaluate as a last resort.

  • The browser process is managed by the plugin: client disconnect, web_shutdown, and SIGINT/SIGTERM all recycle the browser process.

  • Headless mode is on by default; set WEB_BRIDGE_HEADLESS=false for visual debugging.

Known Limitations

  • Shadow DOM / iframe content is not in snapshots: the walker only covers the regular DOM subtree of the main document; if the page hosts interactive elements inside shadow DOM, use web_evaluate or the page's own test hooks (testid=).

  • ref is a positional path: see "Snapshot and ref Mechanism" above.

  • Popups activate automatically: new tabs opened via target=_blank etc. automatically become the active page (the agent's intuitive click behavior); use web_tab_list + web_tab_switch to get other tabs back.

  • The statement-sequence form of web_evaluate (multi-statement including function declarations) executes for side effects and returns no value; expression and function forms return results. Use the async function form for async logic.

Development and Testing

npm run build          # compile with tsc to dist/
npm test               # all tests (unit + browser integration + MCP protocol chain)
npm run test:unit      # unit tests only (config/tool functions/snapshot format/walker)
npm run test:integration  # browser integration tests only

Test coverage: config parsing, walker behavior, snapshot format, result sanitization, 16+ real browser integration scenarios (navigation/click/form fill/screenshot/tabs/history/wait/scroll/failure paths), and a real stdio process chain (including browser-recycle assertions after disconnect).

Project Structure

src/
  index.ts       entry: CLI args, config loading, startup of the MCP server
  config.ts      config (three-level default/file/env merge and validation)
  server.ts      MCP server assembly, error mapping, lifecycle cleanup
  browser.ts     browser session: lazy start / tabs / ref table / shutdown
  walker.ts      page-side accessibility-tree walker (single source shared by Node tests and the page)
  snapshot.ts    snapshot orchestration, ref assignment, text formatting
  scripting.ts   script execution and result sanitization
  locators.ts    ref/selector resolution
  util.ts        argument validation, URL validation, timeout error classification
  tools/         22 tool implementations (grouped by responsibility)
  registry.ts    tool registry
index.js          dsh Cordis bundle bridge (spawns dist/index.js over stdio)
cordis.patch.yml  dsh bundle install row (id: web-bridge, name: web-bridge-mcp)
dsh-plugin.json  plugin manifest (see README for dsh harness integration)
test/           tests and fixtures

License

MIT

Available Tools

22 tools
web_back后退A

在活动标签页中后退到上一页历史记录。

权限说明:触发浏览器历史导航,可能重新加载页面。

Inputs: timeout, wait_until.

web_click点击A

点击页面元素。目标可以是快照引用(推荐,ref 编号见最近一次 web_snapshot 输出)或选择器。支持鼠标按钮、双击与修饰键组合。

权限说明:向页面派发鼠标事件,可能触发跳转、表单提交或脚本副作用。

Inputs: ref, button, timeout, selector, +2 more.

web_evaluate执行脚本A

在页面上下文中执行 JavaScript 并返回结果。支持三种形态:函数表达式(function / async function / 箭头函数,以 arg 为参数调用并返回其返回值);表达式(返回求值结果);语句序列(let/var 多语句,返回最后一个表达式的值;含函数声明的语句序列按副作用执行,不返回结果,如需返回值请改用块箭头函数 + return)。返回值为 JSON 安全结构(undefined→null,循环引用→[Circular],NaN/Infinity→字符串,超长内容截断)。异步逻辑请使用 async 函数形态。

权限说明:高危操作:在页面内执行任意 JavaScript,可读取/修改页面数据、发起网络请求、获取 cookie 与登录态。仅在信任的页面上使用。

Inputs: script (required), arg.

web_fill填写输入A

清空并填写输入框/文本域/可编辑区域。目标是快照引用或选择器。填写后触发 input 与 change 事件。

权限说明:修改页面表单数据,可能触发校验与提交逻辑。

Inputs: value (required), ref, timeout, selector.

web_forward前进A

在活动标签页中前进到下一页历史记录。

权限说明:触发浏览器历史导航,可能重新加载页面。

Inputs: timeout, wait_until.

web_hover悬停A

把鼠标移动到元素上方(常用于触发悬停菜单与提示)。

权限说明:派发鼠标移动事件,可能触发 CSS 悬停效果。

Inputs: ref, timeout, selector.

web_open打开页面A

在活动标签页中导航到指定 URL(无标签页时自动新建)。可选用更细的等待策略控制返回时机,适用于需要等待单页应用渲染完成或网络请求全部结束的场景。

权限说明:发起真实网络请求并渲染目标页面;请确保目标站点允许自动化访问。

Inputs: url (required), timeout, wait_until.

web_press按键A

按下键盘按键(如 Enter、Escape、Tab、Control+a)。可先用 ref/selector 聚焦目标元素;未提供时作用于当前聚焦元素。

权限说明:发送键盘事件到当前页面。

Inputs: key (required), ref, timeout, selector.

web_refresh刷新B

重新加载活动标签页。

权限说明:重新请求当前页面全部资源。

Inputs: timeout, wait_until.

web_resize调整视口A

调整浏览器视口尺寸(CSS 像素)。

权限说明:只改变渲染视口,不产生网络请求。

Inputs: width (required), height (required).

web_screenshot截图A

截取当前页面(视口或整页)或指定元素的图像,作为 MCP image 内容返回;可同时保存到本地文件。适合需要视觉确认的场合;日常结构化观察请优先使用 web_snapshot。

权限说明:只读页面内容;若提供 save_to 参数会向本地文件系统写入文件(路径由调用方指定)。

Inputs: format, quality, save_to, timeout, +2 more.

web_scroll滚动A

滚动页面或元素。direction=into_view 时将元素滚动到视野中央;提供 selector 时在元素内部滚动(或先将其带入视野);未提供 selector 时滚动整个页面。

权限说明:仅改变滚动位置,不产生网络请求。

Inputs: direction (required), amount, timeout, selector.

web_select下拉选择A

在下拉列表(select)中选择一个或多个选项,可按 value 或按显示文本 label 选择。

权限说明:修改页面表单数据。

Inputs: ref, label, value, timeout, +1 more.

web_shutdown关闭浏览器A

关闭浏览器实例并清理全部标签页与引用。之后任何操作都会自动重新启动浏览器。用于释放系统资源或清除会话痕迹。

权限说明:关闭浏览器进程,当前会话的未保存状态(登录态等)将丢失。

Inputs: no named parameters.

web_snapshot页面快照A

生成当前页面的无障碍树快照:包含标题、URL 与带引用编号(ref)的元素树。交互元素(按钮/链接/输入框等)带 [编号] 前缀,后续 web_click / web_fill 等工具可用该编号定位。快照只包含结构化信息,不包含像素图像。

权限说明:只读操作,不产生网络请求;快照内容仅返回给调用方。

Inputs: selector, max_depth, max_nodes.

web_status会话状态A

报告浏览器会话状态:是否运行、标签页列表(含 URL 与标题)、当前活动标签页。

权限说明:只读操作。

Inputs: no named parameters.

web_tab_close关闭标签页A

关闭标签页(默认关闭当前活动标签页)。关闭当前页后自动切换到剩余的第一个标签页。

权限说明:关闭浏览器标签页,未保存的表单数据将丢失。

Inputs: id.

web_tab_list标签页列表A

列出全部标签页及其 URL 与标题。

权限说明:只读操作。

Inputs: no named parameters.

web_tab_new新建标签页B

新建一个标签页,可带初始 URL;默认立即激活。

权限说明:新建浏览器标签页并可能发起网络请求。

Inputs: url, timeout, activate_tab.

web_tab_switch切换标签页A

切换活动标签页,后续动作作用到该标签页。

权限说明:只读操作。

Inputs: id (required).

web_type键入文本A

向当前聚焦元素逐键输入文本,可模拟真实输入节奏。

权限说明:发送键盘事件到当前页面。

Inputs: text (required), delay.

web_wait等待A

按条件等待页面达到预期状态:页面加载完成(load)、网络空闲(networkidle)、元素出现/消失(selector)、URL 匹配(url)、或固定时长(sleep)。适合在页面渲染较慢或导航后需要同步时使用。

权限说明:只读操作(等待本身不产生网络请求)。

Inputs: condition (required), ms, state, timeout, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 22 tools

    Disambiguation4/5

    Each tool has a distinct purpose, but web_status and web_tab_list both report tab information, creating potential confusion. All other tools are clearly separated by their actions (navigation, input, inspection, tab management).

    Naming Consistency5/5

    All tools use the consistent 'web_' prefix with snake_case, and action-oriented names like web_open, web_click, and web_tab_new. The tab management group follows a clear 'tab'_verb pattern, making the naming highly predictable.

    Tool Count4/5

    At 22 tools, the set is slightly above the ideal range, but the breadth of browser automation justifies it: navigation, interaction, inspection, tab management, and session control each have dedicated tools. The count is borderline heavy but not bloated.

    Completeness5/5

    The toolset covers the full browser automation lifecycle: navigation, page interaction, content extraction, tab management, waiting, and shutdown. Missing niche features like file upload or frame switching can be handled via web_evaluate, so there are no critical gaps.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Agent-native browser control MCP server that enables AI agents to browse and interact with web pages via accessibility tree snapshots and ref ID-based commands.
      15
      2
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      MCP 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
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      A zero-dependency MCP server that drives a real Chrome browser through a companion extension, enabling AI agents to automate real user sessions with trusted input events, compact accessibility-tree snapshots, and 14 tools for navigation, interaction, scripting, and inspection.
      374 npm
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      MCP server that lets AI agents drive the locally installed Chrome or Edge, opening pages, taking compact accessibility-tree snapshots with @e references, and clicking, typing, scrolling, or capturing screenshots. It also exposes multi-account and cross-channel tab switching, tab sync rules, and ad-block/perf statistics.
      MIT