feat: MCP parity with playwright-ext — page-event recorder and full tool exposure - #49
Merged
Conversation
added 19 commits
August 17, 2026 00:13
Dialogs pass through to the native implementations until an agent arms them, so an unarmed page behaves exactly as it would without the extension. Body capture is off by default. The script is manifest-declared rather than dynamically registered: crxjs copies web_accessible_resources verbatim without transpiling, so a dynamically-registered .ts never runs. Spec updated to match.
…m EXEC screenshot, the tab plane, bookmark/history search and the downloads lived in the side panel, which the coordinator/MCP EXEC path never touches — so none of them were reachable from an external agent. They now live in background/bg-tools and dispatch from runOneStep before the content-script hop, with the side panel delegating to the same implementations. downloadSpreadsheet builds a data: URL: a service worker has no URL.createObjectURL.
fillInput's slow path calls the native value setter so React/Vue value trackers stay in sync — assigning el.value directly makes the framework conclude nothing changed and drop the input event.
Bands are spaced 120ms apart because captureVisibleTab is quota-limited per second, and capped at 20 so an infinite-scroll page cannot hang the call. The user's scroll position is restored in a finally block.
Attach is best-effort: DevTools or another extension may already hold the tab, and the user can detach at any time. Both paths fall back to the MAIN-world recorder and stamp degradedReason onto later reads, so an agent can distinguish reduced fidelity from an empty page. Under CDP the dialog genuinely suspends, so handleDialog answers a pending dialog immediately instead of only setting a standing policy.
The permission request runs inside the change handler because Chrome requires a user gesture; a declined request leaves the toggle off.
tool-gen flips from a 19-name allow-list to a 3-name block-list, taking the browser_* surface from 19 to 54. runJS now travels as a js step rather than a tool step, and listTabs/openTab get an explicit tab:open capability because they have no BuiltinTool member for the exhaustive switch to match. ATWEBPILOT_MCP_TOOLS=parity trims to the set covering playwright-ext, for users who would rather have the context back. Default is full.
A new MCP server paired with an older extension would advertise browser_drag and fail at call time with "unknown tool". HELLO now carries the names the worker can actually execute, and tools/list is intersected against it. An extension predating the field falls back to the legacy 19-tool surface; no worker at all advertises everything, since tools/list is routinely called before the browser attaches.
Also classifies the 11 new tools in severity.ts — without it they fell through to the dangerous default, which would have made consoleMessages prompt on every side-panel call despite being a safe read.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes AtWebPilot a functional replacement for
@playwright/mcp --extension. Two gaps are closed.Capability existed but was unreachable.
tool-genallow-listed 19 of the extension's built-ins, so external agents saw a strictly weaker AtWebPilot than the side panel did. It is now a 3-name block-list (askUser,attachTab,detachTab), taking the surface from 19 to 54browser_*tools —takeSnapshot,clickByUid,runJS,screenshot,downloadSpreadsheetand the whole page-index family are reachable for the first time.ATWEBPILOT_MCP_TOOLS=paritytrims to the playwright-covering subset for anyone who wants the context back.A prerequisite made this real rather than cosmetic:
screenshot, the tab plane, bookmark/history search and the downloads were implemented in the side panel, which the coordinator/MCPEXECpath never touches. They moved tobackground/bg-tools/behind a router thatrunOneStepconsults before the content-script hop.Capability did not exist. New
page-recordersubsystem plus 11 new built-ins:consoleMessages,networkRequests,networkRequestDetail,handleDialog,recorderConfig,navigateBack,navigateForward,resize,drag,drop,findElements. Four existing tools grew options (clickmodifiers/double/right,fillInputslowly/submit,screenshotfullPage/format/scale,waitFortext/textGone).The recorder ships inert, because it loads on every page the user visits: response bodies off, and
alert/confirm/promptpass straight through to the natives until an agent arms them, so an unarmed page behaves exactly as it would without the extension. Buffers never leave memory. An opt-inchrome.debuggerbackend adds response bodies, pre-injection logs, CORS/CSP errors and genuinely suspended dialogs;debuggeris an optional permission so users who never enable it see no install-time warning. Attach failure and detach both degrade to the MAIN-world backend and stampdegradedReasonon later reads — an agent must be able to tell reduced fidelity from an empty page.Two semantic differences are documented rather than papered over: on the default backend
handleDialogis a pre-set policy (synchronous dialogs cannot await a round trip to the agent), andresizemoves the real window (the viewport lands exactly, via chrome-inset arithmetic).HELLOnow carriessupported_tools, so a new server paired with an older extension no longer advertises tools that fail at call time.Spec:
docs/superpowers/specs/2026-08-17-mcp-playwright-parity-design.mdPlan:
docs/superpowers/plans/2026-08-17-mcp-playwright-parity.mdTest plan
pnpm typecheckclean across all four packagespnpm test— 1023 passing, up from 853 (774 extension + 155 shared + 45 coordinator + 49 mcp-server)pnpm buildproducesdist/with the recorder emitted asworld: "MAIN",run_at: "document_start"recorderConfig({bodies:true})onDetachboth fall back withdegradedReasontools/listintersection verified against a worker reporting an oldersupported_toolsdegradedReasonsurfaces in the nextconsoleMessagesbrowser_takeSnapshot→browser_clickByUid→browser_consoleMessages