npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@orellbuehler/testflight-mcp

v0.2.1

Published

Model Context Protocol server for TestFlight & App Store Connect: retrieve beta tester feedback (screenshots, crashes, crash logs), builds, testers, analytics and provisioning over the official App Store Connect API.

Readme

testflight-mcp

npm CI node license: MIT

MCP server for TestFlight and App Store Connect that exposes the App Store Connect API as tools for AI agents.

Its focus is TestFlight beta feedback retrieval — pulling the screenshot feedback (with the tester's comment), crash feedback and crash logs your testers submit — plus the surrounding context an agent needs to make sense of it: apps, builds, beta testers/groups, analytics & sales reports, provisioning, and App Store metadata. It talks only to the official, documented API using a standard App Store Connect API key (ES256 JWT), and is read-only.

It deliberately does not scrape App Store Connect with your Apple ID / password (no headless browser, no internal iris API) and does not send email to testers. Some third-party TestFlight servers do; this one stays on the supported API.

Install

The package is published as @orellbuehler/testflight-mcp and runs directly with npx — no clone or build needed:

claude mcp add testflight \
  --env ASC_KEY_ID=ABCD123456 \
  --env ASC_ISSUER_ID=12a3b456-7890-1234-5678-9abcdef01234 \
  --env ASC_PRIVATE_KEY_PATH=/path/to/AuthKey_ABCD123456.p8 \
  -- npx -y @orellbuehler/testflight-mcp

For any other MCP client, run the package directly — npx -y @orellbuehler/testflight-mcp with the env vars below set. Requires Node.js 20+.

Getting an API key

The server authenticates with an App Store Connect API key (a .p8 file plus a key ID and issuer ID), the same credentials fastlane/altool use:

  1. In App Store Connect, go to Users and Access → Integrations → App Store Connect API (Team Keys).
  2. Generate a key. A role of App Manager (or Admin) covers TestFlight feedback; Finance is additionally required for sales/finance reports.
  3. Download the AuthKey_XXXXXXXXXX.p8 (you can only download it once — keep it safe), and note the Key ID and the team Issuer ID shown above the keys table.

Provide the key either as a file path (ASC_PRIVATE_KEY_PATH) or inline (ASC_PRIVATE_KEY, newlines may be escaped as \n). The key is read locally and used only to sign short-lived request tokens.

Configuration

| Variable | Required | Description | | ---------------------- | -------- | ------------------------------------------------------------------------------------- | | ASC_KEY_ID | yes | App Store Connect API Key ID. | | ASC_ISSUER_ID | yes | App Store Connect API Issuer ID (per team). | | ASC_PRIVATE_KEY_PATH | yes* | Path to the downloaded .p8 private key file. | | ASC_PRIVATE_KEY | yes* | The .p8 contents inline (alternative to the path; \n escapes are unescaped). | | ASC_VENDOR_NUMBER | no | Vendor number; required only for download_sales_report / download_finance_report. |

* Provide either ASC_PRIVATE_KEY_PATH or ASC_PRIVATE_KEY.

Usage with Claude Code

Add the server to ~/.claude/settings.json (or a project .mcp.json):

{
  "mcpServers": {
    "testflight": {
      "command": "npx",
      "args": ["-y", "@orellbuehler/testflight-mcp"],
      "env": {
        "ASC_KEY_ID": "ABCD123456",
        "ASC_ISSUER_ID": "12a3b456-7890-1234-5678-9abcdef01234",
        "ASC_PRIVATE_KEY_PATH": "/path/to/AuthKey_ABCD123456.p8"
      }
    }
  }
}

If you built from source instead, use "command": "node" with "args": ["/path/to/testflight-mcp/dist/index.js"]. Restart Claude Code and verify with claude mcp list (should show testflight ✓ connected) or /mcp inside a session.

Example prompts

Once connected, ask the agent things like:

  • "List the latest TestFlight screenshot feedback for my app and summarize the recurring complaints."
  • "Show crash feedback for build 1.4.0 and download the crash log for the most recent one."
  • "Which beta testers reported feedback this week, and what devices/OS versions were they on?"
  • "Pull this month's sales summary as CSV."

Tools

Start from list_apps to get an app_id, then drill into feedback. All tools are read-only.

TestFlight feedback

| Tool | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | list_screenshot_feedback | Screenshot feedback for an app: tester comment, screenshot URLs, device/OS, resolved tester and build (build number build.version + TestFlight version build.preReleaseVersion.version). Defaults to the latest version only (app_version: a version like 1.2.0, or all). Filter by build/platform/device/OS/tester. | | list_crash_feedback | Crash feedback for an app: comment, device/OS, resolved tester and build (build number + TestFlight version build.preReleaseVersion.version), crash-log reference. Defaults to the latest version only (app_version: a version like 1.2.0, or all). | | get_screenshot_feedback | One screenshot submission; optionally returns the first screenshot inline as an image. | | get_crash_feedback | One crash submission with full metadata and crash-log reference. | | get_crash_log | Download the crash log text for a crash submission. |

Apps & builds

| Tool | Description | | ----------------------- | -------------------------------------------------------------------------- | | list_apps | Apps in the account (id, name, bundleId, sku). Filter by bundle ID. | | get_app | One app by ID. | | list_builds | TestFlight builds for an app (version, processing state, expiry). | | get_build | One build with its pre-release version. | | list_customer_reviews | Public App Store reviews for a released app (distinct from beta feedback). |

Beta testers & groups

| Tool | Description | | -------------------- | -------------------------------------------------------------------------- | | list_beta_groups | Beta groups for an app (internal/external, public link, feedback enabled). | | list_beta_testers | Beta testers (name, email, invite type, state). Filter by app/group/email. | | list_group_testers | Testers in a specific beta group. |

Analytics & reports

| Tool | Description | | ----------------------------------- | ---------------------------------------------------------------------------- | | create_analytics_report_request | Request an analytics report (the required first step). Returns a request ID. | | list_analytics_reports | Reports available for a request, optionally filtered by category. | | list_analytics_report_segments | Downloadable segments of a report (presigned URLs). | | download_analytics_report_segment | Download + decompress a segment to CSV/TSV text. | | download_sales_report | Sales & Trends report as CSV (needs ASC_VENDOR_NUMBER). | | download_finance_report | Financial report as CSV (needs ASC_VENDOR_NUMBER and a region code). |

Provisioning & devices

| Tool | Description | | ------------------- | --------------------------------------------------- | | list_devices | Registered devices (name, platform, UDID, status). | | list_certificates | Signing certificates (type, name, serial, expiry). | | list_profiles | Provisioning profiles with their bundle ID. | | list_bundle_ids | Registered bundle IDs (identifier, name, platform). |

App metadata & localizations

| Tool | Description | | -------------------------------------- | -------------------------------------------------------------- | | list_app_store_versions | App Store versions for an app (version, platform, state). | | list_app_store_version_localizations | Per-locale metadata (description, keywords, what's new, URLs). | | get_app_store_version_localization | One localization by ID. |

Notes & caveats

  • Read-only. The server cannot add/remove testers, edit metadata, or submit apps. The only POST is create_analytics_report_request, which requests an analytics snapshot so the data can be read; it does not change your app.
  • TestFlight feedback requires builds uploaded with feedback enabled and is retained by Apple for a limited window (~90 days). The tester's typed comment is the comment field on a screenshot submission.
  • Crash logs are resolved from the submission's crash-log URL and downloaded as text. If Apple exposes no download URL for a given submission, get_crash_log returns the raw attributes so you can see what's available.
  • Reports (download_sales_report / download_finance_report) are gzipped CSV decompressed for you, and need the Finance role on the API key plus ASC_VENDOR_NUMBER.
  • Your data goes to the agent/LLM. Feedback includes tester names, emails and device details. Use an API key scoped to the access you actually want.

Development

npm install
npm run build         # tsc -> dist/
npm test              # vitest run
npm run typecheck     # tsc --noEmit
npm run lint          # eslint src
npm run format:check  # prettier --check .

Run a single test file:

npx vitest run src/__tests__/feedback.test.ts

CI / Releasing

  • CI (.github/workflows/ci.yml) runs on every push to main and on pull requests: format:check, lint, typecheck (once) and test + build on Node 20 and 22.
  • Publish (.github/workflows/publish.yml) runs when a GitHub Release is published. It builds, tests, and publishes to npm using trusted publishing (OIDC) — no NPM_TOKEN secret required, with provenance generated automatically. It skips publishing if that version is already on npm.

Cut a release:

npm version patch          # bumps package.json + creates a vX.Y.Z tag (use minor/major as needed)
git push --follow-tags
gh release create "v$(node -p "require('./package.json').version")" --generate-notes

License

MIT © Orell Bühler