web-ui-tester
web-ui-tester
Un servidor MCP que permite a una IA manejar e inspeccionar páginas web reales rápidamente, con sesiones del navegador que siguen activas entre llamadas a herramientas.
Dos cosas lo hacen rápido. Las páginas se exponen como un árbol de accesibilidad con referencias de elementos en lugar de capturas de pantalla o HTML sin procesar, de manera que el modelo puede encontrar y hacer clic en los elementos sin gastar contexto en el marcado ni esperar a la visión. Y las sesiones persisten — las cookies, el estado de la página y el historial sobreviven entre llamadas, así que una interacción larga es una serie de pasos baratos en lugar de arranques en frío repetidos.
También incluye diagnóstico de nivel DevTools — consola, red con cuerpos de respuesta, evaluación de JS, estilos calculados — para que la IA pueda averiguar por qué algo está roto, no solo que está roto.
Inicio rápido
claude mcp add web-ui-tester -- npx -y web-ui-testerCon una clave para el agente incorporado (ver run_task):
claude mcp add web-ui-tester \
-e GOOGLE_GENERATIVE_AI_API_KEY=your-key \
-- npx -y web-ui-testerO en el archivo de configuración de cualquier cliente MCP:
{
"mcpServers": {
"web-ui-tester": {
"command": "npx",
"args": ["-y", "web-ui-tester"],
"env": { "GOOGLE_GENERATIVE_AI_API_KEY": "your-key" }
}
}
}Chromium proviene de Playwright. Si aún no está instalado:
npx playwright install chromium##Cómo funciona una sesión
browser_start → sessionId, kept alive across calls
browser_navigate → page state + snapshot with [ref=eN] handles
browser_click ref=e12 → act on what the snapshot showed you
browser_snapshot → fresh refs after the page changes
browser_close → done (or let it idle out after 30 minutes)Todo lo que viene después de browser_start toma ese sessionId. La instantánea es lo que hay que interiorizar:
- generic [ref=e1]:
- heading "Signup" [level=1] [ref=e2]
- textbox "Name" [ref=e5]:
- /placeholder: Your name
- combobox "Plan" [ref=e7]
- button "Create account" [ref=e10]
- link "Go to second page" [ref=e12] [cursor=pointer]:
- /url: /second.htmlEsas referencias se usan directamente con browser_click, browser_type y el resto. Pertenecen al estado de la página que las generó: tras navegar o después de un cambio del DOM, vuelve a tomar una instantánea. Cuando una herramienta dice que una referencia ya no es válida, toma una nueva instantánea en lugar de reintentar, y el mensaje lo dice explícitamente.
Las herramientas que direccionan elementos también aceptan css, o role + name, si ya conoces el selector y prefieres omitir la instantánea.
Herramientas
Sesión — browser_start (opciones: userAgent, viewportWidth, viewportHeight, headless, baseUrl, url, model), browser_list, browser_close.
Interacción — browser_navigate, browser_click, browser_type, browser_press_key, browser_hover, browser_select_option, browser_scroll, browser_wait_for, browser_go_back, browser_handle_dialog.
Las acciones informan de lo que causaron: la navegación, los nuevos errores de consola, el conteo de peticiones y cualquier diálogo que haya aparecido se devuelven junto con el resultado, de modo que un clic que rompió algo silenciosamente no parezca un éxito.
Los diálogos necesitan una aclaración. Un alert/confirm/prompt bloquea la página hasta que se responde, por lo que la acción que lo abrió no puede también responderlo: un diálogo sin responder se descarta automáticamente en lugar de detener el clic, y el resultado lo explica. Para aceptarlo, o para completle un prompt, llama a browser_handle_dialog antes de la acción que lo dispara, y la respuesta queda armada para el siguiente diálogo.
Inspección — browser_snapshot (acotable por elemento, limitado por depth, interactiveOnly y con página mediante offset), browser_query (busca por rol/nombre, texto o CSS — devuelve referencias y estado), browser_read_text (texto renderizado de la página o un subárbol), browser_screenshot (disponible, aunque el árbol suele ser la mejor herramienta).
Diagnóstico — browser_console (mensajes más errores no capturados con sus pilas), browser_network (estados, tamaños, tiempos), browser_request_detail (cabeceras, desglose de tiempos, cuerpos de petición y respuesta), browser_evaluate (ejecuta JS en la página), browser_inspect_element (estilos calculados, modelo de caja, estado del formulario).
Todos los resultados tienen un límite dentro de un presupuesto de caracteres, y los voluminosos (browser_snapshot, browser_read_text, cuerpos) se paginan con offset en lugar de truncarse silenciosamente.
El agente integrado
run_task entrega una sesión a un modelo rápido que maneja el navegador por sí mismo y devuelve un informe:
run_task(sessionId, "Log in as demo@example.com / hunter2 and check the
dashboard loads without errors")El punto es informar. Devuelve un veredicto estructurado, no solo prosa:
status: success
model: google:gemini-flash-lite-latest
Logged in and opened the dashboard. The revenue widget rendered empty.
findings (3):
[error] Request failed: GET 500 [observed by the harness]
where: https://app.example.com/api/revenue
evidence: HTTP 500
[error] Console exception on the page [observed by the harness]
where: app.js:214:9
evidence: TypeError: Cannot read properties of undefined (reading 'total')
[warning] The revenue widget shows no empty state, just blank space
where: #revenue-card
evidence: card is present but contains no textLos hallazgos provienen de dos lugares y la distinción importa. El agente llama a report_finding mientras avanza, de modo que una ejecución que alcanza su límite de pasos aún devuelve todo lo encontrado hasta ese momento. Además, el banco de pruebas registra cada error de consola, cada petición fallida y cada diálogo de la ejecución, y los notifica hable el agente de ellos o no, marcados como [observed by the harness]. Un modelo que no vea un 500 u olvide mencionar una excepción no puede ocultarlo.
El mismo informe se devuelve como structuredContent bajo un esquema de salida declarado, para que la IA pueda decidir según findings[].severity en lugar de parsear texto. Una tarea puede terminar correctamente y aún así tener hallazgos; success indica si la tarea se logró, no si la página estaba limpia.
Esta es la única parte que necesita una clave de API. Por defecto usa Gemini Flash Lite para la latencia; Anthropic un en un también funciona:
Modelo predeterminado | Clave | |
|
| |
Anthropic |
|
|
Configura WUT_MODEL para elegir formato (anthropic, google:gemini-flash-latest o cualquier provider:modelId). Una sesión puede anularlo con el parámetro model de browser_start, y una llamada individual con model de run_task. Todas las demás herramientas funcionan sin clave.
Modo HTTP
web-ui-tester --port 7399
claude mcp add --transport http web-ui-tester http://127.0.0.1:7399/mcpEn este modo, las sesiones del navegador viven en la larga duración del servidor, no en un proceso del cliente, por lo que truth sobreviven a los reinicios y reconexiones del cliente: reconstringe, pasa el mismo sessionId y la página sigue ahí. GET /health informa sobre el número de sesiones y conexiones.
Por defecto se enlaza a 127.0.0.1, donde la protección de rebote de DNS está activa. --host amplía el alcance, y el servidor advierte cuando se hace: no hay autenticación, y cualquiera que alcance el puerto puede conducir un navegador y ejecutar JavaScript a través de él. Ponlo detrás de un proxy o un cortafuegos.
Configuración
Variable | Predeterminado | Propósito |
|
| Modelo para |
| — | Clave para Gemini |
| — | Clave para Anthropic |
|
| User-Agent predeterminado para nuevas sesiones |
|
| Modo headless no determinante |
|
| Cierra sesiones sin uso durante este tiempo |
|
| Límite de caracteres por resultado de herramienta |
|
| Tiempo máximo de espera para una acción de elemento |
|
| Presupuesto de pasos predeterminado para |
| — | Ruta explícita al binario de Chromium |
| — | Dónde busca Playwright los navegadores |
Banderas de CLI: --port, --host, --headless / --no-headless, --idle-timeout, --version, --help.
Si la versión de Chromium que Playwright espera no está ató, pero hay otra, el servidor la encuentra y la usa en lugar de fallar: algo útil en contenedores preinterpretados. WUT_EXECUTABLE_PATH anula por completo la búsqueda.
Desarrollo
npm install
npm run build
npm test # agent loop (mocked model) + full end-to-end suite
npm run typechecknpm test ejecuta el bucle del agente contra un modelo simulado escrito, y luego ejecuta la liquidación del servidor compilado como un cliente MCP real en ambos transportes contra de una aplicación de prueba local, cubriendo referencias, manejo de referencias obsoletas, diagnostic, persistencia de la sesión entre reconexiones y reaping por inactividad. npm run test:agent:live además somete a prueba run_task contra un proveedor real, y se omite si no se establece ninguna clave.
Licencia
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.
Live browser debugging for AI assistants — DOM, console, network via MCP.
Browser-backed QA with evidence and fix-ready reports for coding agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hofmeister/web-ui-tester'
If you have feedback or need assistance with the MCP directory API, please join our Discord server