asc-mcp
MCP server for the Apple App Store Connect API — Xcode Cloud CI, app management, customer reviews, and sales reports.
Works with Claude Code, Cursor, Windsurf, and any MCP-compatible client.
How it works
sequenceDiagram
participant C as MCP Client<br/>(Claude Code, Cursor…)
participant S as asc-mcp
participant A as App Store Connect API
C->>S: initialize (stdio)
S-->>C: serverInfo + capabilities
C->>S: tools/list
S-->>C: 11 tools with JSON Schema
C->>S: tools/call list_products
S->>S: generate JWT (ES256, cached 15m)
S->>A: GET /v1/ciProducts
A-->>S: JSON:API response
S-->>C: pretty JSON result
Architecture
graph TD
Client["MCP Client<br/>(Claude Code / Cursor / Windsurf)"]
Server["AscMcpServer<br/>tools.rs — rmcp #[tool_router]"]
HttpClient["AscClient<br/>client.rs + client_endpoints.rs"]
Auth["Credentials<br/>auth.rs — ES256 JWT cache"]
Models["models/<br/>JSON:API types"]
API["App Store Connect API v1<br/>api.appstoreconnect.apple.com"]
Client -->|stdio MCP protocol| Server
Server --> HttpClient
HttpClient --> Auth
HttpClient --> Models
HttpClient -->|HTTPS| API
Features
- Xcode Cloud CI/CD — list products, workflows, build runs, actions; trigger builds
- App management — list and inspect apps
- Customer reviews — fetch with full auto-pagination
- Sales reports — download and parse gzip-compressed TSV reports
- JWT auth — ES256 tokens generated and cached for 15 minutes
- Rate-limit handling — automatic retry with
Retry-Afterrespect (3 attempts) - Zero config — three env vars and you're running
Installation
cargo install asc-mcp
Or build from source:
git clone https://github.com/menot-you/apple-store-connect
cd apple-store-connect
cargo install --path .
Configuration
Generate an API key at App Store Connect → Users and Access → Integrations → App Store Connect API.
| Variable | Description |
|---|---|
ASC_KEY_ID |
Key ID shown in App Store Connect |
ASC_ISSUER_ID |
Issuer ID shown at the top of the API keys page |
ASC_PRIVATE_KEY_PATH |
Path to the .p8 file downloaded from App Store Connect |
Usage
Claude Code
Add to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"asc-mcp": {
"command": "asc-mcp",
"env": {
"ASC_KEY_ID": "YOUR_KEY_ID",
"ASC_ISSUER_ID": "YOUR_ISSUER_ID",
"ASC_PRIVATE_KEY_PATH": "/path/to/AuthKey_XXXX.p8"
}
}
}
}
Cursor / Windsurf / other MCP clients
Same structure — add to your client's MCP server config file.
Available Tools
Xcode Cloud
graph LR
list_products --> get_product
get_product --> list_workflows
list_workflows --> list_build_runs
list_workflows --> start_build
list_build_runs --> get_build_run
get_build_run --> list_build_actions
| Tool | Parameters | Description |
|---|---|---|
list_products |
— | List all Xcode Cloud CI products |
get_product |
product_id |
Get details of a specific CI product |
list_workflows |
product_id |
List workflows for a CI product |
list_build_runs |
workflow_id |
List build runs for a workflow |
get_build_run |
build_run_id |
Get details of a specific build run |
start_build |
workflow_id, git_reference_id |
Trigger a new build |
list_build_actions |
build_run_id |
List actions inside a build run |
Apps & Reviews
| Tool | Parameters | Description |
|---|---|---|
list_apps |
— | List all apps in App Store Connect |
get_app |
app_id |
Get details of a specific app |
list_customer_reviews |
app_id |
List customer reviews for an app |
Sales Reports
| Tool | Parameters | Description |
|---|---|---|
get_sales_report |
vendor_number, report_type, report_sub_type, frequency, report_date |
Download and parse a sales report |
report_type values: SALES, SUBSCRIPTION, SUBSCRIPTION_EVENT
frequency values: DAILY, WEEKLY, MONTHLY, YEARLY
report_date format: YYYY-MM-DD
Token lifecycle
stateDiagram-v2
[*] --> NoToken
NoToken --> Generating: first request
Generating --> Cached: JWT signed (ES256)
Cached --> Cached: elapsed < 15m → reuse
Cached --> Generating: elapsed ≥ 15m → refresh
Apple allows 20-minute tokens; this server uses 15-minute TTL for a 5-minute clock-skew buffer.
Development
cargo test # 47 tests, no credentials needed
cargo clippy -- -D warnings
cargo fmt --check
cargo doc --no-deps
Tests use wiremock for real HTTP-level mocking — no Apple account required.
See CONTRIBUTING.md for the full guide and ARCHITECTURE.md for the design walkthrough.
License
AGPL-3.0-or-later — see the LICENSE file for details.
Metadata
Release files for asc-mcp 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| asc_mcp-0.1.1.tar.gz | 4.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| asc_mcp-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 8.7 kB
Release files / asc_mcp-0.1.1.tar.gz
| Download URL | asc_mcp-0.1.1.tar.gz |
|---|---|
| Size | 4.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6eef7161f82338f5264897d0473254b6e927bffbd26f17e3b28e3430424b760c
|
|
BLAKE2b-256 checksum How to use checksums |
f558921f01e23682b14f0bdfec9a55083098585c15230082ddb4b0525abe9a29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / asc_mcp-0.1.1-py3-none-any.whl
| Download URL | asc_mcp-0.1.1-py3-none-any.whl |
|---|---|
| Size | 4.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8eaaedc57961658dfcc90d72c75e567a5cc984f08d9170e8ee8030c2318ded13
|
|
BLAKE2b-256 checksum How to use checksums |
087f2945c63ac36920032f134772415d81b85f260bf0f5974a404f67809aab08
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for asc-mcp 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.