shipstores
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ASC_KEY_ID | No | App Store Connect API key ID (App Store Connect → Users and Access → Integrations → API key with role Admin or App Manager). Required for iOS. | |
| APPLE_TEAM_ID | No | Apple Team ID. Optional; detected by store_doctor from any bundle ID. | |
| ASC_ISSUER_ID | No | App Store Connect API issuer ID. Required for iOS. | |
| PLAY_DEVELOPER_ID | No | Google Play developer ID, the number after /developers/ in the Play Console URL. Used for console forms. | |
| ASC_PRIVATE_KEY_PATH | No | Path to the App Store Connect .p8 private key file (default ~/.config/shipstores/AuthKey_<KEY_ID>.p8). Used for iOS. | ~/.config/shipstores/AuthKey_<KEY_ID>.p8 |
| PLAY_SERVICE_ACCOUNT_PATH | No | Path to the Google Play service account JSON invited in Play Console with release permissions. Required for Android. |
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
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| store_doctorA | Check the credentials for both stores with real API calls. Use this before investigating any authentication error. Returns, for each store, whether the credential authenticates and what is missing. |
| store_browser_sessionA | Login state of the dedicated browser on both consoles. Console forms (App content, Data safety, app creation) run in a headless Chrome with its own profile, so they do not fight the user for the screen. Apple's session expires often; when it does, the automation ends up reading the login screen and returns meaningless results — so check here before investigating a form that "did not save". With relogin=True, opens Chrome WITH a window so a person can authenticate
(2FA cannot be automated). Pass |
| apple_list_appsA | List the apps in the App Store Connect account with id, bundleId and name. The returned |
| apple_register_bundle_idB | Register a new Bundle ID in the Apple Developer portal. This is the first step for a new app and IS supported by the API. After it, the app record itself must be created through the form (apple_create_app_form). platform: IOS, MAC_OS or UNIVERSAL. |
| apple_create_app_formA | Open the App Store Connect new-app form in the browser. Apple's API does not expose app creation (there is no POST /v1/apps), so this step is assisted: the tool opens the page in the already logged-in Chrome and returns the values you need to fill in. Register the Bundle ID first with apple_register_bundle_id. |
| apple_upload_buildA | Upload an .ipa to App Store Connect via xcrun altool. Build processing takes a few minutes after the upload — track it with apple_list_builds. platform: ios, osx or appletvos. |
| apple_list_buildsB | List an app's builds and the processing state of each. processingState PROCESSING means the build cannot be attached to a version yet; VALID means it is ready to use. |
| apple_create_versionA | Create a new App Store version for an existing app. Fails if an editable version already exists — in that case reuse the existing one (apple_list_versions) instead of creating another. |
| apple_list_versionsB | List an app's App Store versions, with the review state of each. |
| apple_update_listingB | Update the store listing texts of a version, for one locale. Only the fields passed are changed. |
| apple_attach_buildA | Attach a processed build to an App Store version. The build must have processingState VALID (see apple_list_builds). |
| apple_submit_for_reviewA | Submit a version for Apple review. External action, hard to reverse. Confirm with the user before calling. Requires the version to already have a build attached and complete metadata. |
| apple_set_app_infoA | Fill in the listing fields that apple_update_listing does not cover. External action. Subtitle and privacy policy URL live on the appInfo; support URL, marketing URL and copyright live on the editable version; categories use Apple IDs (e.g. MEDICAL, HEALTH_AND_FITNESS, LIFESTYLE, EDUCATION, PRODUCTIVITY, BOOKS). Only the fields passed are changed. |
| apple_set_age_ratingA | Answer the age rating questionnaire. External action. Starts from all "no/NONE" and applies |
| apple_set_free_priceC | Make the app free (price 0 in the base territory). External action. |
| apple_set_availabilityB | Choose the countries where the app is available (3-letter ISO, e.g. ["BRA"]). External action. Uses the console's internal API (the public one answers 409), in the dedicated Chrome session. Including the European Union requires the trader declaration (DSA) on the account. |
| apple_set_app_privacyA | Replace and publish the "App Privacy" declaration (privacy nutrition label). External action. usages: one item per collected data type: {"category": "NAME", "purposes": ["APP_FUNCTIONALITY"], "linked": true, "tracking": false} Empty list = "we do not collect data". Accepted categories and purposes are in apple_console.DATA_CATEGORIES / DATA_PURPOSES. Uses the console's internal API. |
| apple_testflight_inviteA | Invite someone to the app's internal TestFlight (a group that receives every build). External action. Internal testing skips review, but the person must be a user on the team in
App Store Connect (check under Users and Access). If no internal group named
|
| apple_cancel_submissionA | Pull a version submitted for review out of the queue (before Apple decides). External action. Use it to swap the build without waiting for the review: the version goes back to DEVELOPER_REJECTED and can be resubmitted with apple_submit_for_review. |
| apple_resubmit_for_reviewA | Resubmit a rejected version after replying to App Review or fixing it. External action. Same as "Update Review" on the version page followed by "Resubmit to App Review": marks the rejected items as resolved and submits the same review submission again. Replying in the Resolution Center alone keeps the version Rejected. Attach a new build first (apple_attach_build) if the fix needed one. |
| apple_review_messagesA | Read the review messages (Resolution Center) and the rejection reasons. The public API does not expose this: it reads through the console's internal API, in the dedicated Chrome session (check store_browser_session if it fails due to login). |
| apple_reply_reviewA | Reply to App Review on a rejected submission, with attachments. External action. For a "Guideline 2.1 - Information Needed" request: send the answers in
|
| apple_review_detailsA | Read a version's App Review information (contact, demo account, notes). The demo account password is masked — the goal here is to check what Apple will see, not to extract credentials. |
| apple_set_review_detailsA | Fill in the information App Review reads before testing. External action. Only the fields passed are changed. When the app has content behind a login, the demo account must be able to reach what Apple wants to evaluate: in a subscription app, an account that already has everything unlocked hides the purchase screen, and review rejects the app for not being able to test it. Passing |
| apple_set_version_stringB | Rename an editable version. External action. Useful to reuse a REJECTED version: while it occupies the slot, Apple refuses to create another one ("You cannot create a new version of the App in the current state"). Renaming it to the new build's version number avoids wiping the already filled-in listing. |
| apple_list_subscriptionsA | List the app's subscription groups, with the products in each.
|
| apple_create_subscription_groupA | Create a subscription group and its localization. External action.
|
| apple_create_subscriptionA | Create a subscription product inside a group. External action.
subscription_period: ONE_WEEK, ONE_MONTH, TWO_MONTHS, THREE_MONTHS, SIX_MONTHS or ONE_YEAR. The App Store has no installment plans. The product starts in MISSING_METADATA: it still needs a price (apple_set_subscription_price) and availability (apple_set_subscription_availability). |
| apple_list_price_pointsA | List the price points available for a subscription in a territory. Apple does not accept arbitrary prices: you pick a point from its price table.
Pass |
| apple_set_subscription_priceA | Set the subscription price from a price point. External action. Get the
|
| apple_set_subscription_availabilityB | Set the countries where the subscription is sold. External action. Without this the product stays in MISSING_METADATA and cannot go to review. The default is Brazil only (BRA). |
| apple_create_intro_offerA | Create the subscription's introductory offer (free trial). External action. duration: THREE_DAYS, ONE_WEEK, TWO_WEEKS, ONE_MONTH, TWO_MONTHS, THREE_MONTHS, SIX_MONTHS or ONE_YEAR. Apple has no "14 days" — TWO_WEEKS is the exact equivalent. offer_mode: FREE_TRIAL (free), PAY_AS_YOU_GO or PAY_UP_FRONT. The last two charge a lower price and require a price point, which this tool does not cover.
|
| apple_upload_subscription_screenshotA | Upload a subscription's App Review screenshot. External action. Every subscription needs a screenshot showing where the purchase happens in the app, otherwise it stays stuck in MISSING_METADATA and cannot be part of any submission — even with price, localization, availability and offer all set. Use the screen where the subscription is offered, not the home screen. App Store Connect uploads happen in three steps: reserve the asset, send the bytes to the URL it returns, and commit with the checksum. |
| apple_upload_screenshotsA | Upload the App Store listing screenshots, in order. External action. Uploads every image in the folder, in alphabetical order of file name, and pins that order in the store — without this the order falls back to creation order, which Apple does not guarantee. Name the files with a numeric prefix (01-, 02-). A screenshot belongs to a VERSION: a READY_FOR_SALE version cannot be changed.
Create the next one with apple_create_version and point to it — the new
version inherits the previous one's screenshots, and display_type: APP_IPHONE_67, APP_IPHONE_65, APP_IPHONE_61, APP_IPAD_PRO_3GEN_129, among others. |
| play_create_app_formA | Open the Play Console app list in the browser to create a new app. The Google Play Developer API cannot create a new packageName — the initial registration must go through the console. This tool opens the page and returns what to fill in. |
| play_track_statusA | List the app's Play tracks and the active releases on each. Read-only — opens and discards an edit without committing anything. Also useful to confirm that the service account has access to the app. |
| play_upload_bundleA | Upload an .aab and release it on a Play track, in a single committed edit. External action: on commit, the release becomes visible to the track's testers (or to the public, if track=production). Confirm the track with the user. track: internal, alpha, beta or production. status: completed, draft, inProgress or halted. |
| play_upload_screenshotsA | Upload the Play Store listing screenshots, in order. External action. The commit publishes to the listing immediately — it does not depend on a release or on review. Store order is upload order, so images go in alphabetical order of file name: name them with a numeric prefix (01-, 02-). image_type: phoneScreenshots, sevenInchScreenshots, tenInchScreenshots, tvScreenshots or wearScreenshots. Each size is a separate set — call once per folder. |
| play_list_screenshotsB | List the published screenshots of one listing image type. Read-only. Returns the sha256 of each image, in the order they appear in the store — you can compare them with local files to confirm what is published. |
| play_promote_releaseA | Promote an already uploaded versionCode to another track, without a new upload. External action: promoting to production publishes the app. Confirm with the user. For a staged rollout use status=inProgress with user_fraction (e.g. 0.1 = 10%). |
| play_update_listingA | Update the Play Store listing texts, for one language. External action: the commit publishes the texts to the store. Google's limits — title 30 characters, short description 80, full description 4000. |
| play_signing_sha1A | Download Play's app signing certificates and return the SHA-1 of each. Use when "Sign in with Google" works on a local build but fails with the store
APK — symptom: the account picker opens, the user picks an account and lands
back on the login screen, with no error. With Play App Signing the distributed
APK is re-signed by Google, and the SHA-1 that reaches the device is the one
from The SHA-1 shown as text on the "App signing" page is the UPLOAD key's and does not work. This is the value to register as an Android OAuth client (package + SHA-1) in the Google Cloud Console — there is no API for that, UI only. |
| play_contact_detailsB | Read the public contact details of the app's Play listing. These fields (contactEmail, contactWebsite, contactPhone) ARE covered by the API — do not automate the console form for them. |
| play_set_contact_detailsA | Update the public contact details of the app's Play listing and commit. External action: these details are shown to users on Google Play. Double-check that the e-mail and website belong to the publishing entity (see store_audit_identity). |
| store_audit_identityA | Scan both stores for text that should not be there. Built to catch identity leaks — the wrong company's e-mail or name in a public
listing, review notes or contact details. |
| play_submission_statusB | Report whether there are changes waiting to be sent, in review, or nothing pending. Reads the "Publishing overview" page. "Changes in review" means the changes were already sent to Google; "Send N changes for review" means they are still waiting to be sent. |
| play_submit_for_reviewA | Send the app's pending changes to Google for review. External action. On a new app this does NOT publish: "Send for review" and "Publish" are separate steps, and the second one remains yours. On an already published app with managed publishing turned off, approval publishes automatically — confirm before using it in that case. Before calling, the release must be confirmed (Production -> Releases -> Edit release -> Next -> Save). Use play_submission_status to check. |
| play_content_statusA | Show how many "App content" declarations are still missing before the app can publish. A draft app on Play only leaves draft once all of them are complete. None of them has an API endpoint — they are console forms. |
| play_content_openA | Open an "App content" declaration in the browser and return its text. Use it to see the questions and options before answering. URL slugs do not follow the form name (e.g. "financial" lives at /finance, "app_access" at /testing-credentials) — this mapping is already resolved. form: privacy_policy, ads, app_access, government, financial, health, data_safety, content_rating. |
| play_content_optionsA | List the controls (radios/checkboxes) of the open declaration and the state of each. Reads from the accessibility tree, not the DOM — Angular Material controls are not usable via querySelector. Call play_content_open first. |
| play_content_answerA | Select an option by its text in the open declaration and confirm it took effect. Material's sits ~15px above the visible circle, so a click at the center toggles nothing. This tool tries several offsets and only reports success when the accessibility tree confirms the state. option: the option's label as shown in the console UI (pt-BR, e.g. "Não"). nth: when the same text appears several times (e.g. several "Não"), which occurrence to select, starting at 0. |
| play_content_saveB | Save the open declaration and dismiss the dialog the console opens afterwards. button: the console button label, matched literally against the pt-BR UI: "Salvar" (Save), "Avançar" (Next, in multi-step wizards) or "Salvar como rascunho" (Save as draft). |
| play_data_safety_exportB | Download the Data safety declaration CSV template. The declaration is a 5-step wizard with hundreds of checkboxes, but it accepts CSV import — much faster and more reliable than clicking screen by screen. The download requires Browser.setDownloadBehavior (Page. does not work) and the file arrives with a GUID name, which this tool renames to datasafety-template.csv. |
| play_data_safety_fillA | Fill in the Data safety CSV and return a summary of what was declared. Imports nothing — it generates the file for review. An incorrect declaration here can take down a published app, so review the summary with the user before play_data_safety_import. collected_data maps the Response ID of each collected data type (e.g. "PSL_EMAIL") to {"group": "PSL_DATA_TYPES_PERSONAL", "shared": false, "optional": false, "purposes": ["PSL_APP_FUNCTIONALITY", "PSL_ACCOUNT_MANAGEMENT"]}. |
| play_data_safety_importA | Import the filled-in CSV into the Data safety declaration. External action: replaces the app's entire declaration. Review the summary from play_data_safety_fill with the user before calling. |
| eas_build_listA | List an Expo project's EAS builds, with the artifact URL. Use this to find out whether a ready binary already exists before spending a new
build. A present platform: ios or android. status: finished, in-queue, in-progress, errored. |
| eas_build_startA | Start an EAS build and return immediately, without waiting for it to finish. Builds take 10 to 40 minutes. This tool does NOT block — track progress with eas_build_status using the returned build_id. platform: ios, android or all. profile: a profile defined in eas.json. |
| eas_build_statusB | Get the state of an EAS build by id. status FINISHED with artifact_url set means it is ready to publish. |
| eas_build_downloadA | Download the binary of a finished EAS build to a local path. This is the link between EAS and the publishing tools: download the artifact and pass the path to apple_upload_build or play_upload_bundle. |
| eas_submitA | Submit an EAS build straight to the store, using the submit profile in eas.json. External action: this really publishes. Confirm the profile and platform with the user. iOS: downloads the .ipa from EAS and uploads it via altool with this server's key (eas submit does not accept an API key without a prompt). Android: eas submit with the submit profile in eas.json. Without build_id, uses the most recent finished build. |
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 60 tools
Tools are mostly distinct with clear prefixes (apple_, play_, eas_, store_) and specific actions, making it easy to select the right one for a given store or task. However, multiple submission-related tools (e.g., eas_submit, apple_submit_for_review, play_submit_for_review) and several 'set_' tools for different metadata fields could cause confusion without careful reading of descriptions.
Tool names follow a highly consistent pattern: a platform prefix (apple_, play_, eas_, store_) followed by a verb_noun structure (e.g., list_apps, create_version, upload_build). There are no deviations in casing or style, making the set predictable and easy to navigate.
With 60 tools, the server far exceeds the typical 3–15 range and even the 25-tool threshold for being overly heavy. While the domain (two app stores plus EAS builds) is broad, the sheer number of tools risks overwhelming an agent and suggests the server could be split into more focused sets.
The tool surface covers the full lifecycle for both Apple and Google Play: builds, uploads, metadata, submissions, subscriptions, screenshots, and content declarations. Minor gaps exist, such as reading Play reviews or managing Apple in-app purchases beyond subscriptions, but these are not critical for the core publishing workflows.