An MCP server that gives Claude real access to the App Store Connect API: read your listings, audit every localization, upload screenshots for a dozen languages in one call, submit for review, manage pricing and answer customer reviews — without leaving the conversation.
222 tools — complete coverage of every App Store Connect API operation that matters for shipping an app: listings and localizations, screenshots and previews, review submission and review details, phased release, customer reviews, pricing, in-app purchases and subscriptions (availability, introductory and promotional offers, offer codes, App Review screenshots), app metadata (categories, age rating, EULA, export compliance), TestFlight and Beta App Review, sandbox testers, product page optimization (A/B tests), custom product pages, in-app events, promoted purchases, pre-orders, App Clips, team members, territories and code signing.
Game Center, Xcode Cloud/CI, alternative distribution and analytics report requests are deliberately out of scope — past roughly 200 tools a model's tool selection starts to degrade, and those families do not serve app releases.
Doing App Store release work by hand means clicking through the same forms once per
language, per device size, per app. The API can do all of it, but its resource model is
unfriendly — prices hide behind opaque appPricePoint ids, screenshots need a
three-step reserve/upload/commit dance, and half the useful filters are undocumented.
This server hides that. You give it a price in euros and a country code; it finds the price tier. You give it a directory of PNGs; it validates the dimensions, creates the sets and uploads them in the right order.
git clone https://github.com/abdouldotdev/appstore-connect-mcp.git
cd appstore-connect-mcp
npm install && npm run buildCreate a .env next to the server (see .env.example):
APPLE_KEY_ID=ABC123DEFG
APPLE_ISSUER_ID=00000000-0000-0000-0000-000000000000
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
...contents of your AuthKey_XXXXXX.p8...
-----END PRIVATE KEY-----"
APPLE_BUNDLE_ID=com.example.appGenerate the key at App Store Connect → Users and Access → Integrations → App Store
Connect API. The .p8 file downloads only once. An App Manager + Sales and Reports
key covers everything except the code signing tools, which need Admin or
Developer.
Register the server (the cd matters — credentials are read from the working
directory):
claude mcp add appstore-connect -s user -- \
sh -c 'cd /absolute/path/to/appstore-connect-mcp && exec node dist/index.js'| Area | Highlights |
|---|---|
| Diagnostics | get_app_release_status answers "where do I stand?" — version, state, attached build, in-flight submission, phased release, and the next action to take |
| Localizations | List every locale with its id, read any listing with per-field character counts against Apple's limits, diagnose which locales block submission |
| Screenshots | Batch upload from <dir>/<locale>/<DISPLAY_TYPE>/*.png, with local dimension validation before anything is sent, and cleanup of the reservation if an upload fails |
| Submission | Modern reviewSubmissions API, one-shot submit, phased release control, manual release |
| Reviews | Filter unanswered reviews, rating distribution and trend, publish or bulk-publish responses |
| Pricing | Give a price in currency, the server resolves Apple's price tier; schedule promotions; add or remove territories without re-listing all 175 |
| Code signing | Certificates, bundle ids, capabilities, devices, profiles, plus a health check for what expires soon |
This server can take actions that are public and irreversible. Three things guard that:
confirm: trueis required on every destructive, public or irreversible tool — submitting to review, releasing, changing prices, delisting territories, replying to reviews, revoking certificates. Without it the tool refuses and explains what it would have done.bulk_respond_to_reviewsreturns a full dry run.- stdio by default. No network port is opened. The optional HTTP transport
(
TRANSPORT=http) refuses to bind a non-loopback interface unless OAuth orMCP_HTTP_TOKENis configured. - Nothing about your key is logged. All diagnostics go to stderr, redacted.
Apple's published specification and its live service disagree in places. These were found by running against production, and each one costs a debugging round if you meet it cold. They are not bugs in this server, and no retry fixes them.
Documented but not served — the tools say so instead of returning a bare 404:
| Endpoint | Reality |
|---|---|
/v1/promotedPurchaseImages |
Collection, resource and the promotionImages relationship all 404. A promotion image can only be set in App Store Connect by hand — and Apple then refuses to delete a promoted purchase that has one, so a promotion created through the API can become removable only from the console. |
/v1/appPriceTiers |
Retired. Use price points (list_app_price_points, set_app_price). |
/v1/builds/{id}/buildBundles |
No such relationship; bundles come only as an include on the build. |
Required despite being marked optional:
- Introductory offers require
territory. There is no worldwide introductory offer — a worldwide free trial is one offer per territory, which is whysubscription_introductory_offer_createacceptsterritory: "ALL"and fans out. - Custom product pages require the version and its first localization inline in the same POST.
- Beta App Clip invocations require a localization inline in the same POST.
Attributes that moved:
- Age rating:
seventeenPlusis gone, replaced byageRatingOverrideV2. The API returns a dozen descriptors the specification omits (advertising,lootBox,messagingAndChat,userGeneratedContent, …). - In-app event assets are the only media family that rejects
sourceFileChecksumon commit; they takeuploadedalone.
Server-side behaviour to expect:
GET /v1/buildBetaDetails?filter[build]=answers HTTP 500 for some builds./v1/builds/{id}/buildBetaDetailworks and is what this server uses./v1/actorsrequiresfilter[id]— actors can be resolved, never enumerated.limitis rejected on custom product page localizations and on v2 experiment treatments.- Experiment treatment locales are seeded asynchronously; POSTing one that has just been seeded answers 500, not 409.
- In-app event resources answer a transient
403 The API key in use does not allow this requestfor a few seconds after a write, on paths the same key serves fine otherwise. Retrying clears it. - App Review screenshots always come back with
fileName: "SOURCE".
Out of scope by choice: Game Center, Xcode Cloud / CI, SCM, alternative distribution, marketplaces, background assets, analytics report requests and diagnostic signatures. Every other operation in the specification that serves an app release is covered.
Not possible at all: Apple does not accept binary uploads over the REST API. That
needs xcodebuild -exportArchive -destination upload or Transporter, then polling
GET /v1/builds. It is a capability gap, not a coverage gap.
Tools live in src/tools/, one module per domain, collected in a registry that fails
loudly on duplicate names. Adding one means creating a file and adding a line. See
CONTRIBUTING.md.
Apple publishes an OpenAPI specification for this API, vendored here as 3.2.json.
It is the fastest way to settle a question about a payload shape — but see the
limitations below before trusting it: on this API the specification and the live
service disagree often enough that the server has to be the authority.
(.gitignore still lists 3.2.json from an earlier decision not to vendor it. The
file was committed first, so the rule never applied — the spec ships with the repo.)
Verified against a live account with 19 apps. Read paths are exercised across it; the write paths are exercised too, in create → verify → delete round trips that restore the starting state — subscriptions, offers, localizations, screenshots and other media uploads, review details and attachments, custom product pages, in-app events, product page experiments, promoted purchases and TestFlight metadata.
Not exercised against production, and flagged as such in their descriptions: anything
that is public and irreversible (submitting to review, releasing a version, ending a
pre-order, removing a user) and anything requiring an account state this one does not
have. Every one of those is guarded by confirm.
Built on the foundation of ryaker/appstore-connect-mcp, itself derived from earlier work by Joshua Riley. The JWT authentication approach comes from that lineage; the transport, the tool registry and the large majority of the tools are new.
MIT licensed — see LICENSE for the full copyright chain.