MCP server for Apple's App Store Connect API - manage iOS, macOS, tvOS, and visionOS apps with AI
npm install asc-mcp


A Model Context Protocol (MCP) server for Apple's App Store Connect API. Manage your iOS, macOS, tvOS, and visionOS apps directly from Claude, Cursor, or any MCP-compatible client.
- App Store Localizations - Full CRUD for version descriptions, keywords, and what's new
- App Management - List and inspect apps across all platforms
- Version Control - Create and manage app store versions
- Beta Testing - Manage TestFlight groups and testers
- Screenshot Management - Upload and organize app screenshots
- Bundle ID Management - Full CRUD for bundle identifiers
- Device Management - List and inspect registered devices
- User Management - List and inspect team users
- Build Management - List and inspect app builds
- Category & Pricing - Browse categories, check pricing and availability
- Secure by Default - ES256 JWT auth with automatic token refresh, credential redaction in logs
- Quick Start
- Installation
- Configuration
- Available Tools
- Usage Examples
- Security
- Troubleshooting
- Development
- License
``bash1. Install
npm install -g asc-mcp
Installation
$3
`bash
npm install -g asc-mcp
`$3
`bash
npx asc-mcp
`$3
`bash
git clone https://github.com/SardorbekR/appstore-connect-mcp.git
cd appstore-connect-mcp
npm install
npm run build
`Configuration
$3
1. Sign in to App Store Connect
2. Go to Users and Access → Integrations → App Store Connect API
3. Click Generate API Key (or use existing)
4. Select appropriate role (Admin or App Manager recommended)
5. Download the .p8 file - you can only download it once!
6. Note your Key ID (shown in the keys list)
7. Note your Issuer ID (shown at the top of the page)
$3
| Variable | Required | Description |
|----------|----------|-------------|
|
APP_STORE_CONNECT_KEY_ID | Yes | Your API Key ID (e.g., ABC123DEFG) |
| APP_STORE_CONNECT_ISSUER_ID | Yes | Your Issuer ID (UUID format) |
| APP_STORE_CONNECT_P8_PATH | Yes* | Path to your .p8 private key file |
| APP_STORE_CONNECT_P8_CONTENT | Yes* | Raw content of .p8 key (alternative to path) |*One of
P8_PATH or P8_CONTENT is required.$3
Claude Desktop
Add to your Claude Desktop config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json`json
{
"mcpServers": {
"app-store-connect": {
"command": "asc-mcp",
"env": {
"APP_STORE_CONNECT_KEY_ID": "YOUR_KEY_ID",
"APP_STORE_CONNECT_ISSUER_ID": "YOUR_ISSUER_ID",
"APP_STORE_CONNECT_P8_PATH": "/absolute/path/to/AuthKey.p8"
}
}
}
}
`
Cursor
Add to your Cursor MCP settings (Settings → MCP Servers):
`json
{
"mcpServers": {
"app-store-connect": {
"command": "npx",
"args": ["-y", "asc-mcp"],
"env": {
"APP_STORE_CONNECT_KEY_ID": "YOUR_KEY_ID",
"APP_STORE_CONNECT_ISSUER_ID": "YOUR_ISSUER_ID",
"APP_STORE_CONNECT_P8_PATH": "/absolute/path/to/AuthKey.p8"
}
}
}
}
`
VS Code with Continue
Add to your Continue configuration:
`json
{
"mcpServers": {
"app-store-connect": {
"command": "asc-mcp",
"env": {
"APP_STORE_CONNECT_KEY_ID": "YOUR_KEY_ID",
"APP_STORE_CONNECT_ISSUER_ID": "YOUR_ISSUER_ID",
"APP_STORE_CONNECT_P8_PATH": "/absolute/path/to/AuthKey.p8"
}
}
}
}
`
Using P8 Content Instead of Path
For CI/CD or containerized environments, you can pass the key content directly:
`json
{
"mcpServers": {
"app-store-connect": {
"command": "asc-mcp",
"env": {
"APP_STORE_CONNECT_KEY_ID": "YOUR_KEY_ID",
"APP_STORE_CONNECT_ISSUER_ID": "YOUR_ISSUER_ID",
"APP_STORE_CONNECT_P8_CONTENT": "-----BEGIN PRIVATE KEY-----\nMIGT...your key here...AB12\n-----END PRIVATE KEY-----"
}
}
}
}
`Available Tools
$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_apps | List all apps in your account | limit? (number, 1-200) |
| get_app | Get details of a specific app | appId (string, required) |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_app_versions | List all versions for an app | appId, platform?, versionState?, limit? |
| get_app_version | Get version details | versionId |
| create_app_version | Create a new app version | appId, platform, versionString, releaseType? |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_version_localizations | List localizations for a version | versionId, limit? |
| get_version_localization | Get localization details | localizationId |
| create_version_localization | Add a new locale | versionId, locale, description?, keywords?, whatsNew? |
| update_version_localization | Update localization | localizationId, description?, keywords?, whatsNew?, promotionalText? |
| delete_version_localization | Remove a locale | localizationId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_app_infos | List app info records | appId, limit? |
| list_app_info_localizations | List name/subtitle localizations | appInfoId, limit? |
| update_app_info_localization | Update app name, subtitle | localizationId, name?, subtitle?, privacyPolicyUrl? |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_beta_groups | List beta groups for an app | appId, limit? |
| list_beta_testers | List testers in a group | betaGroupId, limit? |
| add_beta_tester | Add a tester to a group | betaGroupId, email, firstName?, lastName? |
| remove_beta_tester | Remove a tester from a group | betaGroupId, betaTesterId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_screenshot_sets | List screenshot sets | localizationId, limit? |
| list_screenshots | List screenshots in a set | screenshotSetId, limit? |
| upload_screenshot | Upload a new screenshot | screenshotSetId, fileName, fileSize, filePath |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_bundle_ids | List all bundle IDs | limit?, platform? |
| get_bundle_id | Get bundle ID details | bundleIdId |
| create_bundle_id | Register a new bundle ID | identifier, name, platform |
| update_bundle_id | Update bundle ID name | bundleIdId, name |
| delete_bundle_id | Delete a bundle ID | bundleIdId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_devices | List registered devices | limit?, platform?, status? |
| get_device | Get device details | deviceId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_users | List team users | limit?, roles? |
| get_user | Get user details | userId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_builds | List builds for an app | appId, limit? |
| get_build | Get build details | buildId |$3
| Tool | Description | Parameters |
|------|-------------|------------|
|
list_app_categories | List app categories | limit?, platform? |
| get_app_price_schedule | Get app pricing info | appId |
| get_app_availability | Get app territory availability | appId |Usage Examples
$3
> "Show me all my apps in App Store Connect"
Claude will use
list_apps to retrieve and display your apps.$3
> "Update the English description for version 2.0 of MyApp to: 'A revolutionary app that simplifies your daily tasks.'"
Claude will:
1. Find the app using
list_apps
2. Get the version using list_app_versions
3. Find the English localization using list_version_localizations
4. Update it using update_version_localization$3
> "Add Japanese localization to MyApp version 2.0 with description '素晴らしいアプリです' and keywords 'アプリ,便利,簡単'"
Claude will use
create_version_localization with locale ja.$3
> "Add john@example.com as a beta tester to the Internal Testing group for MyApp"
Claude will:
1. Find the app and beta group using
list_beta_groups
2. Add the tester using add_beta_tester$3
> "What's the status of all versions of MyApp?"
Claude will use
list_app_versions to show version states (PREPARE_FOR_SUBMISSION, IN_REVIEW, READY_FOR_SALE, etc.)Security
$3
- Private keys are never logged or exposed in error messages
- JWT tokens are automatically redacted from any error output
- Issuer IDs (UUIDs) are redacted from logs
- Token caching minimizes key usage (15-min tokens, refreshed at 10 min)
$3
- P8 file paths are validated against directory traversal attacks (
.. not allowed)
- Only absolute paths are resolved$3
1. Never commit credentials - Use environment variables or a secrets manager
2. Restrict API key permissions - Use minimal required role (App Manager for most operations)
3. Rotate keys periodically - Generate new API keys and revoke old ones
4. Secure your .p8 file - Set file permissions to
600 (owner read/write only)`bash
chmod 600 /path/to/AuthKey.p8
`Troubleshooting
$3
Ensure all required environment variables are set:
-
APP_STORE_CONNECT_KEY_ID
- APP_STORE_CONNECT_ISSUER_ID
- APP_STORE_CONNECT_P8_PATH or APP_STORE_CONNECT_P8_CONTENT$3
1. Verify the path in
APP_STORE_CONNECT_P8_PATH is correct and absolute
2. Check file permissions: ls -la /path/to/AuthKey.p8
3. Ensure the file is a valid .p8 from Apple (starts with -----BEGIN PRIVATE KEY-----)$3
This usually means:
1. The API key was revoked in App Store Connect
2. The Key ID or Issuer ID doesn't match the .p8 file
3. The .p8 file is corrupted or incomplete
$3
The server includes built-in rate limiting (50 requests/minute). If you hit Apple's limits:
1. Wait for the indicated retry time
2. Batch your operations when possible
3. The server automatically retries with exponential backoff
$3
1. Verify the server is running: check Claude Desktop logs
2. Ensure the config file path is correct for your OS
3. Restart Claude Desktop after config changes
Development
$3
- Node.js 20+
- npm or pnpm
$3
`bash
Clone the repository
git clone https://github.com/SardorbekR/appstore-connect-mcp.git
cd appstore-connect-mcpInstall dependencies
npm installBuild
npm run buildRun tests
npm testLint
npm run lintType check
npm run typecheck
`$3
`
src/
├── index.ts # MCP server entry point
├── auth/
│ └── jwt.ts # JWT token generation & caching
├── api/
│ ├── client.ts # HTTP client with retry logic
│ └── types.ts # TypeScript interfaces
├── tools/
│ ├── index.ts # Tool registry
│ ├── apps.tools.ts
│ ├── versions.tools.ts
│ ├── localizations.tools.ts
│ ├── app-info.tools.ts
│ ├── beta.tools.ts
│ ├── screenshots.tools.ts
│ ├── bundle-ids.tools.ts
│ ├── devices.tools.ts
│ ├── users.tools.ts
│ ├── builds.tools.ts
│ └── categories.tools.ts
└── utils/
├── errors.ts # Error classes with redaction
└── validation.ts # Zod schemas
`$3
`bash
Development mode with auto-reload
npm run devOr run the built version
npm start
`$3
1. Fork the repository
2. Create a feature branch:
git checkout -b feature/my-feature
3. Make your changes and add tests
4. Run npm test and npm run lint`MIT License - see LICENSE for details.
- Security Policy
- App Store Connect API Documentation
- Model Context Protocol