@alivelabs/expo-orchestrator-mcp
v0.2.1
Published
Model Context Protocol server exposing the Expo CI Orchestrator API to AI agents (build, drive, screenshot iOS simulator sessions).
Readme
@alivelabs/expo-orchestrator-mcp
A Model Context Protocol server that exposes the
Expo CI Orchestrator API to AI agents. It is a thin client of the orchestrator's
REST API — point it at a running API and give it the master token, and an agent can
build iOS apps, drive the simulator (taps/swipes/typing, or tap an element by its
React Native testID), inspect the accessibility tree, and take screenshots.
Transport is stdio, so an MCP host spawns it as a subprocess.
Configuration
Two environment variables:
| Var | Required | Default | What |
|-----|----------|---------|------|
| EXPO_CI_API_TOKEN | ✅ | — | The orchestrator's master API token (API_TOKEN). |
| EXPO_CI_API_URL | | http://localhost:3000 | Orchestrator base URL. |
Run
EXPO_CI_API_TOKEN=… bun run --filter '@alivelabs/expo-orchestrator-mcp' startRegister with an MCP client
Most clients take a command + args + env. Example (Claude Desktop / VS Code / Cursor all use this shape):
{
"mcpServers": {
"expo-ci": {
"command": "bun",
"args": ["/ABSOLUTE/PATH/alive-expo-orchestrator/apps/mcp/src/index.ts"],
"env": {
"EXPO_CI_API_TOKEN": "…",
"EXPO_CI_API_URL": "http://localhost:3000"
}
}
}
}Tools
| Tool | Purpose |
|------|---------|
| list_simulators | List bootable simulators + the recommended default. |
| create_session | Create a build session. Source: git / tarball / local. Options: simulatorName (default: recommended), appRoot (monorepo subdir), devServerUrl (⇒ Debug dev-client; omit ⇒ Release with the bundle embedded), env (extra build-time env vars, e.g. EXPO_PUBLIC_* / IOS_GOOGLE_MAPS_API_KEY). Uploads the tarball when sourceType=tarball. |
| start_session | Start the build (prebuild + xcodebuild + boot + install + launch). |
| get_session | Current status / timing / error. |
| get_logs | Trailing build/run logs. |
| screenshot | Current simulator screen as a JPEG image the agent can see. |
| tap / swipe / type_text / press_button | Drive the simulator (tap/swipe coordinates are in screenshot pixels). |
| tap_by_test_id | Tap the element whose React Native testID matches — resolved via the accessibility tree, no coordinates needed. |
| describe_ui | Dump the frontmost app's accessibility tree as JSON (each node's identifier is its testID, frame its on-screen rect). |
| create_viewer_token | Mint a session-scoped token for an end user (view + drive their session only). |
| delete_session | Tear down the session. |
create_session env vars
env is a map of extra environment variables exposed to the build (names must be
valid shell identifiers; ≤ 100 vars, values ≤ 8 KB). They're applied before the
orchestrator's curated env, so they can never override controlled vars (PATH,
BUILD_DIR, secrets, …). Use them for values your app reads at build time:
EXPO_PUBLIC_*→ embedded into the JS bundle by Metro.- Native config read by a dynamic
app.config.js/.tsduring prebuild — e.g.IOS_GOOGLE_MAPS_API_KEYconsumed viaios.config.googleMapsApiKey: process.env.IOS_GOOGLE_MAPS_API_KEY. (Staticapp.jsoncan't read env; useapp.config.js.)
These are not treated as secrets and may appear in verbose build logs; the orchestrator's
secrets field (npm token / Apple team / signing cert) is the never-logged path.
Typical agent flow
list_simulators→ pick asimulatorName(or omit to use the recommended one).create_session(e.g.sourceType: "git",repoUrl, optionalappRoot/devServerUrl/env).start_session→ then pollget_sessionuntilcompleted(useget_logson failure).- See the app with
screenshot; drive it withtap_by_test_id(preferred — usedescribe_uito discovertestIDs) or coordinatetap/type_text/swipe. - Optionally
create_viewer_tokento hand a human a live view;delete_sessionwhen done.
Security
The server holds the master token — full control of all sessions. Keep it to the
trusted host running the agent; hand end users a scoped token from create_viewer_token
instead. A scoped token may only view + drive its own session (status, logs,
screenshot, accessibility tree, input, tap-by-testID) — never create, start, delete,
upload source, or mint further tokens. stdout is reserved for the MCP protocol; all
diagnostics go to stderr.
