¿Qué hace cli-anything-safari?
Una interfaz de línea de comandos para la automatización del navegador Safari en macOS. Envuelve el servidor MCP Node.js safari-mcp en una CLI Python Click.
La paridad de funcionalidades está garantizada. Cada comando Click se genera automáticamente a partir del esquema de herramientas de safari-mcp (incluido como resources/tools.json). Las 84 herramientas son accesibles con los nombres y tipos de argumentos exactos que espera el servidor MCP.
Cuándo usar esta CLI
Cada invocación de la CLI genera un subproceso nuevo, por lo que hay una sobrecarga por llamada. Si tu agente habla MCP de forma nativa (Claude Code, Cursor, Cline, etc.), usar safari-mcp directamente a través de MCP stdio será más rápido.
Usa esta CLI cuando:
- El marco de trabajo de tu agente no hable MCP (Codex CLI, GitHub Copilot CLI, scripts personalizados, marcos de agente antiguos).
- Necesites scriptear la automatización del navegador desde bash —
cli-anything-safari --json tool snapshot | jq '...'. - Ejecutes en CI/CD y quieras una salida amigable para subprocesos y programable con cron.
- Estés depurando interactivamente desde Terminal.
Instalación
Requisitos previos
- macOS — Safari MCP es solo para macOS.
- Safari — ya instalado en macOS.
- Node.js 18+ —
brew install nodeo desde https://nodejs.org/ - Python 3.10+
- Habilitar Eventos de Apple para Safari: Safari → Develop → Permitir JavaScript de Eventos de Apple
Instalar la CLI
cd safari/agent-harness
pip install -e .
La primera llamada a tool descargará el paquete npm safari-mcp (una sola vez, unos pocos MB).
Estructura de Comandos
La CLI tiene 5 comandos principales:
| Comando | Propósito |
|---|---|
tool | Llamar a cualquiera de las 84 herramientas de safari-mcp (dinámico, basado en esquema) |
tools | Inspeccionar el registro de herramientas incluido (list, describe, count) |
raw | Válvula de escape — llamar a una herramienta por nombre completo con argumentos JSON sin procesar |
session | Estado de sesión en memoria (última URL, pestaña actual) |
repl | REPL interactivo (predeterminado cuando no se da ningún subcomando) |
Ejemplos de Uso
Descubrir la superficie de herramientas
# Contar herramientas (prueba de cordura — debe coincidir con las herramientas registradas de safari-mcp)
cli-anything-safari tools count
# → 84
# Listar cada herramienta
cli-anything-safari tools list
cli-anything-safari tools list --filter click # filtrar por subcadena
# Esquema completo para una herramienta (formato JSON o legible)
cli-anything-safari tools describe safari_scroll
cli-anything-safari --json tools describe safari_click
Llamar a una herramienta (basada en esquema)
# Navegar
cli-anything-safari tool navigate --url https://example.com
# Tomar una instantánea (preferible a la captura de pantalla — texto estructurado con IDs de referencia)
cli-anything-safari --json tool snapshot
# Hacer clic por referencia (las referencias provienen de snapshot; ¡expiran en la siguiente snapshot!)
cli-anything-safari tool click --ref 0_5
# Hacer clic por selector o texto visible
cli-anything-safari tool click --selector "#submit"
cli-anything-safari tool click --text "Iniciar sesión"
# Rellenar un campo
cli-anything-safari tool fill --selector "#email" --value "[email protected]"
# Desplazar por dirección/cantidad (NO x/y — ¡observa el esquema!)
cli-anything-safari tool scroll --direction down --amount 500
# Arrastrar un elemento sobre otro
cli-anything-safari tool drag \
--source-selector ".card" \
--target-selector ".trash"
# Captura de pantalla — devuelve JPEG en base64 en la salida estándar. Decodificar con:
cli-anything-safari --json tool screenshot --full-page \
| python3 -c "import sys,json,base64; \
d=json.load(sys.stdin); \
open('/tmp/shot.jpg','wb').write(base64.b64decode(d['data']))"
# Guardar como PDF (este escribe directamente en el disco)
cli-anything-safari tool save-pdf --path /tmp/page.pdf
# Evaluar JavaScript (nota: el parámetro es --script, no --code)
cli-anything-safari tool evaluate --script "document.title"
Navegar y leer en un solo viaje de ida y vuelta
cli-anything-safari --json tool navigate-and-read --url https://example.com
Relleno de formularios (masivo)
safari_fill_form toma un array de objetos {selector, value}.
Pásalo como una cadena JSON:
cli-anything-safari tool fill-form --fields '[
{"selector": "#email", "value": "[email protected]"},
{"selector": "#password", "value": "hunter2"}
]'
Ejecuta cli-anything-safari tools describe safari_fill_form para ver el esquema exacto, incluidos los nuevos campos que safari-mcp pueda añadir aguas arriba.
Monitoreo de red
cli-anything-safari tool start-network-capture
cli-anything-safari tool navigate --url https://example.com
cli-anything-safari --json tool network
cli-anything-safari tool performance-metrics
Almacenamiento
cli-anything-safari tool get-cookies
cli-anything-safari tool set-cookie --name session --value abc123 --domain example.com
cli-anything-safari tool local-storage --key theme
# export-storage devuelve JSON a la salida estándar — sin argumento --path. Redirigir a un archivo:
cli-anything-safari --json tool export-storage > /tmp/storage.json
Válvula de escape JSON sin procesar
Cuando necesites pasar un objeto anidado complejo o quieras manejar la CLI desde un blob JSON preconstruido:
cli-anything-safari raw safari_evaluate \
--json-args '{"code":"[...document.querySelectorAll(\"a\")].map(a => a.href)"}'
REPL interactivo
cli-anything-safari
El banner del REPL imprime la ruta absoluta a este SKILL.md para que los agentes puedan autodescubrir sus capacidades.
Salida JSON
Todos los comandos admiten --json como bandera global:
cli-anything-safari --json tool snapshot
cli-anything-safari --json tool list-tabs
cli-anything-safari --json tools list
Gestión de Estado
La CLI mantiene una pequeña cantidad de estado en memoria solo para la visualización del REPL:
last_url— última URL a la que navegó la CLI (actualizada después de cadatool navigate,tool navigate-and-readotool new-tabexitoso)current_tab_index— último índice de pestaña activa conocido
No hay sesión persistente, ni deshacer/rehacer, ni modelo de documento. Cada invocación de la CLI comienza con un estado nuevo. El propio Safari MCP no tiene estado por llamada: cada comando tool genera un nuevo subproceso npx safari-mcp, realiza la acción y sale. Esta es una elección de diseño deliberada; consulta HARNESS.md y TEST.md para conocer el razonamiento detrás de esta desviación del patrón estándar de deshacer/rehacer.
Formatos de Salida
Todos los comandos admiten modos de salida dual:
- Legible para humanos (predeterminado): texto clave-valor con sangría para resultados de tipo
dict, listas con viñetas para arrays, texto plano en otros casos - Legible para máquinas (bandera
--json): JSON estructurado para consumo del agente
# Salida humana
cli-anything-safari tool snapshot
# Salida JSON para agentes
cli-anything-safari --json tool snapshot
cli-anything-safari --json tools list
cli-anything-safari --json tools describe safari_click
Para Agentes de IA
Al usar esta CLI programáticamente:
- Usa siempre la bandera
--jsonpara una salida analizable. - Comprueba los códigos de retorno — 0 para éxito, distinto de cero para errores (fallos de validación de URL, fallos de llamadas MCP, argumentos JSON no válidos).
- Analiza stderr para mensajes de error; usa stdout para datos.
- Las herramientas de manejo de archivos tienen nombres de argumentos de ruta inconsistentes — comprueba siempre
tools describe <name>primero:tool save-pdf --path /tmp/x.pdftool upload-file --selector ... --file-path /tmp/x.txt(nota:--file-path, no--path)tool export-storage— sin argumento de ruta; redirige la salida JSON a un archivotool import-storage --path /tmp/x.jsontool screenshot/screenshot-element— devuelven base64 en la respuesta JSON, sin argumento de ruta (decodifícalo tú mismo)
- Instantánea antes de hacer clic — las referencias de
tool snapshotexpiran en la siguiente instantánea. Siempre haz instantánea → encuentra la referencia → haz clic en sucesión cercana. - Descubre herramientas mediante
tools list— el registro incluido es la fuente de verdad sobre lo que está disponible. No codifiques nombres de herramientas que puedan cambiar aguas arriba. - Usa
tools describe <name>para aprender el esquema exacto (argumentos requeridos, opciones de enumeración, argumentos tipados JSON) antes de construir una llamada. Nunca asumas los nombres de los parámetros a partir de la descripción — por ejemplo,safari_evaluatetoma--script(no--code) aunque la descripción diga "código JavaScript a ejecutar".
Guía Específica para Agentes
Encontrar la herramienta adecuada
Usa los comandos de introspección. Se garantiza que la CLI refleje el servidor MCP 1:1:
# Encontrar todas las herramientas relacionadas con clics
cli-anything-safari tools list --filter click
# Obtener el esquema completo (incluyendo cada argumento con tipo, descripción,
# requerido/opcional, opciones de enumeración, valores predeterminados)
cli-anything-safari --json tools describe safari_click
Estrategia de selección de herramientas
tool snapshotsobretool screenshot— el texto estructurado con IDs de referencia es órdenes de magnitud más barato y contiene las referencias necesarias para los clics.tool click --refsobretool click --selector— las referencias son estables dentro de una sola instantánea, los selectores pueden ser frágiles.tool navigate-and-readsobrenavigate+read-page— ahorra un viaje de ida y vuelta.tool click-and-readsobreclick+read-page— ahorra un viaje de ida y vuelta.tool native-clicksolo cuando el clic normal falla con 405/403 (bloqueos WAF, G2, Cloudflare) — mueve físicamente el cursor.
Las Referencias Expiran
Las referencias de tool snapshot expiran cuando tomas una nueva instantánea:
- Primera instantánea: referencias
0_1,0_2,0_3... - Segunda instantánea: referencias
1_1,1_2,1_3...
Siempre haz instantánea → haz clic en sucesión cercana. En caso de duda, toma otra instantánea.
Seguridad de Propiedad de Pestañas
Safari MCP rastrea la propiedad de las pestañas por sesión. Las herramientas que modifican una pestaña (navegar, hacer clic, rellenar) están bloqueadas en pestañas que la sesión no abrió. Para operar en una página específica, comienza siempre con tool new-tab --url ....
Manejo de Errores
Errores comunes:
npx not found→ instala Node.js 18+safari-mcp package not found on npm registry→ comprueba la redNot macOS→ el arnés es solo para macOSAppleScript denied→ habilita "Permitir JavaScript de Eventos de Apple" en Safari → DevelopBlocked URL scheme: file→ la validación de URL rechazó la entrada (por diseño)
Validación de URL
La CLI valida las URLs antes de pasarlas a safari_navigate, safari_navigate_and_read y safari_new_tab. Esquemas bloqueados: file, javascript, data, vbscript, about, chrome, safari, webkit, x-apple y otros esquemas internos del navegador. El comando raw también aplica esto para las herramientas de navegación.
Advertencia de Múltiples Sesiones
Safari MCP aplica una única sesión activa eliminando los procesos Node.js inactivos de más de 10 segundos. Si ejecutas dos instancias de la CLI a la vez, una eliminará el backend de la otra. Actualmente no hay modo daemon — para flujos de trabajo sensibles a la latencia, maneja la CLI desde un script Python de larga duración que importe cli_anything.safari.utils.safari_backend.call() directamente para evitar volver a generar el subproceso en cada invocación.
Enlaces
Consideraciones de Seguridad
Validación de URL
Todas las herramientas de navegación (tool navigate, tool navigate-and-read, tool new-tab y raw safari_navigate*) pasan el argumento url a través de utils/security.py, que bloquea esquemas peligrosos y opcionalmente bloquea redes privadas (establece CLI_ANYTHING_SAFARI_BLOCK_PRIVATE=1).
Aislamiento de Pestañas
Safari MCP aplica la propiedad de pestañas por sesión aguas arriba: las herramientas no pueden operar en pestañas que la sesión no abrió.
Aislamiento de Perfil
Establece la variable de entorno SAFARI_PROFILE para usar un perfil de Safari separado para la automatización:
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
Esto mantiene cookies/inicios de sesión/historial separados de la navegación principal del usuario.
Ejecución de JavaScript
tool evaluate y tool run-script ejecutan JavaScript arbitrario en el contexto de la página. Trata la entrada no confiable con el mismo cuidado que cualquier ruta de ejecución de código dinámico.
Portapapeles
tool clipboard-read y tool clipboard-write tocan el portapapeles del sistema. Ten cuidado al ejecutarlos dentro de la sesión activa de un usuario: sobrescribir el portapapeles en medio de una tarea es disruptivo.
Regenerar el registro de herramientas
Si actualizas safari-mcp, regenera el esquema incluido:
python scripts/extract_tools.py \
"$(npm root -g)/safari-mcp/index.js" \
cli_anything/safari/resources/tools.json
La prueba de paridad (test_parity.py) fija el recuento esperado de herramientas; actualízala cuando cambie la lista de herramientas aguas arriba.
Más Información
- Documentación completa:
cli_anything/safari/README.mden el paquete - Cobertura de pruebas:
cli_anything/safari/tests/TEST.mden el paquete - Análisis de arquitectura:
safari/agent-harness/SAFARI.md - Metodología:
cli-anything-plugin/HARNESS.md - Patrón backend MCP:
cli-anything-plugin/guides/mcp-backend.md
Versión
1.0.0 — apunta a safari-mcp 2.7.8 (84 herramientas). El registro de herramientas incluido se regenera mediante scripts/extract_tools.py cuando safari-mcp se actualiza.