App Store Connect MCP
Manage App Store Connect apps via MCP with read-only defaults, dry-run safety, and resumable workflows.
Read apps, app status, builds, beta groups, testers, listings, screenshots, subscriptions/IAPs, customer reviews, and sales/finance reports.
Upload and distribute TestFlight builds, create beta groups, and invite/remove testers.
Edit store listing metadata, What’s New / What to Test, and age rating answers.
Manage screenshots: upload, replace, reorder, and delete sets safely.
Prepare App Store versions, set App Review details, submit/cancel review submissions, and reply to reviews.
Manage subscription introductory offers: remove offers or add free trials in bulk.
Use
asc_requestas a raw API escape hatch for uncovered endpoints.Safe by default: read-only unless
ASC_WRITE=1; destructive tools dry-run first; operations are idempotent and resumable.Optional Apple Ads keyword research when
ADS_*credentials are configured.
Connects to Apple's App Store Connect API (api.appstoreconnect.apple.com) using an App Store Connect API key (team or individual) to read and modify app data, with read-only access by default and writes gated behind ASC_WRITE=1.
Manages apps in App Store Connect: uploads and distributes TestFlight builds, manages beta groups and testers, edits store listings (What's New, age rating), runs the full screenshot lifecycle (upload, replace, reorder, delete), manages subscriptions and intro offers, replies to customer reviews, downloads sales/financial reports, and prepares versions for App Review including a submission pre-flight and dry-run review submission.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@App Store Connect MCP What's the status of my app? Is the latest build ready for testers?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.jsYou 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 --checkIt 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.jsAdd -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 | |
| API key ID. Required. |
| Issuer ID for team keys. Leave it unset for an individual key, which signs with |
| Path to the |
| The PEM contents instead of a path. Literal |
|
|
| 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. |
| Vendor number for |
| Optional second key used only by |
| Only offer these tools or groups. Default: all. See Turning tools off. |
| Never offer these tools or groups. |
|
|
| Optional Apple Ads credentials for keyword research. See Keyword research with Apple Ads. |
|
|
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 |
| Checks the connection: org, ad accounts, roles, and the account the tools use. |
| Apple's 0-100 popularity for phrases you name, or for phrases containing some text. With |
| 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. |
| 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
releasechannel, the newest version tag (v0.3.0,v0.4.0, …). WithASC_UPDATE_CHANNEL=main, the newest commit onmain.How:
git fetch, then switch to the new version. Then it rebuilds, which takes seconds and works offline.npm ciruns 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 --checkprints 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 examplegit 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_TOOLSis an allowlist. Only the tools listed are offered. Without it, every tool is offered.ASC_DISABLED_TOOLSis a denylist. It's applied afterASC_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 |
| Every read-only tool: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Everything that deletes or can't be taken back: |
| 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 callsIf 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 |
| Apps the key can see, with IDs, bundle IDs and SKUs. |
| One-call overview: versions and their states, the attached build, the latest builds and their TestFlight states, uploads still processing, and review submissions. |
| Recent builds with processing and TestFlight states. |
| One build: compliance, beta review, groups, What to Test, App Store version. Use |
| TestFlight groups: internal or external, public link, tester count. |
| Testers of an app or a group, with status and groups. |
| Name, subtitle, categories, age rating, localized description, keywords, promotional text, What's New and URLs (with character counts), and App Review details. |
| Screenshot sets in display order, with positions, sizes, states and IDs. |
| Subscription groups, subscriptions, price in a territory, introductory offers summarized across territories, and in-app purchases. |
| Customer reviews with your replies. |
| 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. |
| 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 |
| yes | Uploads an |
| 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. |
| yes | Creates a group (or returns the existing one with that name), optionally with a public link. |
| yes | Invites new testers and adds existing ones to a group; people who were already invited elsewhere aren't an error. |
| destructive | Removes testers from a group or from the app. |
| yes | Edits localized metadata, categories and game subcategories, showing old → new for each field and changing only what differs. |
| yes | App Store "What's New" or TestFlight "What to Test". |
| yes | Changes answers in the age rating questionnaire. |
| destructive | Makes a screenshot set match a folder or list of files ( |
| destructive | Replaces one screenshot (by position or ID), without a gap in the listing. |
| yes | Reorders a set. |
| destructive | Deletes screenshots by position or ID. |
| yes | Creates or renames the version being prepared, attaches a build, sets the release type. |
| yes | App Review contact, demo account and notes. The password is never echoed back. |
| destructive | Pre-flight checks, then submits through |
| destructive | Withdraws an active submission, or takes the version out of a draft submission that was never sent. |
| destructive | Bulk-deletes introductory offers (e.g. a free trial) across territories. |
| yes | Bulk-adds a free trial in every territory that lacks an introductory offer. |
| destructive | Publishes a public reply to a customer review; |
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 withdry_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 withdry_run: false. The tools carry MCPdestructiveHintandreadOnlyHintannotations, so clients can ask before running them.Order that never leaves a gap. When
replace_screenshotreplaces 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 |
|
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_buildskips 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 thescreenshot_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.plistThe 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 (buildUploadsandbuildUploadFiles, added in API 4.1). It needs no Xcode, so it works on Linux CI too.method: "altool"runsxcrun altool --upload-appwith 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_ratingwithfill_unanswered: trueanswers 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 sendnull.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/appsdoesn'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_requestfor paid offers. App pricing, Game Center and in-app purchase editing are also in the API but not wrapped yet;asc_requestreaches 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.jsAPI 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:updatedownloads the latest spec from Apple and regenerates the types insrc/generated/asc-api.ts.npm run spec:generateregenerates 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:liveThey'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 toolsadd_free_trialAdd a free trialAIdempotent
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 requestADestructive
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 submissionADestructiveIdempotent
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 groupAIdempotent
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 screenshotsADestructiveIdempotent
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 buildAIdempotent
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 reportARead-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 statusARead-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 buildARead-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 listingARead-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 reviewsARead-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 testersAIdempotent
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 appsARead-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 groupsBRead-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 buildsBRead-onlyIdempotent
Lists an app's most recent builds with processing state, TestFlight states and IDs.
Inputs: app, limit, version, platform, +1 more.
list_screenshotsList screenshotsARead-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 purchasesARead-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 testersARead-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 versionAIdempotent
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 offersADestructiveIdempotent
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 testersADestructiveIdempotent
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 screenshotsAIdempotent
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 screenshotADestructiveIdempotent
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 reviewADestructiveIdempotent
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 detailsAIdempotent
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 newAIdempotent
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 ReviewADestructiveIdempotent
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 ratingAIdempotent
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 listingAIdempotent
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 buildAIdempotent
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 screenshotsADestructiveIdempotent
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
Scored across 31 tools
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.
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.
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.
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
Related MCP Connectors
App Store Connect operator for AI agents: icons, TestFlight builds, listings, IAP, rejection fixes.
Manage App Store and Google Play apps: listings, screenshots, builds, releases, reviews, metrics.
Run App Store Connect from your IDE: pricing, listings, screenshots, releases, AI visibility.
App Store data for agents: app metadata, reviews, chart rankings, prices, in-app purchases.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage Apple App Store Connect through the official API, including apps, metadata, reviews, TestFlight, provisioning, users, and reports.MIT
- AlicenseNot gradedqualityDmaintenanceEnables analysis and management of iOS/macOS apps via the App Store Connect API, including app management, reviews, sales reports, analytics, performance metrics, and TestFlight.21 npm2MIT
- AlicenseNot gradedqualityFmaintenanceEnables AI agents to manage App Store Connect apps, including registering bundle IDs, uploading metadata and screenshots, setting age ratings, managing TestFlight groups and testers, and submitting apps for review.MIT
- AlicenseCqualityDmaintenanceEnables management of App Store Connect resources including app reviews, TestFlight crashes, analytics reports, and Xcode Cloud workflows through natural language or AI agents.401MIT