Safari MCP
Automatización nativa del navegador Safari para agentes de IA — 80 herramientas vía AppleScript, sin sobrecarga de Chrome, conserva las sesiones. Solo macOS.
Documentación
🦁 Safari MCP
El navegador para tu agente de código.
Tu Safari real, con sesión iniciada — sin Chrome, sin calor, sin headless.
Instalar en VS Code · VS Code Insiders · Instalar en Cursor
98 herramientas · Sin necesidad de Chrome/Puppeteer/Playwright · ~5ms por comando · 60% menos CPU que Chrome
Inicio rápido · Las 98 herramientas · Ejemplos · ¿Por qué Safari MCP? · Arquitectura · Registro de cambios

❌ Sin Safari MCP
Tu agente de IA necesita navegar. Así que o bien:
- Inicia Chromium vía Playwright — sin inicios de sesión, sin cookies, sin sesiones
- Usa Chrome DevTools MCP — y funde el ventilador ejecutando un segundo navegador
- Depende de scrapers headless — bloqueados por Cloudflare, reCAPTCHA y detección de bots
✅ Con Safari MCP
Tu IA controla el Safari en el que ya has iniciado sesión — Gmail, GitHub, Ahrefs, Slack, banca.
WebKit nativo. ~60% menos CPU. Operación en segundo plano. 98 herramientas. Un comando npx. Solo macOS.
📰 Destacado en freeCodeCamp: Cómo conectar tu agente de código de IA a un navegador en macOS · HackerNoon: Ingeniería inversa de React, Shadow DOM y CSP
🍎 Apple incluye un Safari MCP oficial —
safaridriver --mcp, primero en Safari Technology Preview 247 (julio de 2026) y en Safari estable desde 27.0. Controla una sesión de automatización aislada para depuración. safari-mcp controla el Safari real en el que ya has iniciado sesión — tus cookies y sesiones, en segundo plano, con 98 herramientas. Consulta la comparación completa a continuación.
Destacados
- 98 herramientas — navegación, clics, formularios, capturas de pantalla, red, almacenamiento, accesibilidad y más
- Cero calor — WebKit nativo en Apple Silicon, ~60% menos CPU que Chrome
- Tu navegador real — conserva todos los inicios de sesión, cookies y sesiones (Gmail, GitHub, Ahrefs, etc.)
- Operación en segundo plano — Safari permanece en segundo plano, sin robar ventanas
- Sin dependencias de navegador — sin Puppeteer, sin Playwright, sin WebDriver, sin Chrome
- Proceso persistente — reutiliza un único proceso osascript (~5ms por comando vs ~80ms)
- Compatible con frameworks — relleno de formularios en React, Vue, Angular, Svelte mediante setters nativos
En palabras de los usuarios
Testimonios no solicitados — citas extraídas del rastreador de incidencias público, cada una enlazada al hilo del que proviene.
"Ejecuto múltiples sesiones de Pi/subagentes contra mi perfil normal de Safari en paralelo. Compartir sus cookies e inicios de sesión es intencional." — @maxim, sobre ejecutar agentes concurrentes contra un navegador real
"El servidor tiene un modelo deliberado de propiedad de pestañas … el código es cuidadoso con esto, y para el caso predeterminado esa es la postura de seguridad correcta." — @turner-moore, sobre por qué los guardias se niegan a tocar tus pestañas
"Validación local directa desde el paquete: Safari MCP doctor 6/6." — @jrepp, quien encontró y corrigió un error de alineación de cola en el helper de enfoque
Inicio rápido
Requisitos previos
- macOS (cualquier versión con Safari)
- Node.js 20+
- Safari → Ajustes → Avanzado → Mostrar funciones para desarrolladores web ✓
- Safari → Ajustes → Desarrollador → Permitir JavaScript desde Apple Events ✓
Instalación (un comando)
npx safari-mcp
Eso es todo — no se necesita instalación global. O instala permanentemente:
npm install -g safari-mcp
Configura tu cliente MCP
Todos los clientes ejecutan Safari MCP de la misma manera — npx safari-mcp. Elige tu editor:
Claude Code
claude mcp add safari -- npx safari-mcp
O edita ~/.mcp.json:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Claude Desktop
Edita ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Reinicia Claude Desktop después de guardar.
Cursor
Un clic: Instalar en Cursor
O edita .cursor/mcp.json en tu proyecto:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
VS Code / VS Code Insiders
Un clic: Instalar en VS Code
O edita .vscode/mcp.json:
{
"servers": {
"safari": {
"type": "stdio",
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Windsurf
Edita .windsurf/mcp.json en tu proyecto (o ~/.codeium/windsurf/mcp_config.json globalmente):
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Cline
Abre Cline en VS Code → haz clic en el icono de MCP → Editar configuración de MCP → añade:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Continue
Edita ~/.continue/config.yaml (o .continue/config.yaml en el espacio de trabajo):
mcpServers:
- name: safari
command: npx
args:
- safari-mcp
Goose
Edita ~/.config/goose/config.yaml:
extensions:
safari:
name: safari
type: stdio
cmd: npx
args:
- safari-mcp
enabled: true
LM Studio
Abre LM Studio → Ajustes → Servidores MCP → Añadir servidor:
- Nombre:
safari - Comando:
npx - Argumentos:
safari-mcp
Zed
Abre Zed → Ajustes → busca "Servidores de contexto" y añade:
{
"context_servers": {
"safari": {
"command": {
"path": "npx",
"args": ["safari-mcp"]
}
}
}
}
Alternativa: Homebrew
brew install achiya-automation/tap/safari-mcp
Alternativa: desde el código fuente
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp && npm install
Flujo de trabajo de uso
El patrón recomendado para agentes de IA que usan Safari MCP:
1. safari_snapshot → Get page state (accessibility tree)
2. safari_click/fill/... → Interact with elements by ref
3. safari_snapshot → Verify the result
Selección de elementos — las herramientas aceptan múltiples estrategias de selección:
| Estrategia | Ejemplo | Mejor para |
|---|---|---|
| Selector CSS | #login-btn, .submit | Elementos únicos |
| Texto visible | "Sign In", "Submit" | Botones, enlaces |
| Coordenadas | x: 100, y: 200 | Lienzo, widgets personalizados |
| Ref de instantánea | ref: "e42" | Cualquier elemento del árbol de accesibilidad |
Consejo: Comienza con
safari_snapshotpara obtener refs de elementos, luego usa refs para una selección precisa. Esto es más rápido y fiable que los selectores CSS.
Ejecutar varios agentes a la vez
Múltiples agentes o subagentes que controlan un mismo Safari al mismo tiempo competirán por la pestaña activa — a menos que los ejecutes contra un daemon HTTP compartido en lugar de un proceso por cliente:
SAFARI_MCP_HTTP=1 SAFARI_MCP_HTTP_PORT=9225 npx safari-mcp
Luego apunta cada cliente a él:
{ "mcpServers": { "safari-mcp": { "type": "http", "url": "http://127.0.0.1:9225/mcp" } } }
Un daemon, muchas sesiones — y cada sesión obtiene su propio estado de pestaña. El servidor vincula activeTabIndex, el indicador de propiedad y un marcador único de pestaña al id de sesión MCP, por lo que la sesión A físicamente no puede leer ni dirigir la pestaña de la sesión B.
Dos propiedades hacen que esto sea seguro en lugar de meramente ordenado:
-
La identidad de pestaña es un marcador, no un índice. Cada sesión sella un id único en la página que abre, por lo que la propiedad sobrevive a la navegación y sobrevive a que el usuario reordene o cierre otras pestañas. Un índice solo se desviaría silenciosamente hacia la pestaña equivocada.
-
Falla de forma cerrada. Si la pestaña marcada de una sesión no se puede reencontrar, cada herramienta se niega en lugar de recurrir a la pestaña que esté al frente — porque esa pestaña suele ser tuya:
Tab tracking lost — refusing to fall back to "current tab of window" (would target the user's active tab). Call safari_new_tab to reopen.
Esto también reduce drásticamente el número de procesos: ~17 procesos node para 17 sesiones concurrentes se convierte en 1.
SAFARI_PROFILE sigue siendo opcional — déjalo sin establecer y las sesiones se vinculan a tus ventanas normales de Safari, con cookies e inicios de sesión intactos. Detalles en docs/http-transport-design.md.
¿Prefieres stdio (un proceso por agente) sobre un daemon persistente? Eso también funciona — el aislamiento entonces proviene del propio límite del proceso. Una advertencia: si tu cliente multiplexa agentes a través de mcporter, mcporter almacena en caché un único cliente MCP para todos ellos — sea cual sea el transporte que elijas — por lo que el servidor nunca ve sesiones distintas y el aislamiento por sesión no puede activarse. mcporter-lanes (una extensión de pi por @maxim, nacida de #76) corrige esto aguas arriba: cada sesión de agente obtiene su propio directorio de daemon — y por lo tanto su propio safari-mcp — con un tiempo de espera de inactividad para que los procesos no se acumulen.
Actuar sobre una pestaña que ya tienes abierta
Por defecto, el servidor solo toca las pestañas que él mismo abrió. Apúntalo a una de las tuyas y se niega:
Tab safety: refusing "click" — current tab (https://mail.example.com/inbox) was not
opened by this MCP session. Use safari_new_tab or safari_switch_tab to target your own tab.
Ese valor predeterminado existe porque las primeras versiones sí hacían clic y cerraban las pestañas de la gente. Pero "leer el artículo que estoy mirando" y "rellenar el formulario en mi pantalla" son casos reales, y reabrir la página pierde el estado de sesión que hacía valiosa tu pestaña. Establece SAFARI_MCP_ALLOW_USER_TABS=1 y un safari_switch_tab explícito adopta la pestaña en lugar de rechazarla; a partir de entonces la sesión trabaja en ella como si fuera propia, y así lo indica:
{ "tabIndex": 3, "safeUrl": "https://mail.example.com/inbox", "note": "(user tab, opted-in)" }
Lo que el indicador deliberadamente no hace:
- Desbloquea la adopción, no los guardias. Solo
safari_switch_tabadopta, y solo la pestaña que nombraste. Un clic o navegación ordinaria nunca aterriza en la pestaña que esté al frente — el servidor actúa sobre la pestaña a la que lo apuntaste, no a la que te desplazaste. safari_close_tabsigue rechazándose. Cerrar es la única acción cuyo costo no se puede deshacer, por lo que una pestaña adoptada es escribible, nunca desechable. Ciérrala tú mismo.- La adopción es local a la sesión. Nada se escribe en el archivo de propiedad compartido, por lo que termina con la sesión en lugar de filtrarse al siguiente proceso en la máquina.
safari_doctor imprime el estado del indicador, y cada operación en una pestaña adoptada registra (user tab, opted-in) — por lo que "por qué tocó mi pestaña" tiene una respuesta en lugar de ser un misterio. Desactivado por defecto; establécelo solo para agentes que quieras que trabajen dentro de tu propia sesión de navegación. Diseñado en #92.
Variables de entorno
| Variable | Predeterminado | Qué hace |
|---|---|---|
SAFARI_MCP_HTTP | off | Ejecuta un daemon HTTP compartido en lugar de un proceso por cliente (ver arriba). |
SAFARI_MCP_HTTP_PORT | 9225 | Puerto para ese daemon. |
SAFARI_PROFILE | sin establecer | Vincula sesiones a un perfil de Safari con nombre. Sin establecer = tus ventanas normales. |
SAFARI_MCP_ALLOW_USER_TABS | off | Permite que safari_switch_tab adopte una pestaña que tú ya tenías abierta, en lugar de rechazarla (ver abajo). |
MCP_MAX_TABS | 6 | Pestañas que una sesión puede mantener abiertas. Abrir una más cierra la pestaña más antigua de esa sesión, y safari_new_tab la nombra en evictedTab (su recibo). |
SAFARI_MCP_RAISE_ON_NAVIGATE | off | Permite que la navegación traiga Safari al frente, y detiene al guardia de enfoque de devolver tu aplicación anterior. |
SAFARI_MCP_SCREENSHOT_MAX_WIDTH | sin establecer | Reduce cada safari_screenshot a este ancho de píxel (las capturas Retina son 2× la ventana gráfica). maxWidth por llamada lo anula. |
SAFARI_MCP_KEEPALIVE_TAB | off | Mantiene una página servida por daemon abierta en la ventana del perfil para que Safari nunca estacione el worker de extensión entre comandos. |
SAFARI_MCP_OPEN_WINDOW_CMD | sin establecer | Comando ejecutado con el nombre del perfil cuando la ventana del perfil está ausente (p. ej., después de un reinicio). Debe abrir la ventana sin enfocar Safari. |
SAFARI_MCP_RAISE_ON_NAVIGATE=1 es para agentes cuyo propósito principal es mostrarte una página — un asistente de voz que responde "abre YouTube", un controlador de demostración. Todo lo demás debería dejarlo desactivado: por defecto Safari MCP trabaja en segundo plano y devuelve el enfoque a la aplicación que estabas usando, por lo que un agente puede controlar una página mientras sigues escribiendo en otro lugar.
Herramientas (98)
Haz clic para expandir la lista completa de herramientas, organizadas por categoría
Navegación (4)
| Herramienta | Descripción |
|---|---|
safari_navigate | Navegar a una URL (HTTPS automático, espera la carga) |
safari_go_back | Retroceder en el historial |
safari_go_forward | Avanzar en el historial |
safari_reload | Recargar la página (recarga forzada opcional) |
Lectura de página (3)
| Herramienta | Descripción |
|---|---|
safari_read_page | Obtener título, URL y contenido de texto |
safari_get_source | Obtener el código HTML completo |
safari_navigate_and_read | Navegar + leer en una sola llamada |
Clic e interacción (6)
| Herramienta | Descripción |
|---|---|
safari_click | Clic por selector CSS, texto visible o coordenadas |
safari_double_click | Doble clic (seleccionar palabra, etc.) |
safari_right_click | Clic derecho (menú contextual) |
safari_hover | Pasar el cursor sobre un elemento |
safari_click_and_wait | Clic + esperar la navegación |
safari_click_and_read | Clic y luego devolver la página actualizada: ahorra un viaje de ida y vuelta (React Router + cargas completas) |
Entrada de formularios (11)
| Herramienta | Descripción |
|---|---|
safari_fill | Rellenar entrada (compatible con React/Vue/Angular) |
safari_clear_field | Limpiar campo de entrada |
safari_select_option | Seleccionar opción de lista desplegable |
safari_fill_form | Rellenar varios campos por lotes |
safari_fill_and_submit | Rellenar formulario + enviar en una sola llamada |
safari_type_text | Escribir pulsaciones de teclas reales (basado en JS, sin Eventos del Sistema) |
safari_press_key | Pulsar tecla con modificadores |
safari_react_select_set | Establecer un valor de react-select v5 mediante React fiber: evita la interfaz del menú |
safari_react_select_list_options | Listar las opciones de una lista desplegable de react-select v5 sin abrirla |
safari_replace_editor | Reemplazar todo el contenido en un editor de código (Monaco, CodeMirror, Ace, ProseMirror) |
safari_verify_state | Verificar que el estado a nivel de framework del editor coincide con lo esperado: detecta DOM obsoleto antes de Enviar |
Capturas de pantalla y PDF (3)
| Herramienta | Descripción |
|---|---|
safari_screenshot | Captura de pantalla como PNG (viewport o página completa) |
safari_screenshot_element | Captura de pantalla de un elemento específico |
safari_save_pdf | Exportar página como PDF |
Desplazamiento (3)
| Herramienta | Descripción |
|---|---|
safari_scroll | Desplazarse hacia arriba/abajo por píxeles |
safari_scroll_to | Desplazarse a una posición exacta |
safari_scroll_to_element | Desplazamiento suave hasta un elemento |
Gestión de pestañas (5)
| Herramienta | Descripción |
|---|---|
safari_list_tabs | Listar todas las pestañas (índice, título, URL) |
safari_new_tab | Abrir nueva pestaña (en segundo plano, sin robar el foco) |
safari_close_tab | Cerrar pestaña |
safari_switch_tab | Cambiar a pestaña por índice |
safari_wait_for_new_tab | Esperar una nueva pestaña (p. ej., ventana emergente de OAuth) y cambiar automáticamente a ella |
Espera (2)
| Herramienta | Descripción |
|---|---|
safari_wait_for | Esperar elemento, texto o cambio de URL |
safari_wait | Esperar una cantidad específica de milisegundos |
JavaScript (3)
| Herramienta | Descripción |
|---|---|
safari_evaluate | Ejecutar JavaScript arbitrario y devolver el resultado |
safari_eval_file | Ejecutar JavaScript leído desde una ruta de archivo (evita scripts en línea enormes) |
safari_list_frames | Listar todos los documentos de la pestaña (página principal + cada iframe) con frameId, URL y longitud de texto: pasa un frameId al safari_evaluate de frame para ejecutar dentro de un iframe de origen cruzado |
Inspección de elementos (4)
| Herramienta | Descripción |
|---|---|
safari_get_element | Detalles del elemento (etiqueta, rect, atributos, visibilidad) |
safari_query_all | Encontrar todos los elementos coincidentes |
safari_get_computed_style | Estilos CSS calculados |
safari_detect_forms | Detectar automáticamente todos los formularios con selectores de campo |
Accesibilidad (2)
| Herramienta | Descripción |
|---|---|
safari_accessibility_snapshot | Árbol de accesibilidad completo: roles, ARIA, elementos enfocables |
safari_snapshot | Árbol de accesibilidad con IDs de referencia para cada elemento interactivo: la forma preferida de ver el estado de la página |
Arrastrar y soltar (1)
| Herramienta | Descripción |
|---|---|
safari_drag | Arrastrar entre elementos o coordenadas |
Operaciones con archivos (2)
| Herramienta | Descripción |
|---|---|
safari_upload_file | Subir archivo mediante JS DataTransfer (¡sin diálogo de archivo!) |
safari_paste_image | Pegar imagen en el editor (¡sin tocar el portapapeles!) |
Diálogo y ventana (2)
| Herramienta | Descripción |
|---|---|
safari_handle_dialog | Gestionar alert/confirm/prompt |
safari_resize | Redimensionar la ventana del navegador |
Emulación de dispositivos (2)
| Herramienta | Descripción |
|---|---|
safari_emulate | Emular dispositivo (iPhone, iPad, Pixel, Galaxy) |
safari_reset_emulation | Restablecer a escritorio |
Cookies y almacenamiento (11)
| Herramienta | Descripción |
|---|---|
safari_get_cookies | Obtener todas las cookies |
safari_set_cookie | Establecer cookie con todas las opciones |
safari_delete_cookies | Eliminar una o todas las cookies |
safari_local_storage | Leer localStorage |
safari_set_local_storage | Escribir localStorage |
safari_delete_local_storage | Eliminar/limpiar localStorage |
safari_session_storage | Leer sessionStorage |
safari_set_session_storage | Escribir sessionStorage |
safari_delete_session_storage | Eliminar/limpiar sessionStorage |
safari_export_storage | Exportar todo el almacenamiento como JSON (sesiones de respaldo/restauración) |
safari_import_storage | Importar estado de almacenamiento desde JSON |
Portapapeles (2)
| Herramienta | Descripción |
|---|---|
safari_clipboard_read | Leer texto del portapapeles |
safari_clipboard_write | Escribir texto en el portapapeles |
Red (6)
| Herramienta | Descripción |
|---|---|
safari_network | Solicitudes de red rápidas mediante la API de rendimiento |
safari_start_network_capture | Iniciar captura detallada (fetch + XHR) |
safari_network_details | Obtener solicitudes capturadas con encabezados/temporización |
safari_clear_network | Limpiar solicitudes capturadas |
safari_mock_route | Simular respuestas de red (interceptar fetch/XHR) |
safari_clear_mocks | Eliminar todas las simulaciones de red |
Consola (4)
| Herramienta | Descripción |
|---|---|
safari_start_console | Iniciar captura de mensajes de consola |
safari_get_console | Obtener todos los mensajes capturados |
safari_clear_console | Limpiar mensajes capturados |
safari_console_filter | Filtrar por nivel (log/warn/error) |
Rendimiento (2)
| Herramienta | Descripción |
|---|---|
safari_performance_metrics | Temporización de navegación, Web Vitals, memoria |
safari_throttle_network | Simular slow-3g/fast-3g/4g/offline |
Extracción de datos (4)
| Herramienta | Descripción |
|---|---|
safari_extract_tables | Tablas como JSON estructurado |
safari_extract_meta | Todos los metadatos: OG, Twitter, JSON-LD, canonical |
safari_extract_images | Imágenes con dimensiones e información de carga |
safari_extract_links | Enlaces con detección de rel, externo/nofollow |
Avanzado (7)
| Herramienta | Descripción |
|---|---|
safari_override_geolocation | Anular la geolocalización del navegador |
safari_list_indexed_dbs | Listar bases de datos IndexedDB |
safari_get_indexed_db | Leer registros de IndexedDB |
safari_css_coverage | Encontrar reglas CSS no utilizadas |
safari_analyze_page | Análisis completo de página en una sola llamada |
safari_doctor | Diagnosticar la cadena de permisos y daemon de macOS (Apple Events, Accesibilidad, Grabación de pantalla, codesign) con correcciones por fallo |
safari_reload_extension | Recargar en caliente la extensión Safari MCP Bridge sin alternancia manual |
Automatización (1)
| Herramienta | Descripción |
|---|---|
safari_run_script | Ejecutar múltiples acciones en una sola llamada (lote) |
Entrada nativa — CGEvent (4)
| Herramienta | Descripción |
|---|---|
safari_native_click | Clic de ratón a nivel de sistema operativo (CGEvent, isTrusted: true): evita la detección de WAF/bots cuando safari_click está bloqueado (405/403) |
safari_native_hover | Desplazamiento del cursor a nivel de sistema operativo: activa :hover/mouseenter reales para tooltips e interfaces ofuscadas |
safari_native_type | Insertar texto mediante la canalización real de pegado: ProseMirror/Slate/Draft.js lo procesan de forma nativa, por lo que Enviar envía datos reales |
safari_native_keyboard | Pulsación de tecla a nivel de sistema operativo + modificadores para Safari, sin robar el foco: llega a los manejadores protegidos por confianza de React (envío en Discord/Slack) |
Validación de iOS y WebKit (4)
| Herramienta | Descripción |
|---|---|
safari_inspect_viewport | Validar la etiqueta <meta name=viewport> para Safari en iOS (device-width, zoom/WCAG, viewport-fit) |
safari_safe_area_insets | Leer valores en vivo de safe-area-inset + uso de viewport-fit / env() (muesca / Dynamic Island) |
safari_check_pwa | Auditar la preparación para "Agregar a pantalla de inicio" / PWA en iOS (apple-touch-icon, manifest, theme-color, splash) |
safari_webkit_compat | Verificar el CSS de la página contra este Safari mediante CSS.supports(): propiedades no compatibles, prefijos -webkit- faltantes, peculiaridades conocidas |
Seguridad
Safari MCP se ejecuta localmente en tu Mac con una superficie de ataque mínima:
| Aspecto | Detalle |
|---|---|
| Red | Sin conexiones remotas: toda la comunicación es local (stdio + localhost) |
| Permisos | Se requieren permisos del sistema macOS (Grabación de pantalla para capturas) |
| Datos | Sin telemetría, sin análisis, sin envío de datos a ningún lugar |
| Extensión | Se comunica solo con los puentes de perfil locales (localhost:9224/9228/9232/9236), validados por Safari |
| Código | Totalmente de código abierto (MIT): audita cada línea |
Safari MCP frente a alternativas
| Característica | Safari MCP | Chrome DevTools MCP | Playwright MCP |
|---|---|---|---|
| CPU/Calor | 🟢 Mínimo | 🔴 Alto | 🟡 Medio |
| Tus inicios de sesión | ✅ Sí | ✅ Sí | ❌ No |
| Nativo de macOS | ✅ WebKit | ❌ Chromium | ❌ Chromium/WebKit |
| Dependencias del navegador | Ninguna | Chrome + puerto de depuración | Entorno de ejecución de Playwright |
| Herramientas | 98 | ~30 | ~25 |
| Subida de archivos | JS (sin diálogo) | CDP | API de Playwright |
| Pegado de imágenes | JS (sin portapapeles) | CDP | API de Playwright |
| Robo de foco | ❌ En segundo plano | ❌ En segundo plano | ❌ Sin interfaz |
| Simulación de red | ✅ | ❌ | ✅ |
| Lighthouse | ❌ | ✅ | ❌ |
| Traza de rendimiento | ❌ | ✅ | ❌ |
Consejo: Usa Safari MCP para tareas diarias de navegación (95 % del trabajo) y Chrome DevTools MCP solo para auditorías de Lighthouse/Rendimiento.
Frente al Safari MCP oficial de Apple (safaridriver)
En julio de 2026, Apple lanzó un servidor Safari MCP oficial basado en safaridriver: primero en Safari Technology Preview 247 y en Safari estable desde la versión 27.0. Es una gran validación para la categoría, y está diseñado para un trabajo diferente. El servidor de Apple impulsa una sesión de automatización WebDriver aislada para depuración; safari-mcp impulsa el Safari real en el que ya has iniciado sesión.
En macOS 27.0 con Safari 27.0, safaridriver --help lista --mcp y su tools/list responde con 17 entradas (verificado el 15-09-2026); Safari 26.5.2 no tenía --mcp (verificado el 23-07-2026). Comprueba tu propia máquina con safaridriver --help | grep mcp.
¿Ejecutando ambos? La guía de configuración de Apple registra su servidor con el nombre
safari-mcp(claude mcp add safari-mcp -- /usr/bin/safaridriver --mcp), el mismo nombre que este paquete. Asigna a uno de ellos un nombre diferente, p. ej.,claude mcp add safari-webdriver -- /usr/bin/safaridriver --mcp, para que tu cliente no sobrescriba uno con el otro ni te deje adivinando qué servidor respondió.
| 🦁 safari-mcp (este repositorio) | Apple safaridriver --mcp | |
|---|---|---|
| Tus inicios de sesión / cookies reales | ✅ Tu Safari real | ⚠️ Sesión de automatización aislada: sin acceso a Autocompletar ni a la actividad de navegación |
| Se ejecuta en | ✅ Safari estable, cualquier Mac | ⚠️ Safari 27 o posterior, o Safari Technology Preview 247+ |
| En segundo plano (sin robar el foco) | ✅ Sí | ❌ Ventana dedicada con un banner de "controlado por automatización" |
La página ve navigator.webdriver | ✅ false: una pestaña normal | ⚠️ true: obligatorio en toda sesión WebDriver |
| Herramientas | 98 | 17 |
| Almacenamiento (cookies, localStorage, IndexedDB) | ✅ 10 herramientas | ❌ |
| Simulación de red + limitación | ✅ Sí | ❌ Inspección de red de solo lectura |
| Emulación de dispositivos (iPhone, iPad) | ✅ Sí | ⚠️ Solo viewport y tipo de medio |
| Configuración | npx safari-mcp | Habilita "Permitir automatización remota y agentes externos" en la configuración de Desarrollador de Safari y luego apunta tu cliente a safaridriver --mcp |
| Soporte oficial de Apple | ❌ Comunidad (MIT) | ✅ Apple, estándar WebDriver |
Acerca de la fila
navigator.webdriver: el estándar WebDriver requiere que cada sesión controlada remotamente informetrue, por lo que el servidor de Apple lo hace. safari-mcp evalúa JavaScript en una pestaña ordinaria, por lo que leefalse(verificado en Safari 27.0, 2026-09-17). Esa es la diferencia si un sitio rechaza el tráfico de WebDriver. No es una función anti-detección — nada más sobre el navegador está disfrazado, y tus inicios de sesión reales están en uso, así que trata cada página como si supiera exactamente quién eres.
Cuándo elegir el servidor de Apple: específicamente quieres una sesión limpia, estándar WebDriver para depuración de compatibilidad en Safari 27 o posterior. Para todo lo demás — automatización diaria en el navegador donde ya has iniciado sesión, en segundo plano — safari-mcp está construido exactamente para eso.
¿Por qué Safari MCP y no los otros proyectos Safari MCP?
Hay varios proyectos "safari-mcp" por ahí. Así se comparan:
| Característica | 🦁 safari-mcp (este repositorio) | lxman/safari-mcp-server | Epistates/MCPSafari | HayoDev/safari-devtools-mcp |
|---|---|---|---|---|
| Herramientas | 98 | ~10 | 23 | ~15 |
| Instalación | npx safari-mcp | Manual | Binario | npx |
| Motor | Doble (Extensión + AppleScript) | WebDriver | Solo extensión | Protocolo DevTools |
| Mantiene tus inicios de sesión reales de Safari | ✅ Sí | ⚠️ Limitado | ✅ Sí | ❌ Sesión de depuración |
| Segundo plano (sin robo de foco) | ✅ Sí | ❌ No | ⚠️ A veces | ✅ Sí |
| Herramientas de almacenamiento (cookies, localStorage, IndexedDB) | 10 | 0 | 0 | 2 |
| Extracción de datos (tablas, meta, imágenes, enlaces) | 4 | 0 | 0 | 0 |
| Simulación de red | ✅ Sí | ❌ No | ❌ No | ❌ No |
| Emulación de dispositivos (iPhone, iPad, Pixel) | ✅ Sí | ❌ No | ❌ No | ❌ No |
| Subida de archivos (sin diálogo) | ✅ JS DataTransfer | ❌ No | ❌ No | ❌ No |
| Pegado de imágenes (sin tocar portapapeles) | ✅ Sí | ❌ No | ❌ No | ❌ No |
| Exportación a PDF | ✅ Sí | ❌ No | ❌ No | ❌ No |
| Captura de consola | 4 herramientas | 0 | 1 | 1 |
| Métricas de rendimiento + Web Vitals | ✅ Sí | ❌ No | ❌ No | ⚠️ Parcial |
| Mantenimiento activo | ✅ Múltiples lanzamientos/semana | 🟡 Esporádico | 🟡 Lento | 🟡 Lento |
| Licencia | MIT | MIT | No especificada | MIT |
| En el Registro MCP | ✅ | ❌ | ❌ | ✅ |
| En Awesome MCP | ✅ | ❌ | ❌ | ❌ |
TL;DR — si quieres el Safari MCP más completo con la instalación más fluida, la mayor cantidad de herramientas y mantenimiento activo, este es el indicado.
Arquitectura
Safari MCP utiliza una arquitectura de doble motor — la Extensión es preferida por velocidad y capacidades avanzadas, con AppleScript como respaldo siempre disponible:
Claude/Cursor/AI Agent
↓ MCP Protocol (stdio)
Safari MCP Server (Node.js)
↓ ↓
Extension (HTTP) AppleScript + Swift daemon
(~5-20ms/cmd) (~5ms/cmd, always available)
↓ ↓
Content Script do JavaScript in tab N
↓ ↓
Page DOM ←←←←←←←←←← Page DOM
Decisiones clave de diseño:
- Doble motor con respaldo automático — la Extensión es preferida; si no está conectada, AppleScript maneja todo sin problemas
- Helper Swift persistente — un proceso de larga duración en lugar de generar uno por comando (16 veces más rápido)
- Operaciones indexadas por pestaña — todo el JS se ejecuta en una pestaña específica por índice, nunca roba el foco visual
- Enfoque JS primero — escribir, hacer clic, subir archivos usan eventos de JavaScript (sin conflictos de teclado con System Events)
- Sin
activate— Safari nunca se trae al primer plano
Extensión de Safari (Opcional)
La Extensión de Safari MCP es opcional pero recomendada. Sin ella, ~80% de la funcionalidad funciona solo con AppleScript. La extensión añade capacidades que AppleScript no puede proporcionar:
Lo que añade la Extensión
| Capacidad | Con Extensión | Solo AppleScript |
|---|---|---|
| Shadow DOM cerrado (Reddit, Web Components) | ✅ Acceso completo | ❌ Invisible |
| Sitios con CSP estricto | ✅ Evita vía mundo MAIN | ❌ A menudo bloqueado |
| Manipulación de estado React/Vue/Angular | ✅ Profunda (Fiber, ProseMirror) | ⚠️ Básica |
| Detección de estado de carga (spinners, skeletons) | ✅ Detección inteligente | ❌ No |
| Manejo de diálogos (alert/confirm) | ❌ | ✅ Solo AppleScript |
| Clic nativo a nivel de SO (CGEvent) | ❌ | ✅ Solo AppleScript |
| Exportación a PDF | ❌ | ✅ Solo AppleScript |
¿Cuándo necesitas la extensión? Si automatizas SPAs modernos con shadow DOM cerrado (por ejemplo, Reddit), sitios con Política de Seguridad de Contenido estricta, o editores con mucho framework (Draft.js, ProseMirror, Slate).
Instalando la Extensión
La extensión requiere una compilación única con Xcode (gratis, incluido con macOS).
Nota para usuarios de npm: El directorio
xcode/no está incluido en el paquete npm. Clona el repositorio de GitHub para compilar desde el código fuente.
Requisitos previos: Xcode (instalar desde App Store — gratis)
# 1. Clone the repo (the npm package does not include the Xcode project)
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp
# 2. Build a clean, Apple Development-signed app
# If needed, first choose your Team in Xcode → Signing & Capabilities.
xcodebuild -project "xcode/Safari MCP/Safari MCP.xcodeproj" \
-scheme "Safari MCP (macOS)" -configuration Release \
-allowProvisioningUpdates clean build
# 3. Locate the signed app
APP_PATH=$(find ~/Library/Developer/Xcode/DerivedData/Safari_MCP-*/Build/Products/Release -name "Safari MCP.app" -maxdepth 2 | head -1)
# 4. Re-sign safari-helper with the Apple Events entitlement
# (helps macOS surface the TCC Automation prompt reliably)
codesign --sign - --force --entitlements safari-helper.entitlements safari-helper
# 5. Open the app (needed once so Safari registers the extension)
open "$APP_PATH"
No vuelvas a firmar ad-hoc
Safari MCP.appconcodesign --deep --sign -. Eso reemplaza la identidad de Desarrollo de Apple en el wrapper y la extensión integrada; Safari actual puede entonces deshabilitar silenciosamente o marcar la extensión como eliminada. Si una compilación anterior fue firmada ad-hoc, ejecuta el comandoclean buildde nuevo.
Alternativamente, abre xcode/Safari MCP/Safari MCP.xcodeproj directamente en Xcode, selecciona tu Apple ID en Signing & Capabilities, y haz clic en Run. Una cuenta gratuita de desarrollador personal de Apple es suficiente para uso local.
Luego en Safari:
- Safari → Ajustes → Avanzado → activa Mostrar funciones para desarrolladores web
- Safari → Ajustes → Desarrollador → Permitir extensiones sin firmar (requerido en cada reinicio de Safari)
- Safari → Ajustes → Extensiones → activa Safari MCP Bridge
La extensión se conecta automáticamente al primer bridge local cuyo perfil de Safari declarado coincida con el suyo. Los puertos de bridge predeterminados son 9224, 9228, 9232 y 9236; una configuración de perfil único normalmente usa 9224.
Nota: "Permitir extensiones sin firmar" se restablece cada vez que Safari se reinicia. Deberás volver a activarlo en Safari → Ajustes → Desarrollador después de cada reinicio. La extensión en sí permanece instalada.
Estado del icono de la barra de herramientas:
- ON — conectado al servidor MCP
- OFF — deshabilitado manualmente vía popup
- (sin insignia) — el servidor no está ejecutándose, se reconectará automáticamente
Permisos de macOS
Safari MCP necesita estos permisos únicos:
| Permiso | Dónde | Por qué |
|---|---|---|
| JavaScript desde Apple Events | Safari → Ajustes → Desarrollador | Requerido para do JavaScript |
| Automatización → Safari | Ajustes del Sistema → Privacidad y Seguridad → Automatización | Requerido para todas las herramientas respaldadas por AppleScript |
| Grabación de pantalla | Ajustes del Sistema → Privacidad y Seguridad → Grabación de pantalla y audio del sistema | Requerido para safari_screenshot sin la extensión, y para safari_save_pdf |
| Accesibilidad (safari-helper) | Ajustes del Sistema → Privacidad y Seguridad → Accesibilidad (llamado Control de dispositivos y acceso a datos en macOS 27) | Requerido para safari_native_click, safari_native_keyboard, safari_native_hover y safari_save_pdf |
Otorgando Accesibilidad a safari-helper (requerido para safari_native_*)
Las herramientas safari_native_click, safari_native_keyboard y safari_native_hover inyectan eventos CGEvent a nivel de SO en Safari sin robar el foco. macOS requiere que el binario helper subyacente sea aprobado en Accesibilidad antes de que esos eventos puedan llegar a una ventana que no está en primer plano.
- Abre Ajustes del Sistema → Privacidad y Seguridad → Accesibilidad (en macOS 27 el panel se llama Control de dispositivos y acceso a datos).
- Haz clic en
+(desbloquea con tu contraseña si es necesario). - Navega al binario helper y agrégalo:
- Instalación global npm:
$(npm root -g)/safari-mcp/safari-helper - Instalación npx / proyecto:
./node_modules/safari-mcp/safari-helper - Desde clon del código fuente:
/path/to/safari-mcp/safari-helper
- Instalación global npm:
- Asegúrate de que el interruptor junto a él esté ON.
El script postinstall vuelve a firmar el helper con un identificador estable (com.achiya-automation.safari-mcp) para que este permiso sobreviva a futuras actualizaciones — sin ese paso, cada npm update revocaría silenciosamente la aprobación porque el identificador firmado ad-hoc del binario cambia por compilación.
Si safari_native_click informa éxito pero la página no reacciona (no se disparan eventos de clic isTrusted: true), lo más probable es que al helper le falte esta aprobación. Las herramientas safari_* (no native_) no la necesitan.
Otorgando Automatización → Safari (importante para usuarios de IDE)
macOS TCC otorga el permiso de Automatización al proceso padre que genera el servidor MCP, no a safari-mcp en sí. Así que necesitas otorgar Automatización → Safari a la aplicación que ejecuta Claude Code / Cursor / Windsurf — típicamente Visual Studio Code o Terminal.
Si el diálogo de permiso nunca aparece automáticamente, ejecuta este comando una vez desde una Terminal que ya tenga permiso de Automatización:
osascript -e 'tell application "Safari" to get URL of current tab of window 1'
Esa llamada registra la aplicación Terminal en la base de datos de Automatización y luego activa el aviso para Safari. Después de que lo apruebes, las llamadas MCP posteriores desde cualquier cadena de procesos hijo funcionarán.
Solución de problemas
| Problema | Solución |
|---|---|
| "Error de AppleScript" | Activa "Permitir JavaScript desde Apple Events" en Safari → Ajustes → Desarrollador |
| "No autorizado para enviar eventos de Apple a Safari" | Otorga Automatización → Safari a tu IDE (ver arriba) |
"No autorizado" después de npm update | Actualizar cambia el cdhash del binario — macOS revoca silenciosamente el permiso de Automatización. Vuelve a ejecutar el one-liner osascript de arriba para volver a otorgarlo |
safari_native_click informa éxito pero la página no reacciona | Añade safari-helper a Ajustes del Sistema → Privacidad y Seguridad → Accesibilidad (ver Otorgando Accesibilidad arriba). Confirma adjuntando un listener de click con {capture:true} en la consola de la página — sin la concesión, ningún evento isTrusted: true se dispara |
| Capturas de pantalla vacías | Otorga Grabación de pantalla y audio del sistema a Terminal/VS Code — o, cuando safari-mcp se ejecuta como LaunchAgent, al binario node en sí (una actualización de Homebrew node cambia su ruta, así que vuelve a otorgar después de actualizar). safari_doctor nombra el binario exacto |
| Extensión faltante después de activar "Permitir extensiones sin firmar" (macOS 27) | Problema conocido de macOS 27.0 (183044008): con el ajuste activado, recompila la aplicación de extensión (ver Instalando la Extensión) y aparecerá |
| Pestaña no encontrada | Llama a safari_list_tabs para refrescar los índices de pestañas |
| Problemas con teclado hebreo | Todo el tecleo usa eventos JS — inmune a la distribución del teclado |
| HTTPS bloqueado | safari_navigate intenta automáticamente HTTPS primero, luego recurre a HTTP |
| Safari roba el foco | Asegúrate de tener la última versión — newTab restaura tu pestaña activa |
FAQ
¿Funciona con Safari Technology Preview?
No. Cada ruta de AppleScript apunta a application "Safari" y el helper nativo busca el bundle id com.apple.Safari, así que STP (com.apple.SafariTechnologyPreview) es una aplicación diferente a la que safari-mcp nunca se dirige. Ejecútalo contra Safari estable.
Ten en cuenta que el servidor safaridriver --mcp propio de Apple es el que necesita STP 247+ (o Safari 27+) — ver Safari MCP vs Alternativas. Los dos no están relacionados.
¿Puede manejar pestañas privadas/de incógnito?
No como un modo soportado, y no está probado. Ninguna herramienta abre una ventana privada, y Safari deshabilita las extensiones en Navegación Privada a menos que actives cada una explícitamente, así que el bridge de extensión — y todo en la columna "Con Extensión" de Extensión de Safari (Opcional) — está desactivado allí por defecto.
Si quieres una identidad aislada, usa un perfil separado de Safari en su lugar: las ventanas de perfil son un concepto de primera clase aquí (ver Ejecutando varios agentes a la vez).
¿Funciona con múltiples ventanas de Safari?
Sí. Las búsquedas de pestañas recorren every window en lugar de asumir la ventana 1, y una pestaña se fija mediante el par (index, tabCount) de su ventana, porque un índice por sí solo es ambiguo una vez que hay dos ventanas abiertas. Las ventanas de perfil se reconocen por el nombre de ventana ProfileName — Tab Title de Safari.
El identificador confiable sigue siendo el recibo que devuelve safari_new_tab: pásalo a cada llamada posterior y la pestaña se aborda directamente, sin importar cuántas ventanas se muevan a su alrededor.
¿Qué versiones de macOS son compatibles?
Cualquier macOS con Safari: el paquete declara "os": ["darwin"] y no tiene un mínimo de SO, y no hay una restricción de versión en el código. Node.js 20+ es el requisito estricto ("engines": { "node": ">=20" }).
Hay dos lugares donde el SO importa en la práctica:
- En macOS 27, el panel de Accesibilidad se renombra a Control de dispositivos y acceso a datos: misma concesión, nuevo nombre (consulta Permisos de macOS).
- Safari 26 y 27 cambiaron varios comportamientos de plataformas web que herramientas específicas tienen en cuenta; esos se manejan, no se bloquean.
¿Puedo ejecutar varias instancias simultáneamente?
Sí, eso es lo que cubre Ejecutar varios agentes a la vez. Cada sesión posee sus propias pestañas, y la propiedad se rastrea por sesión en lugar de por índice de pestaña, por lo que un agente no puede actuar sobre (ni cerrar) una pestaña que otro agente posee.
Un proceso vincula el puerto del puente de extensión; los demás se proxan a través de él y se hacen cargo del puerto si ese proceso sale.
¿Necesito mantener Safari en primer plano?
No. safari_new_tab abre una pestaña en segundo plano y nunca roba el foco, y los pocos comandos que macOS fuerza a activar implícitamente restauran tu aplicación frontal anterior después, con una protección que deja el foco intacto si estabas escribiendo en Safari un momento antes.
Las dos excepciones son las herramientas deliberadamente nativas: safari_native_click, safari_native_keyboard, safari_native_hover — que publican eventos reales del SO y, por lo tanto, aterrizan donde esté la ventana frontal. No las uses mientras trabajas en otra pestaña de Safari.
¿Cómo interactúa con las extensiones de Safari?
Tus extensiones existentes siguen funcionando con normalidad; safari-mcp maneja el mismo Safari que usas, por lo que los bloqueadores de contenido y los gestores de contraseñas se comportan exactamente igual que para ti.
safari-mcp también incluye su propia extensión opcional. Sin ella, aproximadamente el 80% de las herramientas siguen funcionando solo con AppleScript; con ella, además obtienes shadow DOM cerrado, sitios con CSP estricto, estado profundo de frameworks y detección de estado de carga. El manejo de diálogos, los clics nativos y la exportación a PDF van por el otro lado: esos son solo de AppleScript. La división completa está en Extensión de Safari (Opcional).
¿Qué sucede si "Permitir JavaScript desde Apple Events" no está habilitado?
Todo lo que evalúa JavaScript falla — safari_evaluate, safari_read_page, llenado de formularios, extracción — mientras que las acciones puras de AppleScript, como abrir o cambiar de pestaña, siguen funcionando. Esa es la causa habitual de "abre la pestaña pero no lee nada".
Actívalo en Safari → Configuración → Avanzado → Mostrar funciones para desarrolladores web, y luego Safari → Configuración → Desarrollador → Permitir JavaScript desde Apple Events. Ambos están listados en Requisitos previos. safari_doctor recorre el resto de la cadena (Automatización, helper nativo, Accesibilidad, Grabación de pantalla) y menciona esta configuración en su sugerencia de corrección — pero su verificación de Apple Events solo cuenta ventanas, lo que el permiso de Automatización satisface por sí solo, por lo que no fallará en esto para ti.
Funciona con
Safari MCP funciona con cualquier cliente compatible con MCP:
| Cliente | Estado |
|---|---|
| Claude Code | ✅ Probado a diario |
| Claude Desktop | ✅ Probado |
| Cursor | ✅ Probado |
| Windsurf | ✅ Compatible |
| VS Code + Continue | ✅ Compatible |
Contribuciones
¡Las solicitudes de extracción son bienvenidas! Consulta CONTRIBUTING.md para instrucciones de configuración.
El código base son dos archivos:
safari.js— capa de automatización de Safari (AppleScript + JavaScript)index.js— servidor MCP con definiciones de herramientas
Patrocinadores
Safari MCP es gratuito y de código abierto. Si te ahorra tiempo o ciclos de CPU, considera apoyar su desarrollo:
Tu apoyo financia:
- 🧪 Pruebas en varias versiones de macOS y lanzamientos de Safari
- 🛠️ Nuevas herramientas y funciones
- 📖 Documentación y ejemplos
¡Conviértete en el primer patrocinador!
Soporte comercial
¿Necesitas integrar Safari MCP en tu producto o pila de agentes? Achiya Automation ofrece:
- Correcciones de errores prioritarias y desarrollo de herramientas personalizadas para tu caso de uso
- Consultoría de integración: conexión de Safari MCP en sistemas de agentes de producción (Claude, Cursor, n8n, personalizados)
- Soporte de implementación privada: Safari MCP multiusuario, entornos macOS no estándar, CI/CD
- Talleres de capacitación para equipos de ingeniería que adoptan automatización basada en MCP
Creado por el autor de Safari MCP. Inicia una conversación →
Lo que los agentes desbloquean con Safari MCP
Cuando un agente de IA maneja Safari MCP, obtiene cosas que un navegador sin interfaz no puede:
- Sesiones autenticadas reales: Gmail, GitHub, Ahrefs, Slack, paneles bancarios ya están iniciados sesión
- Relleno de formularios consciente de frameworks:
safari_fill_and_submitllama a los setters de React/Vue/Angular de forma nativa, sin adivinar si los eventosinputse dispararon - Operación en segundo plano: el agente trabaja en paralelo mientras sigues usando tu Mac
- Una llamada MCP por flujo de trabajo:
safari_run_scriptagrupa navegación + clics + extracción en un solo viaje de ida y vuelta
El patrón se mantiene en todos los modelos: maneja el navegador en el que el humano ya confía: heredas inicios de sesión, cookies, extensiones y el entorno exacto del usuario en un solo paso.
Comunidad
Más de 6,000 descargas mensuales de npm: los desarrolladores están construyendo agentes de IA en macOS con Safari MCP.
- Discusiones de GitHub: haz preguntas, comparte casos de uso
- Problemas: informes de errores y solicitudes de funciones
: comienza a contribuir
Ecosistema
Otros servidores MCP para macOS que complementan Safari MCP:
| Proyecto | Qué hace | Cuándo usarlo |
|---|---|---|
| mcp-server-macos-use | Automatización de macOS a nivel de SO (accesibilidad, control de pantalla) | Interacciones a nivel de sistema más allá de Safari |
| chrome-devtools-mcp | Protocolo de DevTools de Chrome | Auditorías de Lighthouse, trazas específicas de Chrome |
¿Usas Safari MCP junto con Chrome DevTools MCP? Safari maneja el 95% de la navegación diaria (cero sobrecarga), Chrome maneja el 5% que necesita Lighthouse o trazas específicas de Chrome.
Listado en
Licencia
MIT: úsalo como quieras.
Creado por Achiya Automation — automatización y agentes de IA para empresas.