Heimdall App Store ConnectBLOCK
Heimdall — MCP server for the Apple App Store Connect API and App Store Server API (StoreKit 2). 890 tools across 13 profiles, generated from Apple's OpenAPI spec, plus one-call macros for worldwide pricing, submission readiness and metadata diffs, and confirm-before-write safety. Works with Claude,
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://www.npmjs.com/package/@erayendes/asc-mcp) [](https://www.npmjs.com/package/@erayendes/asc-mcp) [](https://github.com/erayendes/app-store-connect-mcp/actions/workflows/ci.yml) [](LICENSE) [](https://milowda.com)
A real agent session over MCP, sped up. The App Store Connect account is a stand-in so the recording can be public — regenerate with vhs assets/demo/demo.tape.
🇬🇧 English · 🇹🇷 Türkçe
English
Heimdall. One tool for your entire App Store Connect account.
An MCP server for the App Store Connect API and the App Store Server API (StoreKit 2), with every tool generated from Apple's own OpenAPI specification. 13 profiles, 32 sub-profiles, 902 tools.
Apps and metadata, versions and phased releases, TestFlight, subscriptions and in-app purchases, pricing, reviews, Game Center, Xcode Cloud, provisioning, webhooks, and sales and finance reports.
Ask and it answers. Tell it and it's done.
-
ed0ab83ee84cOBSERVED · 2026-10-08Connect
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 asc-mcp --env ASC_PRIVATE_KEY=${ASC_PRIVATE_KEY} -- npx -y @erayendes/[email protected]Exposed tools (47)
37 read · 10 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
Premium | read | Full access. |
analytics__get_report | read | Read an App Store analytics report as rows, in one step. Give the app (name, bundle ID |
app | read | App name, bundle ID or Apple ID. |
app_id | read | Numeric Apple ID of the app. |
asc__account_status | read | Show every app in the account with the version that is live, the version in |
asc__call | read | Read through any tool this profile owns, even one that is not in your tool list — |
asc__describe | read | Show the exact input schema of any tool this profile owns, including ones not |
asc__discover_domains | read | List what this server can reach and what it cannot: in profile mode the profiles |
asc__load | write | Add one of this server |
asc__profile_removed | read | This MCP server is configured for the App Store Connect profile |
asc__search_tools | read | Search all App Store Connect operations by keyword, including domains that are |
asc__status | read | Report server configuration, spec version, loaded domains, JWT token state |
days | read | Lookback window in days. Default 7. |
listing__diff_metadata | read | Compare the store text of two app versions locale by locale, in one call, and |
listing__get_screenshots | read | List the screenshots on an app’s store listing in one step: which locales |
listing__upload_screenshot | write | Upload a screenshot image file to an app’s store listing in one step. Give the app |
metadata_ai__apply_localizations | write | Write store text for several languages at once from a file the user prepared — the |
metadata_ai__audit_localizations | read | Compare an app version’s store text across every language and report what is missing |
metadata_ai__draft_translation | read | Return one language’s store text plus an instruction for you to draft it in the |
preflight__check_subscription | read | Check subscription catalog readiness before submitting for review. Give the app |
preflight__check_version | write | Check whether an app version is complete enough to submit, in one call, and |
price-check | read | Show what a subscription costs worldwide, where the prices are inconsistent, and |
pricing__equalize_price | write | Set one anchor price and let Apple derive the equivalent price in every other |
pricing__get_app_price | read | Read current and scheduled app purchase prices by territory, including currency, |
pricing__get_iap_price | read | Read current and scheduled in-app purchase prices by territory, including currency, |
pricing__get_subscription_price | read | What a subscription costs customers today — in one country, or in every country at |
pricing__set_iap_price | write | Change or set an in-app purchase (IAP) price in one territory (country) without |
pricing__set_subscription_price | write | Change or set a subscription price in one territory (country) in a single step. |
release-readiness | read | Decide whether an app version can be submitted: what is missing, and what the |
release__submit | write | Send an App Store version to Apple for review in one call — it opens the submission, |
review-triage | read | Read the recent App Store reviews for an app, sort them by what needs answering, |
reviews_ai__daily_briefing | read | Fetch the last N days of reviews for an app, with volume and rating trend (computed |
reviews_ai__draft_response | read | Fetch one customer review and return it with an instruction for you to draft a reply |
reviews_ai__triage | read | Fetch recent reviews for an app and return them with an instruction for you to group |
storekit__check_entitlement | read | Answer the single question |
storekit__extend_renewal_date | read | Extend a subscriber |
storekit__get_notification_history | read | Retrieve App Store Server Notification delivery history, including failures. |
storekit__get_refund_history | read | List every refunded transaction for a customer. Useful for auditing refund |
storekit__get_subscription_statuses | read | Get the status of every subscription a customer holds, including expiry date, |
storekit__get_transaction_history | read | Get a customer |
storekit__get_transaction_info | read | Get a single transaction: product, price, dates, ownership type and revocation |
storekit__lookup_order | write | Look up all transactions tied to an order ID from a customer receipt. |
storekit__request_test_notification | write | Ask Apple to send a test notification to your configured webhook endpoint. |
subscription | read | Subscription name or product ID. Optional if the app has one. |
testflight__assign_build_to_groups | read | Assign one processed, unexpired TestFlight build to named beta groups. Checks existing assignments and reports each group, including partial failures. External groups may need beta app review before testers can install the build. RELEASE-level write. |
testflight__feedback_digest | read | Summarize what TestFlight beta testers are reporting: recent crash and screenshot feedback |
version | read | Version string. Defaults to the one being prepared. |
Trust audit
BLOCKgrade F · trust 46/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | FAIL |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- declared (7 observation(s))
- Shell
- declared (2 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (24)
# ASC_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIG..."
# GitHub. A generic `-----BEGIN PRIVATE KEY-----` in a commit is exactly the
Report server configuration, spec version, loaded domains, JWT token state
output = exec(
exec(
generate-profiles.ts
server.listen(port, '127.0.0.1', () => console.log(`fixture on http://127.0.0.1:${port}`));export ASC_BASE_URL="http://127.0.0.1:8787"
const trimmed = text.replace(/^/, '').trim();
# caught and a bare `-----BEGIN PRIVATE KEY-----` is not. That block is
const exec = vi.fn().mockReturnValue('-----BEGIN PRIVATE KEY-----\nMIG...\n');expect(pem).toBe('-----BEGIN PRIVATE KEY-----\nMIG...');.gitleaks.toml
const checksum = createHash('md5').update(bytes).digest('hex');createHash('md5').update(bytes).digest('hex')ASC_BASE_URL: 'http://127.0.0.1:1',
c = client([], { env: { ASC_BASE_URL: `http://127.0.0.1:${port}` } });baseUrl: 'http://127.0.0.1:1', readOnly: false, confirmWrites: 'all',
@apple/app-store-server-library, @modelcontextprotocol/sdk, @anthropic-ai/claude-agent-sdk, @types/node, tsx, typescript, vitest
Full access.
**Going after the key is the most common way a session goes wrong.** In recorded eval runs, of the sessions that abandoned the tools, the largest group went hunting for the private key — `security fin
<sub>One pass, and safe throughout: the access details it needs, then a live credential check. Then your choices — the profiles and sub-profiles you want, and the key ends up in the Keychain, not in a
Apple never returns a key's role from any endpoint, so **App Manager** — not Admin — is the right default for day-to-day release work; Admin only earns its place for user management and for the one-ti
spec/openapi.json
Gates applied: critical_finding, no_behavioural_pass, undeclared_transfer.
ed0ab83ee84cfull audit observations/trust-audit/mcp-server/erayendes__heimdall-app-store-connect.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-08 | ed0ab83ee84c | BLOCK | F | 46 | first audit |
Questions
What is the Heimdall App Store Connect MCP server?
Heimdall — MCP server for the Apple App Store Connect API and App Store Server API (StoreKit 2). 890 tools across 13 profiles, generated from Apple's OpenAPI spec, plus one-call macros for worldwide pricing, submission readiness and metadata diffs, and confirm-before-write safety. Works with Claude,
What tools does Heimdall App Store Connect expose?
47 in total: 37 read-only, 10 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is Heimdall App Store Connect safe to connect to an agent?
No — not without reading the findings first. The audit graded it F (46/100) and found 5 critical or high issues in the source. Each one is listed on this page with the file and line it is on.
What credentials does Heimdall App Store Connect need?
It reads ASC_KEY_ID, ASC_PRIVATE_KEY, ASC_PRIVATE_KEY_KEYCHAIN, ASC_PRIVATE_KEY_PATH and TOKEN_REPORT 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 Heimdall App Store Connect run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as @erayendes/asc-mcp at 2.5.0.
How current is this page?
The grade is for one exact copy of the source (ed0ab83ee84c), read on 2026-10-08. The repository is watched and re-audited when it changes.