Ios Files
About
A local MCP server that lets AI clients safely read and write files on jailbroken iOS devices over SSH/SFTP.
Details
- Author
- xtofuub
- Downloads
- 367
- Categories
- File Management, Other, Developer Tools
Jump to
- Read‑only by default; optional write capability with approval system.
- List, stat, search, and hash files on the iOS device.
- Read text files, plists, SQLite databases, and React Native bundles.
- Detect installed apps and resolve their containers.
- Inspect and decode Hermes bytecode bundles.
- Static analysis via radare2 (device‑side or local fallback).
- Supports all major MCP clients with automatic config setup.
Install Node.js 20+ and ensure OpenSSH is running on the iOS device. Run the installer command with your client (e.g., --client codex), device host, and password. The server writes the MCP configuration automatically for supported clients (Codex, Claude Desktop, OpenCode, VS Code). USB SSH is supported via iproxy and localhost forwarding.
ios-files-mcp
MCP stdio server for controlled SSH/SFTP access to an iOS device filesystem.
AI MCP client -> ios-files-mcp on your computer -> SSH/SFTP -> iOS device
Quick Install
Requirements:
- Node.js 20+
- OpenSSH running on your iOS device
- Your computer can SSH to the device
Find the iOS device IP in Settings -> Wi-Fi -> your network -> IP Address, then test:
ssh mobile@192.168.1.23
Run the command for your coding agent. Replace 192.168.1.23 and change-me. Your default ssh password is alpine if you haven't changed it.
Codex
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client codex --host 192.168.1.23 --password change-me
Writes to ~/.codex/config.toml.
Claude Desktop
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client claude --host 192.168.1.23 --password change-me
Writes to Claude Desktop's MCP config.
OpenCode
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client opencode --host 192.168.1.23 --password change-me
Writes to ~/.config/opencode/opencode.json.
VS Code
Run this from the workspace folder where you want the MCP server enabled.
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client vscode --host 192.168.1.23 --password change-me
Writes to .vscode/mcp.json.
All Supported Clients
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client all --host 192.168.1.23 --password change-me
Supported --client values:
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
The installer writes an ios-files MCP server entry and backs up existing config files to .bak.
Install with optional Hermes bytecode decoders:
npx -p github:xtofuub/ios-files-mcp iosfiles-mcp --client codex --host 192.168.1.23 --password change-me --install-hermes
Hermes decoders are only needed for React Native Hermes bytecode bundle decoding. The flag installs hermes-dec with Python/pipx when available.
For radare2 static analysis, see the radare2 section below — recommended path is to install radare2 on the iOS device itself via Sileo.
USB SSH
Forward iOS device SSH to a local port with iproxy, then install using 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
USB SSH still uses normal SSH auth, so use a password or SSH key.
Manual MCP Config
The installer writes this command:
{
"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"
}
}
Use that under mcpServers.ios-files for Claude/Cline-style clients, or under servers.ios-files for VS Code.
For an explicit package install:
npm install github:xtofuub/ios-files-mcp
To make npm install also write MCP config, set installer env vars first:
$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
Add this env var if you also want Hermes decoders:
$env:IOS_FILES_MCP_INSTALL_HERMES="true"
Useful env vars:
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
Optional JSON Config File
Most users should use MCP env. JSON config files are only needed for advanced/local setups.
Minimal example:
{
"host": "192.168.1.23",
"port": 22,
"username": "mobile",
"password": "change-me",
"readOnly": true,
"allowWrites": false
}
See ios-files-mcp.config.example.json for every option.
Point MCP at the config file with 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"
}
}
}
}
Or pass it as an arg:
{
"mcpServers": {
"ios-files": {
"command": "npx",
"args": [
"--yes",
"--quiet",
"github:xtofuub/ios-files-mcp",
"--config",
"/path/to/ios-files-mcp/ios-files-mcp.config.json"
]
}
}
}
Local Test
This should print help and exit:
npx --yes --quiet github:xtofuub/ios-files-mcp --help
This starts the MCP server and waits for an MCP client:
$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
Press Ctrl+C to stop it.
Development
From a clone:
npm install
npm run build
npm run typecheck
node dist/index.js --help
For local MCP testing without NPX, point your MCP client at node dist/index.js with an absolute path.
First MCP Calls
If app directories look empty, start here:
ios_connection_doctor()
ios_doctor()
ios_diagnose_roots()
Check local MCP client config:
ios_mcp_config_status()
ios_config()
To find 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")
To inspect an app plist:
ios_read_plist("/private/var/containers/Bundle/Application/<UUID>/YouTube.app/Info.plist")
App Paths
App data containers:
/var/mobile/Containers/Data/Application/<UUID>
/private/var/mobile/Containers/Data/Application/<UUID>
App Store .app bundles:
/var/containers/Bundle/Application/<UUID>/<AppName>.app
/private/var/containers/Bundle/Application/<UUID>/<AppName>.app
Info.plist is usually in the .app bundle, not the data container.
Safety
The server is read-only by default. Writes require both:
{
"readOnly": false,
"allowWrites": true
}
When writes are enabled, write approval is still required by default:
{
"requireWriteApproval": true,
"writeApprovalTtlMs": 300000
}
Write-capable tools do not write on the first call. They return an approval request with an approvalId. If you approve the exact operation, call the same tool again with the same arguments plus that approvalId.
Approval ids are:
one-use
time-limited
bound to the exact tool name and arguments
Example:
ios_write_file("/var/mobile/test.txt", "hello")
Returns an approval request. Then, only if approved:
ios_write_file("/var/mobile/test.txt", "hello", approvalId="the-id-from-the-request")
Blocked by default:
/var/Keychains
/var/mobile/Library/Accounts
/var/mobile/Library/SMS
/var/mobile/Library/Mail
/private/var/db
/System
/usr
/bin
/sbin
Every operation is logged to ios-files-mcp.log. File contents and secrets are not logged.
Tools
Basic Filesystem
…
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





