tabgrant
Allows AI agents to access a user-granted tab in the Brave browser, with capabilities for reading page snapshots, highlighting, scrolling, and same-origin navigation under a short-lived lease.
Click on "Install 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., "@tabgrantRead the current tab and summarize the main points."
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.
TabGrant
User-granted, local-first access to real browser sessions for AI agents.
TabGrant connects an MCP client to a tab in the user's existing Chromium-based browser without copying the browser profile or exposing every open tab. The agent requests access, the user grants the current tab from the extension popup, and a short-lived lease limits what that exact client task can do.
Developer Preview
The source checkout is usable for development and evaluation on macOS and Linux. It currently includes:
a local broker daemon using a Unix-domain socket on macOS/Linux or a named pipe on Windows;
a Manifest V3 extension and Chrome Native Messaging host;
explicit grant, visible active state, and revoke controls for one current tab;
nine MCP tools for grant lifecycle, bounded page reading, highlighting, scrolling, and same-origin navigation;
per-connection random broker sessions: a second connection with the same client/task identity cannot see or reuse the first connection's lease, and an agent disconnect revokes its pending requests and leases;
browser-key pairing: every shared-HMAC hello is initially an agent, while the extension must pass broker-owned macOS/Linux user-presence approval and prove a non-extractable P-256 key before receiving browser authority;
document-, origin-, scope-, expiry-, idle-, use-, concurrency-, rate-, and UTF-8 output-bound leases;
domain-separated IPC, capability, and audit keys;
redacted, HMAC-authenticated audit segments plus an ordered signed manifest that are fully verified at startup;
a persistent kill marker that blocks broker restart until a local
tabgrant enable --confirm;a security gate that rejects broad extension permissions and forbidden browser authorities.
This is not a stable or audited release. There is no npm or browser-store release yet, the protocol may change, and real-browser/client compatibility has not been certified. Use a disposable browser profile and synthetic or non-sensitive accounts. See Current verification boundary.
Related MCP server: open-browser-control
Quickstart from source
1. Build TabGrant
Requirements: macOS or Linux, Node.js 20.19.0 or newer, Corepack, and a current Chromium-based browser. Automated validation currently targets Chrome for Testing 152.0.7977.64; other browser versions and channels are not yet certified.
git clone https://github.com/SnakeLil/tabgrant.git
cd tabgrant
corepack enable
pnpm install --frozen-lockfile
pnpm buildThe extension is built at apps/extension/dist. The broker CLI is built at
apps/broker/dist/cli.js.
2. Load the extension
Open the extensions page for your browser, enable Developer mode, choose Load
unpacked, and select the absolute path to apps/extension/dist.
Browser | Extensions page | Installer channel |
Chrome |
|
|
Chrome for Testing |
|
|
Chromium |
|
|
Edge |
|
|
Brave |
|
|
The chrome-for-testing channel is primarily for disposable automated testing.
Chrome for Testing 146 and newer use a Native Messaging host directory distinct
from branded Chrome;
the installer implements that separate mapping.
Copy the 32-character extension ID shown on the extensions page.
3. Install the native messaging host
Set the channel to the browser you loaded in step 2:
node apps/broker/dist/cli.js install \
--extension-id YOUR_32_CHARACTER_EXTENSION_ID \
--browser chromeInstallation is create-only and refuses to overwrite any existing manifest. To
change the extension ID, native-host path, or channel manifest, first run the
matching uninstall command and inspect its result, then install again. A missing
manifest makes uninstall an idempotent no-op.
On macOS and Linux, the manifest points to a unique owner-only launcher created
beside it with mode 0700. The launcher records and executes the absolute Node.js
runtime and native-host entry paths that were verified during installation. This
keeps a GUI-launched browser independent of shell initialization and nvm's
PATH. If that Node installation is moved or removed, run uninstall, rebuild
with the intended Node runtime, and run install again.
Reload the extension. Its popup creates a non-extractable P-256 signing key in
IndexedDB and shows a session-only, 160-bit pairing code. Select Pair this extension.
The broker opens its production user-presence UI: osascript on macOS or
zenity on Linux. Compare the full code, extension ID, browser-instance ID, and
key fingerprint shown by the popup/system prompt, then approve in the OS prompt.
Missing UI tooling, cancellation, or timeout denies pairing. Production pairing
currently fails closed on Windows and is unsupported there.
The code is removed from extension session storage after every attempt, whether
approved, denied, or timed out; reopening the unpaired popup produces a new code.
The broker handles the code only for the live prompt and persists no pairing
state before proof succeeds. Dynamic prompt data is sent to osascript or
zenity over stdin, not exposed in process argv. After approval, the broker creates a
fresh 30-second challenge on that same connection. Only a signature from the
extension's non-extractable key persists browser-pairing.json with owner-only
0600 permissions on supported Unix platforms and upgrades the connection from
agent to browser authority. A failed signature consumes the challenge and leaves
no pairing record. The extension serializes startup authentication and popup
pairing on the exact Native Messaging port. The broker allows one authentication
transition or live challenge per connection; competing starts/pairs fail busy,
and an unknown challenge ID cannot consume the valid challenge. The native host
only relays messages and never receives the
private key. The native host and MCP adapter can start the broker automatically.
Check the persistent kill state, local secrets, native-host manifest, pinned launcher/runtime/entry, and broker IPC endpoint:
node apps/broker/dist/cli.js doctor --browser chromedoctor rejects legacy #!/usr/bin/env node native-host entries because they can
fail under a GUI browser's restricted PATH. It checks local installation state;
it is not a real-browser end-to-end test.
4. Connect Codex through MCP
Codex supports local STDIO MCP servers. Add this source build using an absolute path:
codex mcp add tabgrant -- \
node /ABSOLUTE/PATH/TO/tabgrant/apps/broker/dist/cli.js \
mcp --client-id codex --declared-model-provider openaiThen run codex mcp list; in an interactive Codex session, use /mcp to inspect
the connection. Codex stores MCP configuration in ~/.codex/config.toml, or in
project-scoped .codex/config.toml for a trusted project. The equivalent manual
configuration is:
[mcp_servers.tabgrant]
command = "node"
args = [
"/ABSOLUTE/PATH/TO/tabgrant/apps/broker/dist/cli.js",
"mcp",
"--client-id",
"codex",
"--declared-model-provider",
"openai",
]
startup_timeout_sec = 20
tool_timeout_sec = 60
default_tools_approval_mode = "prompt"declared-model-provider is an unverified label supplied by the MCP client. It is
shown to the user as Client-declared model provider; it is not a credential, an
attestation, or a network policy. TabGrant cannot prove which model or service the
client actually uses and cannot constrain where the client sends returned page
data. Do not put API keys or browser credentials in this configuration.
See the official Codex MCP documentation
for current Codex configuration behavior.
Other local agents can use the same STDIO command when their MCP client can
launch a local process; choose a stable client-id for that client and a fresh
task-id for each task. Hosted ChatGPT Work chats do not read local Codex MCP
configuration and instead use plugins with remote MCP tools. TabGrant does not
ship a remote broker in this Developer Preview because that would introduce a
different authority and data-egress boundary.
5. Grant a tab
Ask the agent to call
browser_access_requestwith a concrete reason.Open the HTTPS page, or loopback HTTP development page, you want to share.
Open the TabGrant extension and review the client, task, reason, scopes, and client-declared model-provider label. Treat that label as a client claim, not a verified destination.
Select Grant current tab.
The agent calls
browser_access_statusorbrowser_tabs_listto obtain the lease ID, then uses the bounded browser tools.Revoke from the extension or with
browser_access_revokewhen finished.
Only one grant can be active in the extension at a time. Granting another tab replaces the current grant.
Current MCP tools
Tool | Current behavior |
| Reports broker/browser connection state; never enumerates tabs. |
| Creates a five-minute pending request for extension approval. |
| Lists requests and leases owned by this exact MCP client task. |
| Revokes a lease owned by this task. |
| Lists only active, explicitly granted tabs, with query/fragment removed. |
| Returns up to 500 visible accessibility-style nodes and short-lived refs. |
| Highlights one ref from the current snapshot for 1.5 seconds. |
| Scrolls the granted document by at most 2,000 px per call. |
| Starts same-origin HTTP(S) navigation, then revokes the document lease. |
Snapshots require both page.a11y.read and explicit data.egress.model scope.
Each serialized snapshot result is limited to 256,000 UTF-8 bytes, and all
successfully returned snapshots share a 1,000,000-byte UTF-8 lease budget.
Element refs are bound to the current document and snapshot epoch; take a new
snapshot after the page changes.
Lease behavior
Default and maximum lifetime: 10 minutes.
Idle timeout: 2 minutes.
Maximum admitted commands: 250.
Concurrency: at most 2 commands in flight per lease.
Rate: at most 30 admitted commands per fixed one-minute window.
Snapshot output: at most 256,000 UTF-8 bytes per result and 1,000,000 UTF-8 bytes cumulatively per lease.
Supported pages: HTTPS and loopback HTTP only.
The Chrome Web Store origins, browser-internal pages, file URLs, and credentialed URLs are not grantable.
Tab close, document change, browser disconnect, agent/MCP disconnect, expiry, revoke, or activation of the persistent kill marker invalidates the lease.
Lease ownership includes an internal random broker-session ID. Reconnecting with the same public client/task identity does not recover the old lease.
Same-origin navigation is allowed only with its explicit scope and replaces the document, so a fresh grant is required afterward.
tabgrant killwrites the private persistent marker directly; there is nobroker.killRPC. A running broker notices the marker, revokes active leases, closes connections, and stops. Autostart remains blocked untiltabgrant enable --confirmis run in a local terminal.
Broker-wide resource bounds
At most 8 pending access requests per agent session and 100 globally.
access.requestadmits at most 20 calls per session and 120 globally per fixed one-minute window.In-memory state retains at most 512 access-request records and 200 lease records; terminal records are eligible for pruning after 15 minutes.
Each IPC connection admits at most 240 inbound requests per fixed one-minute window, before dispatch to a handler.
Audit storage uses at most four 1 MiB segments (4 MiB total), plus a bounded owner-only
audit.jsonl.manifest.json. It rotates at 30 days or before a write would exceed the active segment. Each segment has its own record HMAC chain; the manifest HMAC binds the exact ordered filenames, byte lengths, record counts, SHA-256 digests, and first/last record hashes.
What TabGrant does not currently do
click buttons, fill forms, submit, send, publish, purchase, delete, or change account settings;
take screenshots or return arbitrary/full DOM, page source, or network bodies;
read cookies, passwords, authentication tokens, or raw browser storage;
execute arbitrary JavaScript or expose Chrome DevTools Protocol/debugger access;
enumerate ungranted tabs, browsing history, other profiles, or other clients' leases;
navigate across origins or keep a grant through navigation;
support simultaneous multi-tab grants in one extension instance;
support Firefox, Safari, Windows native-host installation, remote brokers, or hosted/cloud agents;
verify the client's declared model-provider label or prevent an authorized MCP client from forwarding returned page data elsewhere;
protect against arbitrary native code already running as the same OS user, or a fully compromised operating system or browser;
prevent same-UID code from modifying the broker socket/process/private files or consuming the bounded OS-pairing prompt budget to delay legitimate pairing;
bypass CAPTCHAs, anti-bot systems, access controls, or platform policies.
The protocol and policy packages model future actions, including higher-risk actions, but those are not exposed by the current MCP server or extension.
Current verification boundary
As of 2026-08-30, this checkout passes:
pnpm check, including formatting, lint, type checking, 134 automated tests (83 broker, 25 extension, 8 protocol, and 18 policy), and the manifest/source security gate;pnpm build, producing the extension and three broker executables;pnpm pack:smoke, which installs the packedtabgrant@0.1.0tarball and runs its CLI;pnpm e2e:chrome:ciagainst Chrome for Testing 152.0.7977.64 after installing the disposable browser withpnpm e2e:chrome:install.
Automated coverage includes a real MCP STDIO SDK client connected to a spawned
MCP subprocess. Broker unit/integration tests use an in-process mock browser. The
separate Chrome for Testing CI E2E completes extension-key pairing, broker
startup, MCP, Native Messaging, popup rendering and grant, a synthetic
loopback-page snapshot, highlight, scroll, revoke, password-value redaction, and
confirmation that the audit contains no page or pairing content. It launches
Chrome with a PATH containing no Node executable and verifies the production
installer's pinned launcher, plus the popup's distinct pre-pair Pairing required
state. CI imports the
broker source and injects a test-only approver that accepts only the exact
extension ID, browser-instance ID, pairing code, and key fingerprint discovered
by that run. Production broker startup does not expose that injection path.
The E2E runner uses only a disposable browser profile and writes its Native
Messaging manifest inside that profile; it does not read, create, replace, or
remove a global browser manifest. It copies the built extension to a temporary
directory and adds only http://127.0.0.1/* as a test-only host permission. The
production manifest continues to declare no host_permissions, and the security
gate rejects adding one. On GitHub's Ubuntu runner, only the dedicated
e2e:chrome:ci:linux-no-sandbox command adds Chrome's --no-sandbox flag to
work around the runner's restricted user-namespace environment. The harness
rejects that flag unless it is an explicit Linux CI=true run using its
disposable profile; the default and manual commands retain Chrome's sandbox.
This CI exception is not a production configuration or evidence for a sandboxed
browser deployment. The CI test opens and operates the popup programmatically.
Because it bypasses the production osascript/zenity
approver and does not use a real toolbar gesture, it proves neither OS
user-presence UI nor production activeTab acquisition. Branded Chrome removed command-line unpacked-extension loading in
Chrome 137, so
repeatable automation uses Chrome for Testing or Chromium rather than claiming
branded-Chrome coverage. This evidence does not establish:
a live Codex-to-Native-Messaging-to-page workflow;
the production
activeTabtoolbar-gesture path;manual compatibility with each Chrome, Chromium, Edge, or Brave release;
browser-store packaging or installation;
production security, external audit results, or resistance to a compromised browser/operating system.
pnpm e2e:chrome:manual is the interactive harness intended to start the
production broker, show the real macOS/Linux pairing prompt, and wait for a human
toolbar click plus Grant current tab. That OS/UI path is still being debugged;
no successful manual evidence is claimed yet. It requires a graphical local
session, and Linux additionally requires zenity.
Reports from disposable-profile testing are welcome through the compatibility issue form.
CLI operations
tabgrant daemon [--quiet]
tabgrant mcp --client-id <id> --declared-model-provider <provider> [--task-id <id>]
tabgrant install --extension-id <id> [--browser chrome|chrome-for-testing|chromium|edge|brave]
tabgrant uninstall [--browser chrome|chrome-for-testing|chromium|edge|brave]
tabgrant doctor [--browser chrome|chrome-for-testing|chromium|edge|brave]
tabgrant status
tabgrant kill
tabgrant enable --confirm
tabgrant versionFrom a source build, replace tabgrant with
node apps/broker/dist/cli.js. Runtime state defaults to
~/Library/Application Support/TabGrant on macOS and
$XDG_STATE_HOME/tabgrant on Linux when XDG_STATE_HOME is set, otherwise
~/.local/state/tabgrant. Set TABGRANT_HOME to use a separate absolute state
directory for testing.
Broker IPC is a filesystem Unix-domain socket on macOS/Linux and a Windows named pipe, not a TCP loopback listener. Browser Native Messaging installation is still implemented only for macOS and Linux.
Architecture and project policies
License
Licensed under the Apache License 2.0.
This server cannot be installed
Maintenance
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
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Stealth web automation for AI agents. Login, signup, navigate, screenshot.
Stealth web automation for AI agents. Login, signup, navigate, screenshot.
Headless browser primitives for AI agents when sites need real JS rendering.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to control and automate your Chrome browser directly, leveraging existing login states and configurations for tasks like content analysis, semantic search across tabs, screenshots, network monitoring, and interactive operations.10MIT
- AlicenseAqualityDmaintenanceEnables AI agents to control the user's Chrome or Firefox browser, leveraging existing sessions for tasks requiring authentication and user handoff.181715MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with a user's real Chrome browser tabs, executing JavaScript, reading cookies, and making fetch requests within authenticated sessions.
- AlicenseNot gradedqualityCmaintenanceEnables AI coding assistants to control a live Google Chrome browser, allowing tab management, navigation, clicking, typing, screenshots, and JavaScript evaluation through the user's real profile.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/SnakeLil/tabgrant'
If you have feedback or need assistance with the MCP directory API, please join our Discord server