Playwright MCP en Claude Code/Codex: el snapshot de accesibilidad en la práctica
Playwright MCP le da un navegador a tu agente de código. No envía una captura de pantalla: envía el snapshot de accesibilidad, con una referencia (ref) en cada control, y el agente actúa por esas refs. En esta clase un script hace exactamente las llamadas que haría el agente, sin modelo, y después conectas el servidor a Claude Code o a Codex.
3El error común: tomar el snapshot antes de que la página termine
4Conectar con Claude Code (.mcp.json) y con Codex (config.toml)
Objetivo: hacer con Playwright MCP lo que hace el agente: leer el snapshot, encontrar el control por la ref y actuar, y conectar el servidor a tu agente.
01 · Del snapshot al clic
Haz clic en cada bloque.
Después de actuar, un snapshot nuevo
Haz clic en cada bloque del diagrama para ver lo que hace.
La ref vale para ese snapshot. Si cambió la página, toma otro.
02 · Lo que el agente recibe y lo que hace
Leyendo la salida del ensayo.
1. Las herramientas
El servidor expone 25 herramientas de navegador (browser_navigate, browser_snapshot, browser_click, browser_type, browser_select_option, browser_wait_for, browser_console_messages…). El agente las ve todas en la lista y elige.
La documentación del proyecto hoy también recomienda un camino por CLI y skills para agentes de código; el kit usa las herramientas por MCP, que es lo que leen Claude Code y Codex.
2. Refs, no coordenadas
En el ensayo, el script encontró textbox "Seu nome" = e13, combobox "Serviço" = e15 y button "Ver horários" = e18 y actuó por ellas. Nada de píxeles.
Por eso importa el HTML del curso 0: la etiqueta se vuelve nombre, y el nombre es como el agente encuentra la ref.
3. Esperar la prueba
Los horarios llegan 1,5 s después del clic. Con browser_wait_for esperando el texto "horários livres para", el snapshot viene completo. Si no esperas, viene "Carregando horários…" y cero horarios.
Espera el texto que prueba el resultado, no un número de segundos.
Quién paga el errorUn agente que toma el snapshot demasiado pronto responde "no hay horarios" con toda la confianza. La clase 7 vuelve a este caso.
03 · El ensayo: las llamadas del agente, sin modelo
ver-como-agente.mjs conecta Playwright MCP por stdio, como lo haría Claude Code, y hace la tarea "ver los horarios de Revisão completa".
Terminal · hacer la tarea con Playwright MCP
cd ~/projetos/formacao-webmcp-navegador-v72/kit
node ver-como-agente.mjs; echo "saída: $?"
Terminal · lo mismo, sin esperar la lista
cd ~/projetos/formacao-webmcp-navegador-v72/kit
node ver-como-agente.mjs --sem-esperar; echo "saída: $?"
Ejemplo del repositorio
→ browser_navigate {"url":"http://127.0.0.1:PORTA/agendar.html"}
→ browser_snapshot {}
achei: textbox "Seu nome" = e13 · combobox "Serviço" = e15 · button "Ver horários" = e18
→ browser_type {"target":"e13","text":"Ana"}
→ browser_select_option {"target":"e15","values":["Revisão completa"]}
→ browser_click {"target":"e18"}
→ browser_wait_for {"text":"horários livres para"}
→ browser_snapshot {}
status na página: 2 horários livres para Revisão completa em 2026-11-03.
tarefa: horários de Revisão completa em 2026-11-03 → 2 (08:00, 13:00) em 7 chamadas
saída: 0
Siete llamadas. Cada línea con → es una herramienta llamada por el cliente MCP; PORTA reemplaza el puerto aleatorio del servidor local.
→ browser_navigate {"url":"http://127.0.0.1:PORTA/agendar.html"}
→ browser_snapshot {}
achei: textbox "Seu nome" = e13 · combobox "Serviço" = e15 · button "Ver horários" = e18
→ browser_type {"target":"e13","text":"Ana"}
→ browser_select_option {"target":"e15","values":["Revisão completa"]}
→ browser_click {"target":"e18"}
→ browser_snapshot {}
status na página: Carregando horários…
tarefa: horários de Revisão completa em 2026-11-03 → 0 (nenhum) em 6 chamadas
a lista ainda estava carregando quando o snapshot foi tirado
saída: 1
Sin browser_wait_for, el snapshot pilla "Carregando horários…". El script sale con 1, pero un agente apresurado diría que no hay horario.
04 · Tu sitio y tu agente
Primero solo lectura en tu sitio; después el servidor conectado a Claude Code y a Codex, con el Chromium del kit.
Terminal · snapshot de un sitio tuyo
cd ~/projetos/formacao-webmcp-navegador-v72/kit
node ver-como-agente.mjs https://inema.club/; echo "saída: $?"
Terminal · conectar a Claude Code y a Codex
cd ~/projetos/formacao-webmcp-navegador-v72/kit
node configurar.mjs && claude mcp get playwright; echo "saída: $?"
Ejemplo del repositorio
→ browser_navigate {"url":"https://inema.club/"}
→ browser_snapshot {}
- generic [active] [ref=e1]:
- banner [ref=e2]:
- generic [ref=e3]:
- link "INEMA.VIP Participe da Comunidade" [ref=e4] [cursor=pointer]:
- /url: https://inema.vip
- img "INEMA.VIP" [ref=e5]
- generic [ref=e6]: Participe da Comunidade
- link "INEMA.PRO Assine o INEMA.PRO" [ref=e7] [cursor=pointer]:
- /url: https://inema.pro
- img "INEMA.PRO" [ref=e8]
- generic [ref=e9]: Assine o INEMA.PRO
- generic [ref=e10]:
- heading "INEMA.CLUB Portal INEMA" [level=1] [ref=e11]
- paragraph [ref=e12]: "Aprenda Inteligência Artificial na prática: cursos, agentes, automação e comunidade"
- generic [ref=e13]:
(…)
ferramentas WebMCP vistas: 8 · buscar_conhecimento [readOnly], buscar_cursos [readOnly], comparar_cursos [readOnly], …
snapshot: 1040 linhas · 749 elementos com ref
saída: 0
Aquí el sitio es inema.club, del propio INEMA. En tu máquina, cámbialo por la dirección de un sitio tuyo: agente de navegador solo contra un sitio tuyo. El resumen trae cuántas líneas y refs recibe el agente; inema.club tiene token de origin trial, así que el Chromium 156 del kit también vio las 8 herramientas WebMCP de él, sin ninguna flag.
Chromium do kit: chromium-1248/chrome-linux-arm64/chrome
escrevi kit/pw-config.json e kit/.mcp.json (servidores: playwright, devtools)
# Codex: cole em ~/.codex/config.toml se quiser os mesmos servidores lá
[mcp_servers.playwright]
command = "~/projetos/formacao-webmcp-navegador-v72/kit/node_modules/.bin/playwright-mcp"
args = ["--config", "~/projetos/formacao-webmcp-navegador-v72/kit/pw-config.json"]
[mcp_servers.devtools]
command = "~/projetos/formacao-webmcp-navegador-v72/kit/node_modules/.bin/chrome-devtools-mcp"
args = ["--headless", "--isolated", "--executablePath", "~/.cache/ms-playwright/chromium-1248/chrome-linux-arm64/chrome", "--no-usage-statistics", "--no-performance-crux", "--chromeArg=--no-sandbox"]
playwright:
Scope: Project config (shared via .mcp.json)
Status: ⏸ Pending approval (run `claude` to approve)
Type: stdio
Command: ~/projetos/formacao-webmcp-navegador-v72/kit/node_modules/.bin/playwright-mcp
Args: --config ~/projetos/formacao-webmcp-navegador-v72/kit/pw-config.json
To remove this server, run: claude mcp remove playwright -s project
saída: 0
configurar.mjs escribe kit/.mcp.json (Claude Code, alcance de proyecto) e imprime el fragmento de Codex (en la captura, ~ abrevia la ruta; el script imprime la ruta absoluta, que es la que Codex necesita), que pegas en ~/.codex/config.toml si quieres. Un servidor de proyecto queda en "Pending approval" hasta que abras claude dentro de kit/ y lo apruebes; después, /mcp muestra el servidor conectado (ese paso no fue capturado).
05 · Práctica
El ensayo, tu sitio y tu agente. Cada ejercicio tiene un "listo cuando".
E1 · Las siete llamadas
10 min
Ejecuta el ensayo y después la versión sin esperar. Para cada línea con →, di en una frase qué sabía el agente en ese momento.
Listo cuando:node ver-como-agente.mjs → 2 (08:00, 13:00) em 7 chamadas y saída: 0; con --sem-esperar → 0 (nenhum) y saída: 1.
E2 · El snapshot de tu sitio
10 min
Ejecuta el bloque de lectura con la dirección de un sitio tuyo. Abre la misma página en el navegador y encuentra tres controles en la salida por su nombre.
Listo cuando:node ver-como-agente.mjs con la dirección de tu sitio → snapshot: N linhas · M elementos com ref y saída: 0.
E3 · El servidor en tu agente
10 min
Ejecuta configurar.mjs. En Claude Code, abre claude dentro de kit/ y aprueba el servidor del proyecto. En Codex, pega el fragmento impreso en config.toml.
Listo cuando:claude mcp get playwright → Scope: Project config y, después de aprobar, Status: ✓ Connected; en Codex, el servidor aparece en la lista de /mcp.
06 · Prueba de la clase
Pregunta 1 de 4
En el snapshot aparece textbox "Seu nome" [ref=e13]. ¿Cómo escribe el agente en ese campo?competencia
Correcto
Playwright MCP actúa por la ref del snapshot. Las coordenadas son el camino del computer use; la consola es otro servidor (clase 3).
No es esa
Playwright MCP actúa por la ref del snapshot. Las coordenadas son el camino del computer use; la consola es otro servidor (clase 3).Repasar: Del snapshot al clic
Pregunta 2 de 4
El agente hizo clic en "Ver horários", tomó el snapshot al instante y vio "Carregando horários…". ¿Qué faltó?
Correcto
browser_wait_for con el texto "horários livres para" espera la prueba. Recargar pierde lo que se rellenó; volver a hacer clic dispara otra búsqueda.
¿Para qué sirve el campo element en las llamadas de clic y de escritura?
Correcto
element es la descripción legible que se usa para pedir permiso a la persona; quien encuentra el control es target (la ref).
No es esa
element es la descripción legible que se usa para pedir permiso a la persona; quien encuentra el control es target (la ref).Repasar: Del snapshot al clic
Pregunta 4 de 4
Después de configurar.mjs, claude mcp get muestra "Pending approval". ¿Qué hacer?
Correcto
Un servidor de proyecto (.mcp.json) necesita aprobación la primera vez. El kit usa el Chromium de Playwright; no necesita Chrome estable.