App Store Connect MCP Server
Provides tools for interacting with Apple's App Store Connect API, enabling AI agents to manage apps, App Store versions, builds, TestFlight groups and testers, sales and finance reports, analytics, users, bundle IDs, and devices, with read-only operations by default and opt-in write capabilities.
Click on "Install 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 Serverlist all my apps"
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.
@mgcrea/mcp-appstore-connect
Model Context Protocol server for the Apple App Store Connect API — inspect your apps, versions, builds, TestFlight, sales and users, and (opt-in) edit metadata and manage testers, straight from an MCP client like Claude.
Unofficial. Not affiliated with or endorsed by Apple. It talks to Apple's public App Store Connect REST API using an API key you generate yourself.
Features
Broad coverage — apps, App Store versions & localizations, builds, TestFlight groups/testers/feedback, sales & finance reports, analytics, users, bundle ids & capabilities, devices.
Listing round-trip — export the whole store listing to a git-committable metadata tree, edit it locally, apply it back with digest-based conflict detection.
Read by default, writes opt-in — mutating tools are not registered at all unless you ask for them. See Security.
Typed & tested — ESM, built with tsdown, linted/formatted with oxc, tested with vitest. Tests run fully offline.
Related MCP server: xcode-cloud-mcp
Security
You are pointing an AI agent at the account that ships your apps, so the honest details matter more than reassurance.
Supply chain
Two direct dependencies: @modelcontextprotocol/sdk and zod. Nothing else is chosen by us.
Being straight about what that actually costs: those two pull in ~94 packages transitively — the number npm install prints, and every one of them arrives via the official MCP SDK. That's the honest figure, not "two dependencies". Two things keep the real exposure much smaller than 94:
Nothing runs at install time. Not one package in the tree declares a
preinstall,installorpostinstallscript, sonpm installexecutes no third-party code — the most common supply-chain attack path simply isn't open.Only 5 are reachable when the server runs: the SDK,
zod,ajv,ajv-formatsandzod-to-json-schema. This server speaks stdio only, so the SDK's HTTP/SSE/OAuth stack (express,hono,jose,cors,pkce-challenge,eventsource) sits in the tree but is never imported.
Check all of it yourself:
npm view @mgcrea/mcp-appstore-connect dependencies # the two
npm ls --omit=dev --all # the ~94
grep -hoE '^import[^;]*from "[^"]+"' node_modules/@mgcrea/mcp-appstore-connect/dist/*.jsThat last command prints everything the shipped bundle imports — the SDK's stdio entrypoints, zod, and Node builtins. Nothing else.
Verified builds
Neither artifact is published from a laptop:
npm — published by CI through Trusted Publishing (OIDC), so there is no long-lived
NPM_TOKENin existence to leak, plus a provenance attestation.Container — build provenance, an SBOM, and a cosign keyless signature.
Both trace back to the exact commit and CI run that produced them. The commands to check are in Verify — please run them rather than take this section's word for it.
Your credentials
The .p8 never leaves your machine, and never goes over the wire. Tokens are minted locally: the server signs short-lived ES256 JWTs (20-minute cap, re-signed just before expiry) using Node's built-in node:crypto. There is no jsonwebtoken or jose in the signing path — one less dependency between your private key and the network. Under Docker the key is mounted read-only and is never baked into the image.
The server never writes to your disk. export_listing hands back {path, content} pairs and your agent writes them, so every file write stays under your own MCP client's permission prompt rather than happening invisibly inside the server.
Blast radius
Three independent limits, smallest first:
Writes are off by default. Mutating tools aren't merely refused when
APP_STORE_CONNECT_ALLOW_WRITES=1is unset — they are never registered, so they don't appear in the tool list and a confused agent cannot call them. The default install is read-only.Destructive tools need
confirm: true. Deleting a screenshot, removing a tester, or submitting a version to Apple takes an explicit acknowledgement argument, so it can't happen as a side effect of some broader request. Submitting is the one that leaves your account — it is gated the same way, and refuses outright unless the version is in a submittable state with a build attached.Your API key's role is the real ceiling, and this server can't raise it. A read-only role is enough for every list/get tool; issue one of those and no bug here can write anything. Scope the key to the narrowest role that does your job.
Applying a listing has its own rails — digest-based conflict detection, an allowClear gate before any field is emptied, and a whole-apply abort if any field is over Apple's limit. See Listing round-trip.
Configure
Create a key in App Store Connect → Users and Access → Integrations → Keys → App Store Connect API. Apple gives you an Issuer ID, a Key ID, and a one-time .p8 download. Then set:
Variable | Required | Notes |
| yes | The 10-char Key ID. |
| yes | The Issuer ID (a UUID). |
| one of | Path to the |
| one of | Inline PEM contents (for Docker/CI); set this or the path. |
| reports | Needed by the sales/finance reports only, not by analytics. |
| no |
|
| no | Retry budget for 401/429/5xx. Defaults to 3. |
| no | Where the listing tree lives. Defaults to |
| no |
|
See .env.example for the annotated list.
Config file
If you'd rather not put credentials in your shell profile or in every MCP client config, the server reads a config file instead:
// ~/.config/appstore-connect/config.json (chmod 600)
{
"keyId": "XXXXXXXXXX",
"issuerId": "00000000-0000-0000-0000-000000000000",
"p8Path": "~/path/to/AuthKey_XXXXXXXXXX.p8",
"allowWrites": true,
}mkdir -p ~/.config/appstore-connect
$EDITOR ~/.config/appstore-connect/config.json
chmod 600 ~/.config/appstore-connect/config.jsonWith this in place an MCP client needs no env block at all — just npx -y @mgcrea/mcp-appstore-connect.
The environment wins, field by field. A config file supplies whatever the environment doesn't, so Docker and CI keep working exactly as before, and a one-off
APP_STORE_CONNECT_ALLOW_WRITES=0still overrides a file that saystrue.Keys are camelCase (
keyId, notAPP_STORE_CONNECT_KEY_ID),~is expanded inp8Path, andp8takes an inline PEM as the alternative top8Path.metadataRootsets where this machine's repos keep their listing tree — useful if you prefer"AppStore"to the fastlane default. It must be repo-relative; use"."for the repo root.Unknown keys are an error, not ignored — a typo'd
keyIDtells you so instead of silently falling back to the environment.Location:
$APP_STORE_CONNECT_CONFIG, else$XDG_CONFIG_HOME/appstore-connect/config.json, else~/.config/appstore-connect/config.json. An absent file is fine; a malformed one is reported with its path.The server warns on stderr if the file is readable by other users.
The API key's role (set when you create it) decides what it can touch. A read-only role is enough for the list/get tools; editing metadata or managing testers needs App Manager or Admin. Team-scoped keys may require a JWT
scopeclaim — if a call fails with401 NOT_AUTHORIZED, that's the likely cause.
Quick start
Pick one of the three. All talk to the same App Store Connect API — the difference is only how the server is launched. Options A and B need nothing checked out.
A. npx — recommended
Zero install; npx fetches and runs the published package. Wire it into Claude Code (or any MCP client) with your credentials:
{
"mcpServers": {
"appstore-connect": {
"command": "npx",
"args": ["-y", "@mgcrea/mcp-appstore-connect"],
"env": {
"APP_STORE_CONNECT_KEY_ID": "XXXXXXXXXX",
"APP_STORE_CONNECT_ISSUER_ID": "00000000-0000-0000-0000-000000000000",
"APP_STORE_CONNECT_P8_PATH": "/absolute/path/to/AuthKey_XXXXXXXXXX.p8"
}
}
}
}To try it from a shell (reads the same env, or the config file):
npx -y @mgcrea/mcp-appstore-connectB. Docker (stdio)
Runs the container image published to GHCR. The .p8 never goes into the image or the config — mount it read-only and point APP_STORE_CONNECT_P8_PATH at the in-container path. The -e VAR (no value) flags forward the key id / issuer id from the env block, so no secret sits in args:
{
"mcpServers": {
"appstore-connect": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"APP_STORE_CONNECT_KEY_ID",
"-e",
"APP_STORE_CONNECT_ISSUER_ID",
"-e",
"APP_STORE_CONNECT_P8_PATH=/keys/key.p8",
"-v",
"/absolute/path/to/AuthKey_XXXXXXXXXX.p8:/keys/key.p8:ro",
"ghcr.io/mgcrea/mcp-appstore-connect:latest"
],
"env": {
"APP_STORE_CONNECT_KEY_ID": "XXXXXXXXXX",
"APP_STORE_CONNECT_ISSUER_ID": "00000000-0000-0000-0000-000000000000"
}
}
}
}-i keeps stdin open, which the stdio transport needs — don't drop it. The left side of -v is the host path to your .p8; the container only ever sees /keys/key.p8. GHCR is the only registry CI publishes to — it's what carries the provenance/SBOM/cosign signature described in Verify below.
C. From source (development)
git clone https://github.com/mgcrea/mcp-appstore-connect.git
cd mcp-appstore-connect
pnpm install
pnpm build
node dist/cli.js # credentials from the env or the config fileOr wire the built entry directly: "command": "node", "args": ["/absolute/path/to/mcp-appstore-connect/dist/cli.js"].
Inspect the tools
npx @modelcontextprotocol/inspector npx -y @mgcrea/mcp-appstore-connectTools
Apps — list_apps, get_app, update_app* — update_app carries contentRightsDeclaration, one of the gates below.
Submission prerequisites — what a first submission trips over. None of these lives on the version, so nothing in the version's own state hints at them, and submit_version_for_review fails with one error per missing item and no id to chase. Each is set once and outlives every release:
Missing | Apple's error | Fix with |
Category |
|
|
Content rights |
|
|
App price |
|
|
Review contact |
|
|
A free app still needs a price: "free" is a price point, not the absence of one, so an app nobody ever charged for stays blocked until set_app_price points at the 0 price point.
set_app_store_review_detail creates or updates as needed: PATCH against a version with no detail 404s and POST against one that has it 409s, so the verb is a property of server state rather than of what you meant. Absence also arrives two ways — a 404, and a 200 with data: null — and only handling the first sends a PATCH to a nonexistent id.
App Privacy has no public API, and is the fifth gate. A version is refused with
STATE_ERROR.APP_DATA_USAGES_REQUIREDuntil the data-collection questionnaire is answered and published, and there is no route to do it. Tools for it were written against Apple's documented resource names, then removed when every endpoint 404'd. The evidence, so nobody has to establish it twice:
appDataUsages,appDataUsageCategories,appDataUsagePurposes,appDataUsageDataProtectionsandappDataUsageGroupingsall answerPATH_ERROR — The resource 'v1/…' does not exist, andappDataUsagesis absent from the app resource's ~40 relationships.
POSTfails identically toGET. A route that existed but disliked the body would answer 400 or 409; the same path error on both means it is not routed at all.Not a permissions problem — the same key reads
/v1/usersand/v1/apps/{id}/accessibilityDeclarations(a comparably recent app-scoped resource) with 200.
/v2/appDataUsagesandappDataUsagesV2are undefined types, so it is not a version-prefix issue. NotePATH_ERRORis a different code from theNOT_FOUND — path does not match a defined resource typean invented name returns: Apple's gateway appears to know these names while not exposing them, which is why the docs describe resources you cannot call.Do it in the web UI: App Privacy → Get Started, answer, then Publish — saved-but-unpublished is refused exactly as unanswered is. The answers are app-scoped rather than version-scoped, so it is once per app, not once per release.
An app's first non-consumable IAP has no API path either, and this one is worse because nothing fails until it is too late. Apple requires it to travel inside the version's review submission (
STATE_ERROR.FIRST_NON_CONSUMABLE_MUST_BE_SUBMITTED_ON_VERSION), and no route puts it there:reviewSubmissionItemsrejectsinAppPurchaseandinAppPurchaseV2withRELATIONSHIP.UNKNOWN,appStoreVersionshas noinAppPurchasesrelationship, and the IAP has noappStoreVersionrelationship.
submit_version_for_reviewsucceeds and silently leaves the IAP behind. The version goes to review alone, the IAP staysREADY_TO_SUBMIT, and the app ships with a paywall selling a product Apple never approved. So after submitting a release that introduces one, re-readlist_in_app_purchases: a first IAP still readingREADY_TO_SUBMITmeans it was left out. Recovering means cancelling the submission — which returns the version toDEVELOPER_REJECTED, still submittable — and using the version page's Add for Review panel, which lists the IAP beside the version. Second and later IAPs go throughsubmit_in_app_purchase_for_reviewnormally.
Listing round-trip — export_listing, apply_listing* — pull the whole listing into a git-committable metadata tree, edit it locally, push it back. See Listing round-trip.
Versions & metadata — list_versions, get_version (resolves the attached build — which binary the version would actually ship, and when it was uploaded), list_version_localizations, get_version_localization, create_version*, update_version* (release type — auto on approval, manual, or scheduled), update_version_localization* (description, keywords, what's-new, promo text)
Review submissions — list_review_submissions, submit_version_for_review*†, cancel_review_submission*† — hand a finished version to Apple for review, or withdraw it
Release — release_version*† — release an approved version sitting in PENDING_DEVELOPER_RELEASE (the manual "Release This Version" button)
App info — list_app_infos, list_app_info_localizations, get_app_info_localization, update_app_info_localization* (name, subtitle, privacy policy — the fields that outlive a version)
Age rating — get_age_rating_declaration, update_age_rating_declaration* — the questionnaire answers behind the rating, one per appInfo rather than per version. socialMedia must be answered from September 2026 before Apple accepts a new version, an update, or a notarization request.
In-app purchases — list_in_app_purchases, get_in_app_purchase, list_iap_price_points, get_iap_price_schedule, set_in_app_purchase_price*†, update_in_app_purchase* — read the price-point catalogue for a territory, then price the IAP against one. update_in_app_purchase carries the reference name, the review note and familySharable. One-time purchases only; auto-renewable subscriptions are not covered.
In-app purchase metadata — list_iap_localizations, get_iap_review_screenshot, get_iap_availability, create_iap_localization*, update_iap_localization*, delete_iap_localization*†, upload_iap_review_screenshot*†, set_iap_availability*, submit_in_app_purchase_for_review*† — an IAP sits at MISSING_METADATA, and cannot be submitted, until four things exist: a per-locale display name, a description, a review screenshot, and territory availability. Availability is the one people miss, because the App Store Connect UI fills it in silently and the API does not — set_iap_availability defaults to every territory Apple offers. These are the customer-facing strings on the purchase sheet, not the app's own listing, and the limits are much tighter — 30 characters for the name and 45 for the description, checked locally because Apple answers an over-length value with a 409 that names neither the field nor the limit. submit_in_app_purchase_for_review refuses anything not already READY_TO_SUBMIT rather than forwarding a rejection.
Screenshots — list_screenshot_sets, list_screenshots, get_screenshot, upload_screenshot*, delete_screenshot*†, delete_screenshot_set*†, reorder_screenshots*†
Builds — list_builds
TestFlight — list_beta_groups, list_beta_testers, list_beta_feedback, create_beta_group*, invite_beta_tester*, add_tester_to_group*, remove_tester_from_group*† — an app with no group has nowhere to send a build, so create_beta_group is the first step of setting TestFlight up; every other tool here needs the group id it returns. Internal groups take testers who are already Users on the account and skip Beta App Review, so hasAccessToAllBuilds is the quickest way to make builds you have already uploaded installable.
Sales & finance reports — download_sales_report, download_finance_report — the Sales and Trends TSVs: units, proceeds, installs by territory and install type. Needs a vendor number.
Analytics — list_analytics_report_requests, list_analytics_reports, list_analytics_report_instances, list_analytics_report_segments, download_analytics_report_segment, create_analytics_report_request* — App Analytics proper: impressions, product page views, conversion rate, installs, deletions, sessions, retention. See Reading analytics.
Customer reviews — list_customer_reviews — star rating, title, body, territory and date, newest first; filter by rating to read just the complaints. These are written reviews only. Most people rate without writing, and Apple exposes no aggregate star average here, so a distribution computed from these is directional — it is not the App Store rating.
Users — list_users
Bundle IDs — list_bundle_ids, get_bundle_id, create_bundle_id*, enable_capability*, disable_capability*†
Devices — list_devices, register_device*
Italic* tools are writes, hidden unless APP_STORE_CONNECT_ALLOW_WRITES=1. † additionally requires confirm: true.
Tool names are prefixed app_store_connect_ (omitted above for brevity).
A Claude Code skill that drives these tools through a full release ships alongside the server — see Release-prep plugin.
Listing round-trip
export_listing returns the complete listing — name, subtitle, description, keywords,
what's-new, promotional text and URLs, across every locale — as a set of files to write
into your repo:
fastlane/metadata/
.listing.json # ids + baseline digests. Commit it; never hand-edit it.
en-US/
name.txt subtitle.txt description.txt keywords.txt
release_notes.txt promotional_text.txt
marketing_url.txt support_url.txt privacy_url.txt
fr-FR/
...This is the layout fastlane deliver already uses, so the tree interops with it. One
file per field means the file content is the value, byte for byte — a description
containing ## Keywords, a --- rule or a fenced code block is just text, and git diff shows you the field that changed rather than a line number in a wall of copy.
The location is a default, not a requirement. Keep the tree wherever you like — set
APP_STORE_CONNECT_METADATA_ROOT (or metadataRoot in the config file) to change it for
every repo on the machine, or pass metadataRoot to a single export_listing call. The
fastlane path is the default only because it's the one other tools already read.
apply_listing needs no such setting: it finds the tree from wherever you pass
.listing.json, so a tree you move later keeps working.
The server never writes to disk: export_listing hands back {path, content} pairs and
your agent writes them, so every write stays under your own permission prompt and nothing
depends on host paths being visible inside Docker.
Editing and pushing back:
export_listing { appId } # version defaults to "latest"
# ...edit the .txt files, commit, review...
apply_listing { files: [...] } # dry run by default
apply_listing { files: [...], dryRun: false, confirm: true }versionaccepts"latest"(the one you're preparing),"live"(on sale) or an exact"1.4.0". Versions are ordered numerically, so1.10.0beats1.9.0.Pass only the files you changed, plus
.listing.json— it carries the localization ids and the per-field digests recorded at export, and its directory is what tells the server where the tree lives. Every file you pass must sit under that same directory; mixing two trees is an error rather than a silent push against the wrong ids.Those digests make apply a three-way merge. A field edited in App Store Connect's web UI since your export is reported as a conflict and skipped, rather than silently overwritten; re-export and merge, or pass
force: true.An absent file leaves a field alone; an empty file clears it — but clearing needs
allowClear: true, so a file truncated by accident is reported asblockedrather than wiping live copy.Any field over Apple's limit aborts the whole apply before the first write — a half-applied listing is worse than an untouched one.
format: "review"renders a read-only markdown summary with character counts, for when you just want to read the listing. Nothing parses it back.If the metadata tree already exists, diff before overwriting it.
Reading analytics
App Analytics is not a single endpoint. Apple generates the reports asynchronously and files them behind four nested resources, so reaching an actual number is a walk:
analyticsReportRequest one per app, created once, then reused forever
└─ report a named dataset, e.g. "App Store Installation and Deletion"
└─ instance one per granularity (DAILY/WEEKLY/MONTHLY) and processing date
└─ segment the gzipped CSV that holds the rowsOne tool per hop, in order:
create_analytics_report_request— once per app, and only if there isn't one already. Apple rejects a secondONGOINGrequest, so runlist_analytics_report_requestsfirst and reuse the id it returns.ONE_TIME_SNAPSHOTbackfills roughly the last 52 weeks;ONGOINGkeeps producing new instances.list_analytics_reports— filter bycategory:APP_STORE_ENGAGEMENTfor impressions, product page views and conversion rate;APP_USAGEfor installs, deletions, sessions and retention;COMMERCEfor sales and proceeds.list_analytics_report_instances— filter bygranularity, then pick aprocessingDate. There is one instance per date, so an unfiltered list is mostly noise.download_analytics_report_segment— returns the rows as text, truncated tomaxLines.
Notes worth knowing before the first run:
Nothing exists for a day or two after the request. An empty report list is the expected answer immediately after
create_analytics_report_request, not a failure.The download resolves its own segment URL. Those URLs are signed, off the API host, and expire within minutes, so
download_analytics_report_segmenttakes aninstanceIdand re-lists the segments itself. Nothing has to carry a URL between calls.A big instance is refused, not streamed. The segment is decompressed in the server process, so anything over 25 MiB compressed fails with its size; raise
maxBytesto override, or pick aDAILYinstance instead ofMONTHLY.Segments are plural. A large report splits across several;
list_analytics_report_segmentsshows how many, andsegmentIndexselects one.
This is a different pipeline from download_sales_report — that one is Sales and Trends,
keyed by vendor number and date rather than by report request, and it is the better source
for units and proceeds. Analytics is where the funnel metrics live.
Release-prep plugin
This repo doubles as a Claude Code plugin marketplace. The
appstore-toolkit plugin bundles the appstore-release-prep skill, which drives the
round-trip above: it audits what shipped since the last release, writes the CHANGELOG entry
and every store field within Apple's limits, and pushes the result back through
apply_listing.
/plugin marketplace add mgcrea/mcp-appstore-connect
/plugin install appstore-toolkit@mgcrea-appstoreInstalling it also wires up the appstore-connect MCP server, so the skill and the tools it
calls arrive together. The plugin stores no credentials of its own — set up the
config file once and the server finds them wherever you work.
apply_listing is a write tool, so it stays hidden until writes are enabled
("allowWrites": true in the config file, or APP_STORE_CONNECT_ALLOW_WRITES=1). That is
deliberate: installing a plugin should not silently grant it permission to overwrite a live
App Store listing.
The skill also ships an offline auditor (scripts/audit_release.py, stdlib Python, no network
calls) that measures every field against its limit and exits non-zero when one is over or
missing, so it can gate a release from CI.
Notes
Tokens are minted locally. Each request carries a fresh-enough ES256 JWT (
aud: appstoreconnect-v1), cached and re-signed shortly before Apple's 20-minute cap. The.p8never leaves your machine.Reports are TSV, not JSON.
download_sales_report/download_finance_reportgunzip Apple's report and return the text (truncated tomaxLines). Reports lag ~24–48h and are keyed by date/frequency.Analytics is asynchronous and nested. Create the report request once, wait a day or two for Apple to generate it, then walk request → report → instance → segment to reach the rows. See Reading analytics.
upload_screenshotreads the file server-side. Pass an absolutefilePaththe server can reach. Under Docker that means a path inside the container — mount the folder (-v /host/screenshots:/screenshots) and pass the container path, or send small images inline as base64 viafileData.Screenshots validate after upload. Apple checks pixel dimensions asynchronously, so a wrongly-sized image fails during processing rather than at upload; the tool waits (
waitSeconds, default 60) and reports Apple's exact reason. Timing out is not a failure — the upload already succeeded, so pollget_screenshotinstead of retrying. The version must be editable (PREPARE_FOR_SUBMISSIONorDEVELOPER_REJECTED), and a set holds at most 10 screenshots.Screenshot order is explicit.
reorder_screenshotsreplaces a set's full contents, so pass every id you want to keep — an omitted one is removed from the set.
Develop
pnpm dev # tsdown --watch
pnpm test # vitest (offline; no real credentials needed)
pnpm typecheck # tsc --noEmit
pnpm lint # oxlint
pnpm format # oxfmt --write .Tests run entirely offline: JWT signing is verified against a throwaway P-256 key, and the tools are driven over an in-memory MCP transport with a mocked fetch.
Publish
Options A (npx) and B (Docker) resolve only once a release is out. Pushing a v*.*.* tag triggers CI to:
publish to npm via Trusted Publishing (OIDC — no
NPM_TOKENstored anywhere) with a provenance attestation, andbuild, sign, and push the multi-arch image to
ghcr.io/mgcrea/mcp-appstore-connect, with build provenance, an SBOM, and a cosign keyless signature.
Both artifacts are cryptographically traceable back to the exact commit and CI run that produced them — see Verify below. Until a release exists, use Option C from source.
Verify
Before trusting an artifact from Option A or B, you can check it was actually built by this repo's CI rather than published from someone's laptop:
# npm — provenance attestation (also shown as a badge on the npmjs.com package page)
npm audit signatures
# Docker — cosign keyless signature, tied to this repo's GitHub Actions identity
cosign verify \
--certificate-identity-regexp 'https://github.com/mgcrea/mcp-appstore-connect/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/mgcrea/mcp-appstore-connect:latestLicense
MIT — Olivier Louvignes
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityFmaintenanceAn MCP server to communicate with the App Store Connect API for iOS Developers2585330MIT
- AlicenseBqualityAmaintenanceMCP server for managing Xcode Cloud workflows, builds, and test artifacts via the App Store Connect API.1591MIT
- AlicenseAqualityBmaintenanceAn MCP server that drives the full App Store release cycle for iOS and macOS apps: version bump, archive + TestFlight upload, metadata, review submission, and status.832MIT
- AlicenseBqualityCmaintenanceAn unofficial MCP server for the App Store Connect API that enables automation of app management, reviews, TestFlight, analytics, and release processes through natural language.63812MIT
Related MCP Connectors
MCP server for Appcircle mobile CI/CD platform.
MCP server for interacting with the Supabase platform
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mgcrea/mcp-appstore-connect'
If you have feedback or need assistance with the MCP directory API, please join our Discord server