Tabdock
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Tabdockattach to the live page and list its available tools"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tabdock
Tabdock lets MCP clients use the tools of a live web page. The page registers tools through WebMCP, and a small adapter on it dials out to a relay: a remote MCP server with one stable URL that Claude Code, Claude on the web, desktop and phone, or any MCP client adds once. Several people and clients can attach to one page, and the person at the tab approves each, unless the page admits members as observers by policy or that person has minted a Can watch invite, which admits guests as observers in advance.
Why it is different
A page's tools run inside the tab, with the user's own signed-in session and live state, so an agent can work an app that has no API, and your back end gains no endpoint or credential.
The tab dials out to one relay URL, so the browser opens no port and the connector never changes as pages come and go. Several people and their clients share a page with roles: observers call only read-only tools, drivers call the rest, and writes run one at a time. Consequential calls wait for a human, on the page or, where the page allows it, in the calling member's own client. Use cases shows what that makes possible; the comparison with MCP-B's local relay shows where a simpler tool fits better.
Related MCP server: Claude Chrome MCP
How it works
flowchart TB
clients["Clients and their people: Claude Code, Claude on web, desktop and phone, any MCP client"]
relay["Relay: one process, one stable /mcp URL and the /page socket; sign-in, checks, write queue, audit log"]
adapter["Adapter and widget, loaded by the page; checks every call again"]
tools["The page's own tools on document.modelContext"]
operator["Operator: the person at the tab"]
clients -->|"MCP over Streamable HTTP to /mcp, https when public"| relay
adapter -->|"dials out a WebSocket to /page"| relay
adapter -->|"lists and runs"| tools
operator -->|"approves people, answers prompts"| adapterThe relay never runs a tool: it signs clients in and checks and routes each call, and the adapter checks it again before the page's handler runs. It sees calls in plain text, so you run your own. Page origins are allowlisted, tokens and codes never reach a log, and every call is audited; Security has the rest. Concepts explains the parts, the flows, the three dials of roles, consequence and reach, and the words for rooms, state and records.
For a room
Clients see nine fixed tools: list_pages, pair_page, list_page_tools, call_page_tool, detach_page, get_page_state, wait_for_page_state, get_proposal and withdraw_proposal. M6, which arrives in the release after 0.1.0 (CHANGELOG.md), lets one projected tab hold a class or a review. A room needs a relay with a public URL and TABDOCK_INVITES=1, since guests join by invite; in local mode a time-boxed session is a time box only. pnpm demo:m6 runs a whole lesson on this machine, the classroom explainer traces it, and Run a class says what a rehearsal by hand needs; pnpm dev:map serves the canvas map page to try the map profile.
Map and globe pages. A shared tool profile every client drives alike, with a canvas test page to try it on (Map and globe pages).
Images and page state. A tool the page declares returns one still PNG, JPEG or WebP, checked again by the relay and shown only behind the untrusted label; a page publishes a small JSON object any attached client reads or waits on without running a tool (Images and page state).
Proposals and time-boxed sessions. Where a page's
policy.proposalsis'members'or'all', an observer's write becomes a proposal the operator accepts or dismisses in the widget; under the default,'off', it still answersrole_denied. A session of 30 to 240 minutes narrows the policy and shows one QR at a time, and its end closes every live invite and agent token on the page and every attachment they made, earlier ones included (Lessons and reviews).Session records. The widget keeps who did what, saves it as JSON and Markdown only on the operator's click, and
pnpm audit:log --matchholds a saved record to the audit log (The session record).Larger rooms and agent tokens. 40 watching seats apart from the people limit, in a compact roster, a members file read again without a restart, and tokens with which Claude Code or a script watches one page once the operator allows it (Larger rooms); a response ceiling and an optional restart snapshot (Settings for rooms, images and state).
CI checks.
pnpm ci-checkwalks a map page's every stop against local mode, as CI'sci-checkjob does with no secret (Check a page from CI), and another repository can copy it (Copy the CI check).Both sides of a class. Run a class takes a teacher from the relay's settings to a saved record, in order, and Join a shared page is the other side, for a guest with a link, a watcher in a session or a program holding an agent token.
Status
Version 0.1.0, M5's code, is prepared but not yet on npm, so today Tabdock runs from a clone; npx @tabdock/relay and npm install @tabdock/adapter work once 0.1.0 is on npm, and M6's rooms, images and state once the release after it is. Every security requirement in SPEC.md section 9 has automated tests. What has been checked, and where:
Path | Checked in the sandbox | Waiting for the owner's own devices |
Claude Code in local mode | Claude Code 2.1.289 headless, on MCP 2026-07-28 and 2025-11-25, first-class tools included | The header helper on macOS; on Windows, which shell would run one (the PowerShell |
Other MCP clients | The SDK client matrix and the official conformance suite in CI; confirmation in the client with SDK clients | Nothing |
The adapter in a browser | Headless Chromium with the MCP-B polyfill 5.1.0 and 6.0.0 | An hour in a background tab, Energy Saver and laptop sleep |
Claude on web, desktop and phone; QR scans; invites | Public URL mode against a stand-in identity provider, in a phone-sized browser | All of it: none has run live yet |
The container image | Built and smoke-tested | A real host |
M6's rooms, images, proposals and records | The sim page, the canvas map page and the demo in headless Chromium, a stand-in provider, a measured class of 40 on a 512 MiB relay, and Claude Code 2.1.296 with images and an agent token, with no model call | Hosted Claude with images, waits and proposals; a members file and a deploy during a lesson on Fly; a real class |
The open steps are in docs/checklists/ (M3 to M6). WebMCP is an early draft in a Chrome origin trial, so the demo board uses the MCP-B polyfill.
Quick start
You need Node 22.18 or later, pnpm 10 and Claude Code or another MCP client.
git clone https://github.com/PaulMRamirez/tabdock.git
cd tabdock
pnpm install
pnpm devWith no auth settings (in the environment or .env) and outside production, the relay runs in local mode: loopback only, one user, and an owner token in a private file outside the checkout. On macOS and Linux pnpm dev prints a claude mcp add-json line whose header helper reads that token whenever Claude Code connects, so neither the command nor Claude Code's settings hold it. Paste it and check with claude mcp list (never claude mcp get, which prints stored headers). Open the board link it printed, click Connect, ask Claude to pair with the code in the widget, and click Allow as driver. Quick start has the details.
Your own page
import { attach } from '@tabdock/adapter';
const notes: string[] = [];
// A WebMCP runtime must already be installed: Chrome's own, or the MCP-B polyfill.
await document.modelContext?.registerTool({
name: 'add_note',
title: 'Add note',
description: 'Add a note to the page and return how many there are.',
inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
annotations: { readOnlyHint: false },
execute: async (input) => {
const text = (input as { text?: unknown } | null)?.text;
if (typeof text !== 'string') return 'text must be a string';
return { count: notes.push(text) };
},
});
await document.modelContext?.registerTool({
name: 'clear_notes',
title: 'Clear notes',
description: 'Remove every note. This cannot be undone.',
inputSchema: { type: 'object', properties: {} },
annotations: { readOnlyHint: false, consequentialHint: true },
execute: async () => ({ removed: notes.splice(0).length }),
});
// The only control handle: keep it private.
const dock = attach({
relay: 'ws://127.0.0.1:8787/page',
policy: { consequentialTools: ['clear_notes'] },
});That URL serves a page on the relay's own machine, and by default the relay admits http and https pages on localhost, 127.0.0.1 and [::1]; only hosted mode takes wss://<host>/page from pages elsewhere, on origins it lists. TypeScript knows no document.modelContext, so the snippet needs the short declaration in Add to your app.
A tool prompts the operator when its consequentialHint is true or policy.consequentialTools names it. Set both: MCP-B 5.x and Chrome 153 drop the hint, and there, on a page whose tools carry annotations, a list that names no tool makes every tool that is not read-only prompt (ADRs 0002 and 0034). A page that wants no prompts says consequential: 'allow'. Until 0.1.0 is on npm, take the adapter from a clone: pnpm release:pack packs installable tarballs into dist/packages, labelled 0.1.0 but built from the clone's checkout, and pnpm --filter @tabdock/adapter build writes the script-tag file. Add to your app has the rest.
Claude on the web, desktop and phone
Hosted Claude reaches a connector from the cloud, so a relay on loopback cannot serve it. Public URL mode puts the relay behind a tunnel with a fixed https name and signs people in through an OAuth provider that meets SPEC.md section 7, plus a confidential client for the QR page at /pair; pnpm dev:public names the six settings. Pages then still attach only from the relay's machine; hosted mode, behind a host edge, takes them from anywhere on listed origins. In Claude, add https://<relay>/mcp under Customize, Connectors, +, Add custom connector and sign in; Claude Code uses claude mcp add --transport http --scope user tabdock https://<relay>/mcp, then claude mcp login tabdock. See Connect clients and Run a relay.
Docs
The guide is for people using Tabdock; its Where to start table gives a reading order for each task, from a first look to running a class.
For contributors: docs/develop.md (every command), SPEC.md (the source of truth), docs/adr/ (the decisions), docs/threat-model.md (each boundary and its tests), docs/mcp-b-comparison.md, docs/tour/ (the build's history, a milestone a page), docs/deploy.md (the reference deployment), docs/release.md, CHANGELOG.md, .env.example (every setting), and the READMEs of packages/adapter, packages/relay, packages/protocol, packages/sim-page, apps/demo, apps/site, tests/e2e, tests/map-page, tests/ci-check and tests/mcpb6. pnpm site:build builds the demo board, the tour and the guide into a static site for GitHub Pages, not yet published; until it is, run the board with pnpm dev.
Licence
This server cannot be deployed
Maintenance
Related MCP Connectors
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Build your own tools from chat: design, test and host them on a shareable MCP server URL.
1MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn 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.8 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients like Claude Desktop to automate and interact with claude.ai via a Chrome extension and WebSocket relay.9GPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables CLI coding agents to interact with your live browser tabs via MCP, using your real sessions and cookies without a sandbox.MIT
- FlicenseAqualityBmaintenanceLets an AI share the same live browser tab as a person, receiving the user's Alt+click target and enabling the AI to inspect, click, fill, type, navigate, or otherwise operate on that real page. It runs locally and pairs with the browser extension to bridge the user's page to the MCP client.13-