Skip to main content
Glama

orca-webmcp

An MCP server that exposes the WebMCP tools of pages open in Orca's embedded browser to any MCP client — Claude Code, Codex, Cursor, or an agent running inside an Orca terminal.

No Chrome extension, no browser flag, no WebSocket bridge, no external browser.

Why

The existing way to hand WebMCP tools to a desktop agent is the WebMCP Bridge Chrome extension, which needs:

  • a real Chrome install with chrome://flags/#enable-webmcp-testing enabled,

  • the extension installed and manually activated per tab,

  • navigator.modelContextTesting, which only exists behind that flag,

  • a WebSocket server holding 127.0.0.1:12315.

Orca already ships a Chromium browser and an orca eval command that runs JavaScript in a tab. That is everything the job needs: document.modelContext exposes getTools() and executeTool() directly, so tools can be read and invoked without any of the machinery above.

Related MCP server: @teatak/mcp-server-browser

How it works

Orca tab (page registers tools on document.modelContext)
  ↑ orca eval --page <id> --expression "...getTools() / executeTool()..."
orca-webmcp  (this MCP server)
  ↑ stdio / MCP
Any MCP client

On every tools/list the server runs orca tab list, evaluates document.modelContext.getTools() in each tab, and republishes the results as MCP tools named tab{index}_{toolName}. A tools/call resolves that name back to a page id and runs executeTool there.

Tabs without WebMCP contribute nothing and never fail the listing.

Requirements

  • Node.js 18+

  • The Orca app running, with its CLI on PATH (or set ORCA_BIN)

  • A page that exposes document.modelContext — natively, or via @mcp-b/webmcp-polyfill

Install

npm install

Register with a client

# Claude Code
claude mcp add --scope user --transport stdio orca-webmcp -- node /absolute/path/to/src/index.js
// Cursor — .cursor/mcp.json
{ "mcpServers": { "orca-webmcp": { "command": "node", "args": ["/absolute/path/to/src/index.js"] } } }

Configuration

Variable

Default

Purpose

ORCA_BIN

orca

Path to the Orca CLI

ORCA_WEBMCP_WORKTREE

(all tabs)

Scope tools to one worktree's tabs, e.g. active

ORCA_WEBMCP_TIMEOUT

30000

Per-command timeout in ms

Try it

orca tab create --url https://googlechromelabs.github.io/webmcp-tools/demos/pizza-maker/

Then ask your agent to build a pizza. The tools appear as tab0_add_topping, tab0_set_pizza_style, and so on.

In-page agent (no model API key)

The same repo ships a floating chat panel that runs inside the page, so a user can drive a WebMCP site without a terminal, an extension, or a model API key. The brain is a live Claude Code session held open by the bridge, authenticated by the operator's existing login.

Widget in the page  ──HTTP──▶  agent-server  ──▶  live Claude Code session
       ▲                                                     │
       └──────── orca eval ◀── orca-webmcp ◀────── MCP ──────┘

The session stays open per tab. Spawning a process per prompt put ~10-12s of startup in front of ~3s of work; an open session pays that once. Measured end to end through the panel: 41s per prompt before, ~10s after the first.

The turn Claude Code runs already has this project's MCP server registered, so it can call the very tools the page exposes — the request goes out through HTTP and comes back in through the browser.

npm run agent                       # bridge on 127.0.0.1:8765
orca tab create --url https://googlechromelabs.github.io/webmcp-tools/demos/pizza-maker/
npm run inject -- --url pizza-maker # or --page <id>, or --all

The panel lists the page's tools and refreshes on toolchange. Each browser tab keeps its own conversation, so follow-up prompts have context.

Orca's toolbar cannot be extended by third parties, so there is no button to click. Instead, run the watcher and the panel mounts itself on every http(s) tab, surviving navigation:

npm run watch

Variable

Default

Purpose

ORCA_AGENT_PORT

8765

Bridge port

ORCA_AGENT_IDLE_MS

900000

Close a tab's session after this much silence

Why the bridge is not simply open

The bridge is a listening port on the operator's machine, and every page loaded in the browser can reach 127.0.0.1. Two things keep a hostile page from using it:

A per-run token. The server mints a secret at startup and writes it to $TMPDIR/orca-webmcp-token with mode 0600. inject.js and watch.js read it and bake it into the panel they mount, so a page the operator injected can call /chat and a drive-by page gets a 403.

A tool allowlist. The session is restricted to mcp__orca-webmcp__*. Even a request that somehow carried a valid token can only call WebMCP tools in tabs the operator already opened — not read files, not run commands.

The trailing __* is load-bearing. mcp__orca-webmcp on its own matches no tool, and a turn that can call nothing answers as though the page had never registered any.

Nothing about the operator's Claude subscription is stored or transmitted by this project: the Agent SDK reads Claude Code's own credentials, and the bridge only ever sees prompt text and the session's reply.

Making your own page reachable

Orca's Chromium does not ship WebMCP, so document.modelContext only exists on a page that brings it. Load the polyfill and your tools register everywhere — Orca, Chrome with the flag, Chrome without it:

npm i @mcp-b/webmcp-polyfill
import { initializeWebMCPPolyfill } from '@mcp-b/webmcp-polyfill';

initializeWebMCPPolyfill(); // no-op where the browser already provides the API

document.modelContext.registerTool({
  name: 'make_offer',
  description: 'Offer a price for the listing. The seller accepts or counters.',
  inputSchema: {
    type: 'object',
    properties: { amount: { type: 'number', description: 'Offer in US dollars.' } },
    required: ['amount'],
  },
  async execute({ amount }) {
    const verdict = evaluateOffer(amount); // your logic, your rules, your secrets
    return { content: [{ type: 'text', text: verdict }] };
  },
});

The polyfill costs nothing where it is not needed — it returns early when document.modelContext already exists — and without it a page that guards its registration is silently invisible to every agent:

if (document.modelContext) {          // undefined in Orca
  document.modelContext.registerTool(...); // never runs, no tools, no error
}

That guard is why most of the Chrome Labs demos expose nothing here. They are showcases for the native API written for developers running the flag, not sites built to work on a stranger's machine — a distinction worth keeping when borrowing their structure.

Keep the polyfill until native support is the common case. The API moved from navigator.modelContext to document.modelContext during 2026, and the npm package tracks changes like that; a vendored copy does not.

Registration and consumption are separate

document.modelContext is where a page registers tools. Reading and invoking them is a different surface, and which one is available depends on the browser:

Surface

Purpose

Where it exists

document.modelContext.registerTool

a page publishes a tool

native, or via the polyfill

document.modelContext.getTools / executeTool

an agent reads and calls tools

alongside the above — this is what this project uses

navigator.modelContextTesting

the testing consumer API

only behind chrome://flags/#enable-webmcp-testing

Extensions built against navigator.modelContextTesting need that flag and a Chrome new enough to have it. Reading getTools() off document.modelContext needs neither, which is why this project works in a browser that has no WebMCP support of its own.

Known limits

  • Tool names are keyed by tab index, which shifts when tabs are opened or closed. The mapping is rebuilt on every tools/list and refreshed on a miss, but a call issued against a stale listing can land on a different tab.

  • Tool changes are not pushed. The server has no tools/list_changed notification yet, so a client sees new tools on its next listing.

  • Orca's Chromium (Chrome 150 as of app 1.4.190) does not ship WebMCP natively; pages must load the polyfill themselves. All Chrome Labs demos do.

Maintenance

ActivityMaintained
ResponsivenessNo issues

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

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP bridge server that allows AI tools to call functions and execute code directly within a web browser tab. It enables developers to register custom browser-side tools with full access to the DOM, web APIs, and local application state.
    16
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that runs in the browser, letting web pages register custom tools and prompts and expose them to an MCP client over WebSocket. Enables agents to drive UI, call page-scoped APIs, and get human-in-the-loop confirmation.
    15
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables websites to expose JavaScript functions as MCP tools, allowing AI agents to interact with the browser environment via a protocol and Chrome extension.
    1,093

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/FrancoDuran23/orca_webMCP'

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