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
| Herramienta | Qué 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
| Herramienta | Qué 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
| Herramienta | Qué 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
| Herramienta | Qué 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
| Herramienta | Qué 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):
- Abre Sileo en el dispositivo con jailbreak.
- Instala el paquete
radare2desde el repositorio Procursus (predeterminado en jailbreaks modernos como Dopamine y palera1n). - 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:
ios_find_app("App Name")oios_resolve_app_container("com.example.app")ios_r2_app_triage("com.example.app")ios_r2_strings(remotePath, query, limit)con consultas comohttp,api,firebase,token,auth,key,debugios_r2_imports(remotePath, query, limit)con consultas comoSecItem,CommonCrypto,CryptoKit,NSURLSession,SQLite,WKWebViewios_r2_functions(remotePath, limit)ios_r2_function_disasm(remotePath, functionNameOrAddress)en una función o dirección interesante específica
| Herramienta | Qué 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.
| Herramienta | Qué 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
| Herramienta | Qué 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 comorootsi tu dispositivo expone esos directorios solo a root. ios_search_fileses recursivo y puede ser lento a través de SFTP. Usaios_find_app,ios_list_appsoios_resolve_app_containerpara apps.ios_search_filesestá limitado y almacenado en caché por defecto. Repetir la misma búsqueda debería devolver desde memoria durantesearchCacheTtlMs.- Mantén las búsquedas recursivas pequeñas al principio, por ejemplo
maxResults=10ymaxDepth=2. ios_search_filesdevuelve resultados concisos de ruta/tipo por defecto. EstableceincludeMetadata=truesolo cuando se necesiten el tamaño y la hora de modificación.ios_read_filetiene un límite predeterminado de 4 MiB a través demaxReadSize.- Usa
ios_read_file_chunk,ios_tail_fileoios_read_last_linesen lugar de lecturas completas repetidas de archivos. - Usa
ios_download_filepara un archivo grande, oios_zip_downloadpara carpetas o múltiples archivos que quieras copiar desde el dispositivo iOS a tu computadora. - Usa
ios_read_sqlite_schemayios_query_sqlitepara inspección de SQLite de solo lectura en lugar de volcar archivos de base de datos completos en el chat. - Usa
ios_inspect_js_bundleantes deios_decode_js_bundlecuando 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.