Skip to content

Trabajar rápido ​

Lo que más tiempo consume al manejar el simulador desde un agente no es el simulador: es cada ida y vuelta con el modelo, y el tamaño de lo que el servidor le devuelve. El servidor está diseñado para reducir ambas cosas. Sus instrucciones ya le indican al modelo cómo aprovecharlo, pero conviene conocerlo para formular mejor las peticiones.

Menos llamadas ​

Tocar por texto ​

ui_tap_element busca un elemento por su texto visible, su identificador o su tipo, y lo toca, todo en una llamada. Sustituye a la pareja ui_describe_screen más ui_tap.

json
{ "label": "Iniciar sesión" }

Además espera unos segundos a que el elemento aparezca, así que puede usarse justo después de una transición de pantalla. Consulta cómo se localiza un elemento.

Recibir la pantalla resultante ​

Todas las acciones de interfaz aceptan describeAfter: true. La respuesta incluye entonces los elementos que hay en pantalla después de la acción, sin necesidad de pedirlos aparte.

json
{ "label": "Iniciar sesión", "describeAfter": true }

Secuencias ​

ui_sequence ejecuta varios pasos en una sola llamada. Es la opción adecuada para cualquier flujo que se pueda planificar de antemano, como rellenar un formulario:

json
{
  "steps": [
    { "action": "paste_text", "text": "José Muñoz", "label": "Nombre" },
    { "action": "tap_element", "label": "Email" },
    { "action": "type_text", "text": "jose@example.com" },
    { "action": "scroll_to_element", "label": "Enviar" },
    { "action": "tap_element", "label": "Enviar" },
    { "action": "wait_for_element", "label": "Gracias", "timeoutSeconds": 15 }
  ],
  "describeAfter": true
}

La secuencia se detiene en el primer paso que falla. La respuesta indica qué pasos se completaron, el error y lo que hay en pantalla en ese momento, de modo que el modelo puede continuar desde ahí.

Pasos disponibles: tap, tap_element, type_text, paste_text, scroll_to_element, swipe, press_button, press_key, wait y wait_for_element.

Desplazarse hasta un elemento ​

ui_scroll_to_element desliza la pantalla hasta que un elemento es visible y lo devuelve. Sustituye al bucle de ui_swipe y ui_describe_screen. Se detiene cuando el elemento aparece, cuando se llega al final del contenido o tras maxSwipes deslizamientos.

Esperar en vez de sondear ​

ui_wait_for_element espera a que un elemento esté en pantalla. Evita encadenar llamadas a ui_describe_screen mientras una app carga.

Respuestas más pequeñas ​

Pantalla en texto compacto ​

ui_describe_screen devuelve una línea por elemento:

Button "Iniciar sesión" id=login.submit @(195,725) 350x50

Cada línea incluye el tipo, el texto, el identificador, el punto donde tocarlo y su tamaño. Ocupa menos de la mitad que el JSON equivalente.

Capturas en puntos ​

screenshot reduce la imagen a un píxel por punto. En un iPhone con escala 3 es una novena parte de los píxeles, y por tanto muchos menos tokens de imagen. Además, las posiciones de la imagen coinciden con las coordenadas de ui_tap. Usa resolution: "full" cuando necesites la resolución nativa.

Lista de apps sin rutas ​

list_apps devuelve una línea por app, sin la ruta interna del paquete. Si la necesitas, pídela con get_app_container.

Menos trabajo en el servidor ​

Conexión directa con idb_companion ​

idb tiene dos partes: idb_companion, que habla con el simulador, y un cliente en Python. El cliente arranca un intérprete, se conecta, hace una sola cosa y termina, en cada acción.

El servidor habla directamente con idb_companion y mantiene la conexión abierta entre llamadas. Es el cambio que más reduce el tiempo de cada acción de interfaz: un toque pasa de unas seis décimas de segundo a unas pocas centésimas.

Funciona así por defecto. Si idb_companion no se puede arrancar, el servidor recurre al cliente de línea de comandos y lo indica una vez en su salida de errores. Se controla con IOS_SIMULATOR_MCP_UI_BACKEND; consulta Configuración.

Con este modo solo hace falta idb_companion (el paquete de Homebrew); el cliente de Python deja de ser necesario.

Caché de la lista de simuladores ​

Casi todas las llamadas necesitan saber qué simulador usar, y consultar la lista a simctl es de lo más lento que hace el servidor. La lista se reutiliza durante diez segundos entre llamadas.

La caché solo se usa para respuestas positivas. Antes de informar de que un dispositivo no existe o no está arrancado, el servidor vuelve a consultar, de modo que un simulador arrancado desde Xcode se encuentra siempre. Las operaciones que cambian el estado de un simulador la invalidan.

La duración se ajusta con IOS_SIMULATOR_MCP_DEVICE_CACHE_MS; 0 la desactiva.

Mediciones ​

Estas cifras salen de los tests de integración, que se ejecutan en cada cambio contra un iPhone 16e con iOS 26.2 en un runner de macOS de GitHub Actions. Los tiempos absolutos varían bastante entre ejecuciones y entre máquinas; lo que importa son las proporciones.

Las dos formas de hablar con idb, en la misma ejecución:

Modoui_describe_screenui_tap
Conexión directa (companion)0,17 s0,19 s
Cliente de línea de comandos (cli)0,79 s0,62 s

Una vez establecida la conexión, los toques sucesivos bajaron a unos 0,01 s de media.

Pulsar tres veces el mismo botón, con la conexión directa:

MétodoLlamadas a herramientasTiempo en el servidor
ui_describe_screen y ui_tap por coordenadas60,7 s
ui_tap_element30,8 s
ui_sequence11,0 s

Con la conexión directa el tiempo del servidor deja de ser lo relevante: las tres variantes tardan alrededor de un segundo. Lo que las distingue es el número de idas y vueltas con el modelo, que no aparecen en la tabla y suelen costar varios segundos cada una. Con el cliente de línea de comandos, la primera variante tardaba 10,0 s y la segunda 5,6 s.

Otras operaciones:

OperaciónTiempo medio
Listar simuladores, que es lo que la caché evita en cada llamada0,3 a 1,4 s
Una llamada a simctl con el dispositivo en caché0,3 a 1,2 s

Tamaño de las respuestas:

RespuestaTamaño
ui_describe_screen de una pantalla con 16 elementos964 caracteres
Captura a resolución nativa (JPEG)168 kB
Captura en puntos (JPEG)29 kB

La captura en puntos ocupa algo menos de una sexta parte.

Las mediciones de cada ejecución quedan como artefacto simulator-artifacts del flujo de CI.

En el cliente ​

  • Permite las herramientas del servidor para que el cliente no pida confirmación en cada llamada. En Claude Code, con /permissions.
  • Pide flujos completos. «Inicia sesión con el usuario de pruebas y abre Ajustes» permite una sola secuencia; pedirlo paso a paso obliga a una llamada por paso.
  • Reserva las capturas para lo visual. Para saber qué hay en pantalla o dónde tocar, el texto de ui_describe_screen es más rápido y exacto.

Publicado bajo licencia MIT.