app-store-connect-mcp
Provides tools to interact with Apple's App Store Connect and App Store Server (StoreKit 2) APIs, enabling management of apps, pricing, subscriptions, reviews, builds, and TestFlight across both commerce APIs.
Integrates with Apple's App Store Connect and App Store Server API to manage app store operations including app metadata, pricing, subscriptions, submissions, and analytics.
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-mcpList 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.
app-store-connect-mcp
An MCP server for both of Apple's commerce APIs — App Store Connect (1,263 operations) and the App Store Server API / StoreKit 2 (30 operations) — behind five tools, with the private key in the macOS Keychain and consequential writes gated behind an explicit confirmation.
1,293 operations · 5 tools · key never on disk · verified against the live APIsWhy it is built this way
There are several App Store Connect MCP servers. Each solves part of the problem; this one takes the part each got right and drops what they got wrong.
Approach | Kept | Rejected | |
Hand-wrapped tools | One MCP tool per endpoint | Typed, discoverable arguments | 70–900 tool definitions, >100k tokens, stale the moment Apple ships a version |
Code Mode | LLM writes JS, server | Two tools, ~1k tokens, full coverage | Executes generated code in a process holding a signing key |
Meta-tools |
| Same context win, no code execution | — |
This server uses the third. Coverage is a property of Apple's spec, not of how many endpoints someone wrapped; and the model never gets to run code inside a process that can change your pricing.
On the sandbox
Code Mode's premise is that generated JavaScript runs safely inside Node's vm. It does not. Node's own documentation says vm is not a security mechanism, and any host object injected as a global hands back the host realm through its own prototype chain:
spec.constructor.constructor('return process.env.HOME')() // → /Users/youVerified against a faithful reproduction of that sandbox: it returns the host environment. The timeout option does not help either — it only bounds synchronous execution, so an async busy-loop runs forever and starves the event loop.
Parameterised dispatch gets the same coverage and the same token cost with no interpreter to escape.
Related MCP server: App Store Connect MCP Server
Credentials
The private key belongs in the Keychain. Apple lets you download a .p8 exactly once, and a plaintext copy on disk is a copy that can leak.
ASC_KEY=keychain:my-asc-key # recommended
ASC_KEY=/path/to/AuthKey.p8 # works, but plaintext
ASC_PRIVATE_KEY='-----BEGIN…' # discouraged: `ps -E` exposes itA Keychain item may hold a bare PEM, or base64 JSON:
{ "issuerID": "…", "keyID": "…", "privateKeyPEM": "-----BEGIN PRIVATE KEY-----\n…" }The envelope form is worth preferring: the identifiers travel with the key material, so ASC_KEY_ID cannot drift out of sync with the key it names — a mismatch that surfaces only as an opaque 401.
security add-generic-password -s my-asc-key -a api -w "$(
jq -nc --arg i "$ISSUER" --arg k "$KEYID" --arg p "$(cat AuthKey.p8)" \
'{issuerID:$i,keyID:$k,privateKeyPEM:$p}' | base64
)"Install
git clone https://github.com/abd3lraouf-studios/app-store-connect-mcp
cd app-store-connect-mcp
npm install && npm run build{
"mcpServers": {
"app-store-connect": {
"command": "node",
"args": ["/path/to/app-store-connect-mcp/dist/index.js"],
"env": {
"ASC_KEY": "keychain:my-asc-key",
"ASC_BUNDLE_ID": "com.example.app"
}
}
}
}ASC_BUNDLE_ID is required only for App Store Server API calls — Apple rejects a Server API token without a bid claim.
Tools
Tool | Purpose |
| Verify credentials, report reachability and the remaining rate-limit budget. Run first when anything fails — it separates a bad key from a bad request. |
| Search both APIs by keyword, method, tag or risk tier. Returns operationIds and says which tool each belongs to. |
| Parameters, request-body schema with real field names, risk tier. |
| Reads. Path and query parameters, pagination, both APIs. |
| Everything that changes data. Confirmation, |
Reads and writes are separate tools because Claude Code ignores the standard
destructiveHint annotation but honours _meta["anthropic/requiresUserInteraction"]
— and that flag is per-tool. A single dispatcher could not vary it per operation.
asc_write carries it, so a write prompts the user even under bypassPermissions.
That is a stronger guarantee than the in-process gate, which --no-confirm can switch off.
Resources
Reference material the model can pull in deliberately, via @asc::
Resource | Contents |
| Cases where Apple returns a successful response meaning something other than it appears — pagination, alpha-3 territories, rejected |
| All 90 enumerated fields, generated from Apple's spec so they cannot go stale |
| What each risk tier means and how reversible it is |
| Where each API description came from, and when |
| Overflow storage — see below |
A result too large to return inline is not cut off. The list is trimmed to what fits, the truncation is stated along with how to narrow the request, and the complete response is kept as a resource the client can read without spending context. Cutting serialised JSON mid-structure hands the model something unparseable; cutting silently is worse, because a partial list reads as a complete one.
Prompts
Four workflows, available as /mcp__asc__<name>:
release-readiness · pricing-audit · review-triage · testflight-status
Each chains several calls — a slash command wrapping one request is a synonym,
not a workflow — and each encodes the traps, such as sort being rejected on
customerReviews and review text being untrusted input.
Write safety
An HTTP method is a poor proxy for consequence: PATCH /v1/subscriptionPrices and PATCH /v1/appInfos/{id} are both writes, but only one changes what customers are charged, and neither is undone by repeating it. Operations carry a risk tier:
Tier | Count | Meaning |
| 797 | No change. |
| 238 | Changes data. |
| 61 | Pricing, subscriptions, entitlements. |
| 132 | Deletes. |
| 12 | Builds, submissions, what ships. |
| 12 | Who can reach the account. |
| 11 | Certificates, identifiers, callback URLs. |
By default the bottom five tiers return a confirmation token instead of executing. The token is bound by hash to the exact operation, path, query and body, so it cannot be obtained for a cheap call and spent on an expensive one. It is single-use and expires in five minutes.
--read-only block every write --confirm confirm every write
--no-confirm never confirm (default) confirm the five tiers aboveWhen the client supports elicitation, asc_write asks the person directly,
showing the method, path, body and tier. Otherwise it falls back to a
confirmation token bound by hash to the exact operation, path, query and body,
so a token issued for a cheap call cannot be spent on an expensive one. A
client that declares elicitation but fails to serve it falls back rather than
sailing through. dry_run reports the exact request without sending it.
Transports
node dist/index.js # stdio (default)
node dist/index.js --transport http --http-token "$(openssl rand -hex 32)"HTTP binds to 127.0.0.1 and refuses to start without a bearer token. This process holds a key that can change App Store pricing; it should not listen unauthenticated. Binding off-loopback warns and is best paired with a TLS-terminating proxy or an SSH tunnel.
Keeping up with Apple
npm run fetch:specs # re-download both descriptions
npm run build # recompile the operation index
npm run verify # drift check + live calls against both APIsThe two APIs are sourced differently, of necessity:
App Store Connect — Apple publishes a real OpenAPI 3.0 document. It is downloaded and compiled into a slim index (360KB, against a 3.3MB spec) so search stays fast and the full document is opened only to describe one operation.
App Store Server — Apple publishes no OpenAPI document; the documentation is prose. The authoritative machine-readable description is Apple's own client,
apple/app-store-server-library-node, where every endpoint is a literalmakeRequestcall.fetch:specsparses the endpoint set out of that source at a pinned release tag, andverifydiffs it against the catalogue insrc/storekit.ts.
Two details in that catalogue contradict what the documentation implies, and both are load-bearing:
The hosts are
api.storekit.apple.com/api.storekit-sandbox.apple.com. The olderapi.storekit.itunes.apple.comnames no longer serve this API.The mass renewal-extension status path orders its segments
{productId}/{requestIdentifier}— not the reverse.
Verification
npm run verify is read-only and makes real calls. Last run:
1. Catalogue drift — src/storekit.ts vs Apple’s client
✓ all 30 Apple endpoints present in the catalogue
✓ no endpoints in the catalogue that Apple does not define
2. App Store Connect API — live
✓ apps_getCollection → 2 apps
✓ apps_getInstance / builds / appStoreVersions → HTTP 200
✓ pagination walked 3 pages
✓ bogus id → structured 404
3. App Store Server API (StoreKit 2) — live
✓ storekit token carries bid; connect token correctly omits it
✓ getTransactionInfo / getAllSubscriptionStatuses / getTransactionHistory v2
→ authenticated and routed (Apple errorCode 4000006)
✓ getNotificationHistory (30d window) → HTTP 200
14 passed, 0 failedStoreKit probes use a deliberately invalid transaction ID. The signal is the shape of the reply: a structured Apple errorCode proves the request was authenticated and routed, where a 401 would prove it was not.
Robustness
Timeouts and retries. Reads retry on 408/429/5xx; writes retry only on 429, where Apple rejected the request before processing it. A write that fails ambiguously is reported as ambiguous and never resent — a duplicated POST is worse than a reported failure.
Rate limiting. Paced against both the documented hourly limit and the undocumented per-minute one, and corrected from Apple's own
x-rate-limitheader, which accounts for other clients sharing the key.x-request-idis surfaced for Apple support.Host pinning. Every URL, including the
links.nextpagination cursor, is checked against an allowlist of Apple's three API hosts. A cursor is server-supplied input; following one blindly would walk a bearer token to whatever host it names.Response shaping.
linksand links-onlyrelationshipsare stripped,links.nextpreserved — over 60% smaller on a real price-point listing.Lifecycle. The stdio server exits on stdin EOF and on signals, rather than lingering as an orphan holding a signing key.
Known limits
JWS responses are decoded, not verified. StoreKit payloads arrive signed by Apple; verifying the chain needs Apple's root certificates. Decoded values appear in
*_decodedfields and are labelled unverified. Do not treat them as proof of purchase without checking the signature.Risk tiers are pattern-matched from method and path. They are deliberately cautious, but read
asc_describe_endpointbefore a write rather than trusting the tier alone.Keychain storage is macOS-only. Elsewhere, use a file path with restrictive permissions.
--no-confirmdisables the gate entirely. It exists for CI; it is a poor default for an interactive agent.
Licence
MIT
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
- AlicenseBqualityCmaintenanceEnables interaction with Apple's App Store Connect API through natural language to manage apps, beta testing, localizations, analytics, sales reports, and CI/CD workflows for iOS and macOS development.3182MIT
- Flicense-qualityDmaintenanceEnables management of App Store Connect apps including registration, listing, IPA upload, store listing updates, and in-app purchase creation via natural language.
- AlicenseAqualityCmaintenanceEnables AI assistants to manage Apple App Store Connect resources like apps, builds, TestFlight, and reviews through natural language.2018MIT
- Alicense-qualityDmaintenanceEnables managing your iOS app's entire lifecycle with natural language through App Store Connect, offering 48 tools across 14 categories for ASO, reviews, analytics, subscriptions, pricing, and more.6MIT
Related MCP Connectors
Let ChatGPT, Claude & Cursor use your Mac: email, calendar, iMessage, Teams, files. Local, free.
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Manage your NanoCart store from any AI agent: products, orders, coupons, subscribers, reports.
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/abd3lraouf-studios/app-store-connect-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server