Skip to main content
Glama

web-bridge — An MCP tool that lets AI editors control arbitrary static web pages

web-bridge is an MCP Server (a single Node process with dual interfaces) that lets AI editors execute JavaScript, read the console, and simulate clicks / input on static web pages that include client.js. It is suitable for local cross-browser, multi-tab debugging, and can also be deployed to a public server (--transport http, see “Remote Deployment” below).

   AI 编辑器                ┌───────────────────┐              浏览器页面
┌──────────────┐           │    MCP Server     │           ┌──────────────────┐
│  MCP Client  │           │  (Node 单进程)    │           │ <script src=     │
│              │ stdio 或   │ · 接口B: MCP       │  WebSocket │  :3210/client.js">│
│  AI 只到这里  │◄─────────►│   (stdio / http)  │◄──────────►│  client.js       │
└──────────────┘  Streamable│ · 接口A: WebSocket │  接口A     │  (eval 执行/     │
      HTTP(远程)           │ · HTTP /client.js │            │   console 捕获)  │
                           └───────────────────┘            └──────────────────┘

The AI editor and the browser are not directly connected: both connections terminate at the MCP Server (server.js), and the AI indirectly controls the page through tool calls.

Quick Start

cd web-bridge
npm install          # 首次
  1. Include the script in a static web page (any page, any port, cross-origin allowed):

    <script src="http://127.0.0.1:3210/client.js"></script>
  2. Configure the MCP service in your AI editor: replace <REPO>/server.js in mcp.json with the absolute path to this repository, and paste it as described for your editor below. As soon as the editor starts server.js, the WebSocket service (default 127.0.0.1:3210) is ready.

  3. Tell the AI: “Use web-bridge's list_pages to see which pages are connected, then use eval_js to click #btn and read the console.”

Load order note: it doesn't matter if the page loads it first; client.js will automatically reconnect (1s→2s→5s→10s backoff), and the page will reattach automatically after the editor starts. Hub status page: http://127.0.0.1:3210/

MCP Tools

Tool

Parameters

Description

list_pages

List connected pages (pageId, title, URL, connection time)

eval_js

code, optional pageId / timeoutMs

Execute arbitrary JS on the page and return a serialized result; supports await; the last expression is returned automatically, statement blocks can use return; $ / $$ (querySelector / querySelectorAll) are predefined

get_console

optional pageId / limit

Read the page's recent console output and uncaught exceptions

click

selector, optional pageId

Find the element and trigger click() (scrollIntoView first)

type

selector / text, optional pageId

Focus, write text, dispatch input / change events (compatible with contenteditable)

get_text

optional selector (default body), pageId

Read the element's innerText

pageId rule: can be omitted when only one page is connected; when multiple pages are connected and none is specified, the tool returns an error and a list of pages, and the AI will retry with pageId added.

Editor integration

The examples below assume the repository's absolute path is /path/to/web-bridge; replace it as needed.

ZCode / Claude Code (project root .mcp.json, or claude mcp add):

{
  "mcpServers": {
    "web-bridge": {
      "command": "node",
      "args": ["/path/to/web-bridge/server.js"],
      "env": { "PORT": "3210" }
    }
  }
}

Cursor (.cursor/mcp.json): same format as above.

Claude Desktop (claude_desktop_config.json): same format as above.

Command-line arguments: node server.js --port 3210 --host 127.0.0.1 --token <secret> (environment variables PORT / HOST / TOKEN can also be used).

Remote deployment (public server)

The default stdio mode requires the editor to start the process locally; to deploy web-bridge to a public server, switch to HTTP transport mode, and the editor only needs to fill in a url in the MCP configuration:

1. Start it on the server (systemd / pm2 recommended; a token is required on the public internet):

node server.js --transport http --host 0.0.0.0 --port 3210 --token <secret>

2. Editor configuration (Claude Code / Cursor / ZCode, etc., paste it in the original config location):

{
  "mcpServers": {
    "web-bridge": {
      "type": "http",
      "url": "https://your-domain.com/mcp",
      "headers": { "Authorization": "Bearer <secret>" }
    }
  }
}

For a direct connection (no reverse proxy / TLS), set url to http://<服务器IP>:3210/mcp. Note: Claude Desktop only supports local stdio mode, not a remote url.

3. Change the page-side script to point to the server:

<script src="https://your-domain.com/client.js?token=<secret>"></script>

Notes:

  • HTTPS pages can only connect to https/wss (mixed content restriction). It is recommended to use a reverse proxy such as nginx / caddy to terminate TLS and forward to this service; when client.js is served, it automatically detects X-Forwarded-Proto / X-Forwarded-Host and generates the correct wss:// connection address, no extra configuration needed. caddy example (automatic certificate signing):

    your-domain.com {
      reverse_proxy 127.0.0.1:3210
    }
  • After a token is enabled, the /mcp endpoint supports three authentication formats: Authorization: Bearer <secret> (recommended; set headers in the editor configuration), X-Web-Bridge-Token: <secret>, and the url parameter ?token=.

  • The HTTP transport uses the official Streamable HTTP protocol (stateless mode); each request is handled independently and shares the same hub, so multiple editors can connect simultaneously.

  • For public deployment, be sure to: set --token, use TLS, and allow only the needed ports in the firewall.

Security notes

  • By default it listens only on 127.0.0.1. Any web page open on this machine (including third-party sites you browse) can try to connect to the local port — in the default no-token mode, they can receive code sent by the AI and also forge results.

  • In untrusted network environments, or when you want devices on the LAN such as phones to connect (--host 0.0.0.0), be sure to enable --token: in this case, fetching client.js requires ?token=<secret>, and the first WebSocket packet also validates the token.

WebSocket message protocol (internal reference)

The WS messages between the browser and the MCP Server are all JSON text frames; refer to this when maintaining lib/hub.mjs / client.js:

Direction

Message

Fields

Description

Page→Server

hello

role:"page", pageId, url, title, ua, token?

First packet after connecting; disconnected if not received within 5 seconds; when pageId is duplicated (duplicate tab), the new connection replaces the old one

Page→Server

page-info

url, title

Reported after connection, on DOMContentLoaded/load/popstate/hashchange, and via a 5s polling fallback (for SPAs)

Page→Server

console

level, text, ts

Console wrapper and uncaught exception capture, batched with 500ms throttling; hub keeps a ring buffer of 500 messages per page (retained after disconnection)

Page→Server

eval-result

reqId, ok, value?, error?, durationMs

Late responses (already timed out) are ignored

Server→Page

welcome

pageId

hello validation passed

Server→Page

eval

reqId, code, timeoutMs

Code to be executed

Server→Page

error

error

e.g. token error

eval execution conventions (client.js): first wrap as an expression async () => ( code ); on SyntaxError, fall back to a statement block (return allowed); $ / $$ are predefined; timeout is tracked on the hub side (default 30s, max 120s); results are safely serialized as a string preview (Error→stack, DOM→outerHTML summary, circular reference markers, depth ≤ 6, ≤ 50k characters).

Development

  • Testing: npm test (Node e2e: start process + simulated page + call tools over both stdio/HTTP transports); npm run test:browser (Playwright real-browser flow: Chromium loads test/test-page.html, verifies the 6 tools over a real WebSocket; run npx playwright install chromium before the first time). The real-browser flow can also be verified manually by opening the test page.

  • Dependencies: ws (WebSocket), @modelcontextprotocol/sdk (MCP), zod (parameter validation); dev dependency @playwright/test. Node ≥ 18.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Live browser debugging for AI assistants — DOM, console, network via MCP.

  • MCP server for understanding Javascript internals from ECMAScript specification.

  • A paid remote MCP for AI agent browser MCP session, built to return verdicts, receipts, usage logs,

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kirakiray/web-bridge'

If you have feedback or need assistance with the MCP directory API, please join our Discord server