Skip to main content
Glama

EasyPlaywrightMCP

LLM-driven Playwright MCP for automated testing and demo videos.

Capture: synthetic cursor + always-on click highlight, 1920×1080 @ deviceScaleFactor 2, WebM→H.264 60fps minterpolate, smooth rAF scroll.
Narration: Microsoft Edge neural TTS via edge-tts.

Install

Example prompts

Using EasyPlaywrightMCP Make a demo video of the feature in my last PR

Using EasyPlaywrightMCP Connect my google oauth and test this feature in production. Report the success or failure reason for each operation

Using EasyPlaywrightMCP Create a demo video of the steps in this MD

Workflows

Automated testing

  1. login → save profileId (or set_session_auth for Google/bot-blocked OAuth)

  2. start_session (usually headless) with profileId

  3. Loop: query_session → orchestrate_session

  4. end_session

  5. Short answer to the user (pass/fail + findings)

Demo videos

  1. login if auth is needed (or set_session_auth for restricted providers)

  2. start_session with recordVideoPath (demoMode / auto-narrate on by default)

  3. Loop: query_session → orchestrate_session — put spoken lines in description / narration; server TTS + holds

  4. end_session (finalizes WebM, trims idle, writes/updates .cues.json)

  5. compile_demo with clip videoPath only (loads cues automatically)

Demo vs testing: Recording sessions conjoin speech and UI on the server. Testing sessions (no recordVideoPath) keep snappy startMs/endMs pacing.

Restricted auth: For Google OAuth / Sign in with Google (and Microsoft, Discord, Cloudflare bot walls, etc.), do not use headed login. Immediately give the user the login URL, Network → Cookie header steps, and the console snippet from MCP instructions; then set_session_auth with their paste → start_session({ profileId }).

Per-app cookie guides: LinkedIn · Google OAuth / Workspace

Related MCP server: screenwright

Tools & type examples

login

// LoginInput
{
  siteUrl: "https://app.example.com",
  authUrl: "https://app.example.com/login",
  username?: "user@example.com",
  password?: "secret",
  oauth?: {
    accessToken?: "eyJ...",
    cookies?: [{ name: "sid", value: "x", domain: "app.example.com" }],
    localStorage?: [{ name: "token", value: "eyJ..." }]
  },
  httpCredentials?: { username: "u", password: "p" },
  tokens?: { bearer?: "eyJ...", cookies?: [], localStorage?: [] },
  timeoutMs?: 120000,
  profileId?: "prof_abc" // reuse
}
// LoginResult → { ok: true, profileId: "prof_…", strategy: "password" }

Strategies: password · http_basic · token_inject · oauth_tokens · manual (headed OAuth/password window) · reuse_profile

set_session_auth

// SetSessionAuthInput
{
  siteUrl: "https://app.example.com/dashboard",
  credentialsJson: JSON.stringify({
    origin: "https://app.example.com",
    cookies: [{ name: "session", value: "abc", domain: "app.example.com", path: "/" }],
    localStorage: [{ name: "token", value: "eyJ..." }],
    sessionStorage: []
  }),
  sessionId?: "sess_…", // optional: also inject into a live session
  authUrl?: "https://app.example.com/login"
}
// → { ok: true, profileId: "prof_…", strategy: "restricted_auth", sessionId?: "sess_…" }

Use when the user must log in in their own browser. Always (Google OAuth / Sign in with Google, Microsoft, Apple, Discord, Cloudflare Turnstile, Okta/Auth0 social). Accepts Network Cookie-header snippet JSON or Playwright storageState. Always saves a reusable profileId.

start_session

{
  startUrl?: "https://app.example.com/dashboard",
  headed?: false,
  recordVideoPath?: "C:/Videos/clip.webm", // omit = no record; set => demoMode
  narrate?: true, // default true when recording; false = silent capture
  voice?: "en-US-AndrewNeural",
  rate?: "+10%",
  profileId?: "prof_abc"
}
// → { sessionId: "sess_…", headed: false, recording: true, demoMode: true, startUrl?: "…" }

query_sessions / query_session

// query_session
{ sessionId: "sess_…" }
// → { url, title, viewport, ariaSnapshot, interactive: [{ role, name, selectorHint, inputType? }] }

orchestrate_session

{
  sessionId: "sess_…",
  recordStepsPath?: "C:/Videos/steps.md",
  commands: [
    {
      action: "click", // move|click|tap|type|press|scroll|wait|navigate|select|hover|upload
      description: "Open Settings from the sidebar", // also default VO text in demoMode
      narration?: "Spoken override",
      skipNarration?: false,
      startMs: 0, // ignored for pacing while recording
      endMs: 1000,
      selector: "nav >> text=Settings",
      speed: "fast", // fast (default) | slow | timed
      fill?: false, // demos: false for live typing
      files?: ["C:/path/to/file.pdf"], // upload action
      useFileChooser?: false // upload: click + FileChooser instead of setInputFiles
    }
  ]
}
// → { commands: [{ index, description, action, startMs, endMs, videoStartMs?, videoEndMs?, ok, reason? }] }
// Recording also writes C:/Videos/clip.cues.json

end_session

{ sessionId: "sess_…" }
// → { ok: true, videoPath?: "C:/Videos/clip.webm" }

compile_demo

{
  outputPath: "C:/Videos/final-demo.mp4",
  fast?: false, // skip minterpolate for quick check
  content: [
    {
      kind: "slate",
      eyebrow: "INTRO",
      heading: "Product Demo",
      body: "A quick walkthrough",
      durationMs: 3000,
      narration: [{ startMs: 0, endMs: 2800, text: "Welcome to the demo." }]
    },
    {
      kind: "clip",
      videoPath: "C:/Videos/clip.webm" // loads clip.cues.json automatically
    }
  ]
}
// → { ok: true, outputPath: "C:/Videos/final-demo.mp4" }

Prerequisites

  • Node 20+

  • ffmpeg / ffprobe on PATH (Gyan build: winget install Gyan.FFmpeg)

  • python -m pip install edge-tts

  • Chromium via npx playwright install chromium (runs on npm install)

Install

Hey Siri, install https://github.com/Macioa/EasyPlaywrightMCP to cursor

npm install
npm run build
npm start   # stdio MCP
npm test
npm run typecheck

Auth profiles and scratch files live under %USERPROFILE%\.easy-playwright-mcp\.

Available Tools

8 tools
compile_demoA

Compile demo clips + slate segways into one narrated MP4. Pipeline: convert (minterpolate 60fps H.264) → burn captions → VO → splice. For recorded clips, pass videoPath only — loads sibling .cues.json (wins over hand-authored narration). Slates still take explicit narration.

Example:

{
  "outputPath": "C:/Videos/final-demo.mp4",
  "fast": false,
  "content": [
    {
      "kind": "slate",
      "eyebrow": "INTRO",
      "heading": "Product Demo",
      "body": "A quick walkthrough",
      "durationMs": 3000,
      "narration": [{ "startMs": 0, "endMs": 2800, "text": "Welcome to the demo." }]
    },
    {
      "kind": "clip",
      "videoPath": "C:/Videos/demo-clip.webm"
    }
  ]
}

Inputs: content (required), outputPath (required), fast, rate, +1 more.

end_sessionA

End a session and finalize recorded video if any. Recording sessions: trims idle head/tail using cues.json actionSpan, then returns videoPath. Example: { "sessionId": "sess_01HXYZ" } Returns: { "ok": true, "videoPath": "C:/Videos/demo-clip.webm" }

Inputs: sessionId (required).

loginA

Orchestrate login and persist Playwright storageState. Strategies: password form, HTTP Basic, bearer/token inject, OAuth cookies/tokens, manual/OAuth window, reuse profileId. Auto (headless) when enough creds/tokens are provided; otherwise opens a headed window and waits.

DO NOT use this tool for Google OAuth / Sign in with Google, Microsoft/Apple/Discord social login, Cloudflare bot walls, or other restricted IdPs — those require set_session_auth. If you are about to open a headed login for Google OAuth, stop and follow the Restricted auth user-message template instead.

Example input:

{
  "siteUrl": "https://app.example.com",
  "authUrl": "https://app.example.com/login",
  "username": "user@example.com",
  "password": "secret"
}

Example success: { "ok": true, "profileId": "prof_abc", "strategy": "password" }

Inputs: authUrl (required), siteUrl (required), oauth, tokens, +5 more.

orchestrate_sessionA

Execute ordered tap/cursor/keyboard actions. Recording/demoMode: server synthesizes TTS from narration|description, runs the action, holds until VO ends. startMs/endMs are ignored for pacing while recording (placeholders OK). fill=false for live typing. Testing (no recording): startMs/endMs pace the batch; each call clock starts near 0. Optional recordStepsPath writes an MD log. Recording also writes sibling .cues.json.

Example (demo):

{
  "sessionId": "sess_01HXYZ",
  "commands": [
    {
      "action": "click",
      "description": "Open Settings from the sidebar",
      "startMs": 0,
      "endMs": 1000,
      "selector": "nav >> text=Settings",
      "speed": "fast"
    },
    {
      "action": "type",
      "description": "Enter the billing search query",
      "narration": "Now we search for billing.",
      "startMs": 0,
      "endMs": 1000,
      "selector": "input[type=search]",
      "text": "billing",
      "fill": false
    }
  ]
}

Inputs: commands (required), sessionId (required), recordStepsPath.

query_sessionB

Fast page digest for LLM navigation decisions: url, title, viewport, ariaSnapshot, interactive controls. Example: { "sessionId": "sess_01HXYZ" }

Inputs: sessionId (required).

query_sessionsA

List all active sessions with sessionId, url, title, recording, createdAt, headed.

Inputs: no named parameters.

set_session_authA

Inject user-browser credentials into Playwright (restricted auth). ALWAYS saves profileId; optional sessionId applies to a live session.

BEFORE calling this tool: you MUST already have sent the user (same conversation) the login URL + Network Cookie steps + JS snippet from server instructions. Never call this tool "speculatively" without first giving those instructions. Never open headed login for Google OAuth — use this flow.

Triggers: Google OAuth / Sign in with Google, Gmail/Google apps, Microsoft/Entra, Apple, Discord OAuth, Cloudflare Turnstile on login, Okta/Auth0 social IdP, or any login Playwright cannot complete.

Accepts credentialsJson from the console snippet (Cookie header + storage) or Playwright storageState JSON.

Example (after user pastes):

{
  "siteUrl": "https://mail.google.com/",
  "credentialsJson": "{...paste from user...}"
}

Returns: { "ok": true, "profileId": "prof_…", "strategy": "restricted_auth" }

Inputs: siteUrl (required), credentialsJson (required), authUrl, sessionId.

start_sessionA

Start a Playwright Chromium session (headless or windowed) and keep it open. Optional recordVideoPath enables WebM capture at 1920×1080 @ deviceScaleFactor 2 with synthetic cursor and always-on click highlight. When recording, demoMode is on (narrate defaults true): orchestrate auto-paces to TTS. Pass profileId from login or set_session_auth to reuse auth.

Example:

{
  "startUrl": "https://app.example.com/dashboard",
  "headed": false,
  "recordVideoPath": "C:/Videos/demo-clip.webm",
  "profileId": "prof_abc"
}

Returns: { "sessionId": "sess_…", "headed": false, "recording": true, "demoMode": true, "startUrl": "…" }

Inputs: rate, voice, headed, narrate, +4 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 8 tools

    Disambiguation5/5

    Each tool has a clear, distinct purpose: authentication (login, set_session_auth), session querying (query_sessions, query_session), session lifecycle (start_session, orchestrate_session, end_session), and video compilation (compile_demo). No two tools overlap in functionality.

    Naming Consistency4/5

    Tool names follow a mostly consistent verb_noun pattern with snake_case (e.g., query_sessions, start_session). The exception is 'login', which is a bare verb, but it's a common convention and does not cause confusion.

    Tool Count5/5

    With 8 tools, the server is well-scoped. Each tool adds necessary functionality for Playwright automation and demo creation without redundancy or bloat.

    Completeness4/5

    The tool surface covers core workflows: authentication, session management, interaction orchestration, and video compilation. A minor gap is the lack of explicit profile management (e.g., list/delete profiles), but it does not break essential workflows.

    Related MCP Connectors

    Related MCP Servers