Skip to main content
Glama
App Store Connect MCP

App Store Connect MCP

by swlittles

App Store Connect MCP

An MCP server that lets coding agents (Claude Code, Cursor, Codex and others) manage your apps in App Store Connect: TestFlight builds and testers, the store listing, screenshots, subscriptions, App Review submission, customer reviews and sales reports.

Apple doesn't ship an MCP server for App Store Connect. Xcode's xcrun mcpbridge covers building, testing and previews, not App Store Connect. Most community servers expose one tool per REST endpoint and leave the agent to chain them correctly. This one is built differently:

  • Workflows as tools. "Ship this build to these groups with these notes" is one call, and so is "replace screenshot 3". The server handles the ordering, the waiting and the edge cases that agents get wrong.

  • Safe by default. The server is read-only until you set ASC_WRITE=1. Anything destructive is a dry run until the agent confirms it, and the docs recommend a least-privilege API key.

  • Reliable. Every step checks the current state first, so you can re-run a tool after a timeout or a dropped connection. Tools poll Apple's asynchronous processing, back off on rate limits, and return errors that say what to do next.

Status: 0.1. Every tool is tested against an in-memory App Store Connect that checks each request against Apple's OpenAPI spec (v4.5). The workflows have also been run against a real App Store Connect account on a sandbox app: build upload through the API, distribution, groups and testers, listing edits, the whole screenshot lifecycle (including a full set of 10 and an image Apple rejects), version prep and the review pre-flight. Submitting to App Review and Beta App Review was only dry-run, because those send the app to Apple. Please report anything that behaves differently for you.

Quick start

1. Create an API key with the App Manager role. In App Store Connect, go to Users and Access > Integrations > App Store Connect API > Team Keys and generate a key with App Manager access. Never use Admin. Download the .p8 file (Apple only lets you download it once), and note the Key ID and the Issuer ID. The full walkthrough, including where to keep the key, is in docs/api-key.md.

2. Download and build it. You need Node.js 20 or later and git.

git clone https://github.com/swlittles/app-store-connect-mcp.git ~/app-store-connect-mcp
cd ~/app-store-connect-mcp
npm ci                 # installs the exact locked dependencies and builds dist/index.js

You can clone it anywhere. The examples below assume ~/app-store-connect-mcp.

3. Check the key:

ASC_KEY_ID=YOUR_KEY_ID ASC_ISSUER_ID=YOUR_ISSUER_ID ASC_KEY_PATH=~/.appstoreconnect/AuthKey_YOUR_KEY_ID.p8 \
  node ~/app-store-connect-mcp/dist/index.js --check

It lists the apps the key can see.

4. Add it to your agent. Point the agent at dist/index.js, using absolute paths.

Claude Code:

claude mcp add asc --scope user \
  -e ASC_KEY_ID=YOUR_KEY_ID \
  -e ASC_ISSUER_ID=YOUR_ISSUER_ID \
  -e ASC_KEY_PATH=$HOME/.appstoreconnect/AuthKey_YOUR_KEY_ID.p8 \
  -- node $HOME/app-store-connect-mcp/dist/index.js

Add -e ASC_WRITE=1 when you want the agent to make changes, and -e ASC_APP_ID=com.example.app to set a default app.

Cursor (~/.cursor/mcp.json) and other clients that use the mcpServers JSON format:

{
  "mcpServers": {
    "asc": {
      "command": "node",
      "args": ["/Users/you/app-store-connect-mcp/dist/index.js"],
      "env": {
        "ASC_KEY_ID": "YOUR_KEY_ID",
        "ASC_ISSUER_ID": "YOUR_ISSUER_ID",
        "ASC_KEY_PATH": "/Users/you/.appstoreconnect/AuthKey_YOUR_KEY_ID.p8"
      }
    }
  }
}

Codex (~/.codex/config.toml):

[mcp_servers.asc]
command = "node"
args = ["/Users/you/app-store-connect-mcp/dist/index.js"]
env = { ASC_KEY_ID = "YOUR_KEY_ID", ASC_ISSUER_ID = "YOUR_ISSUER_ID", ASC_KEY_PATH = "/Users/you/.appstoreconnect/AuthKey_YOUR_KEY_ID.p8" }

Updates are automatic. Each time your agent starts the server, the server checks GitHub for a newer release (at most every 30 minutes) and installs it in the background. The update is used from the next time the agent starts the server; the running server isn't interrupted. See Updates.

Trying it without cloning: npx -y github:swlittles/app-store-connect-mcp --check (with the same environment variables) downloads and builds it in npm's cache. That's fine for a quick try. For everyday use, clone it: npx rebuilds on first launch, which can be slower than an agent waits for a server to start.

This project is distributed only through GitHub. It isn't published to npm, so a package with this name on npm isn't this project.

Then ask for things in plain language:

  • "What's the status of my app? Is the latest build ready for testers?"

  • "Ship build 202610041200 to the Friends and Public Beta groups with the notes 'New daily puzzles, please try the hint button'."

  • "Replace the third iPhone screenshot with ~/Desktop/shot-3.png."

  • "Upload everything in ./fastlane/screenshots/en-US/iphone as the 6.9-inch iPhone screenshots."

  • "Remove the free trial from the yearly subscription in every country."

  • "Reply to this week's 1-star reviews."

  • "Create version 1.2, attach the latest build, update What's New, and show me what's missing before we submit."

Related MCP server: App Store Connect MCP Server

Configuration

Variable

ASC_KEY_ID

API key ID. Required.

ASC_ISSUER_ID

Issuer ID for team keys. Leave it unset for an individual key, which signs with sub: "user".

ASC_KEY_PATH

Path to the .p8 file. ~ is expanded.

ASC_KEY

The PEM contents instead of a path. Literal \n sequences are accepted.

ASC_WRITE

1 allows changes. Without it the server is read-only: write tools refuse, but still return plans when called with dry_run: true.

ASC_APP_ID

Default app, as an app ID, bundle ID or exact name. If it's unset and the key can see only one app, that app is used.

ASC_VENDOR_NUMBER

Vendor number for download_report (shown in Payments and Financial Reports).

ASC_REPORTS_KEY_ID, ASC_REPORTS_KEY_PATH (or ASC_REPORTS_KEY)

Optional second key used only by download_report, so the main key can stay App Manager. Give it the Finance role (sales and finance reports) or Sales and Reports (sales only). ASC_REPORTS_ISSUER_ID defaults to ASC_ISSUER_ID.

ASC_TOOLS

Only offer these tools or groups. Default: all. See Turning tools off.

ASC_DISABLED_TOOLS

Never offer these tools or groups.

ASC_AUTO_UPDATE

0 turns off automatic updates. On by default.

ADS_CLIENT_ID, ADS_TEAM_ID, ADS_KEY_ID, ADS_KEY_PATH (or ADS_KEY), ADS_AD_ACCOUNT_ID

Optional Apple Ads credentials for keyword research. See Keyword research with Apple Ads.

ASC_UPDATE_CHANNEL

release (default) follows GitHub releases; main follows the newest code on the main branch, including unreleased changes.

The key is only used to sign tokens. The server never logs it or puts it in tool output or error messages, and it only sends tokens to api.appstoreconnect.apple.com. That host is fixed and can't be overridden.

If the configuration is incomplete, the server still starts, and every tool returns an error explaining what's missing. Your client won't just show "failed to connect".

Keyword research with Apple Ads (optional)

To help pick the words for your 100-character keyword field, the server can read Apple's App Store search popularity data through the Apple Ads Platform API. It only reads: nothing here creates campaigns or spends money. Set it up with docs/apple-ads-key.md. The tools appear once the ADS_* variables are set, and they work without ASC_WRITE.

Tool

What it does

ads_status

Checks the connection: org, ad accounts, roles, and the account the tools use.

keyword_popularity

Apple's 0-100 popularity for phrases you name, or for phrases containing some text. With app, it scores your current keyword field and flags keywords that repeat words already in your name or subtitle, which Apple indexes anyway.

search_term_trends

The most-searched terms in a genre and country, weekly or monthly, with rank and popularity. Only covers roughly the top 500 terms per genre and country.

keyword_suggestions

Apple's keyword ideas for an app, most popular first. Generally needs an app that's live on the App Store.

They're in the ads group, so ASC_DISABLED_TOOLS=ads hides them.

Updates

Clones of this repository update themselves:

  • When: on each server start, the server checks GitHub at most every 30 minutes. It does this in the background after starting, so the agent never waits on it.

  • What: with the default release channel, the newest version tag (v0.3.0, v0.4.0, …). With ASC_UPDATE_CHANNEL=main, the newest commit on main.

  • How: git fetch, then switch to the new version. Then it rebuilds, which takes seconds and works offline. npm ci runs instead when dependencies changed. The new version is used from the next start.

  • Safe to leave on:

    • It only moves forward to the newer version, and never touches a copy with local edits or its own commits, such as a development clone.

    • If installing or building fails, it switches back to the previous version and rebuilds it. It won't retry the failed version until a newer one is published.

    • Two servers starting at once can't both update; one waits for the next check.

  • Check status: node ~/app-store-connect-mcp/dist/index.js --check prints the version and the last update result.

  • Update now: node ~/app-store-connect-mcp/dist/index.js --update.

  • Turn it off or pin a version: set ASC_AUTO_UPDATE=0, then pick a version yourself, for example git checkout v0.3.0 && npm ci.

Copies installed before v0.3.0 don't have the updater yet. Update those once by hand: cd ~/app-store-connect-mcp && git checkout -- package-lock.json && git fetch --tags && git checkout v0.3.0 && npm ci.

Turning tools off

There's no settings screen: the server runs in the background of your agent app. Choose its tools with two environment variables, set in the same place as the key:

  • ASC_TOOLS is an allowlist. Only the tools listed are offered. Without it, every tool is offered.

  • ASC_DISABLED_TOOLS is a denylist. It's applied after ASC_TOOLS.

Both take tool names and group names, separated by commas or spaces. Turned-off tools aren't shown to the agent at all, so it can't call them.

Group

Tools

read

Every read-only tool: list_apps, get_app_status, list_builds, get_build, list_beta_groups, list_testers, get_listing, list_screenshots, list_subscriptions, get_reviews, get_ratings, download_report

testflight

upload_build, distribute_build, create_beta_group, invite_testers, remove_testers

listing

update_listing, set_whats_new, update_age_rating

screenshots

upload_screenshots, replace_screenshot, reorder_screenshots, delete_screenshots

release

prepare_version, set_review_details, submit_for_review, cancel_review_submission

subscriptions

remove_intro_offers, add_free_trial

reviews

reply_to_review

raw

asc_request

ads

ads_status, keyword_popularity, search_term_trends, keyword_suggestions (offered only when Apple Ads is configured; also in read)

destructive

Everything that deletes or can't be taken back: remove_testers, upload_screenshots, replace_screenshot, delete_screenshots, submit_for_review, cancel_review_submission, remove_intro_offers, reply_to_review, asc_request

all

Everything

Examples:

-e ASC_TOOLS=read                                 # look, never touch
-e ASC_TOOLS=read,testflight                      # TestFlight only, plus reading
-e ASC_DISABLED_TOOLS=destructive                 # everything except deleting and submitting
-e ASC_DISABLED_TOOLS=submit_for_review,raw       # no App Review submissions, no raw API calls

If an entry isn't a known tool or group, every tool refuses to run until it's fixed. That way a typo in ASC_DISABLED_TOOLS can't leave a tool switched on. --check prints which tools are on.

ASC_WRITE still applies on top: without it, even enabled write tools only return dry-run plans. Your agent app may also let you block tools; for example, Claude Code's permissions.deny takes names like mcp__asc__submit_for_review.

Tools

Tools take an app argument, which can be an app ID, a bundle ID or a name. Results are short, readable text that includes the IDs a follow-up call needs.

Read (always available):

Tool

What it does

list_apps

Apps the key can see, with IDs, bundle IDs and SKUs.

get_app_status

One-call overview: versions and their states, the attached build, the latest builds and their TestFlight states, uploads still processing, and review submissions.

list_builds

Recent builds with processing and TestFlight states.

get_build

One build: compliance, beta review, groups, What to Test, App Store version. Use wait_minutes to wait for processing.

list_beta_groups

TestFlight groups: internal or external, public link, tester count.

list_testers

Testers of an app or a group, with status and groups.

get_listing

Name, subtitle, categories, age rating, localized description, keywords, promotional text, What's New and URLs (with character counts), and App Review details.

list_screenshots

Screenshot sets in display order, with positions, sizes, states and IDs.

list_subscriptions

Subscription groups, subscriptions, price in a territory, introductory offers summarized across territories, and in-app purchases.

get_reviews

Customer reviews with your replies.

get_ratings

Star rating and number of ratings per country, including ratings without a written review. Uses Apple's public App Store lookup, so no extra key role is needed.

download_report

Sales or finance report: unzipped, totaled, optionally saved as TSV.

Workflows (these change things, so they need ASC_WRITE=1; any of them can be called with dry_run: true to see the plan):

Tool

Writes

What it does

upload_build

yes

Uploads an .ipa/.pkg through Apple's build upload API, or with xcrun altool.

distribute_build

yes

Waits for processing, answers export compliance (if you say how), sets What to Test, adds the build to groups, and submits for beta review when an external group needs it.

create_beta_group

yes

Creates a group (or returns the existing one with that name), optionally with a public link.

invite_testers

yes

Invites new testers and adds existing ones to a group; people who were already invited elsewhere aren't an error.

remove_testers

destructive

Removes testers from a group or from the app.

update_listing

yes

Edits localized metadata, categories and game subcategories, showing old → new for each field and changing only what differs.

set_whats_new

yes

App Store "What's New" or TestFlight "What to Test".

update_age_rating

yes

Changes answers in the age rating questionnaire.

upload_screenshots

destructive

Makes a screenshot set match a folder or list of files (replace), or appends to it (append).

replace_screenshot

destructive

Replaces one screenshot (by position or ID), without a gap in the listing.

reorder_screenshots

yes

Reorders a set.

delete_screenshots

destructive

Deletes screenshots by position or ID.

prepare_version

yes

Creates or renames the version being prepared, attaches a build, sets the release type.

set_review_details

yes

App Review contact, demo account and notes. The password is never echoed back.

submit_for_review

destructive

Pre-flight checks, then submits through reviewSubmissions.

cancel_review_submission

destructive

Withdraws an active submission, or takes the version out of a draft submission that was never sent.

remove_intro_offers

destructive

Bulk-deletes introductory offers (e.g. a free trial) across territories.

add_free_trial

yes

Bulk-adds a free trial in every territory that lacks an introductory offer.

reply_to_review

destructive

Publishes a public reply to a customer review; replace: true changes an existing one.

Escape hatch: asc_request(method, path, query, body) calls any App Store Connect endpoint. GET works in read-only mode. POST, PATCH and DELETE need ASC_WRITE=1, and DELETE also needs confirm: true.

How it stays safe

  • Read-only by default. Without ASC_WRITE=1, write tools refuse to change anything, but they still return a plan if called with dry_run: true.

  • Destructive means dry run first. Tools that delete things (screenshots, offers, testers) or can't be taken back (submitting for review) default to dry_run: true. The agent gets the plan, shows it to you, and calls again with dry_run: false. The tools carry MCP destructiveHint and readOnlyHint annotations, so clients can ask before running them.

  • Order that never leaves a gap. When replace_screenshot replaces an image, it uploads the new one, waits until Apple has processed it, puts it in place, and only then deletes the old one. If Apple rejects the image, nothing in the live listing changes. The one exception is a full set of 10. Apple won't allow an 11th screenshot even briefly, so the old one has to be deleted first, and the dry run says so. If the new image then fails, re-running the same call puts it in the old one's place.

  • Least privilege. See below.

Choosing a key role

Use App Manager unless you have a reason not to. Step-by-step instructions are in docs/api-key.md.

Role

Enough for

App Manager

Everything here except sales and finance reports. Recommended.

Marketing

Listing metadata and screenshots, if that's all the agent should touch.

Customer Support

Reading and replying to customer reviews.

Finance or Sales and Reports

download_report. Finance reads sales and finance reports; Sales and Reports reads sales reports only. Neither can change anything through the API.

Admin

Never needed. Don't use it: an Admin key can manage users and other keys.

Reports need a different role from everything else, so you can give the server two keys: an App Manager key as ASC_KEY_ID / ASC_KEY_PATH, and a Finance key as ASC_REPORTS_KEY_ID / ASC_REPORTS_KEY_PATH. download_report uses the reports key, and every other tool uses the main one. Apple doesn't let you add roles to an existing key, so create a new one.

If a tool needs more access than the key has, the error says so. Keep keys out of repositories: store the .p8 somewhere like ~/.appstoreconnect/ with chmod 600, and revoke any key you think has leaked under Users and Access.

Long-running jobs

Apple processes builds (usually 5 to 30 minutes) and images (usually seconds) asynchronously. Tools that wait take wait_minutes, and they send MCP progress notifications while they wait. When time runs out, they don't fail. They return a status such as "still processing; run distribute_build again with the same arguments". Re-running is always safe:

  • distribute_build skips groups the build is already in, notes that already match, and beta reviews already submitted. It treats Apple's "already submitted" response as success.

  • Screenshot tools match files to existing screenshots by MD5, so an image uploaded by an interrupted run isn't uploaded again. Each delete, reorder and commit is its own request. If a step fails partway, the error lists the steps that finished and gives the exact call that finishes the job. For replace_screenshot, that call includes the screenshot_id, because positions can shift between runs. Leftovers from broken uploads never block a set; replacing or uploading to it cleans them up.

  • Bulk jobs (remove_intro_offers, add_free_trial, invite_testers) keep going past individual failures and report what succeeded, what failed and what wasn't tried. They stop early when the hourly rate limit (about 3,600 requests per key) runs low. Running them again finishes the job.

HTTP retries: the server retries GETs, PATCHes and DELETEs on 5xx errors and connection resets, with jittered exponential backoff. It retries POSTs only when Apple says the request didn't happen (429 or 503), because a reset POST may have gone through. It honors Retry-After and refreshes the token once on a 401.

Uploading builds

upload_build uploads an exported .ipa. Make one with:

xcodebuild archive -scheme MyApp -archivePath build/MyApp.xcarchive -destination 'generic/platform=iOS'
xcodebuild -exportArchive -archivePath build/MyApp.xcarchive -exportPath build -exportOptionsPlist ExportOptions.plist

The ExportOptions.plist needs method set to app-store-connect and destination set to export. (With destination set to upload, Xcode uploads the build itself, and you can skip upload_build.)

  • method: "api" (the default) uses App Store Connect's build upload API (buildUploads and buildUploadFiles, added in API 4.1). It needs no Xcode, so it works on Linux CI too.

  • method: "altool" runs xcrun altool --upload-app with the same API key, on a Mac.

xcodebuild -exportArchive registers a placeholder upload with App Store Connect even when it only exports. upload_build recognizes these placeholders and ignores them.

Every upload needs a new, higher CFBundleVersion. A timestamp such as YYYYMMDDHHMM works well. Add ITSAppUsesNonExemptEncryption = NO to Info.plist if it applies to your app, and TestFlight will never ask about export compliance.

Apple's rules worth knowing

These came up when testing against the real API. The tools handle each one, but they explain why a change is refused:

  • What's New can't be set on an app's first version.

  • The age rating questionnaire starts with every answer empty, and Apple won't accept any change until all 21 questions are answered. update_age_rating with fill_unanswered: true answers the rest NONE/false. Check those answers with whoever owns the app.

  • Once App Review details exist, every edit needs the full contact: first and last name, email, and phone with + and the country code.

  • Fields are cleared with null, not an empty string. Pass "" to the tools, and they send null.

  • Apple reports a wrong-size screenshot only as ASSET_FAILED, so the tools check image sizes before uploading. They also delete the rejected upload, so it doesn't take up one of the set's 10 slots.

  • External testers aren't emailed until a build passes Beta App Review.

What the API can't do

These still need the App Store Connect website. This list was checked against API spec 4.5:

  • The App Privacy questionnaire ("nutrition labels"). The public API has no endpoints for it.

  • Creating a new app record. POST /v1/apps doesn't exist. Create the app on the website, then manage it from here.

  • Agreements, tax and banking, including accepting updated Paid Apps agreements. When an agreement is missing, API calls fail with an error that this server explains.

  • Export compliance documentation for apps that use non-exempt encryption.

  • Paid introductory offers, which need a price point per territory. This server only covers free trials, so use asc_request for paid offers. App pricing, Game Center and in-app purchase editing are also in the API but not wrapped yet; asc_request reaches them.

Development

npm install
npm test               # unit and workflow tests against a spec-checked fake App Store Connect
npm run typecheck
npm run build          # dist/index.js

API types are generated from Apple's OpenAPI spec, which is pinned in spec/openapi.oas.json.gz. Its version and SHA-256 are in spec/VERSION.json.

  • npm run spec:update downloads the latest spec from Apple and regenerates the types in src/generated/asc-api.ts.

  • npm run spec:generate regenerates the types from the pinned spec.

Only the schemas listed in scripts/spec-schemas.json (and what they reference) are generated.

Tests run against test/helpers/fake-asc.ts, an in-memory App Store Connect. It supports JSON:API includes, filters, sorting, pagination, relationship endpoints and fault injection (connection resets, 409s, 429s). It also checks every request's path, method and query parameters against the pinned spec, so a typo in an endpoint fails a test. All fixture data is synthetic.

scripts/call-tool.mjs calls one tool on the built server over stdio, which is handy against a real account:

npm run build && node scripts/call-tool.mjs get_app_status '{"app": "com.example.app"}'

Live tests are opt-in. They run against a real account, ideally a sandbox app:

ASC_LIVE_TEST=1 ASC_KEY_ID=… ASC_ISSUER_ID=… ASC_KEY_PATH=… ASC_LIVE_APP_ID=… npm run test:live

They're read-only and dry runs unless you also set ASC_WRITE=1 and ASC_LIVE_WRITE=1. Then they also set and restore the promotional text of the live version.

License

MIT. See LICENSE. Not affiliated with Apple. App Store Connect and TestFlight are trademarks of Apple Inc.

Available Tools

31 tools
add_free_trialAdd a free trialA
Idempotent

Adds a free-trial introductory offer to a subscription in every territory where it's sold (or the ones you list), skipping territories that already have an introductory offer. Runs as a resumable bulk job with progress. Paid introductory offers need a price per territory and aren't covered; use asc_request for those.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: duration (required), subscription (required), app, dry_run, +3 more.

asc_requestRaw App Store Connect requestA
Destructive

Escape hatch for anything the workflow tools don't cover: calls the App Store Connect API directly and returns the JSON. path is relative to https://api.appstoreconnect.apple.com, e.g. /v1/apps/123/appInfos. GET works in read-only mode; POST, PATCH and DELETE need ASC_WRITE=1, and DELETE also needs confirm: true. Prefer the workflow tools: they check state, retry safely and wait for Apple's processing.

Inputs: path (required), body, query, method, +2 more.

cancel_review_submissionCancel App Review submissionA
DestructiveIdempotent

Withdraws the app's active review submission (waiting for or in review), so the version can be edited again. If the only submission is a draft that was never sent (READY_FOR_REVIEW, e.g. after a submit_for_review that failed at the last step), takes its items out instead.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: app, dry_run, platform.

create_beta_groupCreate a beta groupA
Idempotent

Creates a TestFlight group, or returns the existing one with the same name. External groups can have a public link anyone can join. Internal groups can only contain people who are already App Store Connect users on the team.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: name (required), app, dry_run, feedback, +4 more.

delete_screenshotsDelete screenshotsA
DestructiveIdempotent

Deletes screenshots from a set by position (1-based) or ID. The rest keep their order.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: screenshots (required), display_type (required), app, locale, +3 more.

distribute_buildDistribute a TestFlight buildA
Idempotent

Ships a build to TestFlight testers in one call: waits for processing, answers export compliance if you say how, sets the What to Test notes, adds the build to beta groups, and submits it for beta app review when an external group needs it. Every step checks the current state first, so re-running after a timeout or error picks up where it stopped.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: app, build, notes, groups, +7 more.

download_reportDownload a sales or finance reportA
Read-onlyIdempotent

Downloads a sales or finance report (Apple returns gzipped TSV), optionally saves it, and returns the row count, columns, simple totals and the first rows. Needs the vendor number (App Store Connect > Payments and Financial Reports) as vendor_number or ASC_VENDOR_NUMBER, and a key with the Finance or Sales role.

Inputs: report_date (required), kind, rows, save_to, +6 more.

get_app_statusGet app statusA
Read-onlyIdempotent

One-call overview of an app: App Store versions and their states, the build attached to each, the latest builds and their TestFlight states, uploads still processing, and open review submissions.

Inputs: app.

get_buildGet buildA
Read-onlyIdempotent

Shows one build in detail: processing and TestFlight states, export compliance, beta review, groups, What to Test notes and the App Store version it's attached to. Set wait_minutes to wait for Apple to finish processing a fresh upload.

Inputs: app, build, version, platform, +1 more.

get_listingGet store listingA
Read-onlyIdempotent

Shows the App Store listing: app name, subtitle, privacy URL and categories, the version's localized description, keywords, promotional text, what's new and URLs (with character counts against Apple's limits), the age rating, and the App Review contact details.

Inputs: app, full, locale, version, +1 more.

get_reviewsGet customer reviewsA
Read-onlyIdempotent

Lists App Store customer reviews, newest first by default, with your published replies and review IDs (for reply_to_review).

Inputs: app, sort, limit, rating, +2 more.

invite_testersInvite testersA
Idempotent

Adds testers to a beta group, inviting them if they're new. People already invited elsewhere are added to the group instead of failing. External groups accept any email; internal groups only accept App Store Connect users on the team. Safe to re-run with the same list.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: group (required), testers (required), app, dry_run.

list_appsList appsA
Read-onlyIdempotent

Lists the apps this API key can see, with their IDs, bundle IDs and SKUs. Start here to find an app ID.

Inputs: name.

list_beta_groupsList beta groupsB
Read-onlyIdempotent

Lists an app's TestFlight groups: internal or external, access to all builds, public link, feedback, tester count and ID.

Inputs: app.

list_buildsList buildsB
Read-onlyIdempotent

Lists an app's most recent builds with processing state, TestFlight states and IDs.

Inputs: app, limit, version, platform, +1 more.

list_screenshotsList screenshotsA
Read-onlyIdempotent

Lists App Store screenshots for a version, per localization and display type, in display order with positions (1-based), file names, sizes, states and IDs.

Inputs: app, locale, version, platform, +1 more.

list_subscriptionsList subscriptions and in-app purchasesA
Read-onlyIdempotent

Lists subscription groups and their subscriptions (product ID, period, state, price in one territory, introductory offers summarized across territories), plus one-time in-app purchases.

Inputs: app, territory.

list_testersList testersA
Read-onlyIdempotent

Lists TestFlight testers for an app, or for one group, with email, name, status, invite type and groups.

Inputs: app, email, group.

prepare_versionPrepare an App Store versionA
Idempotent

Makes sure an App Store version with this version string is being prepared: reuses it if it exists, renames the version currently being prepared, or creates a new one (Apple copies the metadata from the previous version). Optionally attaches a build and sets the release type.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: version_string (required), app, build, dry_run, +3 more.

remove_intro_offersRemove introductory offersA
DestructiveIdempotent

Deletes a subscription's introductory offers (for example a free trial) in every territory or only some. Apple stores one offer per territory, so this is a bulk job: it reports progress, keeps going past individual failures, stops early if the hourly rate limit runs low, and can be re-run to finish.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: subscription (required), app, dry_run, offer_mode, +1 more.

remove_testersRemove testersA
DestructiveIdempotent

Removes testers from one beta group, or from the app entirely (every group, and their access to builds) when group is omitted. Removing someone from their last group leaves them listed as a tester of the app with no groups; omit group to remove them completely.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: emails (required), app, group, dry_run.

reorder_screenshotsReorder screenshotsA
Idempotent

Changes the order of a screenshot set. order lists current positions (1-based) or screenshot IDs in the new order; any not listed keep their relative order after them. Example: [4] moves screenshot 4 to the front.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: order (required), display_type (required), app, locale, +3 more.

replace_screenshotReplace one screenshotA
DestructiveIdempotent

Replaces one screenshot with a new image, keeping its place. Identify it by position (1-based, from list_screenshots) or by screenshot_id. The new image is uploaded and processed before the old one is removed, so the listing never has a gap (except in a full set of 10, where the old one has to go first). If a run stops partway, it says how to continue: call again with screenshot_id so the right screenshot is replaced even if positions shifted.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: file (required), display_type (required), app, locale, +6 more.

reply_to_reviewReply to a customer reviewA
DestructiveIdempotent

Publishes a developer reply to a customer review. Replies are public, so this is a dry run until confirmed. A review has at most one reply; to change an existing one pass replace: true, which overwrites it.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: text (required), review_id (required), dry_run, replace.

set_review_detailsSet App Review detailsA
Idempotent

Sets the App Review information for the version being prepared: contact name, phone and email, demo account, and notes for the reviewer. Only fields you pass change. The password is never echoed back.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: app, notes, dry_run, version, +8 more.

set_whats_newSet what's newA
Idempotent

Sets release notes. target "app_store" sets the version's "What's New in This Version"; target "testflight" sets a build's "What to Test".

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: text (required), target (required), app, build, +4 more.

submit_for_reviewSubmit for App ReviewA
DestructiveIdempotent

Submits the version being prepared to App Review. First checks what the API can see (build attached and processed, descriptions, keywords, support URL, screenshots, privacy policy URL, review contact) and stops if something is missing. Then creates or reuses a review submission, adds the version and submits it. Things the API can't check: the App Privacy questionnaire, pricing and availability, agreements and tax forms.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: app, dry_run, version, platform, +1 more.

update_age_ratingUpdate age ratingA
Idempotent

Answers the age rating questionnaire of the app info being prepared. Pass the answers to change, using Apple's attribute names, e.g. {"violenceCartoonOrFantasy": "INFREQUENT_OR_MILD", "gambling": false}. Content questions take NONE, INFREQUENT_OR_MILD or FREQUENT_OR_INTENSE: alcoholTobaccoOrDrugUseOrReferences, contests, gamblingSimulated, gunsOrOtherWeapons, horrorOrFearThemes, matureOrSuggestiveThemes, medicalOrTreatmentInformation, profanityOrCrudeHumor, sexualContentGraphicAndNudity, sexualContentOrNudity, violenceCartoonOrFantasy, violenceRealistic, violenceRealisticProlongedGraphicOrSadistic. Yes/no questions take true/false: advertising, ageAssurance, gambling, healthOrWellnessTopics, lootBox, messagingAndChat, parentalControls, unrestrictedWebAccess, userGeneratedContent, plus optional socialMedia. Apple needs every question answered before it accepts any change; fill_unanswered: true answers the rest NONE/false. Confirm those answers with the user.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: app, answers, dry_run, fill_unanswered.

update_listingUpdate store listingA
Idempotent

Updates App Store metadata for one locale. Only fields you pass change, and only if they differ; the result shows each change as old → new. Name, subtitle and privacy URLs live on the app info; description, keywords, promotional text, what's new and URLs on the version. Adds the localization if it doesn't exist yet. Only versions being prepared can change, except promotional text, which can change on the live version (pass version: "live").

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: app, name, locale, dry_run, +15 more.

upload_buildUpload a buildA
Idempotent

Uploads an exported .ipa (or macOS .pkg) to App Store Connect. method "api" uses Apple's build upload API (no Xcode needed); "altool" shells out to xcrun altool on a Mac. Make the .ipa first with xcodebuild archive + xcodebuild -exportArchive (method app-store-connect, destination export). Every upload needs a new, higher build number (CFBundleVersion). After it's processed, use distribute_build to send it to testers.

Changes App Store Connect (needs ASC_WRITE=1). Safe to re-run: steps already done are skipped.

Inputs: file (required), app, method, dry_run, +4 more.

upload_screenshotsUpload screenshotsA
DestructiveIdempotent

Uploads images to one screenshot set of the version being prepared. mode "replace" makes the set exactly these files in this order (the old ones are deleted only after the new ones are processed); mode "append" adds them at the end. Files already in the set (same MD5) aren't uploaded again, so re-running is safe.

Destructive: dry_run defaults to true and returns the plan. Show it to the user, then call again with dry_run: false. Needs ASC_WRITE=1.

Inputs: display_type (required), app, mode, files, +6 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 31 tools

    Disambiguation4/5

    Tools largely target distinct resources and actions (apps, builds, testers, listings, screenshots, reviews, subscriptions). Slight overlap exists between update_listing and set_whats_new for version notes, and among screenshot tools, but descriptions provide clear guidance.

    Naming Consistency5/5

    All tools use consistent snake_case with a leading verb (list_, get_, create_, update_, delete_, etc.), making the pattern predictable. The lone exception asc_request is an intentional escape hatch; overall naming is highly consistent.

    Tool Count4/5

    31 tools is heavy but seems justified by the breadth of App Store Connect workflows (apps, builds, TestFlight, listings, screenshots, reviews, subscriptions, reports). Each tool covers a distinct operation, though the set could benefit from some consolidation.

    Completeness4/5

    Covers core lifecycles for apps, builds, TestFlight, listings, screenshots, reviews, and subscriptions, with an escape hatch for edge cases. Notable gaps remain around pricing/availability, in-app purchase management, and app privacy, but agents can work around them via asc_request.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers