App PublishSAFE
Unified MCP server for App Store Connect & Google Play Console — 91 tools for listings, screenshots, releases, reviews & submissions
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
English | 한국어 | 中文 | 日本語
[](https://www.npmjs.com/package/app-publish-mcp)
A unified MCP (Model Context Protocol) server for App Store Connect and Google Play Console. Manage app listings, screenshots, releases, reviews and submissions — all from your AI assistant.
Publishing Boundary
You provide a release-ready, correctly signed Android .aab / .apk or Apple .ipa. The MCP handles supported store-side work from upload through metadata, testing, review submission, and release. It does not compile the app, own signing keys, or replace Xcode, Gradle, or CI.
The first release of a new app still requires manual setup in App Store Connect or Play Console, including developer enrollment, agreements, app records where required, API access, signing, tax and banking details, and policy, privacy, or content declarations. For an existing, fully configured Android app, a signed AAB is usually enough to let the MCP run the update workflow. A Google edit commit only commits the requested changes; store review, managed publishing, or a staged rollout can delay public availability.
When to Use
Use this MCP when you need to:
- "Update my app's App Store description and keywords" — modify version localizations, app info localizations
- "Upload new screenshots for iPhone 16 Pro" — upload to the Asset Library and place images on the version localization
- "Submit a new version for review" — create version, assign build, set review info, submit
- "Check the status of my app review" — list versions and check review state
- "Respond to a user review on Google Play" — list reviews and reply
- "Create a phased release on Google Play" — create edit, create release on a track, commit
- "Manage TestFlight beta testers" — create groups, invite testers, manage access
- **"Set up
22a036ab3010OBSERVED · 2026-10-09Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add app-publish-mcp --env APPLE_KEY_ID=${APPLE_KEY_ID} --env APPLE_ISSUER_ID=${APPLE_ISSUER_ID} --env GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} --env GOOGLE_REFRESH_TOKEN=${GOOGLE_REFRESH_TOKEN} -- npx -y [email protected]Exposed tools (146)
68 read · 59 write · 19 destructive. Blast radius: 19 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
apple_add_beta_testers_to_group | write | Add beta testers to a group |
apple_assign_build | read | Assign a build to an App Store version |
apple_create_accessibility_declaration | write | Create an accessibility nutrition label declaration for an app on a specific device family (Accessibility Nutrition Labels) |
apple_create_availability | write | Create initial app availability with explicit territory settings; use available=true and preOrderEnabled=false for a normal release |
apple_create_beta_group | write | Create a beta group |
apple_create_bundle_id | write | Register a new bundle ID |
apple_create_certificate | write | Create a certificate |
apple_create_iap | write | Create an in-app purchase |
apple_create_iap_offer_code | write | Create an offer code for a consumable/non-consumable/non-renewing-subscription in-app purchase. Requires per-territory prices — look them up first with apple_get_iap_price_points. |
apple_create_phased_release | write | Enable a seven-day phased release for an app update; phased release is unavailable for an app\ |
apple_create_placement | write | Place a ready library asset on an editable localization using a placement type and group from apple_get_asset_specs. Reuses an existing identical placement. |
apple_create_profile | write | Create a provisioning profile |
apple_create_screenshot_set | write | Legacy: create a screenshot set for a specific display type. Deprecated by Apple; prefer apple_upload_asset and apple_create_placement. |
apple_create_subscription_group | write | Create a subscription group |
apple_create_subscription_offer_code | write | Create a subscription offer code (custom or one-time-use codes distributed outside the App Store). Requires per-territory prices — look them up first with apple_get_subscription_price_points. |
apple_create_version | write | Create a new App Store version for submission |
apple_create_version_localization | write | Create a new localization for a version |
apple_delete_accessibility_declaration | destructive | Delete an accessibility nutrition label declaration |
apple_delete_asset | destructive | Delete an unplaced image or video from the library. Refuses to delete if any localization still uses it; delete the intended placements first. |
apple_delete_beta_group | destructive | Delete a beta group |
apple_delete_beta_tester | destructive | Delete a beta tester |
apple_delete_build_upload | destructive | Explicitly discard an AWAITING_UPLOAD or FAILED Build Upload after checking it with apple_get_build_upload; do not use for PROCESSING or COMPLETE uploads |
apple_delete_iap | destructive | Delete an in-app purchase |
apple_delete_phased_release | destructive | Cancel a phased release configuration before the phased release has started |
apple_delete_placement | destructive | Remove a placement from its localization; the reusable library asset and its other placements remain intact |
apple_delete_profile | destructive | Delete a provisioning profile |
apple_delete_screenshot | destructive | Legacy: delete a screenshot from the deprecated screenshot-set API. Use apple_delete_placement and apple_delete_asset for Asset Library media. |
apple_delete_subscription_group | destructive | Delete a subscription group |
apple_disable_capability | write | Disable a capability on a bundle ID |
apple_enable_capability | write | Enable a capability on a bundle ID |
apple_get_age_rating | read | Get age rating declaration for an app info |
apple_get_app | read | Get detailed info about an app including latest version state |
apple_get_app_info | read | Get app info (categories, age rating, etc) |
apple_get_asset | read | Read an image or video asset’s processing state, matched specId, and delivery errors without exposing presigned upload URLs |
apple_get_asset_library | read | Get the reusable App Asset Library for an app before uploading screenshots, previews, or creative assets |
apple_get_asset_specs | read | Read Apple’s current asset specifications, placement types, device groups, and limits; use the returned IDs instead of hard-coded device sizes |
apple_get_build_upload | write | Get the current state of a Build Uploads API operation, including the imported build when available |
apple_get_iap | read | Get in-app purchase details |
apple_get_iap_offer_code | read | Get details of an in-app purchase offer code |
apple_get_iap_price_points | read | List available price points for an in-app purchase, per territory. Use the returned IDs (with a territory ID) to build the prices for apple_create_iap_offer_code. |
apple_get_next_page | read | Fetch the next App Store Connect page using the exact links.next URL returned by another Apple list tool |
apple_get_phased_release | read | Get phased-release status and progress for an App Store version |
apple_get_pricing | write | Get the app price schedule plus complete, fully paginated manual and automatic price collections |
apple_get_subscription_offer_code | read | Get details of a subscription offer code |
apple_get_subscription_price_points | read | List available price points for a subscription, per territory. Use the returned IDs (with a territory ID) to build the prices for apple_create_subscription_offer_code. |
apple_get_win_back_offer | read | Get details of a win-back offer |
apple_invite_beta_tester | read | Invite a beta tester |
apple_list_accessibility_declarations | read | List accessibility nutrition label declarations for an app, one per device family |
apple_list_app_info_localizations | read | List app info localizations (app name, subtitle, privacy policy URL) |
apple_list_app_price_points | read | List current App Price Points for an app in a base territory; use an ID from this response with apple_set_price |
apple_list_apps | read | List all apps in App Store Connect |
apple_list_asset_placements | read | List every placement that uses an image or video, including other localizations, before deleting or replacing that asset |
apple_list_assets | read | List all image or video assets in an App Asset Library, following every page; use this to reuse files and find interrupted uploads |
apple_list_availability | read | List current App Availability and all related territory availability records |
apple_list_beta_groups | read | List beta groups |
apple_list_beta_testers | read | List beta testers |
apple_list_builds | read | List builds uploaded to App Store Connect |
apple_list_bundle_id_capabilities | read | List capabilities for a bundle ID |
apple_list_bundle_ids | read | List registered bundle IDs |
apple_list_certificates | read | List certificates |
apple_list_devices | read | List registered devices |
apple_list_iap | read | List in-app purchases for an app |
apple_list_iap_offer_codes | read | List custom/one-time-use offer codes configured for an in-app purchase |
apple_list_placements | write | List all placements for a localization in display order, including their image/video assets |
apple_list_profiles | read | List provisioning profiles |
apple_list_reviews | read | List customer reviews for an app |
apple_list_screenshot_sets | read | Legacy: list screenshot sets for a localization. Apple deprecated this API in 4.5.1; use apple_list_placements for Asset Library media. |
apple_list_subscription_groups | read | List subscription groups for an app |
apple_list_subscription_offer_codes | read | List custom/one-time-use offer codes configured for a subscription |
apple_list_version_localizations | read | List all localizations for a version |
apple_list_versions | read | List all App Store versions for an app |
apple_list_win_back_offers | read | List win-back offers configured for a subscription (offers to bring back churned/expired subscribers) |
apple_register_device | read | Register a new device |
apple_release_version | read | Irreversibly request release of an approved version that is in PENDING_DEVELOPER_RELEASE |
apple_remove_beta_testers_from_group | destructive | Remove beta testers from a group |
apple_reorder_placements | write | Set the complete display order for one localization and placement group, then read back and verify the order. In-app event localizations are not orderable. |
apple_respond_to_review | read | Respond to a customer review |
apple_revoke_certificate | destructive | Revoke a certificate |
apple_set_build_encryption | write | Set a processed build\ |
apple_set_price | write | Replace the complete manual app price schedule. Call apple_get_pricing first and include every current and future manual price entry that must be preserved. |
apple_submit_for_review | write | Create or resume an App Store review submission, attach the version idempotently, and submit it while preserving the submission ID for safe recovery |
apple_update_accessibility_declaration | write | Update an existing accessibility nutrition label declaration |
apple_update_age_rating | write | Update the current App Store age-rating questionnaire. Prefer NONE, INFREQUENT, or FREQUENT for frequency fields; legacy values remain accepted by Apple for compatibility. |
apple_update_app | write | Update app-level submission settings: the content-rights declaration and primary locale |
apple_update_app_info_localization | write | Update app name, subtitle, or privacy policy URL for a locale |
apple_update_category | write | Update app primary/secondary category |
apple_update_device | write | Update device name or status |
apple_update_phased_release | write | Pause, resume, or complete an existing phased release; COMPLETE immediately releases the update to all users |
apple_update_review_detail | write | Update app review info (contact info, notes, demo account for reviewer) |
apple_update_territory_availability | write | Change availability, release date, or pre-order state for one existing territory availability record returned by apple_list_availability |
apple_update_version | write | Update an existing App Store version\ |
apple_update_version_localization | write | Update localization fields (description, keywords, whatsNew, etc) |
apple_upload_asset | write | Upload an image or video once to the App Asset Library, commit uploaded=true, and verify processing against a specId from apple_get_asset_specs. Create placements separately to reuse it across localizations. |
apple_upload_build | write | Upload a signed IPA through the App Store Connect Build Uploads API: reserve the upload and file, send every presigned range, commit its SHA-256 checksum, and optionally wait for import |
apple_upload_screenshot | write | Legacy: upload and commit a screenshot while preserving its ID for recovery. Deprecated by Apple; prefer apple_upload_asset and apple_create_placement. |
apple_wait_for_asset | read | Resume waiting for an uploaded asset to become ready; optionally check that Apple matched the intended specification |
apple_wait_for_build_upload | write | Wait until a Build Uploads API operation completes or fails, returning the imported build relationship on success |
google_activate_purchase_option | read | Activate a one-time product purchase option so it becomes available for purchase |
google_activate_subscription_base_plan | read | Activate a subscription base plan so it becomes purchasable. Base plans default to DRAFT after creation; this is required to make them ACTIVE. |
google_commit_edit | write | Commit all pending changes. By default, fail safely instead of canceling changes that are already in review. |
google_create_edit | write | Create a new edit session. Required before making any changes to a Google Play listing. |
google_create_iap | write | Create a new in-app product (managed product) |
google_create_one_time_product | write | Create a new one-time product (buy or rent) on Google Play. Inspect the returned purchase-option state and call google_activate_purchase_option when it is DRAFT. |
google_create_release | write | Create or update one release with an explicit version-code set. Google Play retains fallback releases; send only the desired change. |
google_create_subscription | write | Create a new subscription on Google Play (monetization API). Pass the full subscription body — including listings and at least one base plan with billing details and per-region pricing. Base plans are created in DRAFT state; call google_activate_subscription_base_plan to make them purchasable. |
google_deactivate_purchase_option | read | Deactivate a one-time product purchase option so it stops being available for purchase |
google_deactivate_subscription_base_plan | read | Deactivate a base plan for new subscribers while existing subscribers retain their subscription. Use this instead of the unsupported subscription archive operation. |
google_delete_all_images | destructive | Delete all images of a specific type for a language |
google_delete_edit | destructive | Discard an edit session without committing changes |
google_delete_iap | destructive | Delete an in-app product |
google_delete_image | destructive | Delete a specific uploaded image |
google_delete_listing | destructive | Delete a store listing for a specific language |
google_delete_one_time_product | destructive | Delete a one-time product |
google_get_country_availability | read | Get country availability for a specific track |
google_get_details | read | Get app details (default language, contact email/phone/website) |
google_get_edit | write | Get an edit session, including its ID and expiry time, before resuming pending work |
google_get_iap | read | Get details of a specific in-app product |
google_get_listing | read | Get store listing for a specific language |
google_get_one_time_product | read | Get details of a specific one-time product |
google_get_review | read | Get a specific review with details |
google_get_subscription | read | Get details of a specific subscription |
google_get_testers | read | Get tester configuration for a track |
google_get_track | read | Get details of a specific release track |
google_halt_release | read | Halt an exact in-progress or completed release; halting a completed production release rolls users back to the previous completed release |
google_list_apks | write | List APKs already available in an edit, including version codes and hashes |
google_list_bundles | write | List Android App Bundles already available in an edit, including version codes and hashes |
google_list_iap | read | List all in-app products (managed products) for an app |
google_list_images | read | List uploaded images of a specific type |
google_list_listings | read | List all store listings (all languages) for an app |
google_list_one_time_products | read | List all one-time products (non-subscription purchases, buy or rent) for an app |
google_list_release_statuses | read | List non-obsolete releases and their review/publishing lifecycle states for a track after an edit is committed |
google_list_reviews | read | List user reviews for an app. Note: the Play Developer API reviews.list endpoint only surfaces recent reviews and requires the |
google_list_subscriptions | read | List all subscriptions for an app |
google_list_tracks | read | List all release tracks, including custom closed-test and form-factor tracks |
google_promote_release | read | Promote a release from one track to another (e.g. beta → production) |
google_reply_to_review | read | Reply to a user review |
google_update_data_safety | write | Submit a user-reviewed Data Safety declaration from an up-to-date Google Play CSV export. Google does not provide a corresponding read endpoint. |
google_update_details | write | Update app details (default language, contact email/phone/website) |
google_update_iap | write | Update an existing in-app product |
google_update_listing | write | Update store listing for a specific language (title, descriptions, promo video) |
google_update_one_time_product | write | Update an existing one-time product. Pass the full desired listings/purchaseOptions state plus an updateMask (e.g. |
google_update_testers | write | Update tester Google Groups for a track |
google_upload_apk | write | Upload an APK file |
google_upload_bundle | write | Upload an Android App Bundle (.aab) |
google_upload_image | write | Upload an image (screenshot, icon, feature graphic, etc) |
google_validate_edit | write | Validate an edit session without committing. Useful to check for errors before commit. |
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (1 observation(s))
- Network
- declared (3 observation(s))
- Shell
- none-observed
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (4)
apple_delete_accessibility_declaration, apple_delete_asset, apple_delete_beta_group, apple_delete_beta_tester, apple_delete_build_upload, apple_delete_iap, apple_delete_phased_release, apple_delete_pl
const sourceFileChecksum = createHash('md5')const checksum = createHash('md5').update(bytes).digest('hex');@modelcontextprotocol/sdk, google-auth-library, googleapis, jsonwebtoken, zod, @types/jsonwebtoken, @types/node, tsx
Gates applied: no_behavioural_pass.
22a036ab3010full audit observations/trust-audit/mcp-server/mikusnuz__app-publish.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-09 | 22a036ab3010 | SAFE | B | 89 | first audit |
Questions
What is the App Publish MCP server?
Unified MCP server for App Store Connect & Google Play Console — 91 tools for listings, screenshots, releases, reviews & submissions
What tools does App Publish expose?
146 in total: 68 read-only, 59 that write, and 19 that can delete or overwrite (apple_delete_accessibility_declaration, apple_delete_asset, apple_delete_beta_group, apple_delete_beta_tester, apple_delete_build_upload). Every one is listed on this page with its risk.
Is App Publish safe to connect to an agent?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean server reads B. Separately from the audit: 19 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does App Publish need?
It reads APPLE_ISSUER_ID, APPLE_KEY_ID, APPLE_KEY_TYPE, GOOGLE_CLIENT_SECRET and GOOGLE_REFRESH_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does App Publish run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as app-publish-mcp at 0.6.0.
How current is this page?
The grade is for one exact copy of the source (22a036ab3010), read on 2026-10-09. The repository is watched and re-audited when it changes.