# BrowserTap MCP (pypi · browsertap-mcp)

MCP server that drives the real Chrome you already use, through an extension and CDP.

- Trust score: 79/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-20

## Components

- pypi · `browsertap-mcp`: 79/100 (this document), [markdown](https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp.md), [page](https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp)

## Channel facts

- Registry: `pypi`
- Package: `browsertap-mcp`
- Version: `0.4.12`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-20.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs setuptools.build_meta at install time, a recognised native-build step with no shell scripting around it.
  - 1 of 36 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 35/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: no license is declared.
  - Actively maintained (last published 5 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 80/100
  - AI-judged instruction clarity (excellent).
  - Tool/resource definitions use about 5474 tokens (~99/item across 55 items; 55 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 93/100
  - Stability observed for 28 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (96% of tools); any adoption earns full credit.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 6 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "uninstall_extension" implies "uninstall" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 56 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the BrowserTap MCP server?

BrowserTap MCP runs locally as a PyPI package, launched with uvx browsertap-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add linvireo-browsertap-mcp -- uvx browsertap-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "linvireo-browsertap-mcp": {
      "command": "uvx",
      "args": [
        "browsertap-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "linvireo-browsertap-mcp": {
      "command": "uvx",
      "args": [
        "browsertap-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add linvireo-browsertap-mcp -- uvx browsertap-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "linvireo-browsertap-mcp": {
      "type": "local",
      "command": [
        "uvx",
        "browsertap-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add linvireo-browsertap-mcp --command uvx --arg browsertap-mcp
```

### Hermes

```yaml
mcp_servers:
  linvireo-browsertap-mcp:
    command: "uvx"
    args: ["browsertap-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "linvireo-browsertap-mcp": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "browsertap-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add linvireo-browsertap-mcp -t stdio -c uvx -a browsertap-mcp
```

### Other

```json
{
  "mcpServers": {
    "linvireo-browsertap-mcp": {
      "command": "uvx",
      "args": [
        "browsertap-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-20 (score 79, +1)

No change was recorded against any check on this day. Stability & Change Management went from 90 to 93. That category is still filling its 30-day observation window: 27 days of observed history at the previous scan, 28 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-18 (score 78, +1)

No change was recorded against any check on this day. Stability & Change Management went from 83 to 87. That category is still filling its 30-day observation window: 25 days of observed history at the previous scan, 26 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-16 (score 77, +1)

No change was recorded against any check on this day. Stability & Change Management went from 77 to 80. That category is still filling its 30-day observation window: 23 days of observed history at the previous scan, 24 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-14 (score 76, +1)

No change was recorded against any check on this day. Stability & Change Management went from 70 to 73. That category is still filling its 30-day observation window: 21 days of observed history at the previous scan, 22 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-12 (score 75, +1)

No change was recorded against any check on this day. Stability & Change Management went from 63 to 67. That category is still filling its 30-day observation window: 19 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-09 (score 74, +1)

No change was recorded against any check on this day. Stability & Change Management went from 53 to 57. That category is still filling its 30-day observation window: 16 days of observed history at the previous scan, 17 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-07 (score 73, +1)

No change was recorded against any check on this day. Stability & Change Management went from 47 to 50. That category is still filling its 30-day observation window: 14 days of observed history at the previous scan, 15 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-05 (score 72, +1)

No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

## MCP tools (55)

### `get_automation_profile` (~53 tokens)

Return the active safe/lab automation profile. Lab is the default and skips elicitation unless BROWSERTAP_LAB_NO_ELICIT is explicitly disabled; safe requires approval for every physical action and permission allow.

### `set_automation_profile` (~48 tokens)

Set the safe or lab automation profile for this MCP process. This does not persist or reload the extension; BROWSERTAP_MODE controls the next process.

Input parameters:

- `mode` (string, required)

### `get_setup_status` (~32 tokens)

Return component versions, stale-build actions, extension path, bridge ports, and connection status for setup/diagnostics.

### `list_tabs` (~38 tokens)

List connected tabs across all connected browsers; each tab has a browser field (chrome/edge/opera) and a session id to pass verbatim.

### `list_all_tabs` (~66 tokens)

List every open tab, including chrome-extension:// pages that list_tabs hides. Those never become sessions (content scripts can't run there), so they have no session id — drive them with cdp_command(tab_id=...) instead. Works with no tabs open.

Input parameters:

- `session_id`

### `close_tabs` (~117 tokens)

Close one or more tabs by native tab id or composite session_id. Accepts a single identifier or a list; identifiers in one call must belong to the same browser. By default it closes only tabs created by this MCP task and requires the owner_id returned by open_new_tab; lifecycle generations are checked before removal. Set only_if_agent_owned=false only for an explicit operator request to close a user tab.

Input parameters:

- `only_if_agent_owned` (boolean)
- `owner_id`
- `session_id`
- `tab_id` (required)

### `switch_tab` (~94 tokens)

Set the target tab for later calls by session id, URL substring, or browser name ('chrome'/'edge'/'opera') without focusing the browser. A URL substring must match exactly one tab; pass its full session_id when several tabs match. Use activate=true or activate_tab when foreground work is required.

Input parameters:

- `activate` (boolean)
- `browser`
- `session_id`
- `url_pattern`

### `activate_tab` (~52 tokens)

Bring a tab to the foreground and focus its window. Use this explicitly after switch_tab when foreground work is required, or to re-raise a tab the user has since clicked away from.

Input parameters:

- `session_id`

### `open_url` (~104 tokens)

Navigate the current real-browser tab through CDP without raising its window. beforeunload defaults to dismiss, except lab mode auto-accepts configured shell/IDE hosts. Use accept to leave explicitly, manual to inspect, or intent_leave=false to force the conservative dismiss behavior even on a lab auto host.

Input parameters:

- `beforeunload` (string)
- `intent_leave`
- `session_id`
- `timeout` (number)
- `url` (string, required)

### `handle_dialog` (~66 tokens)

Inspect or handle a JavaScript dialog on the requested real-browser tab. action is dismiss, accept, or manual; manual reports the dialog without choosing.

Input parameters:

- `action` (string, required)
- `prompt_text` (string)
- `session_id`
- `timeout` (number)

### `resolve_leave_dialog` (~60 tokens)

Resolve an intended beforeunload leave in one bounded workflow: protocol accept twice, return immediately when no dialog exists, then use a lab-only foreground Enter fallback after the normal physical-input approval gate only when protocol handling actually fails.

Input parameters:

- `session_id`

### `open_new_tab` (~169 tokens)

Open one real-browser tab in the background by default with an operation_id-backed exactly-once create. Pass active=true only when foreground work is genuinely required. If the create ACK is lost, the same operation_id is reconciled within one total deadline; a completed result is registered only with its exact client_id, tab_id, and generation. Before create is dispatched, an unresolved probe returns status=unknown, may_have_created=false, retry_safe=true; after dispatch, an unresolved operation returns status=unknown, may_have_created=true, retry_safe=false and the operation_id. Never use a URL-based guess or an unmarked create retry.

Input parameters:

- `active` (boolean)
- `owner_id`
- `session_id`
- `timeout` (number)
- `url` (string, required)

### `extension_path` (~22 tokens)

Get absolute path to the unpacked Chrome extension directory for manual installation.

### `list_extensions` (~35 tokens)

List installed browser extensions (id, name, enabled, type, version). Works with no tabs open.

Input parameters:

- `session_id`

### `set_extension_enabled` (~99 tokens)

Enable or disable an installed extension by id. Chrome exposes no API to INSTALL an extension, so this only toggles ones already present; use list_extensions for ids. The BTAP bridge refuses to disable itself -- nothing would be left to re-enable it -- so ask a human to press Reload on chrome://extensions to pick up a new build.

Input parameters:

- `enabled` (boolean, required)
- `extension_id` (string, required)
- `session_id`

### `download_file` (~159 tokens)

Download an http(s) URL through the real browser's native download manager, so the current browser profile's cookies and authenticated session are used. Waits for completion by default and returns the final absolute local path. directory may be any absolute local directory; completed files are moved there without replacing an existing file unless overwrite=true. A directory timeout reports directory_applied=false because Chrome may finish in its default download directory. An explicit session_id must still be live and is never replaced with another profile. Use this for attachments instead of page fetch.

Input parameters:

- `directory`
- `filename`
- `overwrite` (boolean)
- `session_id`
- `timeout` (number)
- `url` (string, required)
- `wait` (boolean)

### `uninstall_extension` (~70 tokens)

Uninstall another installed extension by id. show_confirm_dialog defaults to true; set it false only for an explicitly selected disposable/test extension. The BTAP bridge cannot uninstall itself through its active connection.

Input parameters:

- `extension_id` (string, required)
- `session_id`
- `show_confirm_dialog` (boolean)

### `get_bookmarks` (~27 tokens)

Return the browser bookmark tree. Works with no tabs open.

Input parameters:

- `session_id`

### `create_bookmark` (~66 tokens)

Create a bookmark or folder. Supply url for a bookmark; omit url to create a folder. parent_id is optional and uses Chrome's default bookmark location when omitted.

Input parameters:

- `parent_id`
- `session_id`
- `title` (string, required)
- `url`

### `remove_bookmark` (~50 tokens)

Remove a bookmark by id. Set recursive=true only for a folder whose full subtree should be removed.

Input parameters:

- `bookmark_id` (string, required)
- `recursive` (boolean)
- `session_id`

### `call_extension` (~68 tokens)

Send a JSON message from the BTAP extension service worker to another installed extension. The target must be enabled and list this BTAP extension in externally_connectable. Works with no tabs open.

Input parameters:

- `extension_id` (string, required)
- `message_json` (string, required)
- `session_id`

### `network_capture_start` (~98 tokens)

Start bounded CDP Network capture on a real-browser tab. Captures requests, responses, and optionally response bodies without foregrounding the tab. Call network_capture_stop to return the buffer and release the debugger lease.

Input parameters:

- `body_timeout` (number)
- `include_bodies` (boolean)
- `max_body_bytes` (integer)
- `max_entries` (integer)
- `session_id`
- `timeout` (number)

### `network_capture_stop` (~113 tokens)

Stop Network capture on a real-browser tab, optionally filter returned records by URL, resource type, HTTP status range, or response-body inclusion, and release its debugger lease. url_pattern uses the browser's JavaScript RegExp syntax and invalid patterns return a structured error.

Input parameters:

- `include_response_bodies` (boolean)
- `resource_type` (string)
- `session_id`
- `status_max`
- `status_min`
- `timeout` (number)
- `url_pattern` (string)

### `console_capture_start` (~61 tokens)

Start a bounded Runtime console and exception capture on a real-browser tab without foregrounding it. Use get_console_messages while running and console_capture_stop when done.

Input parameters:

- `max_entries` (integer)
- `session_id`
- `timeout` (number)

### `get_console_messages` (~103 tokens)

Read a page of captured console messages and exceptions from a real-browser tab. Set clear=true to clear the full buffer after reading. Set filter='user' to exclude extension service-worker / content-script logs and keep only the page's own main-world console output.

Input parameters:

- `clear` (boolean)
- `filter` (string)
- `max_items` (integer)
- `offset` (integer)
- `session_id`
- `timeout` (number)

### `console_capture_stop` (~44 tokens)

Stop console capture on a real-browser tab, return the remaining bounded message buffer, and release its debugger lease.

Input parameters:

- `session_id`
- `timeout` (number)

### `scan_page` (~94 tokens)

Read the current page as simplified HTML/text, preserving login state from the real browser. Defaults: cutlist=true, maxchars=35000, timeout=15 seconds.

Input parameters:

- `cutlist` (boolean)
- `extra_js` (string)
- `instruction` (string)
- `maxchars` (integer)
- `session_id`
- `text_only` (boolean)
- `timeout` (number)

### `wait_for` (~149 tokens)

Wait until a condition holds on the page, then return. Use this instead of polling scan_page (each scan re-serializes the whole DOM). Exactly one of selector / text / url_pattern / js must be given: selector waits for a CSS match, text for a substring in body text, url_pattern for a regex on the URL, js for a JS expression to become truthy. Polls inside the page, so it costs one bridge roundtrip regardless of how long the wait takes.

Input parameters:

- `gone` (boolean)
- `js`
- `selector`
- `session_id`
- `text`
- `timeout` (number)
- `url_pattern`

### `wait_for_url` (~131 tokens)

Wait for navigation to settle: blocks until the tab's URL matches url_pattern (regex, or plain substring) and — unless wait_ready=false — document.readyState is 'complete', then returns the final url, title and readyState. Use this after a click or open_url that navigates; wait_for(url_pattern=...) only checks the URL and can return while the new document is still blank. Polls in-page, so a long wait is still cheap.

Input parameters:

- `session_id`
- `timeout` (number)
- `url_pattern` (string, required)
- `wait_ready` (boolean)

### `scroll_page` (~100 tokens)

Scroll the page and report the new position. scan_page omits anything past ±5000px from the current scroll offset, so on a long page: scan, then scroll, then scan again. Pass to='bottom'/'top', a pixel offset, or a CSS selector to bring into view. Defaults: to='bottom', timeout=15 seconds.

Input parameters:

- `session_id`
- `timeout` (number)
- `to` (string)

### `execute_js` (~137 tokens)

Execute arbitrary JS in the requested real-browser tab under one total deadline. BTAP pins every monitor/retry/result roundtrip to an explicit session, uses the service-worker/page route first, and falls back to directed Runtime.evaluate on SPA/CSP bridge failures without retargeting. Use wait_for/wait_for_url instead of setTimeout or sleep Promises; BTAP retries only proven-undelivered work, never an acknowledged script whose side effects may already have run.

Input parameters:

- `dialog_policy` (string)
- `no_monitor` (boolean)
- `script` (string, required)
- `session_id`
- `timeout` (number)

### `cdp_command` (~85 tokens)

Call one Chrome DevTools Protocol command. session_id accepts client:tabId; tab_id accepts either a native number or the same composite session string.

Input parameters:

- `extension_id`
- `method` (string, required)
- `params_json` (string)
- `session_id`
- `tab_id`
- `target_id`
- `timeout` (number)

### `save_pdf` (~113 tokens)

Print a real-browser tab to a validated PDF file through bounded CDP. The file is written atomically only after valid non-empty PDF bytes are returned; a CDP timeout invalidates and detaches the debugger lease.

Input parameters:

- `landscape` (boolean)
- `page_ranges` (string)
- `prefer_css_page_size` (boolean)
- `print_background` (boolean)
- `save_path` (string, required)
- `scale` (number)
- `session_id`
- `timeout` (number)

### `debugger_targets` (~42 tokens)

List every CDP-attachable target, including service workers and extension background pages that list_tabs never shows. Works with no tabs open.

Input parameters:

- `session_id`

### `cdp_batch` (~40 tokens)

Run a CDP bridge batch command; pass the full JSON command object as text.

Input parameters:

- `batch_json` (string, required)
- `session_id`

### `page_click` (~242 tokens)

Click a CSS/structured locator or viewport coordinates in a specific real browser tab using background CDP input. Coordinates are viewport-relative CSS pixels (the space getBoundingClientRect reports), NOT the physical screen pixels mouse_click takes and NOT the device pixels capture_page_screenshot returns -- on a scaled display divide a screenshot pixel by devicePixelRatio first. Ambiguous or unreachable targets dispatch nothing; the tab is not activated and the desktop cursor does not move. Selector offsets are measured from the element's top-left corner; an omitted axis uses the element centre. In selector mode the point is hit-tested before anything is dispatched: an element below the fold is scrolled into view, and a point owned by another element returns status 'obscured' (with occluded_by) or 'outside_viewport' having clicked nothing. Coordinate mode is not hit-tested -- coordinates name a pixel, not an element.

Input parameters:

- `button` (string)
- `clicks` (integer)
- `offset_x`
- `offset_y`
- `selector`
- `session_id`
- `timeout` (number)
- `x`
- `y`

### `page_type` (~101 tokens)

Insert text into the focused element or a CSS/structured-locator field in a specific tab using background CDP input; xterm containers automatically retarget their helper textarea. Optionally clear and submit a key. Missing, ambiguous, or unusable targets dispatch nothing.

Input parameters:

- `clear` (boolean)
- `selector`
- `session_id`
- `submit_key` (string)
- `text` (string, required)
- `timeout` (number)

### `page_press` (~53 tokens)

Press a key or comma-delimited modifier chord in a specific tab using background CDP input, without activating the tab.

Input parameters:

- `keys_csv` (string, required)
- `session_id`
- `timeout` (number)

### `page_drag` (~122 tokens)

Drag between viewport coordinates in a specific tab using one background CDP input sequence, without activating the tab or moving the desktop cursor. Both endpoints are viewport-relative CSS pixels, like page_click's coordinate mode and unlike mouse_drag's physical screen pixels, and neither is hit-tested.

Input parameters:

- `button` (string)
- `duration` (number)
- `session_id`
- `timeout` (number)
- `x1` (number, required)
- `x2` (number, required)
- `y1` (number, required)
- `y2` (number, required)

### `upload_files` (~85 tokens)

Set files on a file input, which JS cannot do (input.files is read-only). Give a CSS selector for the <input type=file> and absolute local paths. Runs as a single CDP batch so the DOM node ids stay valid across the sequence.

Input parameters:

- `paths` (required)
- `selector` (string, required)
- `session_id`
- `timeout` (number)

### `get_cookies` (~36 tokens)

Get cookies for the current page or specified tab via the Chrome extension bridge.

Input parameters:

- `session_id`
- `tab_id`

### `set_site_permission` (~120 tokens)

Temporarily set an origin-scoped browser site permission for 60-600 seconds. Only http/https origins and notifications, geolocation/location, camera, microphone, or clipboard are supported. safe asks on every allow; lab skips prompts by default and restores session approval only when BROWSERTAP_LAB_NO_ELICIT is explicitly disabled. All leases restore their prior setting.

Input parameters:

- `duration_seconds` (integer)
- `origin` (string)
- `permission` (string, required)
- `session_id`
- `setting` (string, required)

### `reset_site_permissions` (~59 tokens)

Restore matching temporary site-permission leases now. Omit origin and permission to reset every lease for the selected browser; origin accepts only http/https.

Input parameters:

- `origin` (string)
- `permission` (string)
- `session_id`

### `set_cookies` (~129 tokens)

Write cookies into the real browser profile. Takes one cookie object or a list (JSON text is accepted): name is required, plus optional value/url/domain/path/expires (Unix seconds)/httpOnly/secure/sameSite. Uses CDP Network.setCookie so HttpOnly and cross-path cookies work; falls back to document.cookie only if CDP is unavailable, and then says which cookies could not carry HttpOnly. Cookies with neither url nor domain are scoped to the current page.

Input parameters:

- `cookies` (required)
- `session_id`
- `tab_id`
- `timeout` (number)

### `delete_cookies` (~97 tokens)

Delete a cookie by name from the real browser profile. Scope defaults to the current page (url), or pass domain/path/url to target another scope. Uses CDP Network.deleteCookies, falling back to expiring it via document.cookie.

Input parameters:

- `domain`
- `name` (string, required)
- `path`
- `session_id`
- `tab_id`
- `timeout` (number)
- `url`

### `storage_get` (~102 tokens)

Read localStorage or sessionStorage. Give a key for one value, or omit it to dump every key (values are truncated past ~20k chars and truncated is reported). area='local' (default) or 'session'.

Input parameters:

- `area` (string)
- `key`
- `max_bytes` (integer)
- `max_items` (integer)
- `offset` (integer)
- `session_id`
- `timeout` (number)

### `storage_set` (~82 tokens)

Write one key into localStorage or sessionStorage and read it back to confirm. area='local' (default) or 'session'. Values are strings; non-string values are JSON-encoded first.

Input parameters:

- `area` (string)
- `key` (string, required)
- `session_id`
- `timeout` (number)
- `value` (string, required)

### `capture_page_screenshot` (~191 tokens)

Capture a viewport, full-page, or clipped screenshot of a page/tab via CDP with optional JPEG/WebP quality. Returns text metadata plus an attached MCP image even when save_path is set; save_path only controls disk output. image_width/image_height are DEVICE pixels (CSS x devicePixelRatio), not the CSS pixels page_click takes, and `size` is the byte count. If the current model cannot consume images, it has not seen the pixels and must use scan_page, execute_js, a page-specific API, or OCR instead. Base64 is included only when return_base64=true.

Input parameters:

- `clip`
- `format` (string)
- `full_page` (boolean)
- `quality`
- `return_base64` (boolean)
- `save_path` (string)
- `session_id`
- `tab_id`
- `timeout` (number)

### `capture_desktop_screenshot` (~93 tokens)

Capture the complete visible virtual desktop across all displays and return text metadata plus MCP image content; this is not a background-tab screenshot, save_path only adds a disk copy, and return_base64 is opt-in. width/height/left/top are PHYSICAL screen pixels and are exactly the range mouse_click accepts, unscaled.

Input parameters:

- `return_base64` (boolean)
- `save_path` (string)

### `mouse_move` (~176 tokens)

Move the real mouse cursor to absolute virtual-desktop coordinates in PHYSICAL screen pixels (the space pointer_info and capture_desktop_screenshot report, not the CSS pixels page_click takes). A point on no display is refused with coordinates_off_screen rather than clamped to a screen edge. Safe mode requires one-action approval; lab skips prompting by default and uses session approval only when BROWSERTAP_LAB_NO_ELICIT is explicitly disabled. By default BTAP foregrounds and verifies the selected browser tab after the quiet-input check; prefer an explicit session_id for browser input. activate_session='none' is only for intentional input to the already-visible desktop or native UI.

Input parameters:

- `activate_session`
- `duration` (number)
- `session_id`
- `x` (integer, required)
- `y` (integer, required)

### `mouse_click` (~188 tokens)

Click on the real desktop at absolute virtual-desktop coordinates in PHYSICAL screen pixels — the space pointer_info and capture_desktop_screenshot report, NOT the viewport CSS pixels page_click takes; on a scaled display the two differ by devicePixelRatio. A point on no display is refused with coordinates_off_screen rather than clamped to a screen edge. Pass session_id — the same one you pass every other tool (preferred) — and that tab is raised after the quiet check so the click lands on it. Without one the current global target is raised, which another task may have changed. Approval may foreground the selected browser tab. activate_session='none' clicks the desktop as-is.

Input parameters:

- `activate_session`
- `button` (string)
- `clicks` (integer)
- `interval` (number)
- `session_id`
- `x`
- `y`

### `mouse_drag` (~191 tokens)

Drag the real mouse from one point to another, both in absolute virtual-desktop PHYSICAL screen pixels (see mouse_click for how that differs from page_drag's CSS pixels). Either endpoint on no display is refused with coordinates_off_screen. Safe mode requires one-action approval; lab skips prompting by default and uses session approval only when BROWSERTAP_LAB_NO_ELICIT is explicitly disabled. By default BTAP foregrounds and verifies the selected browser tab after the quiet-input check; prefer an explicit session_id for browser input. activate_session='none' is only for intentional input to the already-visible desktop or native UI.

Input parameters:

- `activate_session`
- `button` (string)
- `duration` (number)
- `session_id`
- `x1` (integer, required)
- `x2` (integer, required)
- `y1` (integer, required)
- `y2` (integer, required)

### `type_text` (~174 tokens)

Type text via the real keyboard, optionally after clicking a field at click_x/click_y in absolute virtual-desktop PHYSICAL screen pixels (see mouse_click for how that differs from the CSS pixels the page_* tools take); a click point on no display is refused with coordinates_off_screen. Pass session_id — the same one you pass every other tool (preferred) — and that tab is raised after the quiet check so the keystrokes go to it. Without one the current global target is raised, which another task may have changed. Approval may foreground the selected browser tab. activate_session='none' types into whatever already has focus.

Input parameters:

- `activate_session`
- `click_x`
- `click_y`
- `interval` (number)
- `session_id`
- `text` (string, required)

### `hotkey` (~128 tokens)

Send a hotkey chord like 'command,l' or 'ctrl,shift,p' via the real keyboard. Safe mode requires one-action approval; lab skips prompting by default and uses session approval only when BROWSERTAP_LAB_NO_ELICIT is explicitly disabled. By default BTAP foregrounds and verifies the selected browser tab after the quiet-input check; prefer an explicit session_id for browser input. activate_session='none' is only for intentional input to the already-visible desktop or native UI.

Input parameters:

- `activate_session`
- `keys_csv` (string, required)
- `session_id`

### `pointer_info` (~63 tokens)

Report the current desktop mouse position and screen geometry in PHYSICAL pixels. screen_width/screen_height are the PRIMARY display only; screen_bounds is the virtual desktop across every display and is the range mouse_click will accept. These are not the CSS pixels the page_* tools take.

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp#diagnostics

## Score history

- 2026-09-20: 79
- 2026-09-19: 78
- 2026-09-18: 78
- 2026-09-17: 77
- 2026-09-16: 77
- 2026-09-15: 76
- 2026-09-14: 76
- 2026-09-13: 75
- 2026-09-12: 75
- 2026-09-11: 74
- 2026-09-10: 74
- 2026-09-09: 74
- 2026-09-08: 73
- 2026-09-07: 73
- 2026-09-06: 72
- 2026-09-05: 72
- 2026-09-04: 71
- 2026-09-03: 71
- 2026-09-02: 70
- 2026-09-01: 70
- 2026-08-31: 69
- 2026-08-30: 69
- 2026-08-29: 66
- 2026-08-28: 66
- 2026-08-27: 66
- 2026-08-26: 66
- 2026-08-25: 65
- 2026-08-24: 65
- 2026-08-23: 50

## Common questions

### What is the BrowserTap MCP server?

BrowserTap MCP is listed in the public MCP registry as io.github.LinVireo/browsertap-mcp. MCP server that drives the real Chrome you already use, through an extension and CDP. This page covers its PyPI package (browsertap-mcp).

### Is the BrowserTap MCP server safe to use?

BrowserTap MCP scores 79 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the BrowserTap MCP server expose?

BrowserTap MCP exposes 55 tools: get_automation_profile, set_automation_profile, get_setup_status, list_tabs, list_all_tabs, and 50 more. Their descriptions and schemas cost roughly 5,237 tokens of context every time the server is loaded.

### Is the BrowserTap MCP server still maintained?

BrowserTap MCP is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- PyPI project: https://pypi.org/project/browsertap-mcp/
- Socket report: https://socket.dev/pypi/package/browsertap-mcp
- Repository: https://github.com/LinVireo/browsertap-mcp
- Changelog RSS feed: https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp.json
- HTML version of this page: https://verifymcp.io/servers/linvireo-browsertap-mcp/browsertap-mcp
