@appolabs/appo-mcp
v2.0.1
Published
Local MCP server for the Appo app platform: create, publish and manage native iOS/Android apps from your AI assistant.
Maintainers
Readme
@appolabs/appo-mcp
Local MCP (Model Context Protocol) server for the Appo app
platform. It gives an AI agent the same app lifecycle outcomes as the appo CLI
— create, configure, preview, publish, push, rejection recovery, test builds,
resubmission — plus local code-generation dev-tools for the
@appolabs/appo SDK.
The server carries no API client of its own: every lifecycle call reuses the
CLI core (@appolabs/appo ops/api/config). Tool names mirror the canonical
/mcp AppoServer vocabulary documented in
apps-web-app/docs/CROSS-SURFACE-PARITY.md, so an agent sees one vocabulary
across both MCP surfaces.
Installation
Add to your .mcp.json:
{
"mcpServers": {
"appo": {
"command": "npx",
"args": ["-y", "@appolabs/appo-mcp"]
}
}
}Authentication
The server does not prompt for credentials or hold credential state. It resolves auth exactly as the CLI does, so both surfaces always target the same environment:
appo loginonce. After a device-flow login with the CLI, the token is stored in the active profile (~/.appo/config.json). The server reads it through the shared config module — no extra configuration.APPO_TOKENoverride. SetAPPO_TOKENto supply a PAT directly (CI / non-interactive contexts); it takes precedence over the stored profile token.- Base URL / profile.
APPO_API_BASEenv → the active profile'sapi_base→http://localhost:8002. Profile selection:APPO_ENV→ configcurrent→default.
If no token can be resolved, every lifecycle tool returns a structured
{ error: "not_authenticated", message, next_actions: [] } envelope (it never
crashes) — the message tells the operator to run appo login.
Tools (21)
App lifecycle
Reuse the CLI core; names match the canonical /mcp inventory.
| Tool | Outcome | Gate |
|------|---------|------|
| create_app | Create an app (name, base_url) | — |
| configure_app | Set content fields (name, base_url); content-only, mirrors CLI apps update | — |
| set_icon | Set the app icon from an https icon_url | — |
| list_apps | List the apps owned by the authenticated principal | — |
| get_app_overview | App config, publication state, and metadata in one read; single-app default when app_id is omitted. Start here | — |
| preview_app | Open-on-device payload (iOS TestFlight URL, Android deeplink, QR target, per-platform readiness) | — |
| get_build_status | Poll a build by id until ready/failed | — |
| request_test_build | Trigger a test-kind build for a self-managed app (never the operator-internal publish build) | — |
| get_rejection | Curated required action for a rejected app (never raw reviewer text) | — |
| get_fix_recipe | Code-free remediation recipes for the current rejection | — |
| publish_app | Start publication to the chosen stores | confirm |
| unpublish_app | Remove an app from the chosen stores | confirm |
| send_push | Send a push to the app's devices | confirm |
| trigger_resubmission | Resubmit a rejected app for review (requires a customer-owned Apple credential) | confirm |
There is intentionally no ship tool and no publish-build trigger.
Agents chain create_app → publish_app (and trigger_resubmission for
rejection cycles). The publish-kind build is operator-internal (Nova Release);
only the test build is self-serve.
Local dev-tools
Operate on the local project; no CLI or remote-MCP equivalent by design.
| Tool | Description |
|------|-------------|
| generate_hook | Generate a React hook for an SDK feature |
| generate_component | Generate a UI component with SDK integration |
| scaffold_feature | Scaffold a feature (hook + component + types) |
| validate_setup | Validate SDK installation and configuration |
| check_permissions | Analyze permission-handling patterns |
| diagnose_issue | Diagnose common SDK integration issues |
| generate_universal_links | Emit apple-app-site-association + assetlinks.json with hosting instructions |
Confirm-gate semantics
Destructive tools (publish_app, unpublish_app, send_push,
trigger_resubmission) take an optional confirm: boolean. Without
confirm:true they perform no write and return a preview envelope
({ error: "confirm_required", will, ..., next_actions }) describing what would
happen. This mirrors the CLI's --confirm flag / exit-code-3 semantics at the
MCP idiom layer.
Error envelopes
Errors are returned as structured data, never thrown. Every tool returns
{ error, message, next_actions } (plus status for HTTP errors). HTTP status
maps to a stable code: 401 → not_authenticated, 403 → forbidden,
404 → not_found, 409 → conflict, 422 → validation_error, otherwise
request_failed. Each response carries structuredContent (the canonical
envelope) and a JSON text mirror in content for text-only clients.
Resources & prompts
| URI | Description |
|-----|-------------|
| appo://overview | SDK overview and capabilities |
| appo://api/{feature} | API reference per feature |
| appo://examples/{feature} | Code examples per feature |
| appo://best-practices | Integration best practices |
| appo://troubleshooting | Common issues and solutions |
Prompts: setup_wizard, integrate_feature, debug_assistant.
Features: push, biometrics, camera, location, haptics, storage, share, network,
device.
Breaking changes in 2.0.0
This release adopts the canonical tool vocabulary and the CLI-shared auth chain.
get_appremoved — superseded byget_app_overview(single-call config + publication state + metadata, with a single-app default).update_appsplit intoconfigure_app(content fieldsname/base_urlviaPATCH /apps/{id}) andset_icon(POST /apps/{id}/icon, httpsicon_url).update_app's catch-all field list (splash colors, injected CSS/JS, path fields, …) is gone — webview injection is a dashboard concern and is not on the CLI/MCPconfiguresurface.- Env vars renamed —
APPS_API_URL/APPS_API_TOKENare no longer read. Use the CLI-canonicalAPPO_API_BASE/APPO_TOKEN, or simplyappo loginand let the server read the stored profile.
Development
pnpm install
pnpm build # tsup (ESM + CJS + DTS)
pnpm dev # watch
pnpm typecheck # tsc --noEmit
pnpm test # vitestLicense
MIT
