Expo MCP Server
Supports Android emulator automation for Expo apps, including launching, UI interaction through Maestro tools (tap, input, screenshots), and view hierarchy inspection.
Provides session-based automation for Expo/React Native development including dev server management (start, stop, reload), device binding, and Metro bundler log access for iOS simulator, Android emulator, and web browser targets.
Supports iOS simulator automation for Expo apps, including launching, UI interaction through Maestro tools (tap, input, screenshots), and view hierarchy inspection.
Enables automation of React Native app development through Expo integration, including hot reloading, device management, and UI testing capabilities.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Expo MCP Serverlaunch expo on ios simulator and take a screenshot"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
expo-mcp
MCP server for Expo/React Native app automation with Maestro integration.
Features
Session-Based Architecture:
start_sessionlaunches Expo, binds a device, and acquires a lease — no manual device ID managementDevice Lease with TTL: 2-minute lease auto-renewed on every device tool call; expires after inactivity so other instances can use the device
Cross-Instance Coordination: Multiple MCP instances can run simultaneously without device conflicts
Expo Dev Server Management: Start/stop/reload Expo development server
Maestro Integration: Full UI automation tools (tap, input, screenshot, etc.)
Installation
As a Claude Code Plugin (Recommended)
Install as a plugin to get the MCP server, QA agent, flow writer, and usage guide in one step:
# 1. Add the marketplace source
/plugin marketplace add DaveDev42/expo-mcp
# 2. Install the plugin
/plugin install expo-mcp --scope projectOr from the terminal:
claude plugin marketplace add DaveDev42/expo-mcp
claude plugin install expo-mcp --scope projectThis automatically:
Configures the
expoMCP server (no manual.mcp.jsonneeded)Adds a QA agent (
qa) for automated mobile app testingAdds a flow writer agent (
flow-writer) for creating Maestro YAML test flowsAdds a usage guide skill (
/expo-guide) with tool reference and best practicesAdds a validation hook that warns on QA PASS verdicts without execution evidence
As an MCP Server Only
npx -y expo-mcpWith pnpm:
pnpx expo-mcpUsage with Claude Code
Manual MCP Setup
If not using the plugin, add to your .mcp.json:
{
"mcpServers": {
"expo-mcp": {
"command": "npx",
"args": ["-y", "expo-mcp"]
}
}
}Monorepo Setup
Use a positional argument to specify the app directory:
{
"mcpServers": {
"expo-mcp": {
"command": "npx",
"args": ["-y", "expo-mcp", "apps/mobile"]
}
}
}Specific Device
Pin a specific simulator or emulator with --device-id:
{
"mcpServers": {
"expo-mcp": {
"command": "npx",
"args": ["-y", "expo-mcp", "--device-id=6D192F60-1234-5678-ABCD-000000000000"]
}
}
}Tool Filtering
Exclude specific tools with --exclude-tools:
{
"mcpServers": {
"expo-mcp": {
"command": "npx",
"args": ["-y", "expo-mcp", "apps/mobile", "--exclude-tools=list_devices"]
}
}
}Or expose only specific tools with --tools:
{
"mcpServers": {
"expo-mcp": {
"command": "npx",
"args": ["-y", "expo-mcp", "--tools=start_session,stop_session,take_screenshot"]
}
}
}CLI Reference
Usage: expo-mcp [app-dir] [options]
Arguments:
app-dir Path to Expo app directory (default: cwd)
Options:
--device-id=<id> Specific device to use (iOS simulator UUID or Android serial)
--exclude-tools=tool1,tool2 Exclude specific tools from the MCP server
--tools=tool1,tool2 Only expose specific tools
-h, --help Show help message
-v, --version Show version numberQuick Start
# 1. Start session (launches Expo + binds device + acquires lease)
start_session({ target: "ios-simulator" })
# 2. Use tools directly (no device_id needed!)
take_screenshot()
tap_on({ text: "Login" })
input_text({ text: "hello@example.com" })
press_key({ key: "Enter" })
scroll({ direction: "down" })
swipe({ direction: "left" })
# 3. Run Maestro flows
run_maestro_flow({ flow_yaml: "- assertVisible: Welcome" })
check_maestro_flow_syntax({ flow_yaml: "- tap: Login" })
# 4. Reload app after code changes
reload_app()
# 5. Check logs if needed
get_logs({ level: "error" })
# 6. Stop session when done
stop_session()Plugin Features
When installed as a Claude Code plugin, you get these additional features:
QA Agent
Delegate mobile QA testing to the qa agent. It systematically tests your app on a simulator/emulator with strict evidence requirements — no code-review-only verdicts.
# In Claude Code, delegate to the QA agent:
"Test the login flow on iOS simulator" → delegates to qa agentThe agent follows a structured methodology: launch app → inspect UI → interact → verify → report with PASS/FAIL/INCONCLUSIVE verdict.
Flow Writer Agent
The flow-writer agent inspects the live app and creates Maestro YAML test flows:
# Ask the flow writer to create a test flow:
"Write a Maestro flow for the onboarding sequence" → delegates to flow-writer agentIt validates syntax, executes the flow to verify it works, and writes the .yaml file to your project.
Usage Guide
Access the tool reference and best practices with /expo-guide:
/expo-guide # Full guide
/expo-guide session # Session lifecycle
/expo-guide debugging # Debugging tipsTools
Lifecycle Tools
Tool | Description |
| Get session status (server state, device info, lease remaining time) |
| Start Expo server, connect device, and acquire device lease |
| Stop Expo server and release all resources |
| Hot reload the app on connected device |
| Get Metro bundler logs (filterable by level and source) |
| Press a key (Enter, Backspace, Home, Lock, Tab, Volume Up/Down) |
| Scroll the screen in a direction (default: down) |
| Swipe by direction or precise start/end coordinates |
start_session Options
Option | Type | Description |
|
| Target platform to launch |
| string | Specific device (iOS UUID or Android serial). Auto-detected if omitted |
|
| Connection mode |
| number | Server port (default: 8081, auto-increments if busy) |
| boolean | Clear Metro bundler cache |
| boolean | Development mode (default: true) |
| boolean | Minify JavaScript |
| number | Max Metro workers |
| boolean | Offline mode |
| string | Custom URI scheme |
| string | iOS simulator name (e.g., "iPhone 16 Pro") |
| boolean | Clean simulator state before launch (default: false) |
| object | Run a Maestro flow after app loads ( |
Maestro Tools
All Maestro tools work automatically once a session is active — device_id is injected from the session:
Tool | Description |
| Capture screen (auto-resized for LLM context) |
| Tap on UI element by text, id, or coordinates |
| Type text into focused field |
| Press back button |
| Run Maestro YAML flow inline |
| Run Maestro flow files from project directory |
| Validate Maestro YAML flow syntax without running it |
| Get UI element tree of the current screen |
| List all available devices (works without an active session) |
Note: Device tools require an active session. Call
start_sessionfirst.list_devicesandcheck_maestro_flow_syntaxcan be called anytime.
Device Lease System
The device lease prevents one MCP instance from holding a device indefinitely:
Acquire:
start_sessionacquires a 2-minute device leaseAuto-Renew: Every device tool call (
take_screenshot,tap_on, etc.) resets the 2-minute timerExpire: If no device tool is called for 2 minutes, the lease expires and the device becomes available
Re-acquire: Call
start_sessionagain to re-acquire (server stays running, no restart needed)Check:
get_session_statusshows remaining lease time
Multiple MCP instances coordinate via a file-based registry (/tmp/expo-mcp/instances/), so two instances cannot claim the same device simultaneously.
Environment Variables
Variable | Description | Default |
| Path to Expo app directory (CLI positional arg takes precedence) | Current working directory |
| Path to Maestro CLI |
|
| Comma-separated list of tools to expose ( | All tools |
| Comma-separated list of tools to exclude ( | None |
| Max log lines to keep in memory | 400 |
| Expo authentication token (only needed if offline mode is disabled) | None |
How It Works
Session Start:
start_sessionstarts Expo dev server, waits for device connection, and acquires a leaseDevice Binding: Connected device ID is stored in the session with a 2-minute TTL
Automatic Injection: All Maestro device tools automatically use the session's device ID
Lease Renewal: Every device tool call resets the lease timer
Session End:
stop_sessioncleans up everything, or the lease expires after inactivity
Non-Interactive Environments (CI/CD, AI Agents)
This MCP server automatically enables --offline mode when running in CI environments (CI=1). This allows the app to work without requiring an EXPO_TOKEN.
What Offline Mode Does
Skips Expo server communication (manifest signing)
Does NOT affect your app's network features (API calls, fetch, etc.)
Tunnel mode (
--tunnel) is not available in offline mode
If You Need Expo Account Features
For features requiring Expo authentication, disable offline mode and provide EXPO_TOKEN:
{
"mcpServers": {
"expo-mcp": {
"env": {
"EXPO_TOKEN": "your-token-here"
}
}
}
}Then call start_session with offline: false:
start_session({ target: "ios-simulator", offline: false })Requirements
Node.js >= 18
Xcode (for iOS Simulator)
Android Studio (for Android Emulator)
Maestro CLI (for UI automation)
License
MIT
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DaveDev42/expo-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server