Skip to main content
Glama

phantom-mcp

MCP server that allows Claude Code to see and control iOS simulators, Android emulators, and real devices. 24 tools to test mobile apps without leaving the terminal.

Claude can take screenshots, read the screen, tap, scroll, fill in fields, verify assertions, record videos — automatically, on iOS and Android.

A test report with screenshots is generated automatically at the end of each test session.


Architecture

Claude Code
    | MCP protocol (stdio)
    v
Phantom (Node.js TypeScript)
    |                       |
    v                       v
iOS                      Android
  xcrun simctl             ADB
  WebDriverAgent           UIAutomator
  (localhost:8100)         (adb shell)
    |                       |
    v                       v
Simulateur / iPhone    Emulateur / Device

Related MCP server: Glance

Prerequisites

Tool

Required for

How to check

macOS 13+

all

-

Xcode 15+

iOS

xcode-select -p

Node.js 18+

all

node --version

Appium 3+

iOS (WDA)

appium --version

xcuitest driver

iOS (WDA)

appium driver list --installed

Android SDK

Android

adb version


Installation

# 1. Installer le package
npm install -g phantom-mcp

# 2. Installer Appium + driver iOS
npm install -g appium
appium driver install xcuitest

# 3. Enregistrer dans Claude Code
claude mcp add -s user phantom -- npx phantom-mcp

Option B — from source

git clone https://github.com/nthimpulse/phantom-mcp.git
cd phantom-mcp
npm install
npm run build
claude mcp add -s user phantom -- node "$(pwd)/build/index.js"

The 24 tools

Device management

Tool

Description

list_devices

Lists all devices (iOS sims + Android emus + real devices)

set_device

Selects the active device. Auto-boots if off. Auto-prepares the device (opt-out via skip_setup)

prepare_device

Sets the device to a clean state: clear clipboard / status bar overrides / dismiss keyboard / force QWERTY iOS

Observation

Tool

Description

screenshot

Captures the active device screen

get_ui_tree

Accessibility tree with index [N] for each element

wait_for_element

Waits for an element to appear (with timeout)

scroll_until_visible

Scrolls until an element is found

Assertions

Tool

Description

assert_visible

Verifies that text IS on the screen

assert_not_visible

Verifies that text IS NOT on the screen

Interaction

Tool

Description

tap

Taps (by index, coordinates, or text). Auto-dismisses keyboard if target is obscured

long_press

Long press (context menus)

type_text

Text entry with clear option, and verify option to re-read the value after typing

swipe

Swipe (up/down/left/right)

dismiss_keyboard

Closes the soft keyboard (no-op if not visible)

Navigation

Tool

Description

deep_link

Opens a URL / deep link

Device actions

Tool

Description

shake

Simulates a shake

rotate

Changes orientation (portrait/landscape)

video_record

Starts/stops video recording

App lifecycle

Tool

Description

launch_app

Launches an app by bundle ID / package name

kill_app

Closes an app

Analysis & Automation (Tier 3)

Tool

Description

accessibility_audit

Accessibility audit: missing labels, tap targets too small, images without alt text

test_report

Automatic test report: start to begin tracking, end to generate the markdown. Each action is tracked automatically.

visual_diff

Compares two screenshots pixel by pixel to detect visual regressions

multi_device

Executes the same action on multiple devices in one command


Automatic operation

Device selection

Phantom never boots a device automatically. It asks you to choose:

  1. If only 1 device is active, it uses it automatically

  2. If multiple, it asks you to choose with set_device

  3. If none, it shows you the list of available devices

Auto-launch WDA (iOS)

WebDriverAgent is launched automatically on the first iOS tool that needs it. First launch ~60-90s (Xcode build), then instantaneous.

ADB multi-device (Android)

All ADB commands target the device selected via -s <serial>. No multi-device confusion.

Text entry (AZERTY compatible)

Entry uses pbcopy + Cmd+V (paste) instead of the virtual keyboard. It is instantaneous and works on all keyboard layouts (AZERTY, QWERTY, etc.).

Automatic test report

Each action (tap, type, swipe, assert...) is automatically recorded with a screenshot. At the end of the test, a markdown report is generated in /tmp/phantom-report-xxx/.


Security

  • All system commands go through execFile (no shell)

  • Inputs validated by regex: bundle IDs, UDIDs, package names, AVD names, URLs

  • iOS predicates escaped (anti-injection)

  • Android text escaped for the device shell

  • Zero as any, zero exec() shell


Configuration

Optional environment variables:

  • PHANTOM_WDA_PATH — path to WebDriverAgent (default: ~/.appium/...)

  • PHANTOM_WDA_URL — WDA URL (default: http://localhost:8100)


Contributing

See CONTRIBUTING.md for local setup, the pattern for adding a new tool, naming conventions, and the PR workflow.

See also:


Troubleshooting

WDA crash in a loop

MobAI or another tool is using port 8100.

lsof -i :8100
pkill -f "MobAI"

"No device available"

xcrun simctl list devices available   # iOS
adb devices -l                        # Android

WDA does not start

cd ~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent
xcodebuild -project WebDriverAgent.xcodeproj \
  -scheme WebDriverAgentRunner \
  -destination "platform=iOS Simulator,name=iPhone 17 Pro" \
  test

ADB not found

ls ~/Library/Android/sdk/platform-tools/adb

Project structure

phantom/
  src/
    index.ts                Point d'entree MCP (24 tools)
    platforms/
      types.ts              Interfaces communes
      ios/
        simctl.ts            Wrapper xcrun simctl
        wda.ts               Client WDA + auto-launch
      android/
        adb.ts               Wrapper ADB complet
    tools/                   24 tools (21 fichiers)
    utils/
      device-manager.ts      Detection + routing multi-device
      xml.ts                 Parser XML partage
  docs/
    README.md               Ce fichier
    TUTORIAL.md             Tuto pas-a-pas
    FLOWS.md                Exemples de flows de test

Available Tools

24 tools
accessibility_auditA

Verifie l'accessibilite de l'ecran actuel : labels manquants, tap targets trop petits, images sans alt text. Retourne un rapport de violations.

Inputs: no named parameters.

assert_not_visibleA

Vérifie qu'un élément contenant le texte donné n'est PAS visible à l'écran.

Inputs: text (required).

assert_visibleA

Vérifie qu'un élément contenant le texte donné est visible à l'écran. Retourne OK ou FAIL avec les éléments actuellement visibles.

Inputs: text (required).

dismiss_keyboardA

Ferme le clavier sur le device actif (iOS et Android). No-op si pas de clavier visible. À utiliser après un type_text quand le clavier bloque les boutons en bas.

Inputs: no named parameters.

get_ui_treeA

Retourne l'arbre d'accessibilité de l'écran — tous les éléments visibles avec type, texte, position. Fonctionne sur iOS et Android. Chaque élément a un index [N] utilisable avec tap.

Inputs: no named parameters.

kill_appB

Ferme une app sur le device actif.

Inputs: bundle_id (required).

launch_appB

Lance une app sur le device actif. iOS : bundle ID (ex: com.monapp.ios). Android : package name (ex: com.monapp.android).

Inputs: bundle_id (required).

list_devicesA

Liste tous les devices disponibles — simulateurs iOS, émulateurs Android, et vrais devices connectés. Affiche la plateforme et l'état de chaque device.

Inputs: no named parameters.

long_pressA

Appui long sur un élément de l'écran. Utile pour les menus contextuels, drag & drop, ou actions secondaires.

Inputs: index, x, y, text, +1 more.

multi_deviceA

Execute la meme action sur plusieurs devices et retourne les resultats combines. Utile pour tester sur iOS + Android en une seule commande.

Inputs: device_ids (required), action (required), bundle_id.

prepare_deviceA

Prépare le device actif pour une session de test propre : dismiss keyboard, clear clipboard, reset status bar overrides, force keyboard QWERTY (iOS). Tout est opt-out via flags. Auto-appelé par set_device sauf si skip_setup=true.

Inputs: dismiss_keyboard, clear_clipboard, clear_status_bar, force_qwerty.

rotateB

Change l'orientation de l'écran du device (portrait ou landscape).

Inputs: orientation (required).

screenshotA

Prend un screenshot du device actif (iOS ou Android) et le retourne comme image.

Inputs: no named parameters.

scroll_until_visibleA

Scroll vers le bas (ou la direction choisie) jusqu'à trouver un élément contenant le texte donné. Retourne l'élément trouvé ou une erreur après max_scrolls.

Inputs: text (required), direction, max_scrolls.

set_deviceA

Sélectionne le device à utiliser pour cette session de test. Si le device est éteint, il sera démarré automatiquement. Appelle list_devices d'abord pour voir les IDs. Auto-prépare le device (clear clipboard/status bar, dismiss keyboard, force QWERTY iOS) — opt-out via skip_setup=true.

Inputs: device_id (required), skip_setup.

shakeA

Simule un geste de shake sur le device. iOS : via raccourci Simulator (Ctrl+Cmd+Z). Android : swipes rapides.

Inputs: no named parameters.

swipeB

Fait un geste de swipe sur l'écran. Fonctionne sur iOS et Android.

Inputs: direction (required), distance.

tapB

Tape sur un élément de l'écran. Fonctionne sur iOS et Android. Utilise index (du get_ui_tree), coordonnées (x,y), ou texte. Auto-dismiss le clavier si la cible est physiquement masquée par lui (sécurité, pas de retap nécessaire).

Inputs: index, x, y, text, +1 more.

test_reportA

Gère le rapport de test automatique. Le rapport démarre AUTOMATIQUEMENT dès la première interaction (tap, type_text, etc.) — tu n'as PAS besoin d'appeler 'start'. Appelle UNIQUEMENT action='end' quand tu as fini de tester pour générer le rapport markdown. Si tu veux nommer le rapport, appelle action='start' avec un nom AVANT de commencer.

Inputs: action (required), name.

type_textA

Écrit du texte dans un champ. Fonctionne sur iOS et Android. Peut cibler un champ par son label/texte. Avec verify=true (opt-in), re-lit le champ après le type pour détecter les pickers d'autocomplete qui interceptent les keystrokes.

Inputs: text (required), element_text, clear_first, verify.

video_recordA

Enregistre une vidéo de l'écran du device. Utilise action='start' pour commencer et action='stop' pour arrêter et récupérer le fichier.

Inputs: action (required).

visual_diffA

Compare deux screenshots pour detecter des regressions visuelles. action='snapshot' pour sauver une reference, action='compare' pour comparer avec la reference.

Inputs: action (required), name, threshold.

wait_for_elementA

Attend qu'un élément apparaisse à l'écran (utile après navigation ou chargement). Retourne l'élément trouvé ou une erreur après timeout.

Inputs: text (required), timeout, interval.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 24 tools

    Disambiguation5/5

    Each tool targets a distinct action: tap, long_press, swipe, type_text, etc. Even similar tools like assert_visible and assert_not_visible are clearly opposites. No functional overlap.

    Naming Consistency4/5

    All tool names use lowercase snake_case, with a mix of verb-first and noun-first constructions (e.g., 'accessibility_audit' vs 'assert_visible'), but the pattern is largely predictable and readable.

    Tool Count4/5

    24 tools is slightly high but well-scoped for mobile testing: device management, UI interaction, assertions, visual testing, reporting, and gestures are all covered. Each tool has a clear purpose.

    Completeness4/5

    The set covers core workflows: device setup, UI queries, interactions, assertions, screenshots/video, and reporting. Missing explicit drag-and-drop or back navigation, but swipe and long_press compensate.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      An MCP server that lets AI agents drive real mobile-app automation on connected devices, enabling natural-language test tasks, test case generation, and app/build management for Android and iOS.
      -
    • A
      license
      Not graded
      quality
      A
      maintenance
      An MCP server that gives Claude Code a real browser, enabling it to navigate, click, type, screenshot, and inspect web pages during development. It also supports multi-step JSON test scenarios, assertions, session recording, and visual regression testing against web apps.
      106 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      An MCP server that gives Claude Code a real browser, enabling navigation, clicking, form filling, screenshots, and accessibility snapshots directly from the terminal. It also supports multi-step JSON test scenarios, assertions, session recording, and visual regression testing with network and console monitoring.
      106 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      An MCP server that gives Claude Code a real browser, enabling it to navigate pages, click, type, capture screenshots, run multi-step test scenarios with assertions, and monitor console and network activity directly from the terminal.
      106 npm
      MIT