App Store Connect MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ASC_KEY | No | The PEM contents instead of a path. Literal `\n` sequences are accepted. | |
| ASC_TOOLS | No | Only offer these tools or groups. Default: all. See [Turning tools off](#turning-tools-off). | |
| ASC_WRITE | No | `1` allows changes. Without it the server is read-only, and write tools only return plans. | |
| ASC_APP_ID | No | 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_KEY_ID | Yes | API key ID. Required. | |
| ASC_KEY_PATH | No | Path to the `.p8` file. `~` is expanded. | |
| ASC_ISSUER_ID | No | Issuer ID for team keys. Leave it unset for an individual key, which signs with `sub: "user"`. | |
| ASC_AUTO_UPDATE | No | `0` turns off automatic updates. On by default. | |
| ASC_VENDOR_NUMBER | No | Vendor number for `download_report` (shown in Payments and Financial Reports). | |
| ASC_DISABLED_TOOLS | No | Never offer these tools or groups. | |
| ASC_UPDATE_CHANNEL | No | `release` (default) follows GitHub releases; `main` follows the newest code on the main branch, including unreleased changes. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_appsA | Lists the apps this API key can see, with their IDs, bundle IDs and SKUs. Start here to find an app ID. |
| get_app_statusA | 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. |
| list_buildsB | Lists an app's most recent builds with processing state, TestFlight states and IDs. |
| get_buildA | 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. |
| list_beta_groupsB | Lists an app's TestFlight groups: internal or external, access to all builds, public link, feedback, tester count and ID. |
| list_testersA | Lists TestFlight testers for an app, or for one group, with email, name, status, invite type and groups. |
| get_listingA | 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. |
| list_screenshotsA | 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. |
| list_subscriptionsA | 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. |
| get_reviewsA | Lists App Store customer reviews, newest first by default, with your published replies and review IDs (for reply_to_review). |
| download_reportA | 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. |
| upload_buildA | 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. |
| distribute_buildA | 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. |
| create_beta_groupA | 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. |
| invite_testersA | 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. |
| remove_testersA | 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. |
| update_listingA | 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. |
| set_whats_newA | 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. |
| update_age_ratingA | 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, parentalControls, unrestrictedWebAccess, userGeneratedContent, plus messagingAndChat, 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. |
| upload_screenshotsA | 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. |
| replace_screenshotA | 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. |
| reorder_screenshotsA | 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. |
| delete_screenshotsA | 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. |
| prepare_versionA | 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. |
| set_review_detailsA | 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. |
| submit_for_reviewA | 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. |
| cancel_review_submissionA | Withdraws the app's active review submission (waiting for or in review), so the version can be edited again. 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. |
| remove_intro_offersA | 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. |
| add_free_trialA | 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. |
| reply_to_reviewA | 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 deletes the old reply and posts the new one. 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. |
| asc_requestA | 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. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 31 tools
Most tools target a clearly distinct resource+action (builds vs screenshots vs testers vs reviews vs subscriptions), and the destructive/write tools are well-differentiated. Minor overlap exists between set_whats_new and update_listing (which also sets what's new), and asc_request is a deliberate catch-all that could tempt use where a workflow tool fits better.
Every tool is snake_case with a verb-first pattern (list_*, get_*, create_*, update_*, remove_*, upload_*, etc.), matching resource nouns consistently. asc_request is the only mild deviation but is still readable and intentional.
31 tools is on the heavy side and exceeds the comfortable 3-15 range, though the App Store Connect domain is genuinely broad (builds, testers, screenshots, listings, subscriptions, reviews, reports, review submission). The surface is large but mostly earns its place rather than being redundant.
Strong lifecycle coverage: app discovery, build upload/distribution, TestFlight groups and testers, listing/metadata editing, screenshots, age rating, subscriptions/offers, reviews, and review submission. Known gaps (pricing/availability, App Privacy questionnaire, paid intro offers) are explicitly documented and bridged by the asc_request escape hatch.