Skip to main content
Glama
lilingxi01

app-store-connect-mcp

by lilingxi01
README.md
# app-store-connect-mcp

A small, dependency-free local [MCP](https://modelcontextprotocol.io) server for **App Store Connect / TestFlight**. It lets an agent list your apps and beta groups and **add / remove TestFlight beta testers by email**, authenticating with an **individual App Store Connect API key** (a `.p8`) via an ES256 JWT.

Raw JSON-RPC over stdio, no npm dependencies (pure Node `crypto` + `fetch`), a `.env` for config, and plugin manifests for Cursor / Codex.

## What it does

Tools:

| Tool | Description |
|------|-------------|
| `list_apps` | List apps (id, name, bundleId). Find your `appId` here. |
| `list_beta_groups` | List TestFlight beta groups for an app. |
| `list_beta_testers` | List beta testers, optionally filtered by group or email. |
| `add_beta_tester` | Add one tester (by email) to one or more beta groups. |
| `add_beta_testers_bulk` | Add many testers to a single group; per-email success/failure. |
| `remove_beta_tester` | Remove a tester from a group by email. |

Adding a tester triggers Apple's TestFlight invite email.

## Setup

1. **Generate an individual API key** in App Store Connect:
   top-right username → **Edit** → **Individual API Key** → **Generate Key**.
   Download the `.p8` **once** and store it safely (e.g. `~/.appstoreconnect/AuthKey_XXXX.p8`).
   Note the **Key ID** shown next to the key.

2. **Create `.env`** (copy from `.env.example`):

   ```dotenv
   APP_STORE_CONNECT_P8_PATH=~/.appstoreconnect/AuthKey_XXXXXXXXXX.p8
   APP_STORE_CONNECT_KEY_ID=XXXXXXXXXX
   # optional, so you don't pass appId every call:
   # APP_STORE_CONNECT_APP_ID=1234567890
   ```

   Individual keys sign the JWT with `sub: "user"` and **no** issuer id.
   Only set `APP_STORE_CONNECT_ISSUER_ID` if you're using a **team** key instead.

3. **Register the server** with your MCP client. For Cursor, point it at `mcp.json`
   (stdio, `command: ./bin/app-store-connect-mcp`, `envFile: .env`).

## Runtime

This server runs on [Bun](https://bun.sh). The `bin/app-store-connect-mcp` launcher execs a
project-local `vendor/bun` if present, otherwise `bun` on your `PATH`. No `npm install` /
`bun install` needed — there are no dependencies (just Bun's built-in crypto + fetch).

Don't have Bun? Either install it from [bun.sh](https://bun.sh) or vendor a
copy into the repo with `npm run install:bun` (downloads Bun into `vendor/bun/`).

## Test it

```bash
bun scripts/mcp-call.mjs tools/list '{}'
bun scripts/mcp-call.mjs list_apps '{}'
bun scripts/mcp-call.mjs list_beta_groups '{"appId":"1234567890"}'
bun scripts/mcp-call.mjs add_beta_tester '{"email":"tester@example.com","betaGroupIds":["<groupId>"]}'
```

## Security notes

- The `.p8` never leaves your machine; it's read locally only to sign the JWT sent to Apple.
- `.env` and `*.p8` are gitignored.
- The only network destination is `https://api.appstoreconnect.apple.com`.
- Individual keys can't touch provisioning, sales/finance, or `notaryTool` — TestFlight management works fine.