ios-mcp-jailbreak-automation

v2026.09.25

Control jailbroken iOS devices via MCP tools for AI agents to inspect, automate, and manage iPhone applications and system functions

GitHub
Install command
npx skhub add reason-machines/ios-mcp-jailbreak-automation
Markdown
SKILL.md

iOS MCP Jailbreak Automation

Skill by ara.so — MCP Skills collection.

iOS MCP is a Model Context Protocol (MCP) server that runs on jailbroken iPhones, enabling AI agents to directly control and inspect iOS devices through a comprehensive set of 34 automation tools.

What It Does

iOS MCP provides AI agents with the ability to:

  • Touch & Gestures: Tap, swipe, long press, double tap, drag and drop at precise screen coordinates
  • Hardware Buttons: Simulate physical buttons (Home, Power, Volume, Mute) via HID
  • Text Input: Type text via clipboard injection or HID simulation, press special keys
  • Screenshots: Capture screen as Base64 JPEG, get screen dimensions and orientation
  • App Management: Launch, kill, install, uninstall apps; list running and installed apps
  • Accessibility: Query UI element tree, get elements at specific coordinates
  • Clipboard: Read and write clipboard content
  • Device Control: Adjust brightness and volume
  • Device Info: Get model, iOS version, battery, storage, memory, jailbreak type
  • URL Handling: Open URLs or URL schemes
  • Shell: Execute arbitrary shell commands

Installation

Requirements

  • Jailbroken iOS device (iOS 13-18)
  • Appropriate jailbreak type:
    • rootful (iOS 13-18): iphoneos-arm
    • rootless (iOS 15-18): iphoneos-arm64
    • roothide (iOS 15-18): iphoneos-arm64e

Install via Package Manager

  1. Open Cydia or Sileo on your jailbroken device
  2. Search for iOS MCP
  3. Install the package (dependencies: mobilesubstrate/ElleKit, preferenceloader)
  4. Respring SpringBoard

Verify Installation

After installation, verify the server is running:

# From your computer or the device itself
curl http://<DEVICE_IP>:8090/health

Expected response:

{"status":"ok","server":"ios-mcp","version":"1.1.1"}

Configuration

  1. Open Settings → iOS MCP on your device
  2. Enable the MCP service
  3. Tap Copy MCP Prompt Snippet to get the connection configuration
  4. Paste the snippet into your AI agent's configuration

The server runs on port 8090 by default.

MCP Configuration

Add to your MCP settings (e.g., claude_desktop_config.json):

{
  "mcpServers": {
    "ios-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-fetch",
        "http://<YOUR_IOS_DEVICE_IP>:8090/mcp"
      ]
    }
  }
}

Replace <YOUR_IOS_DEVICE_IP> with your device's local IP address.

Available MCP Tools

Touch & Gestures

tap_screen: Tap at specific coordinates

// Parameters: x, y
await mcp.call_tool("tap_screen", { x: 200, y: 400 });

swipe_screen: Swipe from one point to another

// Parameters: from_x, from_y, to_x, to_y, duration (optional)
await mcp.call_tool("swipe_screen", {
  from_x: 200,
  from_y: 600,
  to_x: 200,
  to_y: 200,
  duration: 0.3
});

long_press: Long press at coordinates

// Parameters: x, y, duration (optional)
await mcp.call_tool("long_press", { x: 200, y: 400, duration: 1.0 });

double_tap: Double tap at coordinates

// Parameters: x, y
await mcp.call_tool("double_tap", { x: 200, y: 400 });

drag_and_drop: Drag from one point to another

// Parameters: from_x, from_y, to_x, to_y, duration (optional)
await mcp.call_tool("drag_and_drop", {
  from_x: 100,
  from_y: 300,
  to_x: 300,
  to_y: 500,
  duration: 0.5
});

Hardware Buttons

press_home: Press Home button

await mcp.call_tool("press_home", {});

press_power: Press Power button

await mcp.call_tool("press_power", {});

press_volume_up / press_volume_down: Press volume buttons

await mcp.call_tool("press_volume_up", {});
await mcp.call_tool("press_volume_down", {});

wake_and_home: Wake device and press Home (useful when screen is locked)

await mcp.call_tool("wake_and_home", {});

Text Input

input_text: Fast text input via clipboard

// Parameters: text
await mcp.call_tool("input_text", { text: "Hello from AI agent" });

type_text: Character-by-character typing via HID

// Parameters: text
await mcp.call_tool("type_text", { text: "Slow typing simulation" });

press_key: Press special keys

// Parameters: key (e.g., "return", "delete", "space")
await mcp.call_tool("press_key", { key: "return" });

Screenshots & Screen Info

screenshot: Capture screen as Base64 JPEG

// Returns: { image: "base64_jpeg_data", width: 1170, height: 2532 }
const result = await mcp.call_tool("screenshot", {});
// Decode base64 to save as file if needed

get_screen_info: Get screen dimensions and orientation

// Returns: { width: 1170, height: 2532, orientation: "portrait" }
await mcp.call_tool("get_screen_info", {});

App Management

launch_app: Launch app by bundle ID

// Parameters: bundle_id
await mcp.call_tool("launch_app", { bundle_id: "com.apple.mobilesafari" });

kill_app: Force quit app

// Parameters: bundle_id
await mcp.call_tool("kill_app", { bundle_id: "com.apple.mobilesafari" });

list_apps: List all installed apps

// Returns array of apps with bundle_id, name, version
const apps = await mcp.call_tool("list_apps", {});

list_running_apps: List currently running apps

const running = await mcp.call_tool("list_running_apps", {});

get_frontmost_app: Get currently focused app

// Returns: { bundle_id: "com.example.app", name: "App Name" }
const frontmost = await mcp.call_tool("get_frontmost_app", {});

install_app: Install IPA file

// Parameters: ipa_path (absolute path on device)
await mcp.call_tool("install_app", { ipa_path: "/var/mobile/app.ipa" });

uninstall_app: Uninstall app

// Parameters: bundle_id
await mcp.call_tool("uninstall_app", { bundle_id: "com.example.app" });

UI Accessibility

get_ui_elements: Get UI element tree (accessibility hierarchy)

// Returns nested structure of UI elements with labels, types, frames
const uiTree = await mcp.call_tool("get_ui_elements", {});

get_element_at_point: Get UI element at specific coordinates

// Parameters: x, y
const element = await mcp.call_tool("get_element_at_point", { x: 200, y: 400 });

Clipboard

get_clipboard: Read clipboard content

const content = await mcp.call_tool("get_clipboard", {});

set_clipboard: Write to clipboard

// Parameters: text
await mcp.call_tool("set_clipboard", { text: "New clipboard content" });

Device Control

get_brightness / set_brightness: Control screen brightness

const brightness = await mcp.call_tool("get_brightness", {});
// Parameters: level (0.0 to 1.0)
await mcp.call_tool("set_brightness", { level: 0.5 });

get_volume / set_volume: Control system volume

const volume = await mcp.call_tool("get_volume", {});
// Parameters: level (0.0 to 1.0)
await mcp.call_tool("set_volume", { level: 0.7 });

Device Information

get_device_info: Get comprehensive device information

// Returns: model, iOS version, battery, storage, memory, jailbreak type
const info = await mcp.call_tool("get_device_info", {});
// Example response:
// {
//   "model": "iPhone 14 Pro",
//   "ios_version": "16.1.2",
//   "battery_level": 85,
//   "battery_state": "charging",
//   "storage_total": 256000000000,
//   "storage_free": 128000000000,
//   "memory_total": 6000000000,
//   "jailbreak_type": "rootless"
// }

URL & Shell

open_url: Open URL or URL scheme

// Parameters: url
await mcp.call_tool("open_url", { url: "https://example.com" });
await mcp.call_tool("open_url", { url: "shortcuts://run-shortcut?name=MyShortcut" });

run_command: Execute shell command

// Parameters: command
// WARNING: Use with caution - can execute any shell command
const output = await mcp.call_tool("run_command", { command: "ls -la /var/mobile" });

Common Patterns

Workflow: Automate Safari Navigation

// 1. Wake device and unlock if needed
await mcp.call_tool("wake_and_home", {});

// 2. Launch Safari
await mcp.call_tool("launch_app", { bundle_id: "com.apple.mobilesafari" });

// 3. Wait a moment for app to load
await new Promise(resolve => setTimeout(resolve, 1000));

// 4. Take screenshot to see current state
const screen = await mcp.call_tool("screenshot", {});

// 5. Tap address bar (coordinates depend on device)
await mcp.call_tool("tap_screen", { x: 200, y: 100 });

// 6. Input URL
await mcp.call_tool("input_text", { text: "https://example.com" });

// 7. Press return
await mcp.call_tool("press_key", { key: "return" });

Workflow: UI Inspection and Interaction

// 1. Get UI element tree
const uiTree = await mcp.call_tool("get_ui_elements", {});

// 2. Parse tree to find button with specific label
function findButton(tree, label) {
  // Recursive search implementation
  if (tree.label === label && tree.type === "Button") {
    return tree;
  }
  for (const child of tree.children || []) {
    const found = findButton(child, label);
    if (found) return found;
  }
  return null;
}

const button = findButton(uiTree, "Submit");

// 3. Tap button at its center
if (button && button.frame) {
  const x = button.frame.x + button.frame.width / 2;
  const y = button.frame.y + button.frame.height / 2;
  await mcp.call_tool("tap_screen", { x, y });
}

Workflow: Install and Test App

// 1. Check device info
const deviceInfo = await mcp.call_tool("get_device_info", {});
console.log(`Device: ${deviceInfo.model}, iOS: ${deviceInfo.ios_version}`);

// 2. Install IPA (assume already uploaded to device)
await mcp.call_tool("install_app", { ipa_path: "/var/mobile/Documents/MyApp.ipa" });

// 3. Wait for installation
await new Promise(resolve => setTimeout(resolve, 5000));

// 4. Launch the app
await mcp.call_tool("launch_app", { bundle_id: "com.example.myapp" });

// 5. Take screenshot for verification
const screenshot = await mcp.call_tool("screenshot", {});

// 6. Interact with app...
await mcp.call_tool("tap_screen", { x: 200, y: 400 });

Workflow: Automated Testing Loop

// Automated regression test
async function runTest() {
  // Launch app
  await mcp.call_tool("launch_app", { bundle_id: "com.example.testapp" });
  
  // Perform test actions
  await mcp.call_tool("tap_screen", { x: 100, y: 200 });
  await mcp.call_tool("input_text", { text: "Test Data" });
  await mcp.call_tool("tap_screen", { x: 200, y: 500 });
  
  // Capture result
  const result = await mcp.call_tool("screenshot", {});
  
  // Verify UI state via get_ui_elements
  const ui = await mcp.call_tool("get_ui_elements", {});
  
  // Kill app
  await mcp.call_tool("kill_app", { bundle_id: "com.example.testapp" });
  
  return { screenshot: result, ui };
}

Security & Best Practices

Important Security Notes

  • No Authentication: The MCP server has no built-in authentication. Only use on trusted local networks.
  • Lockscreen Protection: When device is locked or screen is off, interactive tools (tap, swipe, input, launch app, shell) are blocked. Only status queries, screenshots, and wake commands are allowed.
  • Shell Command Risk: run_command can execute arbitrary shell commands with device privileges. Use with extreme caution.
  • Root Privilege: The mcp-root helper provides root escalation for specific tools only.

Recommended Practices

  1. Network Security: Keep iOS MCP on a private, trusted network
  2. Firewall: Consider device firewall rules to limit access to port 8090
  3. Monitoring: Check server logs if unexpected behavior occurs
  4. Testing: Test automation workflows on non-production devices first
  5. Coordinates: Screen coordinates vary by device model and orientation - always verify with get_screen_info

Troubleshooting

Server Not Responding

Problem: curl http://<DEVICE_IP>:8090/health fails

Solutions:

  • Verify device IP address (Settings → Wi-Fi → (i) button)
  • Ensure iOS MCP service is enabled in Settings → iOS MCP
  • Respring SpringBoard after installation
  • Check if firewall is blocking port 8090
  • Ensure device and computer are on same network

Tools Return "Device Locked" Error

Problem: Tap, swipe, or input commands fail with lock error

Solutions:

  • Device screen is locked or off
  • Use wake_and_home to unlock device first
  • Status queries and screenshots still work when locked

Screenshot Returns Invalid Base64

Problem: Screenshot data cannot be decoded

Solutions:

  • Check if screen is on (may return blank if off)
  • Verify screenshot tool returns valid JSON with image field
  • Try get_screen_info first to verify screen state

App Launch Fails

Problem: launch_app doesn't start the app

Solutions:

  • Verify bundle ID is correct: use list_apps to find exact bundle ID
  • Check if app is already running: use get_frontmost_app
  • Ensure device is unlocked
  • Some system apps may have restrictions

UI Elements Tree is Empty

Problem: get_ui_elements returns no elements

Solutions:

  • App may not expose accessibility information
  • Try on a different app (e.g., Settings, Safari)
  • Ensure app is in foreground: use get_frontmost_app to verify

Permission Errors with Shell Commands

Problem: run_command returns permission denied

Solutions:

  • Check jailbreak type and permissions
  • Some commands require root (automatically escalated via mcp-root)
  • Verify command syntax and paths are correct

Install App Fails

Problem: install_app returns error

Solutions:

  • Verify IPA file exists at specified path
  • Check IPA is valid and signed appropriately for jailbroken device
  • Ensure sufficient storage space
  • Path must be absolute (e.g., /var/mobile/Documents/app.ipa)

This skill enables AI agents to fully automate jailbroken iOS devices through MCP, providing comprehensive control over UI interactions, app management, device state, and shell access for advanced automation and testing workflows.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.25

Published

Sep 25, 2026

Category

Uncategorized

License

NOASSERTION

Source path

skills/ios-mcp-jailbreak-automation

Default branch

main

Latest commit

329e67c

Tree SHA

01fd22f