AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Screenwright

mcp-0xjesus-screenwright Β· by 0xjesus

🎬 MCP server that records narrated, subtitled tutorial videos by driving a browser with Playwright β€” captions burned in + .srt sidecar.

β€” No reviews yet
0 installs
39 views
0.0% view→install

Install

$ agentstack add mcp-0xjesus-screenwright

βœ“ scanned Β· βœ“ verified, works with Claude Code, Cursor, and more.

Security review

βœ“ Passed

No issues found. Passed automated security review. Β· v0.1.0 How review works β†’

  • βœ“ Prompt-injection patterns
  • βœ“ Secret / credential exfiltration
  • βœ“ Dangerous shell & filesystem operations
  • βœ“ Untrusted network calls
  • βœ“ Known-malicious package signatures

What it can access

  • βœ“ Network access No
  • βœ“ Filesystem access No
  • βœ“ Shell / process execution No
  • βœ“ Environment & secrets No
  • βœ“ Dynamic code execution No

From automated source analysis of v0.1.0. β€œUsed” means the capability is present in the source β€” more access means more to trust, not that it’s unsafe.

View the full security report β†’

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-0xjesus-screenwright)

Reliability & compatibility

βœ“ Security review passed
0 installs to date
β€” no reviews yet
● 2mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work β†’
Are you the author of Screenwright? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

🎬 Screenwright

> Subtitled tutorial videos, scripted. An MCP server that turns a list of steps into a narrated screen recording β€” by driving a real browser (Playwright) or an Android / Flutter emulator (adb). Captions are burned into the video and exported as an .srt.

The name is a play on Playwright (the engine under the hood) + screen.

steps[]  ──►  Playwright drives the browser  ──►  caption overlay synced per step
         ──►  video recorded  ──►  ffmpeg β†’ .mp4  +  .srt sidecar

✨ Features

  • Scripted walkthroughs β€” goto, click, fill, type, press, hover, scroll, wait.
  • Synced subtitles β€” attach a caption to any step; it's burned into the video and written to a timed .srt.
  • Real voice-over (optional) β€” turn captions into a spoken narration with ElevenLabs or OpenAI TTS. Each line is pre-synthesized and the screen is held while it plays, so audio stays perfectly synced to the subtitles. Configure once via env.
  • Self-contained output β€” bundled ffmpeg (via ffmpeg-static) produces a clean H.264 .mp4.
  • Robust β€” per-action timeouts; mark a step optional so a missing selector doesn't abort the take.
  • **Web and mobile β€” Playwright for the web; adb screen-record + ffmpeg caption-burn for Android / Flutter** apps (no app source needed).
  • Use it from an AI (MCP tool) or straight from Node.

πŸ“¦ Requirements

  • Node.js 18+
  • A Chromium build for Playwright: npx playwright install chromium (run automatically on npm install).

πŸš€ Install

# from GitHub
npm install -g github:0xjesus/screenwright

# or clone
git clone https://github.com/0xjesus/screenwright.git
cd screenwright && npm install

πŸ”Œ Use as an MCP server

Add it to your MCP client. Claude Desktop / Claude Code (claude_desktop_config.json or .mcp.json):

{
  "mcpServers": {
    "screenwright": {
      "command": "node",
      "args": ["/absolute/path/to/screenwright/src/index.js"]
    }
  }
}

(If installed globally, you can use "command": "screenwright" with no args.)

Then just ask your assistant to record a tutorial β€” it calls the record_tutorial tool.

Tool: record_tutorial

| Field | Type | Notes | |---|---|---| | output | string | Path to the output .mp4. | | steps | step[] | Ordered steps (below). | | baseUrl | string? | So goto steps can use relative paths. | | viewport | {width,height}? | Default 1440Γ—900. | | headless | bool? | Default true. | | channel | string? | e.g. "chrome" to use the system browser. | | burnIn | bool? | Burn captions into the video. Default true. | | srt | string? | Custom .srt path. Default .captions.srt. | | tts | object? | Voice-over β€” see [πŸŽ™οΈ Voice-over](#️-voice-over-tts). | | captionStyle | object? | { position, fontSize, bg, color, maxWidth }. |

Step = { caption?, narration?, action, url?, selector?, text?, key?, deltaY?, delayMs?, timeoutMs?, dwellMs?, optional? }. selector is any Playwright selector β€” CSS, text=…, xpath=…, or :has-text(…).

Tool: record_android_tutorial πŸ“±

Same idea, for a Flutter / Android app on an emulator or device. Captions can't be injected into a native app, so the screen is recorded with adb screenrecord and the captions are burned in afterwards with ffmpeg (libass) from the synced .srt.

Requires: Android platform-tools (adb) + a running emulator/device (it must show in adb devices). For Flutter: flutter emulators --launch , then run your app.

| Field | Notes | |---|---| | output | Output .mp4. | | steps | Ordered steps (below). | | serial | adb -s serial when several devices are connected. | | size | Recording size "WxH" (default: device resolution). | | bitRate Β· srt Β· burnIn Β· adbPath Β· captionStyle | Optional. | | tts | Voice-over β€” see [πŸŽ™οΈ Voice-over](#️-voice-over-tts). |

Step actions (coordinates are device pixels) β€” each may carry a caption and dwellMs:

  • tap β€” { x, y }
  • text β€” { text }
  • swipe β€” { x1, y1, x2, y2, durationMs? }
  • key β€” { key } (BACK, HOME, ENTER, MENU, APP_SWITCH, or a KEYCODE_*)
  • launch β€” { package, activity? }
  • wait β€” { dwellMs }

See examples/android-flutter.json. From Node: import { recordAndroidTutorial } from 'screenwright/android'.

πŸŽ™οΈ Voice-over (TTS)

Turn your captions into a real spoken narration β€” same tool, both drivers (web + Android). Provider and voice are set once via env (the same MCP config), so any record_* call with captions gets narrated automatically. Each line is synthesized before recording and the screen is held while it plays β†’ the voice stays locked to the burned-in subtitles.

Configure in your MCP server env (or shell):

{
  "mcpServers": {
    "screenwright": {
      "command": "node",
      "args": ["/absolute/path/to/screenwright/src/index.js"],
      "env": {
        "SCREENWRIGHT_TTS_PROVIDER": "elevenlabs",
        "ELEVENLABS_API_KEY": "sk_...",
        "ELEVENLABS_VOICE_ID": "21m00Tcm4TlvDq8ikWAM",
        "ELEVENLABS_MODEL": "eleven_multilingual_v2"
      }
    }
  }
}

OpenAI instead: SCREENWRIGHT_TTS_PROVIDER=openai, OPENAI_API_KEY=..., OPENAI_TTS_VOICE=onyx, OPENAI_TTS_MODEL=gpt-4o-mini-tts.

Per-call override (wins over env), plus a narration field when the spoken line should differ from the on-screen caption:

await recordAndroidTutorial({
  output: 'out/tour.mp4',
  tts: { provider: 'elevenlabs', voiceId: '…', speed: 1.0, stability: 0.5 },
  steps: [
    { action: 'launch', package: 'com.acme.app', caption: 'Meet Acme', narration: 'This is Acme β€” your market copilot.', dwellMs: 1500 },
    { action: 'tap', x: 540, y: 1925, caption: 'Generate a signal', dwellMs: 1000 },
  ],
});
// β†’ { mp4, srt, durationMs, steps, captions, narration: { provider, lines } }
  • tts fields: provider (elevenlabs|openai), apiKey?, voiceId?/voice?, model?, speed?, stability?, similarityBoost?, style?, tailPadMs? (silence after each line, default 450).
  • Requires the bundled ffmpeg (already a dependency) to mix + mux the audio. Multilingual voices (e.g. eleven_multilingual_v2) narrate Spanish/English captions cleanly.
  • No tts and no env provider β†’ silent captions, exactly as before.

πŸ§ͺ Use from Node (no MCP)

node scripts/run-example.js                 # records examples/demo.json
node scripts/run-example.js examples/capleton.json
import { recordTutorial } from 'screenwright/recorder';

await recordTutorial({
  output: 'out/tour.mp4',
  baseUrl: 'https://playwright.dev',
  steps: [
    { action: 'goto', url: '/', caption: 'Welcome to the tour 🎬', dwellMs: 2600 },
    { action: 'scroll', deltaY: 600, caption: 'Each step can carry a synced subtitle…', dwellMs: 2400 },
    { action: 'goto', url: '/docs/intro', caption: '…burned into the video and exported as .srt', dwellMs: 3000 },
  ],
});
// β†’ { mp4, srt, durationMs, steps, captions }

πŸ’‘ Tips

  • Don't double your subtitles. The .mp4 already has burned-in captions. Players like VLC auto-load an .srt that shares the video's name and draw it on top. Screenwright defaults the sidecar to *.captions.srt (a non-matching name) so that doesn't happen β€” keep it that way, or disable the subtitle track in your player. Want selectable-only subs? Pass burnIn: false for a clean video + the .srt.
  • Black video in VLC on Linux? That's a GPU/output glitch, not the file. Launch with vlc --avcodec-hw=none --vout=xcb_x11, or set those in VLC β†’ Preferences.
  • Headless still records β€” no display needed.

πŸ“ License

MIT Β© 0xjesus

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source β€” we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.