Skip to main content
Glama
README.md
<div align="center">

# Play Store MCP

### Manage Google Play releases, store listings, testers, and reviews from your AI agent.

![Node.js 20+](https://img.shields.io/badge/Node.js-20%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)
![22 MCP tools](https://img.shields.io/badge/MCP-22_tools-5c4ee5?style=flat-square)
[![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](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

A3.5/5.0

Scored across 22 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count3/5

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.

Completeness4/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues