Skip to main content
Glama
ryan-grey
by ryan-grey

Chrome Page MCP

A local MCP server and Chrome extension by Ryan Grey for reading visible webpage text and operating DOM controls without screenshots or computer control.

Features

  • Find an extension by exact name and request its removal using its verified ID and name; requires management permission. Chrome always displays its native removal confirmation. Pending requests return immediately; retry the same UUID for completion and verify absence with find_extension. Self-removal and policy-managed extensions are blocked. No browser settings-page control is added.

  • Discover ordinary HTTP(S) tabs, open tabs, and navigate existing tabs.

  • Find or save an exact-URL bookmark on the bookmarks bar, including an empty title for icon-only display; requires Chrome's bookmarks permission.

  • Read visible text and controls in the top frame, same-origin iframes and open shadow roots.

  • Plain, short leaf labels are returned separately as text_targets (up to 80) for SPAs that delegate clicks without button roles or pointer styling. These are not confirmed interactive controls; use them only for requested actions and verify the result. Their references retain visibility, disabled-state, signature, frame and snapshot checks. unmapped_text provides bounded presentation diagnostics without HTML, field values or action references.

  • Fill supported fields, select options, and click controls using fresh element references.

  • Recognize ARIA tabs, menu items, toggles and compact pointer-styled custom SPA controls, including those in same-origin frames; custom detection is heuristic and does not expose every canvas, icon or framework-specific interaction.

  • Unlabeled icon controls include bounded visible ancestor context and SVG class/fragment hints, without input values or image URLs; actions reject changes to that context (for example, a drive card changing identity).

  • Pause all access or exclude individual tabs.

  • Keep health checks responsive when a page stalls; page injection reads time out after 10 seconds.

Related MCP server: OpenCode in Chrome

Install on macOS

Requires Google Chrome, Python 3.11 or newer, and Node.js 20 or newer for DOM tests.

Clone this repository into a local development directory, then run:

python3 -m venv ~/.local/chrome-page-mcp/.venv
~/.local/chrome-page-mcp/.venv/bin/python -m pip install -r requirements.txt
~/.local/chrome-page-mcp/.venv/bin/python install.py

In Chrome, open chrome://extensions, enable Developer mode, choose Load unpacked, and select this repository's extension directory. Chrome controls permission approval. The extension ID is ifbphlbegdjlbokcdbihikoadjianhgl; the manifest key is a public extension identity key, not a credential.

Configure your MCP client to launch the virtual environment's Python executable with the absolute path to server.py as its sole argument. For clients accepting an mcpServers configuration, replace both example paths with your actual paths:

{
  "mcpServers": {
    "chrome-page": {
      "command": "/absolute/path/to/.local/chrome-page-mcp/.venv/bin/python",
      "args": ["/absolute/path/to/chrome-page-mcp/server.py"]
    }
  }
}

Restart the MCP client after configuration changes. Run ~/.local/chrome-page-mcp/.venv/bin/python verify_connection.py to verify the tool handshake and live extension connection.

After changing extension code, reload it in Chrome Extensions. If the native connection disconnects, open the extension popup to reconnect.

Page reads include bounded table_rows with cell text and visible icon labels and classes. Screen-reader-only labels are omitted, so an inactive status label is not mistaken for a rendered status icon. Icon URLs and field values are not returned. Page-owned javascript: links can be activated with a fresh element reference through a normal DOM click; the tool never accepts or evaluates caller-supplied JavaScript. Other non-web link schemes remain blocked.

Tools

Tool

Purpose

connection_status

Check connection, enabled state and accessible tab count

list_tabs

List up to 500 accessible HTTP(S) tabs

read_page

Read bounded visible text and up to 500 controls

act_on_element

Click, fill or select using a fresh snapshot and element reference

open_tab

Open an HTTP(S) tab

navigate_tab

Navigate an accessible tab

exclude_tab

Exclude a tab for the extension session

find_bar_bookmark

Find exact-URL bookmarks directly on the bookmarks bar

save_bar_bookmark

Create or update an exact-URL bookmark; empty title means icon-only

find_extension

Find installed extensions by exact name and inspect removal eligibility

remove_extension

Request removal of a verified ID/name through Chrome confirmation

Custom combobox/option actions use mouse-down and focus where appropriate; options removed during selection are not clicked again. Formatting-only leaf labels can appear as bounded text targets. Filled inputs receive focus before their value setter and input/change events. These are synthetic DOM operations, so read back the result rather than inferring server acceptance.

Bookmark writes require a user request, honor the access pause, reject non-HTTP(S) URLs and embedded credentials, and verify Chrome's saved record. Existing exact-URL bookmarks are updated in place; multiple matches require duplicate resolution. No bookmark deletion or unrestricted bookmark-tree tool is exposed. After adding this permission, reload Chrome Page MCP in Chrome Extensions and approve any Chrome permission prompt. Reload the MCP client to discover the new tools.

Read before an action and again afterward. Use a canonical UUID request ID for actions/navigation and reuse it when checking a retry. Successful dispatch is not proof of server acceptance. Outcomes are deduplicated within the current service-worker lifetime, with a 1,000-action limit; after reloading, inspect the page before repeating an uncertain action.

Status, tab discovery and reads run independently of the mutation queue. Page injection reads return page_read_timeout after 10 seconds; the timeout does not cancel Chrome's underlying read. Queued mutations expire before dispatch after 15 seconds. In-flight mutations are never automatically retried.

DOM traversal prunes hidden subtrees and stops at a 2.5-second traversal deadline, returning truncated when a bound is reached. Unlabeled custom icons may receive synthetic DOM hover events on nearby ancestors before a click; labelled dropdowns do not. These heuristics do not guarantee access to every custom interface.

Intermittent bridge_request_uncertain and page_read_timeout results remain possible even when an action has taken effect. Inspect the resulting state before another action; do not assume failure or repeat an uncertain mutation. A tab's foreground/background state may affect responsiveness, but that cause has not been established. Navigating to the same URL is not a reliable refresh.

Access and privacy

Access covers ordinary HTTP(S) tabs after the user approves the extension. The popup can pause access. This is not authorization to send messages, make purchases or perform other actions outside the user's request; webpage content is untrusted data.

No screenshot, mouse/keyboard control, debugger, cookie, history, password retrieval or arbitrary JavaScript tool is exposed. Input values are omitted, and password/file/hidden/OTP/payment-card fields are excluded from supported controls. Cross-origin iframes, closed shadow roots, canvas interfaces, browser internal pages, Chrome Web Store and native dialogs are unsupported.

The native host uses an owner-only Unix socket at ~/.local/share/chrome-page-mcp/bridge.sock (directory mode 700, socket mode 600). There is no TCP listener or cloud service. One Chrome profile owns the bridge at a time; multiple local MCP clients can connect. The bridge does not persist page text or form values, but client conversation logs may retain tool results.

Verification

Page reads wait for 250 ms without DOM changes, bounded at 1.5 seconds and 64 accessible documents. dom_settled reports whether that quiet period was reached; it does not confirm that a server accepted a preceding action. Read the resulting controls and verify server state before retrying a submission.

~/.local/chrome-page-mcp/.venv/bin/python -m pytest -q
npm ci --ignore-scripts
npm test

For an end-to-end check, serve fixture/ on loopback using python3 -m http.server 8765 --bind 127.0.0.1 --directory fixture, then run ~/.local/chrome-page-mcp/.venv/bin/python verify_fixture.py http://127.0.0.1:8765/ in another terminal. This opens a harmless fixture tab and checks reads, fill/select/click, navigation, deduplication and exclusion; stop the HTTP server when finished.

The automated suite includes stalled-injection isolation, native framing, socket round trips, hidden-field filtering, stale snapshots and iframe controls.

License

MIT. See LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables local opencode agents to control a live Chrome browser via MCP tools, including tab management, JavaScript execution, clicking, form filling, page reading, screenshots, and console log retrieval.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables local control of existing Chrome/Chromium browser tabs through MCP, including tab management, navigation, content reading, screenshots, and page interaction.
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables remote agents to control a local Chrome/Edge browser via MCP, supporting navigation, snapshots, clicks, typing, screenshots, and script execution.
    153 npm
    ISC