ios-files

Un servidor MCP local que permite a los clientes de IA leer y escribir archivos de forma segura en dispositivos iOS con jailbreak a través de SSH/SFTP.

Documentación

ios-files-mcp

Servidor MCP stdio para acceso SSH/SFTP controlado al sistema de archivos de un dispositivo iOS.

AI MCP client -> ios-files-mcp on your computer -> SSH/SFTP -> iOS device

Instalación rápida

Requisitos:

  • Node.js 20+
  • OpenSSH ejecutándose en tu dispositivo iOS
  • Tu computadora puede conectarse por SSH al dispositivo

Encuentra la IP del dispositivo iOS en Settings -> Wi-Fi -> your network -> IP Address, luego prueba:

ssh mobile@192.168.1.23

Ejecuta el comando para tu agente de codificación. Reemplaza 192.168.1.23 y change-me. Tu contraseña ssh predeterminada es alpine si no la has cambiado.

Codex

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client codex --host 192.168.1.23 --password change-me

Escribe en ~/.codex/config.toml.

Claude Desktop

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client claude --host 192.168.1.23 --password change-me

Escribe en la configuración MCP de Claude Desktop.

OpenCode

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client opencode --host 192.168.1.23 --password change-me

Escribe en ~/.config/opencode/opencode.json.

VS Code

Ejecuta esto desde la carpeta del espacio de trabajo donde deseas habilitar el servidor MCP.

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client vscode --host 192.168.1.23 --password change-me

Escribe en .vscode/mcp.json.

Todos los clientes compatibles

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client all --host 192.168.1.23 --password change-me

Valores de --client compatibles:

codex      -> ~/.codex/config.toml
claude     -> Claude Desktop config
opencode   -> ~/.config/opencode/opencode.json
vscode     -> .vscode/mcp.json in the current folder
all        -> all supported clients

El instalador escribe una entrada de servidor MCP ios-files y respalda los archivos de configuración existentes en .bak.

Instala con decodificadores opcionales de bytecode Hermes:

npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client codex --host 192.168.1.23 --password change-me --install-hermes

Los decodificadores Hermes solo se necesitan para la decodificación de paquetes de bytecode Hermes de React Native. La bandera instala hermes-dec con Python/pipx cuando esté disponible.

Para análisis estático con radare2, consulta la sección de radare2 a continuación: la ruta recomendada es instalar radare2 en el propio dispositivo iOS a través de Sileo.

SSH por USB

Reenvía el SSH del dispositivo iOS a un puerto local con iproxy, luego instala usando localhost:

ssh -p 2222 mobile@127.0.0.1
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client codex --host 127.0.0.1 --port 2222 --password change-me

El SSH por USB aún usa autenticación SSH normal, así que usa una contraseña o clave SSH.

Configuración manual de MCP

El instalador escribe este comando:

{
  "command": "npx",
  "args": ["--yes", "--quiet", "github:xtofuub/ios-files-mcp"],
  "env": {
    "IOS_FILES_MCP_HOST": "192.168.1.23",
    "IOS_FILES_MCP_USERNAME": "mobile",
    "IOS_FILES_MCP_PASSWORD": "change-me"
  }
}

Úsalo bajo mcpServers.ios-files para clientes estilo Claude/Cline, o bajo servers.ios-files para VS Code.

Para una instalación explícita del paquete:

npm install github:xtofuub/ios-files-mcp

Para que npm install también escriba la configuración de MCP, establece primero las variables de entorno del instalador:

$env:IOS_FILES_MCP_INSTALL_CLIENTS="codex"
$env:IOS_FILES_MCP_HOST="192.168.1.23"
$env:IOS_FILES_MCP_USERNAME="mobile"
$env:IOS_FILES_MCP_PASSWORD="change-me"
npm install github:xtofuub/ios-files-mcp

Agrega esta variable de entorno si también deseas decodificadores Hermes:

$env:IOS_FILES_MCP_INSTALL_HERMES="true"

Variables de entorno útiles:

IOS_FILES_MCP_HOST
IOS_FILES_MCP_PORT
IOS_FILES_MCP_USERNAME
IOS_FILES_MCP_PASSWORD
IOS_FILES_MCP_KEY_PATH
IOS_FILES_MCP_ALLOWED_ROOTS
IOS_FILES_MCP_READ_ONLY
IOS_FILES_MCP_ALLOW_WRITES
IOS_FILES_MCP_REQUIRE_WRITE_APPROVAL
IOS_FILES_MCP_ENABLE_R2
IOS_FILES_MCP_R2_MODE
IOS_FILES_MCP_R2_DEVICE_R2_PATH
IOS_FILES_MCP_R2_DEVICE_RABIN2_PATH
IOS_FILES_MCP_R2_PATH
IOS_FILES_MCP_RABIN2_PATH
IOS_FILES_MCP_R2_TIMEOUT_MS
IOS_FILES_MCP_R2_MAX_OUTPUT_BYTES
IOS_FILES_MCP_R2_MAX_BINARY_SIZE
IOS_FILES_MCP_SFTP_OP_TIMEOUT_MS
IOS_FILES_MCP_CONFIG

Archivo de configuración JSON opcional

La mayoría de los usuarios deberían usar MCP env. Los archivos de configuración JSON solo se necesitan para configuraciones avanzadas o locales.

Ejemplo mínimo:

{
  "host": "192.168.1.23",
  "port": 22,
  "username": "mobile",
  "password": "change-me",
  "readOnly": true,
  "allowWrites": false
}

Consulta ios-files-mcp.config.example.json para conocer todas las opciones.

Apunta MCP al archivo de configuración con IOS_FILES_MCP_CONFIG:

{
  "servers": {
    "ios-files": {
      "command": "npx",
      "args": [
        "--yes",
        "--quiet",
        "github:xtofuub/ios-files-mcp"
      ],
      "env": {
        "IOS_FILES_MCP_CONFIG": "/path/to/ios-files-mcp/ios-files-mcp.config.json"
      }
    }
  }
}

O pásalo como argumento:

{
  "mcpServers": {
    "ios-files": {
      "command": "npx",
      "args": [
        "--yes",
        "--quiet",
        "github:xtofuub/ios-files-mcp",
        "--config",
        "/path/to/ios-files-mcp/ios-files-mcp.config.json"
      ]
    }
  }
}

Prueba local

Esto debería imprimir ayuda y salir:

npx --yes --quiet github:xtofuub/ios-files-mcp --help

Esto inicia el servidor MCP y espera a un cliente MCP:

$env:IOS_FILES_MCP_HOST="192.168.1.23"
$env:IOS_FILES_MCP_USERNAME="mobile"
$env:IOS_FILES_MCP_PASSWORD="change-me"
npx --yes --quiet github:xtofuub/ios-files-mcp

Presiona Ctrl+C para detenerlo.

Desarrollo

Desde un clon:

npm install
npm run build
npm run typecheck
node dist/index.js --help

Para pruebas locales de MCP sin NPX, apunta tu cliente MCP a node dist/index.js con una ruta absoluta.

Primeras llamadas MCP

Si los directorios de aplicaciones se ven vacíos, comienza aquí:

ios_connection_doctor()
ios_doctor()
ios_diagnose_roots()

Verifica la configuración local del cliente MCP:

ios_mcp_config_status()
ios_config()

Para encontrar YouTube:

ios_find_app("YouTube")
ios_find_app("com.google.ios.youtube")
ios_snapshot_app("com.google.ios.youtube")
ios_app("com.google.ios.youtube")

Para inspeccionar un plist de aplicación:

ios_read_plist("/private/var/containers/Bundle/Application/<UUID>/YouTube.app/Info.plist")

Rutas de aplicaciones

Contenedores de datos de aplicaciones:

/var/mobile/Containers/Data/Application/<UUID>
/private/var/mobile/Containers/Data/Application/<UUID>

Paquetes .app de App Store:

/var/containers/Bundle/Application/<UUID>/<AppName>.app
/private/var/containers/Bundle/Application/<UUID>/<AppName>.app

Info.plist generalmente está en el paquete .app, no en el contenedor de datos.

Seguridad

El servidor es de solo lectura por defecto. Las escrituras requieren ambas:

{
  "readOnly": false,
  "allowWrites": true
}

Cuando las escrituras están habilitadas, la aprobación de escritura aún se requiere por defecto:

{
  "requireWriteApproval": true,
  "writeApprovalTtlMs": 300000
}

Las herramientas con capacidad de escritura no escriben en la primera llamada. Devuelven una solicitud de aprobación con un approvalId. Si apruebas la operación exacta, llama a la misma herramienta nuevamente con los mismos argumentos más ese approvalId.

Los ids de aprobación son:

one-use
time-limited
bound to the exact tool name and arguments

Ejemplo:

ios_write_file("/var/mobile/test.txt", "hello")

Devuelve una solicitud de aprobación. Luego, solo si se aprueba:

ios_write_file("/var/mobile/test.txt", "hello", approvalId="the-id-from-the-request")

Bloqueado por defecto:

/var/Keychains
/var/mobile/Library/Accounts
/var/mobile/Library/SMS
/var/mobile/Library/Mail
/private/var/db
/System
/usr
/bin
/sbin

Cada operación se registra en ios-files-mcp.log. Los contenidos de archivos y secretos no se registran.

Herramientas

Sistema de archivos básico

HerramientaQué hace
ios_list_dir(path)Lista archivos y carpetas en un directorio.
ios_stat(path)Devuelve metadatos de archivo como tipo, tamaño, propietario, modo y hora de modificación.
ios_exists(path)Verifica si una ruta existe sin fallar si falta.
ios_hash_file(path)Calcula un hash SHA-256 para un archivo.
ios_search_files(root, pattern, maxResults, maxDepth, includeMetadata, useCache)Ejecuta una búsqueda recursiva limitada de nombres de archivo/ruta. Usa las herramientas de aplicaciones primero para aplicaciones instaladas.

Lectura de archivos

HerramientaQué hace
ios_read_file(path)Lee un archivo de texto UTF-8 en el chat, limitado por maxReadSize.
ios_read_file_chunk(path, offset, length, encoding)Lee una sección acotada de un archivo. Úsala para archivos de texto grandes o binarios.
ios_tail_file(path, maxBytes)Lee los últimos bytes de un archivo, útil para registros.
ios_read_last_lines(path, lines, maxBytes)Lee las últimas N líneas de un archivo de texto.
ios_read_plist(path)Analiza archivos plist XML o binarios y devuelve datos seguros para JSON.
ios_inspect_js_bundle(path)Detecta si un paquete de React Native es JavaScript plano, bytecode Hermes o binario desconocido.
ios_decode_js_bundle(path, mode, localPath, maxOutputBytes, beautify)Embellece archivos .jsbundle planos o ejecuta el decodificador Hermes configurado para paquetes de bytecode.
ios_list_hermes_decoders()Muestra el decodificador configurado, los comandos de decodificador auto-detectados y notas de configuración.

Copiar archivos a tu computadora

HerramientaQué hace
ios_download_file(remotePath, localPath, overwrite)Copia un archivo del dispositivo iOS a una carpeta local permitida en tu computadora. Esto no está limitado por maxReadSize.
ios_zip_download(paths, localPath, overwrite)Crea un ZIP local que contiene uno o más archivos/carpetas del dispositivo iOS. Úsalo para carpetas de aplicaciones, registros o exportaciones agrupadas.

localPath debe estar dentro de localArtifactRoots.

Ayudantes de aplicaciones de App Store

HerramientaQué hace
ios_find_app(query)Encuentra una aplicación instalada por nombre visible, nombre .app o id de paquete sin hacer una búsqueda recursiva lenta.
ios_list_apps(query, limit)Lista paquetes de aplicaciones instaladas, opcionalmente filtrados por nombre o id de paquete.
ios_resolve_app_container(bundleId)Resuelve un id de paquete a su paquete .app, contenedor de datos de la aplicación y contenedores de grupos de aplicaciones cuando son visibles.
ios_list_preferences(bundleId)Lista archivos plist en la carpeta Library/Preferences del contenedor de datos de la aplicación.
ios_read_preferences(bundleId, includeAll, maxFiles)Lee archivos plist de preferencias de aplicaciones. Por defecto solo lee el plist exacto del id de paquete.

SQLite

HerramientaQué hace
ios_read_sqlite_schema(path)Lee nombres de tablas/vistas, definiciones SQL y columnas de tablas de una base de datos SQLite.
ios_query_sqlite(path, sql, limit)Ejecuta una declaración SQL de solo lectura y devuelve filas limitadas. Permite SELECT, PRAGMA, WITH y EXPLAIN.

Paquetes de React Native

Los archivos .jsbundle de React Native plano son texto JavaScript. ios_decode_js_bundle puede embellecerlos y previsualizar el resultado en la respuesta MCP o guardarlo en un archivo local.

Los paquetes Hermes son bytecode. El servidor puede detectarlos y usar automáticamente hbc-decompiler, hbc-disassembler, hermesc o hbctool si uno está en PATH. La salida suele ser pseudo-código, HASM o bytecode/desensamblado, no el código fuente original.

Ejecuta ios_list_hermes_decoders() cuando falle la decodificación. Te dice lo que el servidor MCP puede ver desde su propio proceso.

Ayudante de decodificador opcional:

npx -p github:xtofuub/ios-files-mcp ios-files-mcp-install-hermes-dec
npx -p github:xtofuub/ios-files-mcp ios-files-mcp-check-hermes-decoders

Herramientas de análisis estático radare2

Por defecto, estas herramientas detectan radare2 en el dispositivo iOS y lo ejecutan allí a través de SSH, sin necesidad de copiar binarios. Si r2 no está instalado en el dispositivo, el MCP recurre a ejecutar r2/rabin2 en tu computadora después de copiar el binario a una carpeta local temporal. Ejecuta ios_r2_check para ver qué ejecutor está activo.

Instalación recomendada (en el dispositivo iOS, a través de Sileo):

  1. Abre Sileo en el dispositivo con jailbreak.
  2. Instala el paquete radare2 desde el repositorio Procursus (predeterminado en jailbreaks modernos como Dopamine y palera1n).
  3. Desde tu computadora, ejecuta ssh mobile@<device-ip> 'r2 -v' para confirmar.

Rutas comunes del dispositivo después de la instalación de Sileo:

/usr/bin/r2          (rootful jailbreaks: unc0ver, checkra1n, classic palera1n)
/var/jb/usr/bin/r2   (rootless jailbreaks: Dopamine, palera1n rootless)

El MCP sondea command -v r2 a través de SSH, por lo que detecta lo que haya en el $PATH del dispositivo. Anula con IOS_FILES_MCP_R2_DEVICE_R2_PATH=/your/path si el binario está en una ubicación no estándar.

Modos:

  • IOS_FILES_MCP_R2_MODE=auto (predeterminado): intenta primero en el dispositivo, recurre a local.
  • IOS_FILES_MCP_R2_MODE=device: requiere r2 del lado del dispositivo; falla rápido si falta.
  • IOS_FILES_MCP_R2_MODE=local: siempre se ejecuta en esta computadora (copia el binario a una carpeta temporal).

Env opcional:

IOS_FILES_MCP_ENABLE_R2=true
IOS_FILES_MCP_R2_MODE=auto
IOS_FILES_MCP_R2_DEVICE_R2_PATH=/var/jb/usr/bin/r2
IOS_FILES_MCP_R2_DEVICE_RABIN2_PATH=/var/jb/usr/bin/rabin2
IOS_FILES_MCP_R2_PATH=r2
IOS_FILES_MCP_RABIN2_PATH=rabin2
IOS_FILES_MCP_R2_TIMEOUT_MS=30000
IOS_FILES_MCP_R2_MAX_OUTPUT_BYTES=16777216
IOS_FILES_MCP_R2_MAX_BINARY_SIZE=134217728

Nota de migración: el instalador anterior del lado del host (ios-files-mcp-install-radare2) y la bandera postinstall IOS_FILES_MCP_INSTALL_R2 se han eliminado. Instala radare2 en el dispositivo iOS a través de Sileo, o instálalo localmente con tu propio administrador de paquetes si prefieres IOS_FILES_MCP_R2_MODE=local.

Cuándo usar:

  • Usa ios_r2_app_triage(bundleId) para la visión general más rápida de una aplicación instalada.
  • Usa ios_r2_binary_info(remotePath) cuando ya conozcas la ruta del binario.
  • Usa ios_r2_strings(remotePath, query, limit) para endpoints, secretos, Firebase, URLs, cadenas de depuración y banderas de funciones.
  • Usa ios_r2_imports(remotePath, query, limit) para uso de frameworks/APIs como Keychain, criptografía, redes, SQLite, WebKit, integridad del dispositivo y verificaciones anti-depuración.
  • Usa ios_r2_functions(remotePath, limit) para mapear funciones disponibles.
  • Usa ios_r2_function_disasm(remotePath, functionNameOrAddress) para inspeccionar una función o dirección seleccionada.

Flujo de análisis recomendado:

  1. ios_find_app("App Name") o ios_resolve_app_container("com.example.app")
  2. ios_r2_app_triage("com.example.app")
  3. ios_r2_strings(remotePath, query, limit) con consultas como http, api, firebase, token, auth, key, debug
  4. ios_r2_imports(remotePath, query, limit) con consultas como SecItem, CommonCrypto, CryptoKit, NSURLSession, SQLite, WKWebView
  5. ios_r2_functions(remotePath, limit)
  6. ios_r2_function_disasm(remotePath, functionNameOrAddress) en una función o dirección interesante específica
HerramientaQué hace
ios_r2_check()Muestra si el soporte r2 está habilitado y si r2/rabin2 locales están disponibles.
ios_r2_binary_info(remotePath)Devuelve metadatos Mach-O y bibliotecas vinculadas para una ruta de binario.
ios_r2_app_triage(bundleId)Resuelve una aplicación instalada, encuentra su ejecutable y devuelve información del binario, imports/cadenas interesantes, vista previa de funciones y próximas acciones.
ios_r2_strings(remotePath, query, limit)Busca en cadenas binarias URLs, endpoints, tokens, configuración de Firebase, texto de depuración y banderas de funciones.
ios_r2_imports(remotePath, query, limit)Busca símbolos importados/APIs de frameworks como Keychain, criptografía, redes, SQLite, WebKit y llamadas anti-depuración.
ios_r2_functions(remotePath, limit)Lista nombres de funciones y direcciones antes de una inspección más profunda.
ios_r2_function_disasm(remotePath, functionNameOrAddress)Devuelve desensamblado JSON estructurado para una función o dirección seleccionada.

Escritura de archivos

Estas herramientas están deshabilitadas a menos que readOnly=false y allowWrites=true.

HerramientaQué hace
ios_write_file(path, content)Escribe contenido UTF-8 en un archivo. Los archivos existentes se respaldan cuando backupBeforeWrite=true.
ios_append_file(path, content)Agrega contenido UTF-8 a un archivo, o lo crea si falta.
ios_delete_file(path)Elimina un archivo o directorio vacío.
ios_move_file(from, to)Mueve o renombra un archivo. Los destinos existentes se respaldan cuando están configurados.
ios_copy_file(from, to)Copia un archivo en el dispositivo iOS. Los destinos existentes se respaldan cuando están configurados.
ios_mkdir(path)Crea un directorio.

Las herramientas con capacidad de escritura también aceptan approvalId opcional. Si requireWriteApproval=true, la primera llamada devuelve una solicitud de aprobación y no escribe. Reintenta la misma herramienta con el approvalId devuelto solo después de aprobar la operación exacta.

Diagnóstico

HerramientaQué hace
ios_doctor()Encuentra problemas de configuración: conexión SSH/SFTP, raíces de apps visibles, carpetas de exportación locales, configuración de MCP y disponibilidad del decodificador Hermes.
ios_connection_doctor()Comprueba la conexión SSH/SFTP, las raíces visibles, las raíces de artefactos locales, la configuración de MCP y la disponibilidad del decodificador Hermes.
ios_config()Comprueba si Codex, Claude, OpenCode y VS Code están configurados para iniciar este servidor MCP correctamente.
ios_mcp_config_status()Muestra si los archivos de configuración de Codex, Claude, OpenCode y VS Code contienen la entrada de servidor ios-files esperada.
ios_app(bundleId)Ofrece una visión general rápida de la app: ruta del bundle, contenedor de datos, grupos de apps, resumen de Info.plist, archivos de preferencias, archivos SQLite y bundles JS.
ios_snapshot_app(bundleId)Construye una instantánea de la app centrada en metadatos: rutas de bundle/datos/grupos de apps, resumen de Info.plist, archivos de preferencias, archivos SQLite y bundles JS.
ios_diagnose_roots()Comprueba si las raíces comunes de apps iOS son visibles a través del inicio de sesión SSH/SFTP actual y da notas para directorios vacíos.

Notas

  • Reinicia el cliente MCP después de recompilar.
  • Si los directorios están vacíos como mobile, prueba SSH/SFTP como root si tu dispositivo expone esos directorios solo a root.
  • ios_search_files es recursivo y puede ser lento a través de SFTP. Usa ios_find_app, ios_list_apps o ios_resolve_app_container para apps.
  • ios_search_files está limitado y almacenado en caché por defecto. Repetir la misma búsqueda debería devolver desde memoria durante searchCacheTtlMs.
  • Mantén las búsquedas recursivas pequeñas al principio, por ejemplo maxResults=10 y maxDepth=2.
  • ios_search_files devuelve resultados concisos de ruta/tipo por defecto. Establece includeMetadata=true solo cuando se necesiten el tamaño y la hora de modificación.
  • ios_read_file tiene un límite predeterminado de 4 MiB a través de maxReadSize.
  • Usa ios_read_file_chunk, ios_tail_file o ios_read_last_lines en lugar de lecturas completas repetidas de archivos.
  • Usa ios_download_file para un archivo grande, o ios_zip_download para carpetas o múltiples archivos que quieras copiar desde el dispositivo iOS a tu computadora.
  • Usa ios_read_sqlite_schema y ios_query_sqlite para inspección de SQLite de solo lectura en lugar de volcar archivos de base de datos completos en el chat.
  • Usa ios_inspect_js_bundle antes de ios_decode_js_bundle cuando no estés seguro de si un bundle de React Native es JavaScript plano o bytecode de Hermes.
  • Más orientación sobre búsqueda de apps está en SKILLS.md.