WebdriverIO MCP
Un servidor del Protocolo de Contexto de Modelo (MCP) que permite a Claude Desktop interactuar con navegadores web y aplicaciones móviles utilizando WebDriverIO. Automatiza navegadores Chrome, aplicaciones iOS y aplicaciones Android, todo a través de una interfaz unificada.
Documentación
Servidor MCP de WebdriverIO
Un servidor de Protocolo de Contexto de Modelo (MCP) que permite a los asistentes de IA interactuar con navegadores web, aplicaciones Electron locales y aplicaciones móviles mediante WebdriverIO. Automatiza Chrome, Firefox, Edge, Safari, Electron, iOS y Android a través de una interfaz unificada.
Instalación
Agrega la siguiente configuración a la configuración de tu cliente MCP:
Configuración estándar (funciona en la mayoría de los clientes):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Claude Desktop
Edita ~/Library/Application Support/Claude/claude_desktop_config.json (macOS),
%APPDATA%\Claude\claude_desktop_config.json (Windows) o ~/.config/Claude/claude_desktop_config.json (Linux):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Claude Code
claude mcp add wdio-mcp -- npx -y @wdio/mcp@latest
Cline
Agrega a tu archivo settings.json o cline_mcp_settings.json de VS Code:
{
"mcpServers": {
"wdio-mcp": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Cursor
Ve a Cursor Settings → MCP → Add new MCP Server, o crea .cursor/mcp.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Codex
Usa la CLI de Codex:
codex mcp add wdio-mcp npx "@wdio/mcp@latest"
O edita ~/.codex/config.toml:
[mcp_servers.wdio-mcp]
command = "npx"
args = ["@wdio/mcp@latest"]
Goose
Ve a Advanced settings → Extensions → Add custom extension, o ejecuta:
goose configure
O edita ~/.config/goose/config.yaml:
extensions:
wdio-mcp:
name: WebDriverIO MCP
cmd: npx
args: [ -y, "@wdio/mcp@latest" ]
enabled: true
type: stdio
Windsurf
Edita ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Zed
Edita la configuración de Zed (~/.config/zed/settings.json):
{
"context_servers": {
"wdio-mcp": {
"source": "custom",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
VS Code (Copilot)
code --add-mcp '{"name":"wdio-mcp","command":"npx","args":["-y","@wdio/mcp@latest"]}'
⚠️ Reinicio requerido: Después de agregar la configuración, reinicia completamente tu cliente MCP para aplicar los cambios.
Opción 2: Instalación global
Si prefieres instalar globalmente:
npm install -g @wdio/mcp
Luego usa wdio-mcp como comando:
{
"mcpServers": {
"wdio-mcp": {
"command": "wdio-mcp"
}
}
}
📖 ¿Necesitas ayuda? Sigue la guía de instalación de MCP.
Transporte HTTP (para clientes que no usan subprocesos)
Por defecto, el servidor usa transporte stdio (subproceso). Para clientes que no pueden lanzar subprocesos (p. ej., llama.cpp, modo seguro de OpenAI Codex), habilita el transporte HTTP:
npx @wdio/mcp --http --port 3000
| Indicador | Predeterminado | Descripción |
|---|---|---|
--http | — | Habilita el modo de transporte HTTP |
--port | 3000 | Puerto de escucha |
--allowedHosts | localhost,127.0.0.1,::1 | Valores permitidos del encabezado Host (protección contra rebinding de DNS) |
--allowedOrigins | (ninguno — clientes de navegador bloqueados) | Valores permitidos de Origin para CORS. Usa * para permitir todos. |
Luego apunta tu cliente MCP a http://localhost:3000/mcp.
Requisitos previos para la automatización de aplicaciones móviles
- Servidor Appium: Instálalo globalmente con
npm install -g appium - Controladores de plataforma:
- iOS:
appium driver install xcuitest(requiere Xcode en macOS) - Android:
appium driver install uiautomator2(requiere Android Studio)
- iOS:
- Dispositivos/Emuladores:
- Simulador de iOS (macOS) o dispositivo físico
- Emulador de Android o dispositivo físico
- Para dispositivos iOS reales: Necesitarás el UDID (Identificador Único de Dispositivo) del dispositivo
- Encuentra el UDID en macOS: Conecta el dispositivo → Abre Finder → Selecciona el dispositivo → Haz clic en el nombre/modelo del dispositivo para revelar el UDID
- Encuentra el UDID en Windows: Conecta el dispositivo → iTunes o la aplicación Apple Devices → Haz clic en el ícono del dispositivo → Haz clic en "Número de serie" para revelar el UDID
- Método con Xcode: Ventana → Dispositivos y Simuladores → Selecciona el dispositivo → El UDID se muestra como "Identificador"
Inicia el servidor Appium antes de usar funciones móviles:
appium
# Server runs at http://127.0.0.1:4723 by default
Proveedores en la nube
Ejecuta pruebas de navegador y aplicaciones móviles en dispositivos y navegadores reales en la nube sin configuración local. Actualmente es compatible con BrowserStack, Sauce Labs, LambdaTest, TestingBot y Digital.ai Testing.
Requisitos previos
Establece las credenciales de tu proveedor como variables de entorno o en la configuración de tu cliente MCP:
BrowserStack
export BROWSERSTACK_USERNAME=your_username
export BROWSERSTACK_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"BROWSERSTACK_USERNAME": "your_username",
"BROWSERSTACK_ACCESS_KEY": "your_access_key"
}
}
}
}
Sauce Labs
export SAUCE_USERNAME=your_username
export SAUCE_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"SAUCE_USERNAME": "your_username",
"SAUCE_ACCESS_KEY": "your_access_key"
}
}
}
}
| SAUCE_USERNAME | Nombre de usuario de Sauce Labs (requerido) |
| SAUCE_ACCESS_KEY | Clave de acceso de Sauce Labs (requerida) |
El centro de datos se establece por sesión mediante el parámetro region en start_session (predeterminado: eu-central-1).
LambdaTest (TestMu)
export TESTMU_USERNAME=your_username
export TESTMU_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"TESTMU_USERNAME": "your_username",
"TESTMU_ACCESS_KEY": "your_access_key"
}
}
}
}
| TESTMU_USERNAME | Nombre de usuario de LambdaTest (requerido) |
| TESTMU_ACCESS_KEY | Clave de acceso de LambdaTest (requerida) |
TestingBot
export TESTINGBOT_KEY=your_key
export TESTINGBOT_SECRET=your_secret
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"TESTINGBOT_KEY": "your_key",
"TESTINGBOT_SECRET": "your_secret"
}
}
}
}
| TESTINGBOT_KEY | Clave de TestingBot (requerida) |
| TESTINGBOT_SECRET | Secreto de TestingBot (requerido) |
Digital.ai Testing
export DIGITALAI_CLOUD_URL=https://your-cloud.example.com
export DIGITALAI_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"DIGITALAI_CLOUD_URL": "https://your-cloud.example.com",
"DIGITALAI_ACCESS_KEY": "your_access_key"
}
}
}
}
| DIGITALAI_CLOUD_URL | Host de la nube de Digital.ai, p. ej., https://your-cloud.example.com (requerido) |
| DIGITALAI_ACCESS_KEY | Clave de acceso de Digital.ai (requerida) |
La clave de acceso se envía mediante la capacidad digitalai:options (móvil) o la capacidad plana digitalai:accessKey (web).
Informa el estado de aprobación/fallo: WebdriverIO usa por defecto el protocolo BiDi, sobre el cual la nube de Digital.ai no puede observar fallos de comandos, por lo que los informes se marcan como "Aprobado" por defecto. Para que la nube refleje el estado real de aprobación/fallo, opta por el WebDriver clásico por sesión:
start_session({
provider: 'digitalai', platform: 'browser', browser: 'chrome', os: 'Windows 10',
capabilities: { 'wdio:enforceWebDriverClassic': true }
})
(Los fallos de aserción puramente del lado del cliente aún se informan como "Aprobado"; solo se detectan los fallos que llegan a la nube como errores de comando de WebDriver).
Móvil (Appium): configura tu proyecto de Digital.ai para ejecución con servidor Appium y elige su versión predeterminada de Appium mediante la configuración "Administrar versión predeterminada del servidor Appium" del proyecto; la versión se elige a nivel de proyecto (y sigue las versiones que tu nube admite), por lo que este MCP no fija una. Consulta Ejecución de pruebas con servidor Appium.
Sesiones de navegador
Ejecuta un navegador en una combinación específica de sistema operativo/versión:
// BrowserStack
start_session({
provider: 'browserstack',
platform: 'browser',
browser: 'chrome', // chrome | firefox | edge | safari
browserVersion: 'latest', // default: latest
os: 'Windows', // e.g. "Windows", "OS X"
osVersion: '11', // e.g. "11", "Sequoia"
reporting: {
project: 'My Project',
build: 'v1.2.0',
session: 'Login flow'
}
})
// Sauce Labs
start_session({
provider: 'saucelabs',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName
osVersion: '11', // e.g. "11", "15" (numbered Mac naming)
region: 'eu-central-1', // default: eu-central-1
reporting: {
build: 'v1.2.0',
session: 'Login flow'
}
})
// LambdaTest
start_session({
provider: 'testmu',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName
osVersion: '11', // e.g. "11", "Sequoia" (optional)
reporting: {
project: 'My Project',
build: 'v1.2.0',
session: 'Login flow'
}
})
// TestingBot
start_session({
provider: 'testingbot',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName (default: Windows 11)
osVersion: '11',
reporting: {
build: 'v1.2.0',
session: 'Login flow'
}
})
// Digital.ai
start_session({
provider: 'digitalai',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → digitalai:osName (optional)
osVersion: '11',
reporting: {
session: 'Login flow' // → digitalai:testName (flat capability, not nested)
}
})
Comportamiento específico del proveedor para
os/osVersion:
- BrowserStack —
osyosVersionse asignan a campos separados debstack:options.os/bstack:options.osVersion.- Sauce Labs / LambdaTest / TestingBot —
osyosVersionse combinan en la capacidad W3CplatformName(p. ej.,os: 'Windows'+osVersion: '11'→platformName: 'Windows 11'). Estos proveedores usan valores deplatformNamecomo"Windows 11","MacOS Sequoia"o"Linux". TestingBot usaWindows 11por defecto cuando se omiteos.- Digital.ai —
osyosVersionse combinan en la capacidad planadigitalai:osName(NOplatformName), p. ej.,os: 'Windows'+osVersion: '11'→digitalai:osName: 'Windows 11'.
Sesiones de aplicaciones móviles
Prueba en dispositivos reales en la nube. Primero sube tu aplicación (o usa una URL de aplicación existente):
// BrowserStack: returns bs:// URL
upload_app({ provider: 'browserstack', path: '/path/to/app.apk' })
// Sauce Labs: returns storage:filename= reference
upload_app({ provider: 'saucelabs', path: '/path/to/app.apk' })
// LambdaTest: returns lt:// URL
upload_app({ provider: 'testmu', path: '/path/to/app.apk' })
// TestingBot: returns tb:// URL
upload_app({ provider: 'testingbot', path: '/path/to/app.apk' })
// Digital.ai: returns cloud:<package-or-bundle> reference
upload_app({ provider: 'digitalai', path: '/path/to/app.apk' })
// Start a session
start_session({
provider: 'browserstack',
platform: 'android',
app: 'bs://abc123...',
deviceName: 'Samsung Galaxy S23',
platformVersion: '13.0'
})
// Sauce Labs native app
start_session({
provider: 'saucelabs',
platform: 'android',
app: 'storage:filename=myapp.apk',
deviceName: 'Samsung.*',
platformVersion: '16'
})
// LambdaTest native app
start_session({
provider: 'testmu',
platform: 'android',
app: 'lt://abc123...',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// TestingBot native app
start_session({
provider: 'testingbot',
platform: 'android',
app: 'tb://abc123...',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// Digital.ai native app — devices are selected via a deviceQuery
start_session({
provider: 'digitalai',
platform: 'android',
app: 'cloud:com.example.app',
deviceQuery: "@os='android' and @version='14' and @name='.*Pixel.*'"
// or omit deviceQuery and pass deviceName / platformVersion to build one
})
Sesiones de navegador móvil
Ejecuta un navegador en un dispositivo móvil en la nube (real o emulador/simulador) sin subir una aplicación:
// BrowserStack — Chrome on Android emulator
start_session({
provider: 'browserstack',
platform: 'android',
browser: 'chrome',
deviceName: 'Google Pixel 7',
platformVersion: '13'
})
// Sauce Labs — Safari on iOS simulator
start_session({
provider: 'saucelabs',
platform: 'ios',
browser: 'safari',
deviceName: 'iPhone 15',
platformVersion: '18',
region: 'eu-central-1'
})
// LambdaTest — Chrome on Android emulator
start_session({
provider: 'testmu',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// TestingBot — Chrome on Android emulator
start_session({
provider: 'testingbot',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// Digital.ai — Chrome on an Android device (real or emulator; selected via a deviceQuery)
start_session({
provider: 'digitalai',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
// or omit deviceName / platformVersion and pass deviceQuery directly, e.g.
// deviceQuery: "@os='android' and @emulator='true'" to force an emulator
})
Nota: Las sesiones de navegador móvil no requieren
app,appPathninoReset. El proveedor lanza un navegador directamente en el dispositivo seleccionado, ya sea real o emulador/simulador.
Usa list_apps para ver aplicaciones subidas anteriormente:
list_apps({ provider: 'browserstack' })
list_apps({ provider: 'saucelabs', sortBy: 'app_name' })
list_apps({ provider: 'testmu' })
list_apps({ provider: 'testingbot' })
list_apps({ provider: 'digitalai' })
list_apps({ provider: 'browserstack', organizationWide: true })
Túnel local
Para probar URLs que solo son accesibles en tu máquina local o red interna, habilita un túnel local:
// Auto-start tunnel (provider manages lifecycle)
start_session({
provider: 'saucelabs',
platform: 'browser',
tunnel: true // auto-starts tunnel before session
})
// Use an already-running tunnel
start_session({
provider: 'saucelabs',
platform: 'browser',
tunnel: 'external' // uses existing tunnel
})
El parámetro tunnel reemplaza los parámetros obsoletos browserstackLocal, saucelabsLocal y testmuLocal. Establécelo en true para iniciar automáticamente el túnel (se detiene automáticamente después de la sesión), o en 'external' para usar un túnel que ya se esté ejecutando en tu máquina.
Nota: Con
tunnel: true, el proveedor descarga y administra el binario del túnel por ti. Paratunnel: 'external', lo ejecutas tú mismo; los recursoswdio://saucelabs/local-binary,wdio://testmu/local-binaryywdio://testingbot/local-binaryproporcionan URLs de descarga e instrucciones de configuración. El túnel de TestingBot es un único JAR de Java multiplataforma (requiere Java 11+) en lugar de un binario por plataforma.
Etiquetas de informes
Todos los tipos de sesión admiten etiquetas reporting que aparecen en el panel del proveedor:
| Campo | Descripción |
|---|---|
reporting.project | Agrupa sesiones bajo un nombre de proyecto |
reporting.build | Etiqueta sesiones con una etiqueta de compilación/versión |
reporting.session | Nombre para la sesión de prueba individual |
Herramientas de proveedores en la nube
| Herramienta | Descripción |
|---|---|
upload_app | Sube un .apk o .ipa local al proveedor; devuelve una URL/referencia de aplicación |
list_apps | Lista aplicaciones subidas anteriormente al almacenamiento de aplicaciones del proveedor |
Ambas herramientas requieren un parámetro provider ('browserstack', 'saucelabs', 'testmu', 'testingbot' o 'digitalai').
Funciones
Automatización de navegador
- Gestión de sesiones: Inicia y cierra sesiones de navegador (Chrome, Firefox, Edge, Safari) con modos headless/headed
- Navegación e interacción: Navega por URLs, haz clic en elementos, completa formularios y recupera contenido
- Análisis de página: Obtén elementos visibles, árboles de accesibilidad, toma capturas de pantalla
- Gestión de cookies: Obtén, establece y elimina cookies
- Desplazamiento: Desplazamiento suave con distancias configurables
- Adjuntar a Chrome en ejecución: Conéctate a una ventana de Chrome existente mediante
--remote-debugging-port— ideal para probar sesiones autenticadas o preconfiguradas - Conectarse a endpoints de WebDriver existentes: Reutiliza un endpoint de WebDriver compatible con Selenium que ya esté en ejecución, como un navegador administrado por un framework o un puente de automatización de webview de escritorio (como Tauri)
- Emulación de dispositivos: Aplica ajustes preestablecidos de móvil/tableta (iPhone 15, Pixel 7, etc.) para simular diseños responsivos sin un dispositivo físico
- Grabación de sesiones: Todas las llamadas de herramientas se graban automáticamente y se pueden exportar como JS de WebdriverIO ejecutable
Automatización de aplicaciones móviles (iOS/Android)
- Pruebas de aplicaciones nativas: Prueba aplicaciones de iOS (.app/.ipa) y Android (.apk) mediante Appium
- Gestos táctiles: Tocar, deslizar, mantener presionado, arrastrar y soltar
- Ciclo de vida de la aplicación: Iniciar, poner en segundo plano, terminar, verificar el estado de la aplicación
- Cambio de contexto: Cambia sin problemas entre contextos nativos y webview para aplicaciones híbridas
- Control de dispositivos: Rotar, bloquear/desbloquear, geolocalización, control de teclado, notificaciones
- Selectores multiplataforma: IDs de accesibilidad, XPath, UiAutomator (Android), Predicados (iOS)
Herramientas disponibles
Gestión de sesiones
| Herramienta | Descripción |
|---|---|
start_session | Iniciar un navegador, aplicación Electron local o sesión de aplicación móvil; attach: true conserva el modo de conexión CDP de Chrome existente |
attach_session | Adjuntar a una sesión remota existente de WebDriver/Appium por ID sin crear una nueva sesión |
launch_chrome | Lanzar una nueva instancia de Chrome con depuración remota habilitada (para usar con start_session({ attach: true })) |
close_session | Cerrar o desconectar la sesión actual (admite detach: true para desconectar sin terminar) |
emulate_device | Emular un ajuste preestablecido de dispositivo móvil/tableta (viewport, DPR, UA, táctil); requiere sesión BiDi |
open_web_extension | Instalar una extensión web a través de WebDriver BiDi y abrir una de sus páginas de extensión para que las herramientas de página normales puedan controlar su interfaz |
Navegación e Interacción con la Página (Web y Móvil)
| Herramienta | Descripción |
|---|---|
navigate | Navegar a una URL |
get_elements | Obtener elementos visibles e interactuables en la página. Admite inViewportOnly (predeterminado: true) para filtrar elementos del viewport, y includeContainers (predeterminado: false) para incluir contenedores de diseño en móvil |
get_accessibility_tree | Obtener el árbol de accesibilidad de la página con roles, nombres y selectores. Admite filtrado por rol y paginación. Solo navegador. |
get_screenshot | Tomar una captura de pantalla de la página o pantalla actual (codificada en base64, redimensionada automáticamente a máximo 2000px / 1MB) |
get_tabs | Listar todas las pestañas abiertas del navegador con identificador, título, URL y estado activo. Solo navegador. |
scroll | Desplazarse en una dirección (arriba/abajo) por píxeles especificados. Solo navegador. |
execute_script | Ejecutar JavaScript arbitrario en el navegador, o comandos móviles de Appium en dispositivos |
execute_electron_script | Ejecutar JavaScript privilegiado en el proceso principal de Electron (solo sesiones de Electron) |
trigger_electron_deeplink | Activar un deeplink de Electron cuyo esquema fue configurado explícitamente al inicio de la sesión |
mock | Configurar un mock de ámbito de sesión: una función API del proceso principal de Electron o una solicitud de red del navegador |
get_mock_calls | Inspeccionar argumentos de llamada (Electron) o registros de solicitudes interceptadas (navegador) para un mock de ámbito de sesión |
manage_mock | Limpiar, restablecer o restaurar un mock de ámbito de sesión |
switch_tab | Cambiar a una pestaña diferente del navegador por identificador o índice basado en 0. Solo navegador. |
switch_frame | Cambiar a un iframe por selector CSS/XPath, o volver al marco de nivel superior si no se proporciona selector. Solo navegador. |
Interacción con Elementos (Web y Móvil)
| Herramienta | Descripción |
|---|---|
click_element | Hacer clic en un elemento |
set_value | Escribir texto en campos de entrada |
Gestión de Cookies (Web)
| Herramienta | Descripción |
|---|---|
get_cookies | Obtener todas las cookies de la sesión actual, o una sola cookie por nombre |
set_cookie | Establecer una cookie con nombre, valor y atributos opcionales |
delete_cookies | Eliminar todas las cookies o una cookie específica |
Gestos Móviles (iOS/Android)
| Herramienta | Descripción |
|---|---|
tap_element | Tocar un elemento por selector o coordenadas |
swipe | Deslizar en una dirección (arriba/abajo/izquierda/derecha) |
drag_and_drop | Arrastrar de una ubicación a otra |
Cambio de Contexto (Aplicaciones Híbridas)
| Herramienta | Descripción |
|---|---|
get_contexts | Listar contextos de automatización disponibles (NATIVE_APP, WEBVIEW_*) y el actualmente activo |
switch_context | Cambiar entre contextos nativos y webview |
Control de Dispositivo (iOS/Android)
| Herramienta | Descripción |
|---|---|
get_app_state | Obtener el estado actual del ciclo de vida de una aplicación móvil (no instalada / no en ejecución / en segundo plano / en primer plano) |
rotate_device | Rotar a vertical u horizontal |
hide_keyboard | Ocultar teclado en pantalla |
set_geolocation | Establecer ubicación GPS del dispositivo |
Búsqueda de Documentación
| Herramienta | Descripción |
|---|---|
query_docs | Buscar en la documentación oficial de WebdriverIO y devolver los extractos más relevantes con página, sección y URL de origen. query es obligatorio (2-3 palabras clave distintivas — una frase diluye la clasificación); limit tiene como predeterminado 5 (máximo 20); fullPage (predeterminado: false) devuelve las páginas completas coincidentes en lugar de extractos. Independiente de la sesión |
Recursos MCP (solo lectura, no se necesita llamada de herramienta)
| Recurso | Descripción |
|---|---|
wdio://sessions | Índice de todas las sesiones registradas |
wdio://session/current/steps | Registro de pasos de la sesión activa |
wdio://session/current/code | JS de WebdriverIO ejecutable generado para la sesión activa |
wdio://session/{id}/steps | Registro de pasos de cualquier sesión pasada por ID |
wdio://session/{id}/code | JS generado para cualquier sesión pasada por ID |
wdio://session/current/elements | Elementos interactuables (solo viewport por predeterminado) |
wdio://session/current/accessibility | Árbol de accesibilidad |
wdio://session/current/screenshot | Captura de pantalla (base64) |
wdio://session/current/cookies | Cookies del navegador |
wdio://session/current/tabs | Pestañas abiertas del navegador |
wdio://session/current/contexts | Contextos nativos/webview (móvil) |
wdio://session/current/context | Contexto actualmente activo (móvil) |
wdio://session/current/app-state/{bundleId} | Estado del ciclo de vida de la aplicación móvil para un ID de paquete dado |
wdio://session/current/geolocation | Geolocalización del dispositivo |
wdio://session/current/capabilities | Capacidades de WebDriver resueltas para la sesión activa |
wdio://session/current/logs | Registros de fallos/consola para la sesión actual. Detecta automáticamente el tipo de sesión — navegador: registros de consola + excepciones JS; Android: logcat; iOS: crashlog + syslog |
wdio://browserstack/local-binary | URL de descarga del binario de BrowserStack Local y comando de inicio |
wdio://saucelabs/local-binary | URL de descarga del binario de Sauce Connect y comando de inicio |
wdio://testmu/local-binary | URL de descarga del binario de TestMu Tunnel y comando de inicio |
wdio://testingbot/local-binary | URL de descarga del JAR de TestingBot Tunnel y comando de inicio (Java 11+) |
wdio://docs/index | Cada página de la documentación oficial de WebdriverIO como título separado por tabulaciones, ruta de origen y slug |
wdio://docs/page/{slug} | Markdown completo de una página de documentación, truncado a 40000 caracteres. Los slugs provienen de wdio://docs/index ("~" en lugar de "/") |
Ejemplos de Uso
Casos de Prueba del Mundo Real
Ejemplo 1: Prueba de la Aplicación Android Demo (Escaneo de Libros)
Test the Demo Android app at C:\Users\demo-liveApiGbRegionNonMinifiedRelease-3018788.apk on emulator-5554:
1. Start the app with auto-grant permissions
2. Get visible elements on the onboarding screen
3. Tap "Skip" to bypass onboarding
4. Verify main screen loads
5. Take a screenshot
Ejemplo 2: Prueba del Sitio de Comercio Electrónico World of Books
You are a Testing expert, and want to assess the basic workflows of worldofbooks.com:
- Open World of Books (accept all cookies)
- Get visible elements to see navigation structure
- Search for a fiction book
- Choose one and validate if there are NEW and used book options
- Report your findings at the end
Automatización de Navegador
Solicitud básica de prueba web:
You are a Testing expert, and want to assess the basic workflows of a web application:
- Open World of Books (accept all cookies)
- Search for a fiction book
- Choose one and validate if there are NEW and used book options
- Report your findings at the end
Opciones de configuración del navegador:
// Default settings (headed mode, 1280x1080)
start_session({platform: 'browser'})
// Firefox
start_session({platform: 'browser', browser: 'firefox'})
// Edge
start_session({platform: 'browser', browser: 'edge'})
// Safari (headed only; requires macOS)
start_session({platform: 'browser', browser: 'safari'})
// Headless mode
start_session({platform: 'browser', headless: true})
// Custom dimensions
start_session({platform: 'browser', windowWidth: 1920, windowHeight: 1080})
// Pass custom capabilities (e.g. Chrome extensions, profile, prefs)
start_session({
platform: 'browser',
headless: false,
capabilities: {
'goog:chromeOptions': {
args: ['--user-data-dir=/tmp/wdio-mcp-profile', '--load-extension=/path/to/unpacked-extension']
}
}
})
Mocking
El mocking está disponible a través de mock, get_mock_calls y manage_mock, tanto para funciones API del proceso principal de Electron como para solicitudes de red del navegador.
mockType acepta 'electron' o 'browser'. Los mocks de navegador son el predeterminado en sesiones de WebDriver cuando se omite mockType. Las sesiones de Electron requieren una selección explícita porque pueden apuntar a ambos tipos de mocks. Las sesiones de Appium de iOS/Android no admiten mocking.
mock({
mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog',
behavior: 'mockResolvedValue', value: { canceled: false, filePaths: ['/tmp/example.txt'] }
})
// Interact with the renderer to open the application's file picker, then inspect its calls.
get_mock_calls({ mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog' })
manage_mock({ mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog', action: 'restore' })
El behavior de Electron tiene como predeterminado mockReturnValue; mockResolvedValue y mockRejectedValue admiten APIs asíncronas. Cada uno tiene una variante Once para respuestas en cola. La configuración repetida conserva el mock existente y el historial de llamadas. Los valores deben ser JSON; omita value para undefined. clear elimina el historial de llamadas, reset también elimina el comportamiento y las respuestas en cola, y restore restablece la función original. Estas herramientas admiten funciones API individuales; los mocks de clases y las implementaciones de mock arbitrarias no están expuestos.
Browser mocks interceptan solicitudes de red que coinciden con un glob url (por ejemplo **/api/todos) con un filtro opcional method. behavior es opcional: omítelo para registrar pasivamente las solicitudes coincidentes sin alterarlas — el mock continúa cada solicitud. respond y respondOnce requieren value (el cuerpo de respuesta JSON) y aceptan statusCode y headers opcionales; abort/abortOnce fallan la solicitud, y redirect/redirectOnce la envían a la URL en value. get_mock_calls devuelve { calls, callCount } para las solicitudes interceptadas, y manage_mock toma clear, reset o restore.
start_session({ platform: 'browser', browser: 'chrome', capabilities: { webSocketUrl: true } })
// Observe-only: record every request to /api/todos without changing responses.
mock({ mockType: 'browser', url: '**/api/todos' })
navigate({ url: 'https://example.com/todos' })
get_mock_calls({ mockType: 'browser', url: '**/api/todos' })
// Or overwrite the response instead.
mock({ mockType: 'browser', url: '**/api/todos', method: 'GET', behavior: 'respond', value: [{ id: 1, title: 'Buy milk' }], statusCode: 200 })
// Interact with the page, then inspect the intercepted requests.
get_mock_calls({ mockType: 'browser', url: '**/api/todos', method: 'GET' })
manage_mock({ mockType: 'browser', url: '**/api/todos', method: 'GET', action: 'restore' })
Los browser mocks requieren una sesión con BiDi habilitado — iníciala con capabilities: { webSocketUrl: true }. Las sesiones adjuntas tienen BiDi desactivado por defecto, por lo que los browser mocks no funcionan allí a menos que la sesión adjunta haya negociado BiDi; en sesiones de Electron, los browser mocks además requieren BiDi. Los handles pertenecen a la sesión de navegador activa y no pueden reutilizarse después de que se cierre o sea reemplazada. Las tres herramientas participan en el rastreo y la reproducción generada.
Aplicaciones Electron
El soporte de Electron es solo local y utiliza el ciclo de vida independiente oficial @wdio/electron-service. Requiere Node.js 22.12 o superior. Coloca opciones de servicio como appBinaryPath, appEntryPoint y appArgs en capabilities['wdio:electronServiceOptions']; usa electronRootDir de nivel superior para el descubrimiento de Electron Builder/Electron Forge del servicio. Al probar un binario fuera del proyecto, establece browserVersion a la versión de Electron para que el servicio pueda seleccionar un Chromedriver compatible.
start_session({
platform: 'electron',
browserVersion: '33.2.1',
capabilities: {
'wdio:electronServiceOptions': {
appBinaryPath: '/path/to/MyApp.app/Contents/MacOS/MyApp',
appArgs: ['--disable-gpu']
}
}
})
// Privileged: this code runs in the Electron main process, not the renderer.
execute_electron_script({ script: 'return electron.app.getName()' })
Las herramientas DOM existentes del navegador funcionan contra el renderizador de Electron. close_session siempre cierra las sesiones de Electron gestionadas por MCP; detach: true no es compatible intencionalmente. La captura de registros del proceso principal/renderizador se puede habilitar con captureMainProcessLogs o captureRendererLogs más logDir. Para activar un deeplink de la aplicación, configura explícitamente su esquema de URI al iniciar la sesión de Electron. El esquema no tiene dos puntos y solo se pueden despachar URLs con ese esquema exacto:
start_session({
platform: 'electron',
electronDeeplinkScheme: 'myapp',
capabilities: {
'wdio:electronServiceOptions': {
appBinaryPath: '/path/to/MyApp.app/Contents/MacOS/MyApp'
}
}
})
trigger_electron_deeplink({ url: 'myapp://open/item' })
Adjuntar a una instancia de Chrome en ejecución:
// First, launch Chrome with remote debugging enabled:
//
// macOS (must quit Chrome first — open -a ignores args if Chrome is already running):
// pkill -x "Google Chrome" && sleep 1
// /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
// --remote-debugging-port=9222 \
// --user-data-dir=/tmp/chrome-debug &
//
// Linux:
// google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug &
//
// Verify it's ready: curl http://localhost:9222/json/version
start_session({attach: true})
start_session({attach: true, port: 9333})
start_session({attach: true, port: 9222, navigationUrl: 'https://app.example.com'})
Conectar a un endpoint WebDriver existente:
Usa provider: 'external' cuando otro proceso ya posee el ciclo de vida del navegador o webview y expone un endpoint W3C WebDriver. Esto es útil para sesiones de Selenium Grid, controladores de navegador gestionados externamente, o aplicaciones de escritorio como apps de Tauri que integran un webview y exponen WebDriver por separado. El servidor MCP se conecta al endpoint; no inicia ni detiene la aplicación objetivo, no abre túneles ni gestiona la configuración específica del framework.
// Defaults to http://127.0.0.1:4445/ and browserName: 'chrome'
start_session({provider: 'external', platform: 'browser'})
// Custom WebDriver endpoint and capabilities
start_session({
provider: 'external',
platform: 'browser',
webdriverConfig: {
protocol: 'http',
hostname: '127.0.0.1',
port: 4445,
path: '/'
},
capabilities: {
browserName: 'tauri'
}
})
Para aplicaciones de escritorio con webview como Tauri, primero inicia la aplicación y su puente WebDriver fuera de este servidor MCP, luego pasa el endpoint y las capacidades requeridas. Por ejemplo, un puente WebDriver de Tauri puede requerir capabilities: {browserName: 'tauri'}.
Adjuntar a una sesión WebDriver o Appium existente:
Usa attach_session cuando la sesión ya ha sido creada por otro proceso. El MCP reutiliza el endpoint y las credenciales del proveedor seleccionado, registra el conjunto de comandos de navegador/móvil apropiado localmente y no emite una solicitud de nueva sesión. Las sesiones adjuntas se gestionan externamente: close_session() se desconecta por defecto, mientras que close_session({detach: false}) termina explícitamente la sesión remota.
// Existing BrowserStack App Automate session
attach_session({
provider: 'browserstack',
platform: 'ios',
sessionId: 'existing-browserstack-session-id',
capabilities: {
'appium:deviceName': 'iPhone 15',
'appium:automationName': 'XCUITest'
}
})
// Existing session on a local Appium server
attach_session({
provider: 'local',
platform: 'android',
sessionId: 'existing-appium-session-id',
appiumConfig: {
protocol: 'http',
host: '127.0.0.1',
port: 4723,
path: '/'
}
})
// Existing mobile session on a custom W3C WebDriver endpoint
attach_session({
provider: 'external',
platform: 'ios',
sessionId: 'existing-grid-session-id',
webdriverConfig: {
protocol: 'https',
hostname: 'grid.example.com',
port: 443,
path: '/wd/hub'
}
})
Una sesión en la nube existente debe seguir usando el túnel con el que fue creada. attach_session nunca inicia ni detiene un túnel, así que mantén el proceso del túnel original vivo mientras la sesión lo necesite.
Emulación de dispositivos (requiere sesión BiDi):
// Device emulation (requires BiDi session)
start_session({capabilities: {webSocketUrl: true}})
emulate_device() // list available presets
emulate_device({device: 'iPhone 15'}) // activate emulation
emulate_device({device: 'Pixel 7'}) // switch device
emulate_device({device: 'reset'}) // restore desktop defaults
Extensiones web (requiere sesión BiDi):
start_session({platform: 'browser', browser: 'chrome', capabilities: {webSocketUrl: true}})
open_web_extension({
extensionData: {type: 'path', path: '/path/to/unpacked-extension'},
path: 'options.html'
})
// Drive the extension UI with the normal page tools.
get_elements()
click_element({selector: '#save'})
// For remote/cloud sessions, send a packaged extension archive as base64.
open_web_extension({
extensionData: {type: 'base64', value: '<base64-encoded-zip>'},
path: 'options.html'
})
Automatización de Aplicaciones Móviles
Probar una app de iOS en simulador:
Test my iOS app located at /path/to/MyApp.app on iPhone 15 Pro simulator:
1. Start the app session
2. Tap the login button
3. Enter "testuser" in the username field
4. Take a screenshot of the home screen
5. Close the session
Preservar el estado de la app entre sesiones:
Test my Android app without resetting data:
1. Start app session with noReset: true and fullReset: false
2. App launches with existing login state and user data preserved
3. Run test scenarios
4. Close session (app remains installed with data intact)
Probar una app de iOS en dispositivo real:
Test my iOS app on my physical iPhone:
1. Start app session with:
- platform: iOS
- appPath: /path/to/MyApp.ipa
- deviceName: My iPhone
- udid: 00008030-001234567890ABCD (your device's UDID)
- platformVersion: 17.0
2. Run your test scenario
3. Close the session
Probar una app de Android:
Test my Android app /path/to/app.apk on the Pixel_6_API_34 emulator:
1. Start the app with auto-grant permissions
2. Get visible elements (use inViewportOnly: false to see all elements)
3. Swipe up to scroll
4. Tap on the "Settings" button using text matching
5. Verify the settings screen is displayed
Detección avanzada de elementos:
Test my app and debug layout issues:
1. Start the app session
2. Get visible elements with includeContainers: true to see the layout hierarchy
3. Analyze ViewGroup, FrameLayout, and ScrollView containers
4. Use inViewportOnly: false to find off-screen elements that need scrolling
Pruebas de apps híbridas (cambio de contextos):
Test my hybrid app:
1. Start the Android app session
2. Tap "Open Web" button in native context
3. List available contexts
4. Switch to WEBVIEW context
5. Click the login button using CSS selector
6. Switch back to NATIVE_APP context
7. Verify we're back on the home screen
Notas Importantes
⚠️ Gestión de Sesiones:
- Solo una sesión (navegador O app) puede estar activa a la vez
- Siempre cierra las sesiones cuando termines para liberar recursos del sistema
- Para cambiar entre navegador y móvil, cierra la sesión actual primero
- Usa
close_session({ detach: true })para desconectarte sin terminar la sesión en el servidor Appium - La preservación de estado se puede controlar con los parámetros
noResetyfullResetdurante la creación de la sesión - Las sesiones creadas con
noReset: trueo sinappPathse desconectarán automáticamente al cerrar - Las sesiones adoptadas con
attach_sessionsiempre se desconectan al cerrar a menos quedetach: falsese solicite explícitamente
⚠️ Planificación de Tareas:
- Divide la automatización compleja en operaciones más pequeñas y enfocadas
- Claude puede consumir los límites de mensajes rápidamente con automatización extensa
⚠️ Automatización Móvil:
- El servidor Appium debe estar en ejecución antes de iniciar sesiones móviles
- Asegúrate de que los emuladores/simuladores estén en ejecución y los dispositivos estén conectados
- La automatización de iOS requiere macOS con Xcode instalado
- Dispositivos iOS Reales: Probar en dispositivos iOS físicos requiere el UDID del dispositivo (identificador único de 40 caracteres). Consulta la sección de Requisitos Previos para saber cómo encontrar tu UDID
Referencia Rápida de Sintaxis de Selectores
Web (CSS/XPath):
- CSS:
button.my-class,#element-id - XPath:
//button[@class='my-class'] - Texto:
button=Exact text,a*=Contains text
Móvil (Multiplataforma):
- ID de Accesibilidad:
~loginButton(funciona en iOS y Android) - UiAutomator de Android:
android=new UiSelector().text("Login") - Predicado de iOS:
-ios predicate string:label == "Login" AND visible == 1 - XPath:
//android.widget.Button[@text="Login"]
Funciones Avanzadas
Preservación del Estado de la App
Preservación de estado con noReset/fullReset:
Controla el estado de la app al crear nuevas sesiones usando los parámetros noReset y fullReset:
| noReset | fullReset | Comportamiento |
|---|---|---|
true | false | Preservar estado: La app permanece instalada, datos preservados |
false | false | Borrar datos de la app pero mantenerla instalada (por defecto) |
false | true | Restablecimiento completo: Desinstalar y reinstalar la app (estado limpio) |
Ejemplo con preservación de estado:
// Preserve login state between test runs
start_session({
platform: 'android',
appPath: '/path/to/app.apk',
deviceName: 'emulator-5554',
noReset: true, // Don't reset app state
fullReset: false, // Don't uninstall
autoGrantPermissions: true,
capabilities: {
'appium:chromedriverExecutable': '/path/to/chromedriver',
'appium:autoWebview': true
}
})
// App launches with existing user data, login tokens, preferences intact
Desconectarse de Sesiones:
La herramienta close_session admite un parámetro detach que desconecta de la sesión sin terminarla en el servidor Appium:
// Detach without killing the session
close_session({detach: true})
// Explicit session termination (closes the app and removes session)
close_session({detach: false})
Las sesiones creadas con noReset: true o sin appPath se desconectarán automáticamente al cerrar.
Las sesiones adoptadas con attach_session se gestionan externamente y también se desconectan por defecto; pasa detach: false solo cuando el MCP deba terminar deliberadamente la sesión remota existente.
Esto es particularmente útil cuando:
- Se preserva el estado de la app para continuar pruebas manuales
- Se depuran flujos de trabajo de varios pasos (dejar la sesión en ejecución entre invocaciones de herramientas)
- Se prueban escenarios donde quieres que la app permanezca instalada y en su estado actual
Detección Inteligente de Elementos
- Clasificación de elementos específica de la plataforma: Identifica automáticamente elementos interactuables vs contenedores de diseño
- Android: Button, EditText, CheckBox vs ViewGroup, FrameLayout, ScrollView
- iOS: Button, TextField, Switch vs View, StackView, CollectionView
- Múltiples estrategias de localizadores: Cada elemento proporciona ID de accesibilidad, ID de recurso, texto, XPath y selectores específicos de la plataforma
- Filtrado de viewport: Controla si obtener solo elementos visibles o todos los elementos, incluidos los fuera de pantalla
- Depuración de diseño: Opcionalmente incluye elementos contenedores para entender la jerarquía de la interfaz
Manejo Automático de Permisos y Alertas
Tanto las sesiones de iOS como las de Android ahora admiten el manejo automático de permisos y alertas del sistema:
autoGrantPermissions(por defecto: true): Otorga automáticamente permisos de la app (cámara, ubicación, etc.)autoAcceptAlerts(por defecto: true): Acepta automáticamente alertas y diálogos del sistemaautoDismissAlerts(opcional): Establécelo en true para descartar alertas en lugar de aceptarlas
Esto elimina la necesidad de manejar manualmente las ventanas emergentes de permisos durante las pruebas automatizadas.
Detalles Técnicos
- Construido con: TypeScript, WebDriverIO, Appium
- Soporte de Navegadores: Chrome, Firefox, Edge (con interfaz/sin interfaz, gestión automatizada de controladores), Safari (solo con interfaz; macOS)
- Soporte Móvil: iOS (XCUITest) y Android (UiAutomator2/Espresso)
- Protocolo: Model Context Protocol (MCP) para integración con Claude Desktop
- Modelo de Sesión: Sesión activa única (navegador o app móvil)
- Formato de Datos: TOON (Token-Oriented Object Notation) para comunicación eficiente con LLM
- Detección de Elementos: Análisis de fuente de página basado en XML con filtrado inteligente y generación de localizadores de múltiples estrategias
Grabación de Sesiones y Exportación de Código
Cada llamada de herramienta se registra automáticamente en un historial de sesión. Puedes inspeccionar sesiones y exportar código ejecutable a través de los recursos MCP — sin necesidad de llamadas de herramienta adicionales:
wdio://sessions— lista todas las sesiones grabadas con tipo, marcas de tiempo y número de pasoswdio://session/current/steps— registro de pasos de la sesión activawdio://session/current/code— JS de WebdriverIO ejecutable generado para la sesión activawdio://session/{sessionId}/steps— registro de pasos de cualquier sesión pasada por IDwdio://session/{sessionId}/code— JS generado para cualquier sesión pasada por ID
El script generado reconstruye la sesión completa — incluyendo capacidades, navegación, clics y entradas — como un archivo import { remote } from 'webdriverio' independiente. Para sesiones de proveedores en la nube incluye el try/catch/finally completo con marcado automático del resultado de la sesión a través de la API REST del proveedor.
Grabación de Trazas
Pasar trace: true a start_session produce un zip .trace compatible con Playwright en el directorio .trace/ cuando la sesión se cierra. El zip se puede reproducir en player.vibium.dev y muestra una tira de capturas de pantalla junto con la línea de tiempo de acciones.
Cómo se temporizan las capturas de pantalla
El viaje de ida y vuelta de takeScreenshot de Appium toma 700–1300 ms en un emulador local, lo cual es suficiente para que las animaciones de la acción anterior se asienten. Aprovechamos esto: cada captura de pantalla se toma antes de que se dispare la siguiente acción, por lo que lo que el servidor Appium devuelve ya es el resultado asentado de la acción anterior.
La parte complicada es hacer que el reproductor de trazas muestre esa captura bajo la acción correcta. El reproductor asocia un evento screencast-frame con la ventana de tiempo de la acción que contiene el campo timestamp del fotograma. Si la marca de tiempo se establece en "ahora" (tiempo de captura), cae antes del startTime de la acción actual y el reproductor la etiqueta como el estado antes de la siguiente acción — una acción desincronizada.
La solución: sellar cada screencast-frame con lastAfterEndTime — el endTime de la acción que acaba de completarse. Eso coloca el fotograma dentro de la ventana de la acción anterior, por lo que el reproductor lo muestra como el resultado de esa acción, no como el precursor de la siguiente.
Timeline (monotonic ms):
prev.endTime ← frame timestamp stamped here
│
│ [screenshot captured here — shows settled state after prev action]
│
curr.startTime
│
│ [action executes]
│
curr.endTime ← next frame will be stamped here
La captura de pantalla final al cierre de la sesión se sella con el endTime de la última acción, por lo que se renderiza bajo esa acción en lugar de aparecer como un fotograma huérfano después de que termine la línea de tiempo.
Registros de Sesión
El recurso wdio://session/current/logs devuelve informes de fallos, errores de consola y registros del sistema para la sesión actual, detectando automáticamente el tipo de sesión para obtener el búfer de registro correcto:
| Tipo de sesión | Fuentes de registro | Contenidos |
|---|---|---|
| Navegador | getLogs('browser') | Salida de consola + excepciones JS no capturadas |
| Android | getLogs('logcat') | Registros del sistema, volcados de memoria, excepciones fatales |
| iOS | getLogs('crashlog') + getLogs('syslog') | Informes de fallos/pánicos + diagnósticos del sistema |
Nota: Leer este recurso limpia el búfer de registro (según la especificación de WebDriver). Las lecturas posteriores devuelven solo entradas acumuladas desde la última lectura. Los registros del navegador requieren Chromium (Chrome/Edge) — Firefox y Safari no admiten el comando
getLogs.
La respuesta es JSON con sessionType, logTypes (tipos de registro disponibles) y entries — cada entrada incluye level,
message, timestamp (ms Unix) y timestampISO.
Solución de problemas
¿La automatización del navegador no funciona?
- Asegúrate de que Chrome, Firefox, Edge o Safari estén instalados (Safari requiere macOS)
- Intenta reiniciar Claude Desktop por completo
- Verifica que no haya otras instancias de WebDriver en ejecución
¿La automatización móvil no funciona?
- Verifica que el servidor de Appium esté en ejecución:
appium - Comprueba que el dispositivo/emulador esté en ejecución:
adb devices(Android) o Xcode Devices (iOS) - Asegúrate de que los controladores de plataforma correctos estén instalados
- Verifica que la ruta de la aplicación sea correcta y accesible
¿Encontraste problemas o tienes sugerencias? ¡Comparte tus comentarios!