Labsco
chrishayuk logo

iOS Device Control

โ˜… 5

from chrishayuk

An MCP server to control iOS simulators and real devices, enabling AI assistant integration on macOS.

๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅโœ“ VerifiedFreeNeeds API keys

iOS Device Control (chuk-mcp-ios)

Comprehensive iOS device control system supporting both simulators and real devices. Available as both a standalone CLI tool and MCP (Model Context Protocol) server for AI assistant integration.

๐Ÿš€ Features

  • ๐ŸŽฏ Unified Device Management: Control iOS simulators and real devices through a single interface
  • ๐Ÿ“‹ Session Management: Create and manage device sessions for organized automation workflows
  • ๐Ÿ“ฑ App Lifecycle: Install, launch, terminate, and manage iOS applications
  • ๐ŸŽฎ UI Automation: Tap, swipe, type, and interact with device interfaces
  • ๐Ÿ“ธ Media & Location: Add photos/videos, simulate GPS locations and routes
  • ๐Ÿ” Debugging: Access logs, crash reports, and debugging information
  • ๐Ÿค– MCP Server: Integration with Claude and other AI assistants
  • โšก CLI Tool: Standalone command-line interface for direct control

โš ๏ธ Current Status & Recommendations

CLI Issues Detected

Based on testing, the CLI has several bugs that need fixing:

  1. Session Resolution: Sessions show active but commands fail to find devices
  2. Import Errors: Missing time import causing crashes
  3. Device Resolution: Direct UDID usage also failing

1. Direct simctl (Most Reliable)

# Use native simulator tools directly
xcrun simctl list devices
xcrun simctl boot "iPhone 15" 
xcrun simctl io booted screenshot screenshot.png
xcrun simctl launch booted com.apple.Preferences

2. Python API (Full Features)

# Use the Python API directly for full functionality
python3 -c "
import asyncio
from chuk_mcp_ios.mcp.tools import ios_create_session, ios_screenshot
session = asyncio.run(ios_create_session())
print(f'Session: {session}')
"

3. MCP Server (AI Integration)

# Use MCP server for AI assistant integration
uvx chuk-mcp-ios mcp
# Then connect via Claude or other AI assistants

4. CLI (Limited, Has Bugs)

# CLI currently has issues but basic commands work:
uvx chuk-mcp-ios cli status        # โœ… Works
uvx chuk-mcp-ios cli device list   # โœ… Works  
uvx chuk-mcp-ios cli session list  # โœ… Works
uvx chuk-mcp-ios cli ui screenshot # โŒ Broken
uvx chuk-mcp-ios cli app list      # โŒ Broken

Step-by-Step Working Example

Here's a complete sequence that actually works:

# 1. Check your system status
uvx chuk-mcp-ios cli status

# 2. List available devices to see what's available
uvx chuk-mcp-ios cli device list

# 3. Create a new session (this gives you a fresh session ID)
uvx chuk-mcp-ios cli session create --device "iPhone 15"
# Note: Copy the session ID from the output, e.g., session_1749425214_4b7f748f

# 4. List active sessions to verify
uvx chuk-mcp-ios cli session list

# 5. Use the actual session ID from step 3 for commands:
# Replace YOUR_SESSION_ID with the actual ID from step 3
uvx chuk-mcp-ios cli ui screenshot YOUR_SESSION_ID -o screenshot.png

# 6. Launch Settings app
uvx chuk-mcp-ios cli app launch YOUR_SESSION_ID com.apple.Preferences

# 7. Take another screenshot to see Settings
uvx chuk-mcp-ios cli ui screenshot YOUR_SESSION_ID -o settings.png

# 8. List installed apps
uvx chuk-mcp-ios cli app list YOUR_SESSION_ID

# 9. Clean up when done
uvx chuk-mcp-ios cli session terminate YOUR_SESSION_ID

Working Example (With Workarounds)

# Method 1: Try session ID first, fallback to UDID
SESSION_ID="session_1749425214_4b7f748f"
UDID="D5ABE678-7395-4EF6-880B-E649F4FEDEE5"

# Try session ID
uvx chuk-mcp-ios cli ui screenshot $SESSION_ID -o screenshot.png

# If that fails, try UDID directly
if [ $? -ne 0 ]; then
    echo "Session failed, trying UDID..."
    uvx chuk-mcp-ios cli ui screenshot $UDID -o screenshot.png
fi

# Method 2: Direct device approach (most reliable)
# Get UDID from device list
uvx chuk-mcp-ios cli device list
# Copy the UDID and use it directly
uvx chuk-mcp-ios cli ui screenshot D5ABE678-7395-4EF6-880B-E649F4FEDEE5 -o screenshot.png

# Method 3: Fresh session approach
# Clean slate approach if sessions are buggy
uvx chuk-mcp-ios cli session terminate session_1749425214_4b7f748f
uvx chuk-mcp-ios cli session terminate automation_1749424425_58872b30
NEW_SESSION=$(uvx chuk-mcp-ios cli quick-start | grep -o 'session_[a-zA-Z0-9_]*')
uvx chuk-mcp-ios cli ui screenshot $NEW_SESSION -o screenshot.png

Immediate Fix for Your Situation

# Based on your current sessions, try these in order:

# 1. Try direct UDID (most likely to work)
uvx chuk-mcp-ios cli ui screenshot D5ABE678-7395-4EF6-880B-E649F4FEDEE5 -o screenshot.png

# 2. If UDID doesn't work, test direct simctl
xcrun simctl io D5ABE678-7395-4EF6-880B-E649F4FEDEE5 screenshot test.png

# 3. If simctl works but CLI doesn't, it's a CLI bug
# Use Python API as workaround:
python3 -c "
import asyncio
from chuk_mcp_ios.mcp.tools import ios_screenshot
result = asyncio.run(ios_screenshot('D5ABE678-7395-4EF6-880B-E649F4FEDEE5', 'screenshot.png'))
print('Success!' if result.get('success') else f'Error: {result.get(\"error\")}')
"

Alternative: Use Quick Start

# Auto-setup with best available device
uvx chuk-mcp-ios cli quick-start

# This creates a session and tells you the ID to use
# Then use that ID for subsequent commands

๐Ÿ“š CLI Examples

First, check what commands are actually available:

# Check main commands
chuk-mcp-ios cli --help

# Check UI subcommands
chuk-mcp-ios cli ui --help

# Check device subcommands  
chuk-mcp-ios cli device --help

# Check session subcommands
chuk-mcp-ios cli session --help

# Check app subcommands
chuk-mcp-ios cli app --help

Device Management

# List all available devices (simulators + real devices)
chuk-mcp-ios cli device list

# List only simulators
chuk-mcp-ios cli device list --type simulator

# Show device details
chuk-mcp-ios cli device info DEVICE_UDID

# Boot a specific simulator
chuk-mcp-ios cli device boot DEVICE_UDID

# Shutdown simulator
chuk-mcp-ios cli device shutdown DEVICE_UDID

Session Management

# Create session with auto-selected device
chuk-mcp-ios cli session create

# Create session with specific device name
chuk-mcp-ios cli session create --device "iPhone 15"

# Create session with specific UDID
chuk-mcp-ios cli session create --udid ABCD-1234-EFGH-5678

# List active sessions
chuk-mcp-ios cli session list

# Terminate session
chuk-mcp-ios cli session terminate session_123

App Management

# List installed apps
chuk-mcp-ios cli app list session_123

# List only user apps (exclude system apps)
chuk-mcp-ios cli app list session_123 --user-only

# Install app from .app bundle
chuk-mcp-ios cli app install session_123 /path/to/MyApp.app

# Launch app by bundle ID
chuk-mcp-ios cli app launch session_123 com.example.myapp

# Terminate running app
chuk-mcp-ios cli app terminate session_123 com.example.myapp

# Uninstall app
chuk-mcp-ios cli app uninstall session_123 com.example.myapp

UI Automation

# Take screenshot
chuk-mcp-ios cli ui screenshot session_123 -o /path/to/screenshot.png

# Tap at coordinates
chuk-mcp-ios cli ui tap session_123 100 200

# Type text (available commands based on your CLI implementation)
chuk-mcp-ios cli ui type session_123 "Hello World"

# Check available UI commands
chuk-mcp-ios cli ui --help

Note: The exact UI commands available depend on your CLI implementation. Check chuk-mcp-ios cli ui --help for the complete list.

Media & Location

# Note: Check available commands with --help first
chuk-mcp-ios cli --help

# Location and media commands may be available under different subcommands
# Check for location commands:
chuk-mcp-ios cli location --help  # if location subcommand exists
chuk-mcp-ios cli media --help     # if media subcommand exists

# If not available via CLI, use Python API:
python3 -c "
from chuk_mcp_ios.core.media_manager import UnifiedMediaManager
media = UnifiedMediaManager()
media.set_location_by_name('your_session_id', 'San Francisco')
"

Finding Available Commands

The CLI structure may differ from this documentation. Always check available commands:

# Discover main command structure
chuk-mcp-ios cli --help

# Check subcommands for each area
chuk-mcp-ios cli device --help
chuk-mcp-ios cli session --help  
chuk-mcp-ios cli app --help
chuk-mcp-ios cli ui --help

# If certain commands aren't available in CLI, they may be:
# 1. Available only via MCP tools
# 2. Available only via Python API
# 3. Named differently than documented

# Example: Check what UI commands actually exist
chuk-mcp-ios cli ui --help
# Output might show: tap, screenshot, type (but not press, swipe, etc.)

Command Alternatives:

# If CLI command doesn't exist, try Python API:
python3 -c "
import asyncio
from chuk_mcp_ios.mcp.tools import ios_press_button
result = asyncio.run(ios_press_button('session_123', 'home'))
print(result)
"

# Or check if it's an MCP-only feature
chuk-mcp-ios mcp  # Start MCP server and use via AI assistant

๐Ÿ“Š Examples & Demos

Run Built-in Demos

# Interactive demo (menu-driven)
python -m chuk_mcp_ios.examples.interactive_demo

# Automated end-to-end demo
python -m chuk_mcp_ios.examples.automated_demo

# MCP server demonstration
python -m chuk_mcp_ios.examples.e2e_mcp_demo

# Web scraping demo (Techmeme)
python -m chuk_mcp_ios.examples.techmeme --auto

Custom Automation Scripts

# examples/custom_automation.py
from chuk_mcp_ios import *

def test_settings_navigation():
    """Test navigating through iOS Settings."""
    with AutomationSession() as session:
        # Launch Settings
        session.launch_app('com.apple.Preferences')
        session.screenshot('settings_main.png')
        
        # Navigate to WiFi
        session.tap_text('Wi-Fi')
        session.screenshot('wifi_settings.png')
        
        # Navigate back
        session.tap_back_button()
        session.screenshot('settings_back.png')

if __name__ == "__main__":
    test_settings_navigation()

๐Ÿ—๏ธ Architecture

chuk-mcp-ios/
โ”œโ”€โ”€ core/                   # Core functionality (device-agnostic)
โ”‚   โ”œโ”€โ”€ base.py            # Base classes and interfaces
โ”‚   โ”œโ”€โ”€ device_manager.py  # Unified device management
โ”‚   โ”œโ”€โ”€ session_manager.py # Session lifecycle management
โ”‚   โ”œโ”€โ”€ app_manager.py     # App installation and control
โ”‚   โ”œโ”€โ”€ ui_controller.py   # UI automation and gestures
โ”‚   โ”œโ”€โ”€ media_manager.py   # Photos, videos, and location
โ”‚   โ”œโ”€โ”€ logger_manager.py  # Logging and crash reports
โ”‚   โ””โ”€โ”€ utilities_manager.py # Misc utilities and settings
โ”œโ”€โ”€ devices/               # Device-specific implementations
โ”‚   โ”œโ”€โ”€ simulator.py       # iOS Simulator support
โ”‚   โ”œโ”€โ”€ real_device.py     # Real device support
โ”‚   โ””โ”€โ”€ detector.py        # Device discovery and detection
โ”œโ”€โ”€ mcp/                   # MCP server implementation
โ”‚   โ”œโ”€โ”€ tools.py          # MCP tool definitions
โ”‚   โ”œโ”€โ”€ models.py         # Pydantic models for validation
โ”‚   โ””โ”€โ”€ main.py           # MCP server entry point
โ”œโ”€โ”€ cli/                   # Command-line interface
โ”‚   โ””โ”€โ”€ main.py           # CLI entry point and commands
โ””โ”€โ”€ examples/              # Usage examples and demos
    โ”œโ”€โ”€ interactive_demo.py
    โ”œโ”€โ”€ automated_demo.py
    โ”œโ”€โ”€ e2e_mcp_demo.py
    โ””โ”€โ”€ techmeme.py

๐Ÿงช Development

Setup Development Environment

# Clone repository
git clone https://github.com/yourusername/chuk-mcp-ios.git
cd chuk-mcp-ios

# Install in development mode with dev dependencies
pip install -e ".[dev]"

# Or with uv
uv sync --dev

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=chuk_mcp_ios

# Run specific test file
pytest tests/test_device_manager.py

# Run integration tests (requires simulators)
pytest tests/integration/ -m "not slow"

Code Quality

# Format code
black src/ tests/

# Sort imports
isort src/ tests/

# Type checking
mypy src/

# Lint
flake8 src/

Adding New Features

  1. Add interfaces to core/base.py
  2. Implement functionality in appropriate core module
  3. Add MCP tool in mcp/tools.py with proper validation
  4. Add CLI command in cli/main.py
  5. Write tests in tests/
  6. Add examples in examples/
  7. Update documentation

๐Ÿค Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Format code (black, isort)
  5. Test thoroughly (pytest)
  6. Commit changes (git commit -m 'Add amazing feature')
  7. Push branch (git push origin feature/amazing-feature)
  8. Open Pull Request

Contribution Guidelines

  • Add tests for new features
  • Update documentation
  • Follow existing code style
  • Add examples for complex features
  • Update changelog

๐Ÿ“„ License

MIT License - see LICENSE file for details

๐Ÿ™ Acknowledgments

  • Apple for iOS Simulator and development tools
  • Facebook for idb (iOS Development Bridge)
  • Anthropic for MCP (Model Context Protocol)
  • Open source community for tools and libraries used

๐Ÿ“ž Support


Made with โค๏ธ for iOS automation and AI integration