Playwright E2E MCP

Ejecuta, depura e inspecciona pruebas de extremo a extremo de Playwright desde cualquier agente de IA: resultados estructurados con diagnósticos de fallos archivo:línea, inspección de DOM en vivo, validación de selectores, diferencias visuales y diagnóstico de pruebas inestables.

Servidor MCP alojado

npx add-mcp 'https://playwright-e2e-mcp.vercel.app/api/mcp'

Se instala en Claude Code, Codex, Cursor y más

Documentación

playwright-e2e-mcp

CI release MCP Registry

Un servidor MCP que permite a los agentes de IA ejecutar, depurar e inspeccionar pruebas end-to-end de Playwright — con resultados estructurados, diagnósticos de fallos accionables e inspección de DOM en vivo.

run-test ──▶ get-failure ──▶ inspect-page ──▶ validate-selector ──▶ fix ──▶ re-run
   ▲                                                                    │
   └──────────────────────── list-tests ◀────────────────────────────────┘

En lugar de entregar al agente la salida cruda de Playwright, este servidor convierte cada ejecución en resultados procesables por máquina: estadísticas de aprobados/fallidos, mensajes por fallo con file:line, un tipo de fallo (aserción, tiempo de espera, cierre del navegador, error de sintaxis, servidor de desarrollo caído, disco lleno…), y una pista concreta de "cómo solucionarlo". Cuando una prueba falla porque un selector ya no coincide, el agente puede abrir la página en vivo en un navegador sin interfaz, ver el DOM real con selectores CSS únicos y validar el selector de reemplazo antes de volver a ejecutar.

Demo

Endpoint alojado — lo que un viaje de ida y vuelta de initialize + tools/list contra https://playwright-e2e-mcp.vercel.app/api/mcp devuelve para un cliente que envía el token de portador (sin uno, solo se listan list-tests y get-failure):

Token-protected endpoint: initialize handshake and all 8 tools

Una ejecución de prueba real — run-test servido a través de stdio por npx -y playwright-e2e-mcp contra el examples/sample-test.spec.ts incluido (salida real, sin editar):

run-test result: 4 passed, 0 failed, 5.1s

Las imágenes se renderizan con node scripts/gen-demo-images.mjs: la tarjeta de ejecución de prueba es salida capturada real; la tarjeta de endpoint es una ilustración del listado autenticado.

Instalación

Funciona con Claude Desktop, Claude Code, Cursor, Windsurf, Codex, Gemini CLI, Freebuff y cualquier otro cliente MCP — elige la ruta que mejor se adapte:

RutaCómo
npm (canónico, más rápido)npx -y playwright-e2e-mcp
Registro MCP (los clientes que conocen el registro lo descubren automáticamente)io.github.trajectiq-ai/E2E — listado
Cualquier cliente, sin necesidad de cuenta npmnpx -y github:trajectiq-ai/E2E#v0.1.2 (fija una etiqueta de versión)
Claude Desktop, sin configuración de Nodedoble clic en la extensión .mcpb
Clientes solo remotos (conectores ChatGPT)https://playwright-e2e-mcp.vercel.app/api/mcp

Detalles y configuración por cliente: Instalación · Configuración del cliente MCP.


Herramientas

HerramientaPropósito
run-testEjecutar pruebas de Playwright y devolver estadísticas, fallos, diagnósticos y pistas
get-failureAnálisis profundo de un fallo: pila, esperado/real, instantánea del DOM en el fallo (del trace de Playwright), siguientes pasos
inspect-pageAbrir una URL sin interfaz y devolver el DOM renderizado: selectores, visibilidad, cajas, texto, salida de consola, HTML
list-testsListar pruebas disponibles (file, line, título completo, proyectos) con filtrado
validate-selectorComprobar un selector CSS contra una página en vivo: validez, número de coincidencias, ejemplos de coincidencias
generate-e2e-testCrear una prueba de Playwright a partir de una descripción usando los selectores reales del proyecto, descubiertos a partir de cambios recientes de archivos
compare-visual-stateRegresión visual: captura de pantalla antes/después de un cambio e informe de qué se movió y cómo cambiaron los colores
diagnose-flakyEjecutar una prueba fallida 2–10 veces con reintentos deshabilitados y devolver un veredicto de evidencia: CONSISTENTLY FAILING, FLAKY o NOT REPRODUCING

run-test

ArgumentoTipoDescripción
projectRootstringDirectorio del proyecto dentro de la raíz configurada (predeterminado: directorio de trabajo del servidor)
testFilesstring[]Archivos/directorios relativos a la raíz; se admiten file:line. Omitir para ejecutar todo
grepstringEjecutar solo pruebas cuyo título coincida con esta expresión regular
browserchromium | firefox | webkitProyecto de Playwright a ejecutar (coincidido contra los nombres de proyecto de la configuración)
headedbooleanVentana de navegador visible
timeoutMsnumberLímite de tiempo real duro para la ejecución (predeterminado 120000); todo el árbol de procesos se mata al superarlo y se devuelven resultados parciales
testTimeoutMsnumberTiempo de espera por prueba pasado a Playwright
workers / retriesnumberSe pasan a Playwright
configstringRuta de playwright.config o índice basado en 1 cuando el proyecto tiene varios
retryOnFailurebooleanReintentar automáticamente los fallos una vez antes de informarlos (predeterminado true; ignorado cuando retries está establecido)
lastFailedbooleanSolo volver a ejecutar pruebas que fallaron en la ejecución anterior (Playwright --last-failed) — el bucle rápido de corregir → re-ejecutar
argsstring[]Banderas adicionales de Playwright de una lista permitida (--repeat-each=N, --max-failures=N, --update-snapshots, --shard=1/3, --trace=on, …); los valores van después de = y se verifican, y las banderas que toman una ruta, como --config o --output, se rechazan

Manejo de inestabilidad: por defecto el servidor inyecta --retries=1 (a menos que la configuración ya establezca retries), por lo que una prueba que pasa en el reintento se informa como inestable, no fallida. Los traces se capturan automáticamente (--trace=retain-on-failure) para que get-failure pueda mostrar el DOM en el momento del fallo.

Ejemplo de resultado:

## Playwright run — ❌ FAILED

**Command:** `playwright test --config playwright.config.ts tests/checkout.spec.ts --reporter=json`
**duration 4.2s · exit 1 · config `playwright.config.ts`**

| passed | failed | flaky | skipped | duration |
| ---: | ---: | ---: | ---: | ---: |
| 0 | 1 | 0 | 0 | 1.1s |

### ❌ 1 failing test(s)

### 1 of 1. checkout.spec.ts › pays with card
**File:** `checkout.spec.ts:5`  |  **failed · server-unreachable**

### ⚠️ SERVER_NOT_RUNNING
Your app (dev server) does not appear to be reachable. Start it in another terminal
(e.g. npm run dev / npm start), keep it running, then retry — or configure `webServer`
in playwright.config.* so Playwright starts it automatically.

get-failure

ArgumentoTipoDescripción
indexnumberÍndice de fallo basado en 1 de la última ejecución (predeterminado 1)
projectRootstringSolo se usa al releer el informe almacenado

Devuelve el mensaje/marco de código, esperado vs real, pila, tipo de fallo con un diagnóstico, la salida de consola de la prueba, la instantánea del DOM del trace de Playwright (más la acción fallida, su selector y el registro de acciones que llevaron a ella), las solicitudes de red que fallaron (4xx/5xx, endpoints muertos, sin respuesta — con método, URL, estado y tipo de recurso), los errores/advertencias de consola que la página registró antes del fallo, y pasos siguientes numerados (re-ejecutar esta prueba individual por file:line, modo con interfaz/depuración, validate-selector cuando el mensaje menciona un localizador, …).

inspect-page

ArgumentoTipoDescripción
urlstringURL http(s) completa a abrir (obligatorio)
projectRootstringProyecto cuyo Playwright lanza el navegador
selectorstringInspeccionar coincidencias de este selector CSS en lugar de todo el DOM
waitForstringEsperar un selector (CSS o text=…) antes de inspeccionar
waitUntilload | domcontentloaded | networkidleCondición de espera de navegación
includeHtmlbooleanIncluir el HTML renderizado (limitado)
maxHtmlCharsnumberLímite de HTML, predeterminado 20000
timeoutMsnumberLímite general, predeterminado 45000

Devuelve el selector CSS único de cada elemento, etiqueta, visibilidad, caja delimitadora, texto y atributos, más los mensajes de consola capturados (errores primero).

list-tests

ArgumentoTipoDescripción
projectRootstringDirectorio del proyecto
configstringRuta de configuración o índice basado en 1
testDirstringRestringir el escaneo a un directorio (debe permanecer dentro del proyecto)
filterstringFiltro de subcadena sin distinción de mayúsculas/minúsculas en file › title
limitnumberMáximo de pruebas devueltas, predeterminado 500

Usa playwright test --list cuando Playwright funciona, y vuelve a un escaneo de código fuente (manteniendo la razón) cuando la instalación o un archivo de especificaciones está roto.

validate-selector

ArgumentoTipoDescripción
urlstringPágina en vivo para probar (obligatorio)
selectorstringSelector CSS a validar (obligatorio)
projectRootstringProyecto cuyo Playwright lanza el navegador
timeoutMsnumberLímite general, predeterminado 45000

Veredictos: ✅ VALID — N matches (con una muestra de coincidencias), ✅ VALID — 0 matches (con consejos de depuración), ❌ INVALID (error de análisis + corrección), o una advertencia cuando la entrada usa un motor solo de Playwright (text=, xpath=, >>, :has-text()), que no es CSS plano.

generate-e2e-test

ArgumentoTipoDescripción
descriptionstringLo que la prueba debe cubrir (obligatorio)
pageUrlstringPágina en la que comienza la prueba (predeterminado: baseURL / webServer.url de la configuración)
testDir / filestringDónde escribir la especificación (predeterminado: testDir detectado + generated/<slug>.spec.ts); file debe terminar en .spec.* o .test.*
writebooleanEscribir el archivo en disco (predeterminado true)
overwritebooleanReemplazar una especificación existente en la ruta de destino; solo las especificaciones generadas por esta herramienta pueden reemplazarse
liveInspectbooleanVerificar selectores contra la página en vivo (predeterminado activado cuando se conoce una URL)
projectRoot / configstringIgual que las otras herramientas

Lee los cambios recientes del agente (git status, con respaldo a git diff HEAD~1, luego mtimes recientes), extrae los localizadores que esos archivos realmente declaran (data-testid, getByRole, aria-label, placeholder, id, name, texto de elemento), clasifica primero los selectores verificados en vivo, escribe una especificación construida a partir de ellos e informa cada selector con su file:line de origen.

compare-visual-state

ArgumentoTipoDescripción
urlstringPágina a capturar (obligatorio)
namestringId de línea base, p. ej. checkout-page (letras, dígitos, . _ -)
actioncompare | baselinecompare (predeterminado) diffs; baseline re-captura la referencia
selectorstringCapturar solo este elemento
fullPagebooleanCapturar la página completa desplazable
tolerancenumberPorcentaje de píxeles que pueden diferir (predeterminado 0.1)
pixelThresholdnumberDelta de canal por píxel considerado diferente (predeterminado 60)
waitUntil / waitFor / timeoutMs—Igual que inspect-page

La primera llamada guarda una línea base bajo .pw-mcp/visual/ (agrega eso a .gitignore, o haz commit para comparaciones de CI). Las llamadas posteriores informan recuentos de píxeles cambiados, regiones fusionadas ((x, y) 120×40 — 1,200 px), el cambio de color promedio ("azul → rojo"), y escriben una imagen de diff resaltada en rojo para revisión.

diagnose-flaky

ArgumentoTipoDescripción
testFilesstring[]Pruebas a diagnosticar (se admiten file:line). Predeterminado: las pruebas que fallaron en la ejecución más reciente
runsnumberVeces a ejecutarlas, 2–10 (predeterminado 3)
browser / headed / workers / config—Igual que run-test
timeoutMsnumberLímite de tiempo real duro por ejecución (predeterminado 120000)
projectRootstringDirectorio del proyecto

Cada ejecución se realiza con --retries=0 y reintento automático deshabilitado, por lo que cada resultado es evidencia honesta. La respuesta contiene una tabla por ejecución (estado, duración, primer fallo), el recuento de firmas de error normalizadas distintas, y uno de:

  • ❌ FALLANDO CONSISTENTEMENTE — falló en cada ejecución (mismo error → error reproducible, errores diferentes → aún roto, solo ruidoso). Arrégialo; no es inestable.
  • ⚠️ INESTABLE — algunas ejecuciones pasaron. Incluye recuentos de N of M y si los fallos comparten una firma (error intermitente real) o varían (inestabilidad de tiempo/entorno).
  • ✅ NO SE REPRODUCE — pasó en cada re-ejecución; el fallo original fue de una sola vez.

La última ejecución se almacena, por lo que get-failure puede analizarla inmediatamente después.


Instalación

Requisitos:

  • Node.js ≥ 20 (el servidor está construido sobre MCP SDK v2 — la línea de especificación 2026-07-28)
  • Un proyecto con @playwright/test instalado y navegadores disponibles (npx playwright install chromium)

No se necesita cuenta de npm — instala directamente desde GitHub (el script prepare compila dist/ automáticamente al instalar). Fija una etiqueta de versión: un github:trajectiq-ai/E2E sin fijar ejecuta lo que haya en la rama predeterminada en ese momento.

npx -y github:trajectiq-ai/E2E#v0.1.2
npm install -D github:trajectiq-ai/E2E#v0.1.2 @playwright/test   # or as a project dependency
npx playwright install chromium

O descarga el paquete comprimido desde la página de GitHub Releases del repositorio e instálalo localmente:

npm install -D https://github.com/trajectiq-ai/E2E/releases/download/v0.1.2/playwright-e2e-mcp-0.1.2.tgz

Listado en el Registro MCP oficial como io.github.trajectiq-ai/E2E — los clientes compatibles con el registro lo descubren allí, y cada etiqueta de versión v* republica la entrada desde CI mediante server.json.

Configuración del cliente MCP

Claude Code / genérico (a nivel de proyecto):

{
  "mcpServers": {
    "playwright-e2e": {
      "command": "npx",
      "args": ["-y", "github:trajectiq-ai/E2E#v0.1.2"],
      "env": { "PW_MCP_PROJECT_ROOT": "/absolute/path/to/your/project" }
    }
  }
}

Claude Desktop / Cursor / Windsurf: agrega el mismo bloque a su archivo de configuración MCP. El servidor usa su directorio de trabajo como raíz del proyecto; establece PW_MCP_PROJECT_ROOT cuando el cliente lo inicie en otro lugar (por ejemplo, tu directorio personal).

CLIs de Codex / VS Code / Copilot:

codex mcp add playwright-e2e -- npx -y github:trajectiq-ai/E2E#v0.1.2
code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:trajectiq-ai/E2E#v0.1.2"]}'

Los valores predeterminados de Codex entran en conflicto con este servidor: el primer lanzamiento clona el repositorio y ejecuta tsc (medido 30 s en una caché fría de npx, frente a un valor predeterminado de 10 s de startup_timeout_sec), y una ejecución de Playwright con reintentos supera el valor predeterminado de 60 s de tool_timeout_sec. Aumenta ambos en ~/.codex/config.toml:

[mcp_servers.playwright-e2e]
command = "npx"
args = ["-y", "github:trajectiq-ai/E2E#v0.1.2"]
startup_timeout_sec = 60
tool_timeout_sec = 600

Claude Desktop (un clic): descarga y haz doble clic en la Extensión de Escritorio .mcpb adjunta a la última versión — el paquete incluye sus propias dependencias, por lo que no se requiere configuración de Node. Al instalarlo, te pide que elijas tu raíz del proyecto (obligatorio, sin valor predeterminado: elige la carpeta del proyecto, no tu directorio personal) y la conecta a PW_MCP_PROJECT_ROOT, de modo que las herramientas apunten a un proyecto real desde la primera llamada.

Claude Code:

claude mcp add playwright-e2e -- npx -y github:trajectiq-ai/E2E#v0.1.2

Gemini CLI / Qwen Code: pega el bloque mcpServers anterior en .gemini/settings.json (Qwen Code: .qwen/settings.json) — ambos hablan el mismo formato de configuración de MCP.

Freebuff / Codebuff (a nivel de proyecto): este repositorio incluye un .agents/mcp.json confirmado, por lo que abrir el checkout en Freebuff adjunta el servidor a todo el espacio de trabajo — no se necesita configuración global. Tus propios proyectos pueden hacer lo mismo: coloca un mcp.json con el bloque anterior en su directorio .agents/. Freebuff te pide que confíes en el .agents/ de un repositorio en la primera ejecución.

Todas las herramientas incluyen anotaciones de herramientas MCP (readOnlyHint, destructiveHint, idempotentHint, openWorldHint), para que los clientes puedan mostrar avisos de seguridad precisos antes de ejecutar cualquier cosa.

Desde un checkout local:

{
  "mcpServers": {
    "playwright-e2e": {
      "command": "node",
      "args": ["/path/to/playwright-e2e-mcp/dist/index.js"],
      "env": { "PW_MCP_PROJECT_ROOT": "/path/to/your/project" }
    }
  }
}

Endpoint alojado (ChatGPT y clientes remotos)

Algunos clientes — especialmente los conectores personalizados de ChatGPT — solo aceptan servidores MCP HTTPS remotos y se niegan a iniciar un proceso local de npx. Este repositorio incluye un puente HTTP Streamable para exactamente ese caso:

Endpointhttps://playwright-e2e-mcp.vercel.app/api/mcp
TransporteMCP Streamable HTTP (JSON POST de entrada, JSON o SSE de salida)
Autenticacióntoken bearer opcional (PW_MCP_HTTP_TOKEN); sin uno solo se sirven herramientas de solo lectura
Fuenteapi/mcp.ts → src/http.ts

El puente ejecuta el mismo createServer() que el transporte stdio; el SDK atiende cada solicitud con una instancia de servidor nueva, que es lo que una función serverless quiere. test/http-bridge.test.mjs impulsa el adaptador real de Node a través de node:http, por lo que un puente roto falla en CI, no en ChatGPT.

Abierto vs. protegido por token. Cuando la implementación no tiene PW_MCP_HTTP_TOKEN, cualquiera puede alcanzar la URL, por lo que el puente sirve solo list-tests y get-failure, en modo restringido: list-tests escanea fuentes en lugar de ejecutar playwright test --list (que ejecutaría la configuración del proyecto), los llamadores no pueden elegir otro projectRoot, y nada inicia un proceso, maneja un navegador o escribe un archivo. Establece PW_MCP_HTTP_TOKEN (al menos 16 caracteres; usa un valor aleatorio) para servir las ocho herramientas a clientes que envíen Authorization: Bearer <token>; otras solicitudes reciben 401. Los procesos secundarios iniciados a través de HTTP obtienen solo un entorno en la lista de permitidos. PW_MCP_ALLOWED_HOSTS (separados por comas, * para cualquiera) limita el encabezado Host aceptado; sin token y sin esa variable, solo se aceptan nombres localhost y los nombres de host de Vercel de la implementación (protección contra el reenlace de DNS).

Agrégalo a ChatGPT: Configuración → Conectores → activa Modo avanzado → Desarrollador → Crear conector personalizado → pega el endpoint anterior → autenticación Ninguna (herramientas de solo lectura).

Codex también puede usar el transporte remoto en lugar de iniciar npx, si prefieres no enviar Playwright a cada máquina:

codex mcp add playwright-e2e-remote --url https://playwright-e2e-mcp.vercel.app/api/mcp

Qué esperar: list-tests funciona e informa las especificaciones incluidas con la implementación. Incluso con un token, las herramientas que inician un navegador (run-test, inspect-page, validate-selector, diagnose-flaky, …) no pueden descargar Chromium en una función serverless, por lo que devuelven su pista normal de NO_PLAYWRIGHT. Usa la instalación stdio para ejecuciones reales; el endpoint alojado es para descubrimiento y para clientes que no pueden ejecutar procesos locales.

# verify the handshake without any client
curl -X POST https://playwright-e2e-mcp.vercel.app/api/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

Redespliega después de un cambio: fusiona en main. La integración de Git de Vercel implementa cada push, por lo que no hay token que gestionar ni paso de CLI — observa el estado de confirmación de Vercel para el resultado de la implementación.

Configuración

Variable de entornoPredeterminadoPropósito
PW_MCP_PROJECT_ROOTcwd del servidorRaíz del proyecto predeterminada para cada herramienta
PW_MCP_ALLOWED_ROOTS—Directorios adicionales que un llamador puede pasar como projectRoot (separados por :, ; en Windows). Cualquier cosa fuera de estos y de la raíz predeterminada se rechaza
PW_MCP_HTTP_TOKEN—Solo puente HTTP: token bearer (16+ caracteres) que desbloquea todas las herramientas (ver arriba)
PW_MCP_ALLOWED_HOSTSlocalhost + nombres de host de Vercel cuando no hay tokenSolo puente HTTP: lista de permitidos de Host separada por comas; * acepta cualquiera
PW_MCP_PASSTHROUGH_ENV—Solo puente HTTP: variables adicionales separadas por comas pasadas a las ejecuciones de prueba (por ejemplo, BASE_URL)
PW_MCP_MAX_CHILDREN4Solo puente HTTP: cuántas ejecuciones de prueba y sondeos de navegador pueden ejecutarse a la vez
PW_MCP_BLOCK_PRIVATE_URLSdesactivado (activado para el puente HTTP)1 hace que las herramientas de URL rechacen direcciones de bucle local, red privada y metadatos de nube, incluidos redireccionamientos y subrecursos
LOG_LEVELinfodebug | info | warn | error | silent
LOG_FORMATtexttext o json (estructurado)

Los registros siempre van a stderr — stdout está reservado para el protocolo MCP.

Flujo de trabajo típico

  1. generate-e2e-test { "description": "checkout with a saved card" } — crea una especificación a partir de tus selectores reales (se omite si escribes la prueba tú mismo).
  2. list-tests — mira lo que existe (tests/checkout.spec.ts:5 checkout › pays with card).
  3. run-test { "testFiles": ["tests/checkout.spec.ts"] } — ejecútala; obtén estadísticas + fallos (las pruebas inestables se reintentan automáticamente una vez antes de considerarse fallos).
  4. get-failure { "index": 1 } — lee el marco de código, esperado/real, la instantánea del DOM en el fallo desde el trace, las solicitudes de red fallidas, los errores de consola de la página y los siguientes pasos.
  5. Si parece relacionado con selectores: inspect-page { "url": "http://localhost:3000/checkout" } para ver el DOM real, luego validate-selector para probar que el selector de reemplazo funciona.
  6. Después de cambiar CSS/componentes: compare-visual-state { "url": "…", "name": "checkout" } para detectar regresiones visuales no intencionadas.
  7. Si un fallo parece intermitente: diagnose-flaky { "runs": 3 } — obtén el veredicto de evidencia (inestable vs. consistentemente roto) antes de decidir qué corregir.
  8. Corrige la especificación o la aplicación, luego vuelve a ejecutar solo lo que falló: run-test { "lastFailed": true }, y repite hasta que esté en verde.

Casos límite manejados

SituaciónComportamiento
Playwright no instaladoError NO_PLAYWRIGHT con los comandos de instalación exactos para tu gestor de paquetes
Servidor de desarrollo no ejecutándoseFallo clasificado como server-unreachable / SERVER_NOT_RUNNING con una pista de "inicia tu servidor de desarrollo" (y consejo de webServer)
La prueba excede timeoutMsEl grupo de procesos se elimina (SIGINT→SIGKILL en POSIX, taskkill /T /F en Windows) y se devuelven resultados parciales
El navegador se bloqueaClasificado como browser-crash con guía de reintento / reinstalación
Barras invertidas de WindowsTodas las rutas se normalizan léxicamente (C:\a\..\b → C:/b); probado unitariamente en ambas plataformas
Pruebas inestablesLas pruebas que fallan se reintentan automáticamente una vez (--retries=1) antes de informarse; los pases aparecen como inestables con una advertencia de estabilidad; diagnose-flaky decide inestable-vs-roto con evidencia de múltiples ejecuciones
Contexto de trace/DOM--trace=retain-on-failure se pasa automáticamente, por lo que get-failure puede mostrar el DOM exacto en el momento del fallo — además de las solicitudes de red fallidas (registros de *.network) y errores de consola del mismo trace
Re-ejecuciones lentas después de una correcciónrun-test con lastFailed: true re-ejecuta solo las pruebas que fallaron la última vez (--last-failed)
Varios archivos playwright.configDevuelve un menú numerado (MULTIPLE_CONFIGS); elige con config: "2" o una ruta
Error de sintaxis en una especificaciónSYNTAX_ERROR con archivo:línea; nada se bloquea; list-tests recurre a un escaneo de fuentes
El cliente MCP se desconectaEl AbortSignal por solicitud elimina la ejecución; el fin de stdin activa el apagado, y cada árbol de procesos secundarios rastreado se elimina a la fuerza (killActiveChildren)
Disco llenoENOSPC detectado → DISK_FULL con una pista de "libera espacio"; el registro nunca lanza excepciones
Rutas maliciosas../../etc/passwd, rutas absolutas fuera de la raíz, un projectRoot fuera de las raíces permitidas, enlaces simbólicos que salen de la raíz, URLs y bytes nulos se rechazan con INVALID_PATH; los argumentos CLI adicionales deben ser banderas de Playwright en la lista de permitidos

Notas de seguridad

  • Sin shell: Playwright se lanza como node <playwright/cli.js> … con un array de argumentos — sin interpolación de comandos. Los args adicionales se limitan a una lista permitida de flags de Playwright, cada uno con un valor verificado (--flag=value), por lo que un llamador no puede intercambiar otro --config o --output ni pasar a git una opción a través de --only-changed. Las rutas con un segmento que comienza con - se rechazan, por lo que un nombre de archivo de prueba no puede leerse como un flag.
  • Sandbox de rutas: las rutas del usuario deben permanecer dentro de la raíz del proyecto, verificadas léxicamente y nuevamente con los enlaces simbólicos resueltos. Un projectRoot proporcionado por el llamador debe estar dentro de PW_MCP_PROJECT_ROOT (o una entrada de PW_MCP_ALLOWED_ROOTS).
  • Código generado: generate-e2e-test solo escribe archivos *.spec.* / *.test.*, solo sobrescribe especificaciones cuyo encabezado escribió él mismo, nunca escribe a través de un enlace simbólico, y escapa cada valor que coloca en cadenas o comentarios.
  • Puente HTTP: herramientas de solo lectura a menos que PW_MCP_HTTP_TOKEN esté configurado; los procesos hijos iniciados a través de HTTP reciben solo un entorno de lista permitida (PATH, HOME, directorios temporales, locale, CI, PLAYWRIGHT_*, npm_config_* sin credenciales incrustadas, más cualquier cosa en PW_MCP_PASSTHROUGH_ENV), como máximo PW_MCP_MAX_CHILDREN se ejecutan a la vez (un cliente desconectado libera su espacio inmediatamente), y los mensajes de error internos no se devuelven a los clientes. La lista permitida solo cubre el entorno del propio hijo: el código de prueba se ejecuta como el mismo usuario del SO, por lo que en Linux podría leer el entorno de inicio del servidor desde /proc. Por eso solo los titulares de tokens pueden ejecutar código del proyecto; mantén otros secretos fuera del entorno del puente, o ejecútalo bajo un usuario separado.
  • Protección SSRF: en el puente HTTP (o con PW_MCP_BLOCK_PRIVATE_URLS=1) las herramientas de URL rechazan hosts que resuelven a direcciones de loopback, privadas, link-local/metadata o reservadas, y enrutan el navegador a través de un proxy local que aplica la misma verificación a cada salto de redirección y subrecurso; las formas IPv6 que incrustan una dirección IPv4 (mapeada, NAT64, 6to4, Teredo) también se bloquean, y WebRTC UDP está deshabilitado para que una página no pueda alcanzar la red alrededor del proxy. Está desactivado para stdio por defecto porque abrir servidores de desarrollo http://localhost es para lo que sirven estas herramientas.
  • Limpieza: los archivos temporales de informes/scripts se escriben en el directorio temporal del SO y se eliminan; los procesos hijos se rastrean y se matan al apagar. La descompresión de trazas tiene un presupuesto de tamaño por archivo, y los PNG están limitados a 16,384 px por lado y 50 M píxeles.

Desarrollo

src/
├── index.ts            # bin entry point (--version/--help, main-module guard)
├── server.ts           # McpServer setup, tool registration, shutdown handling
├── tools/              # the eight tools + shared plumbing
├── utils/              # playwright-runner, report-parser, project-detector, path-utils,
│                       # logger, trace-reader (trace.zip → DOM/network/console),
│                       # image-diff (PNG codec + pixel diff), change-analyzer
└── types/              # shared interfaces and the ErrorKind taxonomy

Construido sobre @modelcontextprotocol/server v2 (la línea de especificación MCP 2026-07-28) con esquemas estándar Zod v4; cada herramienta declara anotaciones de herramienta de especificación.

npm install
npm run build   # tsc → dist/ (zero errors)
npm test        # build + test/run-tests.mjs (unit tests, any Node ≥20)
npm run e2e     # build + e2e/run.mjs: live MCP ↔ Playwright integration suite

Las pruebas cubren el analizador de informes (JSON de Playwright de muestra, adjuntos de trazas), utilidades de rutas (rutas de Windows y macOS, sandboxing), el detector de proyectos (fixtures de directorios temporales: descubrimiento de configuración, múltiples configuraciones, instalación faltante, escaneo de archivos de prueba), los helpers compartidos de herramientas, el lector de trazas (trace.zip sintético: error, acción fallida, instantánea DOM, análisis de solicitudes fallidas *.network, eventos de consola de error/advertencia), el diff de imágenes (round-trip PNG, regiones, cambio de color, cambios de dimensiones), el analizador de cambios (extracción de selectores, rutas git + mtime), la lógica de veredicto flaky (firmas de fallo, CONSISTENTLY FAILING / FLAKY / NOT REPRODUCING / NO TESTS RAN), el puente HTTP (token, modo restringido, lista permitida de Host), las regresiones de seguridad (escapes de sandbox, contrabando de argumentos, escrituras de enlaces simbólicos, inyección de código, rangos SSRF, limpieza de entorno, límites de decodificación), el manifiesto .mcpb y los archivos de configuración MCP.

Suite de integración (npm run e2e)

Las pruebas unitarias prueban la lógica; la suite de integración prueba el bucle. Inicia el servidor real sobre stdio contra una aplicación fixture en vivo y un proyecto de Playwright bajo e2e/fixture/, luego lo maneja exactamente como un cliente MCP y afirma ~40 comportamientos que solo aparecen de extremo a extremo:

  • handshake de inicialización, 8 herramientas, anotaciones de herramienta de especificación y esquemas de entrada de objetos,
  • inspección DOM en vivo, validación de selectores CSS (coincidencias, cero coincidencias, sintaxis de motor, errores de análisis), detección de servidor muerto,
  • regresión visual: línea base → comparación sin cambios → detección de diff blue → red,
  • estadísticas de aprobado/fallido/run-test y líneas de metadatos lastFailed,
  • diagnósticos de traza get-failure: DOM en el fallo, la solicitud de red 404, el mensaje console.error, diagnóstico y próximos pasos,
  • reintento automático que convierte un fallo de primera ejecución en PASSED (1 flaky),
  • veredicto diagnose-flaky FLAKY (2 de 3 ejecuciones) con reintentos deshabilitados,
  • generate-e2e-test escribiendo su andamiaje, más rutas de error (ruta de prueba faltante, herramienta desconocida, servidor inalcanzable).

La primera ejecución necesita el navegador una vez: npx playwright install chromium. CI ejecuta la suite en Ubuntu y Windows (ver .github/workflows/ci.yml).

Prueba el ejemplo

Con Playwright instalado en tu proyecto:

npx playwright test examples/sample-test.spec.ts

o pide a tu agente que llame a run-test con "testFiles": ["examples/sample-test.spec.ts"] — accede a la página pública example.com, por lo que verifica navegadores, red y el pipeline MCP de una sola vez.

Licencia

MIT