Skip to content

feat: bidi install/uninstall extension#119

Merged
Winify merged 4 commits into
webdriverio:mainfrom
nathom791:add-extension-install
Jun 18, 2026
Merged

feat: bidi install/uninstall extension#119
Winify merged 4 commits into
webdriverio:mainfrom
nathom791:add-extension-install

Conversation

@nathom791

Copy link
Copy Markdown
Contributor

Proposed changes

Add BiDi-based web extension support to the MCP server.

This introduces three new tools for browser sessions with webSocketUrl: true:

  • install_web_extension to install unpacked, archived, or base64-encoded extensions
  • uninstall_web_extension to remove an installed extension by id
  • open_web_extension_page to navigate to an extension page so standard page tools can
    inspect and drive it

The change also tracks installed extension ids in session metadata, wires the new tools into
recording/code generation, updates trace tool mapping, and adds README examples for BiDi
extension workflows.

Types of changes

  • Polish (an improvement for an existing feature)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as
    expected)
  • Documentation update (improvements to the project's docs)
  • Internal updates (everything related to internal scripts, governance documentation and
    CI files)

Checklist

  • I have squashed commits that belong together
  • I have tested with Claude Desktop (or another MCP-compatible client)
  • I have read the [CONTRIBUTING](https://github.com/webdriverio/webdriverio/blob/main/
    CONTRIBUTING.md) doc
  • I have added the necessary documentation for new/changed tools (if appropriate)
  • I have added proper type definitions for new commands (if appropriate)

Further comments

The implementation is intentionally scoped to BiDi-capable browser sessions. For remote/cloud
sessions, base64 extension payloads are supported so the driver does not need access to the
MCP server filesystem.

Tested using OpenCode against Bitwarden web extension

extension-install-step

Recording support mirrors the live tools, including replay of extension install/uninstall
calls and extension-page navigation.

Reviewers: @webdriverio/project-committers

@nathom791 nathom791 changed the title add bidi install/uninstall extension feat: bidi install/uninstall extension Jun 15, 2026
@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a single combined open_web_extension MCP tool that installs a WebDriver BiDi web extension and navigates to one of its pages in one step. The PR also wires the tool into recording/code-generation with scheme inference for replay, adds trace mapping, and ships thorough documentation and tests.

  • New tool (src/tools/web-extension.tool.ts): guards against non-BiDi sessions, mobile sessions, and unexpected driver responses; intentionally back-fills args.scheme on the MCP params object so withRecording captures the inferred scheme in the replay record — explicitly tested.
  • Code generator (src/recording/code-generator.ts): emits const { extension } = await browser.webExtensionInstall(...) and a template-literal browser.url(...) call; the inferred scheme is now stored in the recording, so Firefox replays use moz-extension:// correctly.
  • Tests cover all error paths, scheme inference, leading-slash normalisation, and the recording contract.

Confidence Score: 5/5

Safe to merge — all changes are additive, well-tested, and confined to the new BiDi extension tool and its recording support.

The new tool is fully guarded against invalid session states and the previously-noted issues (missing return-value capture, Firefox scheme inference) are both addressed and covered by tests. The only open item is a minor code-generator correctness gap around backtick or template-literal characters in extension paths, which is benign in practice.

No files require special attention. The code-generator has the minor template-literal escape gap but it does not affect normal extension paths.

Important Files Changed

Filename Overview
src/tools/web-extension.tool.ts New tool that installs a BiDi web extension and navigates to an extension page. Well-guarded against missing sessions, mobile sessions, non-BiDi sessions, and unexpected driver responses. Intentionally mutates args.scheme so withRecording captures the inferred scheme — tested explicitly.
src/recording/code-generator.ts Adds open_web_extension codegen case with scheme inference for replay. Minor: escapeStr escapes backslashes and single quotes but not backticks or ${, so a path containing those characters would produce syntactically broken template-literal code in the replay script.
src/server.ts Wires open_web_extension tool into the MCP server with instrument wrapper — consistent with how other tools are registered.
src/trace/tool-mapping.ts Adds trace mapping for open_web_extension to { class: 'Page', method: 'navigate' }, which is a reasonable classification for the navigation side of the combined action.
tests/tools/web-extension-tool.test.ts Comprehensive test suite covering all error paths, scheme inference, leading-slash stripping, and the scheme-write-back recording contract.
tests/recording/code-generator.test.ts Adds three tests for open_web_extension codegen including the inferred-Firefox scheme path — addresses the gap previously noted for replay correctness.
README.md Documents open_web_extension with a clear example; new BiDi code block shows the combined install+navigate workflow.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant LLM as LLM / MCP Client
    participant MCP as MCP Server
    participant Tool as open_web_extension tool
    participant Driver as WebDriver BiDi

    LLM->>MCP: open_web_extension
    MCP->>Tool: instrument wraps withRecording
    Tool->>Tool: getBrowserSession check BiDi
    Tool->>Driver: webExtensionInstall extensionData
    Driver-->>Tool: extension id
    Tool->>Tool: inferExtensionScheme write back scheme
    Tool->>Driver: browser.url extension page
    Driver-->>Tool: navigation complete
    Tool-->>MCP: success result
    MCP->>MCP: appendStep with scheme in params
    MCP-->>LLM: tool result
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant LLM as LLM / MCP Client
    participant MCP as MCP Server
    participant Tool as open_web_extension tool
    participant Driver as WebDriver BiDi

    LLM->>MCP: open_web_extension
    MCP->>Tool: instrument wraps withRecording
    Tool->>Tool: getBrowserSession check BiDi
    Tool->>Driver: webExtensionInstall extensionData
    Driver-->>Tool: extension id
    Tool->>Tool: inferExtensionScheme write back scheme
    Tool->>Driver: browser.url extension page
    Driver-->>Tool: navigation complete
    Tool-->>MCP: success result
    MCP->>MCP: appendStep with scheme in params
    MCP-->>LLM: tool result
Loading

Reviews (3): Last reviewed commit: "consolidate web extension to one tool" | Re-trigger Greptile

Comment thread src/recording/code-generator.ts Outdated
Comment thread src/recording/code-generator.ts Outdated
Comment thread src/session/state.ts Outdated
Comment thread src/tools/web-extension.tool.ts Outdated
@Winify

Winify commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

@nathom791 I have a suggestion to collapse this PR to one tool:

open_web_extension({ extensionData: ..., path: 'options.html' })
→ installs extension via BiDi
→ navigates to chrome-extension:///options.html
→ assistant interacts with the page

No state to track, no ID to thread, no uninstall to call. The assistant gets a page it can drive with get_elements/click_element immediately. If it needs to open a different extension page later, it can pass the same extensionData again — WebDriver BiDi's webExtension.install is idempotent for already-installed extensions (or the tool can detect that and skip to navigation).

Three tools down to one, zero new state and no lifecycle concerns

@nathom791

Copy link
Copy Markdown
Contributor Author

@Winify - agreed, that simplifies things quite a bit. There could be a point to be made for very specific scenarios that one would want to test with installing multiple/uninstalling, but I imagine those are few and far between. I've pushed those changes. Thank you!

@Winify Winify merged commit 66adf9d into webdriverio:main Jun 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants