Play Store MCP
<div align="center">
# Play Store MCP
### Manage Google Play releases, store listings, testers, and reviews from your AI agent.


[](LICENSE)
[Quick start](#quick-start) · [What it can do](#what-it-can-do) · [Google credentials](#configure-google-credentials) · [MCP clients](#connect-your-mcp-client) · [Tool reference](#tool-reference) · [License](#license)
</div>
Play Store MCP is a [Model Context Protocol](https://modelcontextprotocol.io/) server for the official [Google Play Developer API](https://developers.google.com/android-publisher/api-ref/rest). MCP clients launch it from the npm registry with `npx`; no repository checkout or global installation is needed. The server runs over stdio and uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials). App bundles and listing images are read from the machine running the MCP client when you choose to upload them.
## Quick start
1. Install Node.js 20 or newer, then [configure Google credentials](#configure-google-credentials) and grant the service account access to your app in Play Console.
2. Register the npm package with your MCP client. For example, with Codex:
```sh
codex mcp add play-store \
--env GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.json \
-- npx -y play-store-developer-mcp
codex mcp list
```
`npx` downloads the package from npm and starts its MCP server. The credential value is an **absolute path to a private JSON file**, not the JSON contents. See [Claude Code, Claude Desktop, and Codex instructions](#connect-your-mcp-client) for other setups.
3. Start with a read-only request to your agent:
```text
List the reviews for com.example.app and summarize the recurring issues.
```
To inspect releases, ask for `list_track_releases` on a named track. Edit-backed tools need an existing `editId`.
## What it can do
| Area | Capabilities |
| --- | --- |
| Reviews | Read reviews with pagination and translation; publish developer replies. |
| Releases | Inspect tracks and bundles; upload an AAB; stage, validate, and commit a track release. |
| Testing | Read and replace Google Groups assigned to a testing track. |
| Store presence | Read and patch localized listing text; list and upload listing images. |
| Internal sharing | Upload an AAB for a shareable internal app artifact without a track release. |
Publishing uses Google's transactional [app edits](https://developers.google.com/android-publisher/edits):
```text
create_edit → upload_bundle → update_track → validate_edit → commit_edit
│ │
└─ list_bundles └─ get_track / list_tracks
```
For AAB releases, `upload_bundle` reads an absolute `.aab` path on the machine running the server. `update_track` replaces the track's **entire** release list, so include releases you want to keep. `commit_edit` applies **every** staged change in the edit, including listing and tester changes, and requires `confirmPublish: true`. Read tools do not create or commit edits.
## Tool reference
| Tool | Action |
| --- | --- |
| `list_reviews` | List app reviews with page tokens and optional translation. |
| `get_review` | Read one review. |
| `list_track_releases` | Read up to 20 non-obsolete releases and lifecycle states for a track. |
| `list_store_listings` | Read all localized store listings from an existing app edit. |
| `get_store_listing` | Read one localized store listing from an edit. |
| `patch_store_listing` | **Changes draft state:** patch supplied text or video fields in one localized listing. |
| `list_listing_images` | Read images for a language and image type in an edit. |
| `upload_listing_image` | **Changes draft state:** add a local PNG or JPEG to a listing in an edit. |
| `get_track` | Read track configuration and active releases from an existing app edit. |
| `list_tracks` | Read every track, including tracks without releases, from an edit. |
| `list_bundles` | Read app bundles and version codes from an edit. |
| `get_edit` | Read an edit's ID and expiration time. |
| `get_testers` | Read Google Groups assigned to a testing track in an edit. |
| `update_testers` | **Changes draft state:** replace the Google Groups assigned to a testing track. |
| `reply_to_review` | Publish or replace the public developer reply to a review. |
| `create_edit` | **Changes draft state:** create an app edit and return its ID; can invalidate another open edit. |
| `upload_bundle` | **Changes draft state:** upload a local `.aab` into an edit; returns its version code. |
| `update_track` | **Changes draft state:** replace a track's full release list in an edit. |
| `validate_edit` | Check an edit for publishing errors without committing it. |
| `commit_edit` | **Publishes:** commit all staged changes in an edit. |
| `discard_edit` | **Deletes draft state:** discard an edit and its uncommitted changes. |
| `upload_internal_sharing_bundle` | **Uploads for sharing:** upload a local `.aab` and return a sharing artifact. |
Every tool requires an Android `packageName` such as `com.example.app`; the server does not discover apps. Track tools also require a name such as `production`, `qa` (internal testing), or `wear:production` ([track names](https://developers.google.com/android-publisher/tracks)). Edit-backed tools require an `editId` returned by `create_edit` or an existing publishing workflow. Read tools never create or commit edits. `reply_to_review` publishes a public reply, so check the review and reply text before calling it.
`update_testers` replaces the full `googleGroups` array; pass `[]` to remove all groups. The [testers API](https://developers.google.com/android-publisher/api-ref/rest/v3/edits.testers) does not manage individual email lists. `patch_store_listing` accepts at least one of `title`, `shortDescription`, `fullDescription`, or a YouTube `video` URL. For images, choose one of `phoneScreenshots`, `sevenInchScreenshots`, `tenInchScreenshots`, `tvScreenshots`, `wearScreenshots`, `icon`, `featureGraphic`, or `tvBanner` ([image types](https://developers.google.com/android-publisher/api-ref/rest/v3/AppImageType)). `upload_listing_image` reads an absolute local PNG or JPEG path and **adds** an image; it does not replace existing images. A store listing must exist for the selected language when listing its images. All draft changes take effect only after `commit_edit`; committing also applies any other staged changes in that edit.
## Configure Google credentials
You need a Play Console developer account with the target app, a Google Cloud project, and Node.js 20 or newer. The server uses [Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/application-default-credentials) with the `https://www.googleapis.com/auth/androidpublisher` OAuth scope. Google no longer requires linking the Play developer account to the Cloud project. Follow these steps to configure a service account for your MCP client. [Google Play API setup](https://developers.google.com/android-publisher/getting_started)
1. **Select or create a Google Cloud project.** In that project, open [Google Play Developer API](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com) and select **Enable**. If you cannot enable it, ask a project administrator for **Service Usage Admin** (`roles/serviceusage.serviceUsageAdmin`) or an equivalent custom role. This role is for the person enabling the API, not for the MCP service account. [Cloud role requirements](https://cloud.google.com/service-usage/docs/enable-disable)
2. **Create a service account.** In the same project, open [IAM & Admin → Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts), select **Create service account**, and save its email address (for example, `play-mcp@example-project.iam.gserviceaccount.com`). You can leave **Grant this service account access to project** empty for this MCP: app access is granted in Play Console in the next step. If you cannot create the account, the setup operator needs **Create Service Accounts** (`roles/iam.serviceAccountCreator`) or equivalent permission. [Cloud service account setup](https://cloud.google.com/iam/docs/service-accounts-create)
3. **Invite that email to Play Console.** In [Play Console → Users and permissions](https://play.google.com/console/users-and-permissions), select **Invite new users**, enter the service account email, choose **App permissions**, and grant access only to the app this MCP will manage. Select the permissions below, then select **Invite user**. These are **Play Console permissions**, not Cloud IAM roles. [Google's Play permission definitions](https://support.google.com/googleplay/android-developer/answer/9844686)
| Tools | Play Console app permission |
| --- | --- |
| `list_reviews`, `get_review`, `list_store_listings`, `get_store_listing`, `list_listing_images`, `get_track`, `list_tracks`, `list_bundles`, `get_edit`, `get_testers` | **View app information (read-only)**; test read access with the selected app. |
| `list_track_releases` | **View app quality information (read-only)** covers basic track and release information; **View app information (read-only)** is also appropriate if you use the other read tools. |
| `reply_to_review` | **View app information (read-only)** plus **Reply to reviews**. |
| `create_edit`, `upload_bundle`, `update_track`, `validate_edit`, `commit_edit`, `discard_edit` | **Release apps to testing tracks** for test-track releases; **Release to production, exclude devices, and use Play App Signing** for production releases. |
| `upload_internal_sharing_bundle` | **Release apps to testing tracks**, which includes internal app sharing upload access. |
| `update_testers` | **Manage testing tracks and edit tester lists**. |
| `patch_store_listing`, `upload_listing_image` | **Manage store presence**. |
These are the Play Console categories that match the actions each tool performs. Google does not publish a per-method permission matrix for these endpoints, so verify your selected permissions against a test app. Grant production release permission only if this service account will publish to production. [Play Console permission definitions](https://support.google.com/googleplay/android-developer/answer/9844686)
4. **Provide local ADC.** For a desktop MCP client, the straightforward option is a service account JSON key: open the service account's **Keys** tab, select **Add key → Create new key → JSON**, and store the downloaded file **outside this repository** in a private location. If key creation is blocked by organization policy, use an approved ADC method instead. The setup operator may need **Service Account Key Admin** (`roles/iam.serviceAccountKeyAdmin`) to create the key; that role should not be granted to the service account itself. [Key creation and restrictions](https://cloud.google.com/iam/docs/keys-create-delete)
On macOS or Linux, restrict access to the downloaded file:
```sh
chmod 600 /absolute/path/to/service-account.json
```
Set `GOOGLE_APPLICATION_CREDENTIALS` in the MCP client configuration to that **absolute file path**, as shown below. The variable contains a path, never the JSON contents. ADC can also use credentials supplied by the host environment without this variable. [ADC credential lookup](https://cloud.google.com/docs/authentication/application-default-credentials)
## Connect your MCP client
Replace `/absolute/path/to/service-account.json` below with the path on your machine. The JSON file stays private; only its path belongs in the MCP configuration. The examples use `npx -y play-store-developer-mcp`, which runs the package from npm. If a desktop app cannot find `npx`, use the absolute path shown by `command -v npx`. Keep `GOOGLE_APPLICATION_CREDENTIALS` in the process that launches the MCP server; setting it in an unrelated terminal will not configure a desktop client.
### Claude Code
```sh
claude mcp add play-store \
--env GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.json \
-- npx -y play-store-developer-mcp
claude mcp list
```
Run `/mcp` inside Claude Code to check the connection. Claude Code stores this server for the current project by default. Add `--scope user` before `play-store` if you want it in all Claude Code projects. See [Claude Code MCP setup](https://code.claude.com/docs/en/mcp).
### Claude Desktop
Add the `play-store` entry to the existing `mcpServers` object in `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS:
```json
{
"mcpServers": {
"play-store": {
"command": "npx",
"args": ["-y", "play-store-developer-mcp"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/service-account.json"
}
}
}
}
```
Preserve any other servers already in the file, then fully quit and reopen Claude Desktop. Check the server and its tools under Connectors or Extensions. See [Claude Desktop local MCP setup](https://support.claude.com/en/articles/10949351-getting-started-with-local-mcp-servers-on-claude-desktop).
### Codex CLI or app
```sh
codex mcp add play-store \
--env GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.json \
-- npx -y play-store-developer-mcp
codex mcp list
```
Codex shares MCP configuration between its CLI and IDE extension. In the Codex terminal UI, use `/mcp` to inspect the server. See the [official OpenAI Docs for Codex MCP](https://learn.chatgpt.com/docs/extend/mcp).
## License
Play Store MCP is licensed under the [MIT License](LICENSE). Third-party dependencies retain their own licenses and copyright notices.
TDQS
Scored across 22 tools
The tools split cleanly along resource lines (edits, tracks, listings, bundles, reviews, testers) and read vs. mutate operations are mostly self-evident from names. The only real overlaps are upload_bundle vs upload_internal_sharing_bundle and list_track_releases vs get_track, though the descriptions distinguish them by edit requirements and sharing destination.
Every tool follows a consistent snake_case verb_noun pattern (list_reviews, get_review, create_edit, patch_store_listing, commit_edit, reply_to_review). The one-word suffix forms like create_edit/discard_edit are still verb_noun and highly predictable.
22 tools is at the heavy end for a single server, and the surface spans several sub-domains (edits, tracks, listings, images, testers, reviews, bundles). Each tool arguably earns its place, but the count makes discovery and selection more burdensome than a tighter core set would.
The edit lifecycle is fully covered (create/get/validate/commit/discard), and tracks, listings, testers, bundles, and reviews each have read/write operations. Gaps remain: there is no way to delete listing images or listings, and no tool for app-level metadata or halting/rolling back a rollout.