Appo MCP
Official# @appolabs/appo-mcp
> **Retired.** The Appo MCP is the remote connector served by Appo itself: `https://apps.goappo.io/mcp`.
> Register it with `npx @appolabs/appo mcp`, or add it as an HTTP MCP server in your client
> (`claude mcp add --transport http appo https://apps.goappo.io/mcp`, `codex mcp add appo --url https://apps.goappo.io/mcp`).
> This package is no longer maintained.
Local MCP (Model Context Protocol) server for the [Appo](https://goappo.io) 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](https://github.com/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`:
```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:
1. **`appo login` once.** 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.
2. **`APPO_TOKEN` override.** Set `APPO_TOKEN` to supply a PAT directly (CI /
non-interactive contexts); it takes precedence over the stored profile token.
3. **Base URL / profile.** `APPO_API_BASE` env → the active profile's `api_base`
→ `http://localhost:8002`. Profile selection: `APPO_ENV` → config `current` →
`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 (20)
### 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` | — |
| `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). Build triggering is not exposed: the `store-publish`-kind build
is operator-internal (Nova Release), and self-serve verification is via `preview_app`
(the managed preview).
### 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_app` removed** — superseded by `get_app_overview` (single-call config +
publication state + metadata, with a single-app default).
- **`update_app` split** into `configure_app` (content fields `name`/`base_url`
via `PATCH /apps/{id}`) and `set_icon` (`POST /apps/{id}/icon`, https
`icon_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/MCP `configure` surface.
- **Env vars renamed** — `APPS_API_URL` / `APPS_API_TOKEN` are no longer read.
Use the CLI-canonical `APPO_API_BASE` / `APPO_TOKEN`, or simply `appo login`
and let the server read the stored profile.
## Development
```bash
pnpm install
pnpm build # tsup (ESM + CJS + DTS)
pnpm dev # watch
pnpm typecheck # tsc --noEmit
pnpm test # vitest
```
## License
MIT
TDQS
Scored across 21 tools
Some tools have clear boundaries (create_app, list_apps, set_icon), but several overlap in purpose: generate_hook, generate_component, and scaffold_feature all produce SDK integration code, and diagnose_issue, get_fix_recipe, and get_rejection all deal with app rejection/diagnosis. The descriptions help somewhat, but an agent could easily confuse generate_hook with generate_component or diagnose_issue with get_fix_recipe.
Most tools follow a consistent verb_noun pattern (validate_setup, generate_hook, list_apps, configure_app, set_icon, publish_app, get_app_overview, send_push). Minor deviations exist: trigger_resubmission and generate_universal_links are longer but still verb-based, and scaffold_feature is a verb_noun pair. Overall the pattern is predictable.
21 tools is on the higher end but reasonable for a server covering both SDK code generation and app lifecycle management. The count is slightly heavy, but each tool addresses a distinct aspect of the Appo platform, and the two clusters (code generation vs. app management) justify the size.
The server covers the core app lifecycle well: create, list, configure, set icon/permissions, publish, unpublish, preview, build status, rejection handling, and push. Minor gaps exist: there's no delete_app or update_app (only configure_app for content fields), and no tool for managing team members or viewing analytics. The code generation side is also somewhat redundant but complete.