214 lines
22 KiB
Markdown
214 lines
22 KiB
Markdown
# Playwright MCP mediante Docker
|
||
|
||
## Arquitectura y alcance
|
||
|
||
Codex arranca el servidor `playwright` definido en [`.codex/config.toml`](../.codex/config.toml). El cliente y el servidor intercambian JSON-RPC por stdin/stdout; Chromium headless se ejecuta dentro de la imagen oficial de Microsoft. No se instala un navegador en WSL ni se publica un puerto MCP.
|
||
|
||
```text
|
||
Codex ── stdio ── docker run ── Playwright MCP + Chromium headless
|
||
│ red host
|
||
▼
|
||
http://localhost:5173
|
||
│ Vite /api
|
||
▼
|
||
http://127.0.0.1:3001
|
||
│
|
||
MariaDB local :3307
|
||
```
|
||
|
||
5173 es el puerto habitual de Vite, no una constante impuesta por el proyecto: `apps/web/vite.config.ts` no fija `port` ni `strictPort`. Siempre comprobar la dirección anunciada al arrancar. El puerto 3001 corresponde a la API y no sirve la interfaz.
|
||
|
||
La configuración utiliza `--network=host` para que Chromium alcance el frontend mediante el mismo origen local que utiliza Metis. No monta el repositorio, archivos `.env`, perfiles del navegador ni el socket Docker dentro del contenedor. `--isolated` mantiene el perfil en memoria y `--rm` retira el contenedor al terminar. El directorio de salida de MCP está dentro del contenedor y es efímero. `--shm-size=1g` reserva capacidad de memoria compartida para Chromium, sin preasignar ese consumo.
|
||
|
||
La imagen oficial ejecuta Chromium sin su sandbox interno; el contenedor y la red host no son una frontera adecuada para visitar contenido no confiable. No añadir `--privileged`. La configuración está destinada a la aplicación local y no introduce un servicio MCP accesible por HTTP. Véase la [documentación oficial de Microsoft](https://github.com/microsoft/playwright-mcp).
|
||
|
||
## Requisitos y portabilidad WSL2
|
||
|
||
- WSL2 con Ubuntu 24.04 o equivalente, con el repositorio en el filesystem Linux.
|
||
- Node.js 24.x y PNPM según `packageManager` de `package.json`, para ejecutar Metis.
|
||
- Docker CLI y acceso a un daemon Linux desde el mismo usuario que ejecuta Codex. Comprobar `docker version`, `docker context show` y `docker info`.
|
||
- Python 3.11 o posterior para el comprobador incluido; utiliza solamente la biblioteca estándar. Ubuntu 24.04 proporciona Python 3.12.
|
||
- Acceso a `mcr.microsoft.com` para descargar la imagen, espacio para sus capas y la aplicación arrancada antes de navegar.
|
||
|
||
Python y Docker son requisitos del host. El instalador no utiliza sudo, no instala un daemon, no cambia grupos de usuarios ni habilita servicios del sistema: evita entrar en conflicto con Docker Desktop o un Engine ya existente. En Ubuntu 24.04, si falta Python, instalarlo explícitamente con `sudo apt-get update` y `sudo apt-get install python3`. Preparar Docker Engine local o Docker Desktop con integración WSL antes de ejecutar el instalador; Metis ya utiliza Docker para MariaDB. Si falta un requisito, el script termina con error y una indicación, sin anunciar una instalación completa.
|
||
|
||
Con Docker Engine dentro de la misma distribución WSL, la red host comparte directamente la red de esa distribución. Es el escenario probado aquí.
|
||
|
||
Con Docker Desktop, activar la integración con la distribución WSL y, en Docker Desktop 4.34 o posterior, **Settings → Resources → Network → Enable host networking**, aplicar y reiniciar. Requiere contenedores Linux; comprobar la conectividad con el procedimiento de este documento. Las condiciones y limitaciones están descritas en [Docker: host network driver](https://docs.docker.com/engine/network/drivers/host/). No se ha validado Docker Desktop en esta entrega.
|
||
|
||
Un contexto Docker remoto comparte la red del host del daemon, no la del terminal WSL que ejecuta el comando. No asumir que `localhost` corresponde entonces a Metis. Usar un daemon local compatible con esta configuración o diseñar y verificar la conectividad específica antes de utilizarla.
|
||
|
||
## Configuración MCP versionada
|
||
|
||
Hay una única entrada de proyecto, `mcp_servers.playwright`, con `command = "docker"` y transporte stdio implícito. No usar `-t`: asignar una TTY rompe la separación del protocolo. Tampoco añadir `-p`, `--port` ni un servidor HTTP MCP para este caso.
|
||
|
||
Imagen fijada:
|
||
|
||
```text
|
||
mcr.microsoft.com/playwright/mcp:v0.0.83@sha256:690763cbb437ee7233f538a953bb5390bf03791eb5c965b471e59d17a6132fcb
|
||
```
|
||
|
||
El 21 de octubre de 2026 se contrastaron el tag `v0.0.83` y el digest mediante `docker buildx imagetools inspect` contra Microsoft Container Registry. El digest identifica el índice multi-arquitectura, con manifiestos Linux amd64 y arm64; no obliga a usar una arquitectura concreta. La ejecución arm64 queda pendiente de validación.
|
||
|
||
Los plazos de arranque y de herramientas son 120 segundos. Descargar la imagen antes de iniciar Codex para que una conexión lenta no consuma el plazo de arranque.
|
||
|
||
Codex admite configuración local en `.codex/config.toml` y solo la carga en proyectos de confianza. Abrir este repositorio como proyecto de confianza y reiniciar la sesión después de cambiar la configuración. Comprobar `/mcp` en el cliente o `codex mcp list --json` desde la raíz. Debe aparecer un único `playwright` habilitado con transporte stdio. No ejecutar `codex mcp add` para duplicarlo en la configuración global. Referencias: [MCP en Codex](https://developers.openai.com/codex/mcp/) y [configuración de Codex](https://developers.openai.com/codex/config-basic/).
|
||
|
||
## Instalación en un equipo nuevo
|
||
|
||
Desde bash dentro de WSL, en la raíz del clon:
|
||
|
||
```bash
|
||
node --version
|
||
pnpm --version
|
||
python3 --version
|
||
docker version
|
||
docker context show
|
||
pnpm install --frozen-lockfile
|
||
```
|
||
|
||
Preparar la herramienta permanente de auditoría:
|
||
|
||
```bash
|
||
bash scripts/setup-playwright-wsl.sh
|
||
```
|
||
|
||
Se puede ejecutar desde cualquier directorio indicando la ruta del script; localiza el clon mediante su propia ubicación, sin rutas de usuario prefijadas. Requiere WSL2 y Python 3.11+, valida Docker Linux y lee la referencia de `.codex/config.toml`. Si la imagen exacta existe, la reutiliza; si falta, la descarga. No sobrescribe configuraciones ni instala paquetes de producción.
|
||
|
||
Después abre un endpoint temporal en `127.0.0.1` con un puerto asignado por el sistema y comprueba que el contenedor lo alcanza. Ese endpoint solo devuelve un token de diagnóstico y no sirve archivos. En el mismo contenedor arranca Chromium con la biblioteca Playwright incluida en la imagen y el canal `chromium`, igual que MCP. Se comprueba así la compatibilidad efectiva de navegador y biblioteca, además de la red host. El contenedor y el endpoint se retiran al terminar. Una segunda ejecución repite las comprobaciones sin reinstalar nada.
|
||
|
||
No ejecutar `npx playwright install` en el host ni instalar versiones separadas de Playwright: el servidor y los binarios compatibles se distribuyen juntos, fijados por el digest. En esta imagen el canal `chromium` utiliza el navegador completo en modo headless; un `chromium.launch()` sin canal intenta usar un headless shell que la imagen no incluye.
|
||
|
||
El instalador no arranca Metis ni valida la interfaz: completar la comprobación real descrita a continuación y abrir una nueva sesión Codex en el repositorio de confianza.
|
||
|
||
## Ejecución de Metis para auditorías y verificación
|
||
|
||
Preparar la base con `pnpm db:up`, según [puesta en marcha](puesta-en-marcha.md). Esto conserva el volumen y genera la configuración local si falta. No copiar secretos entre equipos ni versionar `.env`.
|
||
|
||
Para una comprobación aislada de datos reales, arrancar la API sobre la base de pruebas desde otra terminal WSL:
|
||
|
||
```bash
|
||
cd apps/server
|
||
DB_NAME=metis_desk_test NODE_ENV=test APP_ORIGIN=http://localhost:5173 PORT=3001 \
|
||
node --env-file=../../.env --import tsx src/index.ts
|
||
```
|
||
|
||
El arranque aplica las migraciones y la preparación normal a esa base de pruebas. No ejecutar dos API en el mismo puerto. En otra terminal, desde la raíz, arrancar Vite con un puerto explícito para esta comprobación:
|
||
|
||
```bash
|
||
pnpm --filter @metis/web exec vite --host 127.0.0.1 --port 5173 --strictPort
|
||
```
|
||
|
||
Si el puerto está ocupado, detener únicamente el proceso propio o elegir otro puerto y actualizar coherentemente el `APP_ORIGIN` de la API de prueba. Si se cambia el puerto de la API, proporcionar también `API_PROXY_TARGET` a Vite. Para el uso habitual, `pnpm dev` sigue siendo el procedimiento del proyecto; no sustituye el aislamiento de datos exigido para pruebas con persistencia.
|
||
|
||
Con ambos procesos disponibles:
|
||
|
||
```bash
|
||
python3 scripts/check-playwright-mcp.py http://localhost:5173
|
||
```
|
||
|
||
El argumento es obligatorio: indicar la URL real, sin credenciales. El comprobador lee la configuración versionada, arranca un contenedor temporal con ella, negocia MCP, descubre herramientas y ejecuta `browser_navigate`, `browser_evaluate` y `browser_take_screenshot`. Espera un formulario real de acceso/configuración y comprueba el título de Metis Desk y el user agent de Chromium headless. No envía formularios ni crea usuarios. Es una prueba de conexión y renderizado inicial, no una suite funcional de pantallas autenticadas.
|
||
|
||
El comprobador elimina exclusivamente su propio contenedor al terminar, incluso ante un fallo normal del cliente. No requiere un SDK MCP, Playwright instalado en WSL ni un navegador local. Después de la comprobación, detener las terminales de API y Vite con Ctrl+C si solo se arrancaron para ella.
|
||
|
||
## Clientes Codex y alternativa sin configuración global
|
||
|
||
La documentación oficial describe la configuración MCP compartida entre clientes del mismo host y la configuración de proyecto para repositorios de confianza. Esto no prueba que cualquier versión o sesión abierta haya cargado sus herramientas. Windows y WSL pueden tener instalaciones, permisos, PATH y configuraciones efectivas distintos. Referencias: [MCP](https://developers.openai.com/codex/mcp/), [configuración](https://developers.openai.com/codex/config-basic/) y [entornos Windows y WSL](https://developers.openai.com/codex/windows/).
|
||
|
||
| Cliente | Uso recomendado y alcance comprobado |
|
||
| --- | --- |
|
||
| Codex CLI en WSL | Lanzarlo desde el clon de confianza y comprobar `codex mcp list --json` y `/mcp` en la nueva sesión. CLI 0.114.0 reconoce aquí una única entrada de proyecto. El listado valida configuración; no sustituye una llamada real a sus herramientas. |
|
||
| Extensión de VS Code | Abrir el clon mediante Remote WSL y comprobar que Codex y Docker se ejecutan en esa distribución. Reiniciar la sesión tras cambios y revisar las herramientas disponibles. La extensión no se ha ejecutado ni validado en esta entrega. |
|
||
| Codex Desktop | Confirmar el host de ejecución del agente y del servidor MCP, el proyecto abierto y la configuración efectiva de esa versión. Un terminal integrado WSL no demuestra que un proceso MCP se lance en WSL. No se ha validado Desktop ni se afirma que todas sus versiones carguen correctamente la entrada de proyecto. Si no lo hace, usar el CLI WSL con la alternativa siguiente. |
|
||
| Sesión de agente ya abierta | La configuración puede aparecer en `mcp list` sin estar expuesta en su catálogo de herramientas. En esta sesión no se exponen herramientas Playwright directamente: las capturas se verifican con el cliente stdio independiente. Reabrir la sesión y comprobar `/mcp` antes de atribuir una prueba al cliente Codex. |
|
||
|
||
Si el cliente no carga el servidor del proyecto, el lanzador alternativo lee la misma entrada y la pasa al CLI mediante overrides `-c` válidos únicamente para ese proceso:
|
||
|
||
```bash
|
||
bash scripts/codex-playwright-wsl.sh mcp list --json
|
||
bash scripts/codex-playwright-wsl.sh
|
||
```
|
||
|
||
Localiza la raíz del clon, mantiene el nombre `playwright` y conserva el resto de ajustes del usuario. No escribe configuración global, no cambia `CODEX_HOME`, no copia autenticación y no requiere duplicar tags ni digests en el lanzador. Conserva stdin, terminal y señales para su uso interactivo. Los argumentos adicionales se pasan al CLI, por ejemplo `-c 'service_tier="fast"'` para la incompatibilidad concreta descrita en resolución de errores. `METIS_CODEX_BIN` permite seleccionar explícitamente otro ejecutable del CLI cuando el comando del PATH tenga problemas con su empaquetado; no se fija una ruta personal en Git.
|
||
|
||
Este mecanismo alternativo inicia el CLI; no registra automáticamente herramientas en la extensión o Desktop. Si sus políticas administradas impiden ejecutar Docker, resolver los permisos con el administrador: el lanzador no evita esas restricciones. El comprobador Python permite verificar stdio y la captura independientemente de la carga de herramientas del cliente, sin afirmar que con ello Desktop o la extensión estén validados.
|
||
|
||
## Conectividad y origen
|
||
|
||
La URL del navegador y `APP_ORIGIN` deben coincidir exactamente en esquema, host y puerto. `localhost` y `127.0.0.1` son orígenes distintos aunque alcancen el mismo servicio. Si se usa el origen LAN del proyecto, comprobar ese origen y la configuración de la API; no desactivar sus protecciones.
|
||
|
||
La alternativa de Docker bridge con `host.docker.internal:host-gateway` no es equivalente: cambia el host del navegador y puede requerir ajustes de escucha, hosts admitidos por Vite y `APP_ORIGIN`. Por eso esta integración utiliza red host y no añade excepciones amplias en Vite ni modifica la configuración de negocio.
|
||
|
||
Comprobaciones locales útiles:
|
||
|
||
```bash
|
||
ss -ltnp
|
||
curl --fail --silent --output /dev/null http://localhost:5173/
|
||
docker ps --format '{{.Names}}\t{{.Image}}\t{{.Ports}}'
|
||
```
|
||
|
||
Que `curl` funcione en WSL no demuestra por sí solo que Chromium acceda desde Docker. El comprobador MCP es la verificación completa de ese recorrido.
|
||
|
||
## Capturas y evidencia
|
||
|
||
La salida predeterminada del comprobador es:
|
||
|
||
- `.artifacts/playwright/metis-desk.png`: imagen recibida del MCP, validada como PNG con dimensiones positivas.
|
||
- `.artifacts/playwright/metis-desk.json`: imagen Docker, versión del servidor, protocolo, herramientas disponibles, URL, dimensiones, tamaño, SHA-256, resultado de inspección de página y mensajes de consola de nivel error.
|
||
|
||
Este directorio se excluye de Git porque las capturas pueden contener información de la aplicación. Se puede elegir otro destino con `--output`, pero mantener la evidencia fuera del versionado. No guardar contraseñas, cookies ni perfiles persistentes. En una sesión interactiva, usar la imagen devuelta por `browser_take_screenshot`; los archivos que el servidor escriba en `/tmp/metis-desk-playwright` permanecen dentro del contenedor y se pierden al retirarlo.
|
||
|
||
Abrir e inspeccionar el PNG antes de afirmar una revisión visual. La cabecera PNG, la existencia de un formulario y un snapshot accesible no prueban que la composición visual sea correcta. Para auditar cambios, comprobar además tamaños de pantalla, teclado, foco y estados pertinentes mediante las herramientas MCP; documentar únicamente escenarios ejecutados. No crear usuarios o modificar datos reales como parte de una auditoría sin autorización específica.
|
||
|
||
## Resolución de errores
|
||
|
||
| Síntoma | Comprobación y solución |
|
||
| --- | --- |
|
||
| Docker no responde o deniega acceso al socket | Arrancar el daemon y comprobar acceso del usuario de Codex. En entornos con sandbox, la herramienta puede necesitar autorización para Docker y conexiones locales. No resolverlo con `chmod 777` del socket. |
|
||
| El instalador rechaza el entorno | Ejecutarlo en WSL2 con Python 3.11+, Docker Linux y `timeout` disponibles. Instalar los requisitos explícitamente; no se ejecuta sudo automáticamente. |
|
||
| El instalador falla al comprobar red host | Activar host networking en Docker Desktop compatible, comprobar el contexto y repetirlo. El endpoint de diagnóstico no depende de que Metis esté arrancado. |
|
||
| Descarga cortada o arranque MCP agotado | Reintentar `docker pull` con la misma referencia fijada; Docker reutiliza las capas descargadas. Descargar antes de iniciar el MCP. No cambiar a `latest` para esquivar el fallo. |
|
||
| `ERR_CONNECTION_REFUSED` | Confirmar Vite, puerto anunciado y contexto Docker. En Desktop, comprobar la opción de red host y la integración WSL. |
|
||
| Página cargada pero error de `/api` | Confirmar API en 3001 y proxy de Vite. El HTML de Vite puede responder aunque la API esté parada. |
|
||
| Formularios rechazados por origen | Alinear URL del navegador y `APP_ORIGIN`. No desactivar la comprobación de origen. |
|
||
| Vite arranca en otro puerto | Consultar su salida; para la prueba, usar `--port` y `--strictPort` y alinear la API. |
|
||
| No aparece el servidor en Codex | Abrir el repositorio de confianza, revisar TOML, reiniciar sesión y comprobar `/mcp`. No duplicarlo globalmente. |
|
||
| `auth_status: unsupported` en el listado CLI | Es normal para este servidor stdio sin OAuth; no implica fallo de Chromium. |
|
||
| CLI antigua rechaza `service_tier = "default"` | Se observó con Codex CLI 0.114.0 y una configuración global preexistente. Para el diagnóstico se usó `codex -c 'service_tier="fast"' mcp list --json`, sin modificarla. Preferir una CLI compatible; el override es solo para esa invocación. |
|
||
| El comprobador no encuentra un formulario | Está orientado al acceso/configuración inicial con perfil aislado. Revisar que sea Metis y que la API funcione; no sustituir el backend por HTML simulado para dar la prueba por superada. |
|
||
| Se corta el cliente abruptamente | Revisar contenedores `metis-desk-playwright-check-*` con `docker ps` y retirar únicamente el contenedor propio que haya quedado huérfano. |
|
||
|
||
## Actualización de la imagen
|
||
|
||
1. Elegir un tag estable publicado por Microsoft. Consultar las versiones reales, no inventar tags ni digests.
|
||
2. Ejecutar `docker buildx imagetools inspect mcr.microsoft.com/playwright/mcp:<tag>` y comprobar el digest del índice y las plataformas. Si no está disponible Buildx, consultar el manifiesto con herramientas del registro antes de actualizar.
|
||
3. Sustituir la referencia `tag@sha256:...` únicamente en `.codex/config.toml` y actualizar la referencia informativa de este documento. Mantener el índice multi-arquitectura.
|
||
4. Descargar esa referencia, comprobar su ayuda y ejecutar el comprobador contra Metis. Abrir la captura, verificar las herramientas necesarias y revisar posibles cambios de flags.
|
||
5. Reiniciar Codex y comprobar que reconoce una sola entrada. Versionar configuración y documentación; conservar las capturas fuera de Git.
|
||
|
||
La fijación por digest impide que un movimiento del tag sustituya silenciosamente la imagen utilizada. No hay actualización automática a `latest`.
|
||
|
||
## Verificación de esta entrega
|
||
|
||
Comprobación ejecutada el 21 de octubre de 2026:
|
||
|
||
- Docker Engine 29.7.2, contexto local `default`, Linux amd64 dentro de WSL. La descarga sufrió tres cortes de conexión; el siguiente `docker pull` por digest terminó correctamente. Se inició un diagnóstico alternativo de descarga directa, pero no se importó ni reconstruyó la imagen: la prueba utilizó la imagen obtenida por Docker.
|
||
- Digest del índice verificado en el registro y en la imagen descargada. Se comprobó su punto de entrada real, el usuario `node` y la ayuda de sus flags.
|
||
- Una única entrada `playwright` reconocida por Codex CLI. Se utilizó el override de compatibilidad descrito para la CLI 0.114.0, sin cambiar su configuración global. Los cambios se activan en el cliente al abrir una nueva sesión del proyecto.
|
||
- Vite en `127.0.0.1:5173`, navegación en `http://localhost:5173`, API en `127.0.0.1:3001` con `APP_ORIGIN=http://localhost:5173` y `DB_NAME=metis_desk_test`. No se enviaron formularios ni se crearon usuarios.
|
||
- Negociación MCP `2025-06-18`, 25 herramientas y servidor que se identifica como `Playwright`, versión `1.64.0-alpha-1790635538000`. Esta versión informada por el protocolo es distinta del tag de distribución Docker `v0.0.83`.
|
||
- Navegación real a `/login`, título `Metis Desk` y user agent `HeadlessChrome/155.0.0.0`. Captura recibida por MCP: PNG de 1280×720, 33 549 bytes, SHA-256 `43d892c90d7ddb4befdae69637231c4f8f45112f300856684919493163f9e565`. Se abrió e inspeccionó: muestra la pantalla de acceso con los campos vacíos.
|
||
- La consola registró un 404 de `/favicon.ico`, conservado en el informe local. No impidió el renderizado ni se modificó código de aplicación para corregirlo.
|
||
- Se retiraron los contenedores MCP temporales y se detuvieron la API y Vite arrancados para esta comprobación. Se conservó el contenedor de MariaDB existente y la imagen descargada en la caché Docker.
|
||
- Se comprobó la sintaxis Python y TOML, el rechazo de URLs con credenciales y la exclusión de artefactos de Git. No se ejecutaron typecheck, lint, tests ni build del negocio porque los cambios se limitan a configuración, documentación y el comprobador independiente.
|
||
|
||
La comprobación no cubre sesiones autenticadas, formularios de negocio, responsive ni accesibilidad completa. Docker Desktop y ejecución arm64 siguen pendientes de validación. La existencia de sus opciones o manifiestos no equivale a una prueba en esas plataformas.
|
||
|
||
### Ampliación del procedimiento WSL
|
||
|
||
En el mismo entorno se ejecutó `bash scripts/setup-playwright-wsl.sh` dos veces, con código de salida cero en ambas: reutilizó la imagen y comprobó red host y Chromium `155.0.8059.12`. Se validaron la sintaxis de ambos scripts con `bash -n`, `--help` y el rechazo de argumentos desconocidos con salida 2. No se simuló un WSL recién instalado ni se volvió a descargar la imagen: el camino de descarga ya se había comprobado durante la integración inicial.
|
||
|
||
Se contrastó el listado real del CLI 0.114.0 con y sin el lanzador alternativo: ambos muestran una sola entrada `playwright`. Se mantuvo el override puntual de `service_tier`, sin modificar configuración global. También se comprobó con un ejecutable de diagnóstico que el lanzador serializa overrides TOML válidos, funciona desde otro directorio y conserva stdin; no se atribuye esa comprobación a una sesión interactiva completa de Codex.
|
||
|
||
Se repitió la navegación real mediante `scripts/check-playwright-mcp.py` contra API de prueba y Vite: devolvió las 25 herramientas y la misma captura PNG de acceso, que se abrió e inspeccionó. Se registró de nuevo el 404 del favicon. La disponibilidad directa de las herramientas en esta sesión de agente, la extensión y Desktop permanece sin validar; el comprobador stdio y la carga de configuración del CLI son evidencias separadas.
|