aipps.dev

MCP server and email-code sign-up

An AI agent or a script can do everything a person does on aipps.dev: make an account, add an app, start a build, read the log and hand back the install page with its QR code. No browser and no password. Builds use the account and the store keys of the person who owns the app.

Sign up with an email code

Send an email address and aipps.dev emails a 6-digit code. Send the email and the code back and you get a session key. A new email gets a free account right there; an email that already has one signs in to it, and the same account opens in the console later.

curl -s https://aipps.dev/api/auth -H 'content-type: application/json' \
  -d '{"email":"you@example.com"}'
# {"otp_sent": true, "expires_in_seconds": 600, ...}

curl -s https://aipps.dev/api/auth -H 'content-type: application/json' \
  -d '{"email":"you@example.com","otp":"123456"}'
# {"session_key": "ais_...", "token_type": "Bearer", "expires_at": "...", "email": "you@example.com"}
  • Send the key as Authorization: Bearer ais_… on every later call, REST or MCP. It lasts 30 days.
  • Codes last 10 minutes and allow 5 tries; at most 3 codes per email in 15 minutes.
  • Already have an API key (ak_…, from the console under Keys)? Send it as X-Api-Key or as the Bearer token, or trade it: {"api_key":"ak_..."}.
  • Sign out: POST /api/auth/logout with the session key in Authorization.
  • The address needs a real mailbox: throwaway email domains are refused.

MCP server

https://aipps.dev/api/mcp speaks the Model Context Protocol over Streamable HTTP (JSON-RPC 2.0 on POST; protocol versions 2024-11-05, 2025-03-26 and 2025-06-18). initialize and tools/list need no sign-in, so an agent can find the tools first and call auth to sign up. Agents that use plain function calling can read the same tools as JSON schemas at /api/mcp/schema.

Client setup

Most MCP clients take a block like this in their settings (the file name depends on the client):

{
  "mcpServers": {
    "aipps": {
      "url": "https://aipps.dev/api/mcp",
      "headers": { "Authorization": "Bearer ak_your_api_key" }
    }
  }
}

Leave out headers to start signed out: the agent calls auth with your email, asks you for the code, and sends the session key it gets back. Clients that can't set headers can use that path too.

curl

curl -s https://aipps.dev/api/mcp -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

curl -s https://aipps.dev/api/mcp -H 'content-type: application/json' \
  -H 'Authorization: Bearer ais_...' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"start_build","arguments":{"app":"checklists","platform":"android"}}}'

A tool result comes back as text holding JSON in result.content[0].text. When a call fails the result has isError: true and the text is {"error", "status", "message"}, for example wrong_code or 401 when you aren't signed in.

Tools

ToolArguments (* required)What it does
authemail, otp, api_keySign up or sign in. {email} emails a 6-digit code; {email, otp} returns a session key. Or trade an API key for one.
get_pricing–Free builds a day, what a build pack adds, build size classes. No sign-in needed.
get_account–Email, build packs and today's usage (allowance, counted, pending, left).
list_apps–Your apps: slug, name, framework, iOS bundle id, Android package.
create_appname*, slug, framework, ios_bundle_id, android_packageAdds an app. Do it once per project; start_build takes its slug.
start_buildapp*, platform*, profile, message, submitStarts a build and returns upload_url: PUT the project .tar.gz there and it joins the queue.
list_buildsapp, limitRecent builds, newest first.
get_buildbuild_id*Status (waiting_source, queued, running, succeeded, failed, canceled); install_url and qr_url once it has succeeded.
get_build_logsbuild_id*, offsetLog text from offset; call again with next_offset until done is true.
cancel_buildbuild_id*Stops a build. Nothing is counted if it hadn't started.
list_updatesapp*, channelAn Expo app's over-the-air updates, newest first, and url for app.json updates.url. Publishing is npx aipps update.
rollback_updateapp*, channel, to, runtime_version, platform, messageto=embedded (needs runtime_version): back to the bundle inside the build. to=<update or group id>: publish it again, or promote it to another channel.

A build, step by step

  1. auth with the person's email, then again with the code they read out (or use their API key).
  2. create_app once with the app's name, framework and bundle id / package.
  3. start_build with the slug and android or ios.
  4. Pack the project as one .tar.gz (git-tracked files, no node_modules, no .env or keys) and PUT it to upload_url with the same Authorization header. Or run npx aipps build in the project instead of steps 3 and 4.
  5. get_build every 20 to 30 seconds (or follow get_build_logs) until the status is succeeded, then give the person install_url. A failed build's error says why.

Signed iPhone builds and store uploads use the owner's own App Store Connect key and Play service account, kept encrypted on the app (see iPhone builds). aipps.dev never asks for an Apple or Google password.

Errors and limits

MCP builds count like any other build: 3 a day are free across all your apps, and a build pack adds more (see get_pricing or the pricing page). A build that would go over today's allowance is refused with a message saying so; nothing is counted for builds that never start.