google-play-mcp
Wraps the Google Play Android Publisher API v3 to inspect app subscription catalogs and tracks, and to update regional base-plan prices. Provides read tools to list and fetch subscriptions (base plans, regional price configs, listings), a read tool to inspect release tracks (production, beta, alpha, internal) without committing any edit, and a write tool that patches the price of an existing regional config on a base plan with validation and safety checks.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
google-play-mcp
A minimal MCP server (stdio transport) that wraps the Google Play Android Publisher API v3 for subscription catalog inspection, track inspection, and regional base-plan price updates.
Transport: stdio, newline-delimited JSON-RPC 2.0. No network port is opened.
Auth: a Google Cloud service account key file, read only inside this process. The key is never written to stdout, logs, request bodies, or error messages.
Read tools:
play_list_subscriptions,play_get_subscription,play_get_track.Write tool:
play_patch_base_plan_price(the only tool that modifies anything).play_get_trackcreates a temporary app edit, reads the track, and deletes the edit. It never commits an edit. Nothing in this server publishes, submits, or commits.
The protocol framing is implemented by hand (no MCP SDK dependency) to keep the server
small and auditable. Dependencies are google-auth and requests only.
Setup
1. Create a service account for the Play Developer API
In the Google Cloud console, create (or reuse) a project and enable the Google Play Android Developer API.
Create a service account (IAM & Admin → Service Accounts) and download a JSON key.
In the Play Console → Users and permissions, invite the service account's email address and grant it access to the app(s) you want to manage. For the tools in this repository you need at least:
View app information and download bulk reports (read tools),
Manage orders and subscriptions / Manage products or equivalent permission that allows editing subscriptions (for
play_patch_base_plan_price),Edit and delete draft apps / release-view permission for
play_get_track(it creates and deletes an uncommitted edit).
Store the key file outside this repository, with restrictive permissions (
chmod 600). The.gitignoreexcludes*.jsonas a safety net, but do not rely on it.
The OAuth scope used is https://www.googleapis.com/auth/androidpublisher.
2. Install
git clone https://github.com/re-x-inc/google-play-mcp.git
cd google-play-mcp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txtPython 3.10+ is required.
3. Pass the key file path
The server reads the key path from the environment variable
GOOGLE_PLAY_SA_KEY_FILE. The path is the only thing passed around; the key contents are
read by the server process itself.
export GOOGLE_PLAY_SA_KEY_FILE=/path/to/service-account.jsonNever pass the key contents via arguments, environment variables, or MCP requests.
4. Run
GOOGLE_PLAY_SA_KEY_FILE=/path/to/service-account.json .venv/bin/python server.pyThe server speaks MCP on stdin/stdout. Use absolute paths when launching it from a
non-interactive shell (for example ssh host /abs/path/.venv/bin/python /abs/path/server.py),
because no login profile is loaded there.
Helper modes for manual checks:
.venv/bin/python server.py --list-tools # print the tool list as JSON
.venv/bin/python server.py --call play_get_subscription \
'{"packageName":"com.example.app","productId":"premium_yearly"}' # call one tool, print JSON
python examples/stdio_client.py com.example.app [productId] # end-to-end stdio smoke testExample MCP client configuration (Claude Desktop / Claude Code style):
{
"mcpServers": {
"google-play": {
"command": "/abs/path/google-play-mcp/.venv/bin/python",
"args": ["/abs/path/google-play-mcp/server.py"],
"env": { "GOOGLE_PLAY_SA_KEY_FILE": "/path/to/service-account.json" }
}
}
}Related MCP server: play-store-mcp
Tools
All tools return a JSON object both as structuredContent and as a text block. Errors
from the Google API are returned with isError: true and the API's error body
(httpStatus, method, url, error). Validation errors are returned as
{"error": "invalid_request", "message": ...}.
play_list_subscriptions (read)
monetization.subscriptions.list.
Input | Type | Required | Notes |
| string | yes | e.g. |
| integer 1..1000 | no | API default 50 |
| string | no | from a previous |
| boolean | no | return raw |
Output: { packageName, count, subscriptions: [Summary | Subscription], nextPageToken? }.
A Summary is
{ packageName, productId, listings: { <lang>: {title, description} }, basePlans: [BasePlanSummary] }
and a BasePlanSummary is
{ basePlanId, state, type: {kind, ...}, offerTags, regionalConfigs: [{regionCode, newSubscriberAvailability, price, priceText}], otherRegionsConfig }.
state is DRAFT | ACTIVE | INACTIVE; price is a google.type.Money
({currencyCode, units, nanos?}).
play_get_subscription (read)
monetization.subscriptions.get.
Input | Type | Required |
| string | yes |
| string | yes |
Output: { summary: Summary, raw: Subscription } (raw is the untouched API resource).
play_get_track (read)
edits.insert → edits.tracks.get → edits.delete. The edit is never committed.
Input | Type | Required | Notes |
| string | yes | |
| string | no |
|
Output:
{ packageName, track, releases: [{name, status, versionCodes, userFraction, inAppUpdatePriority, countryTargeting, releaseNotes}], edit: {id, committed: false, deleted} }.
status is draft | inProgress | halted | completed. releases is empty when the
track has no active release.
play_patch_base_plan_price (write)
monetization.subscriptions.patch with updateMask=basePlans. The server fetches the
subscription, replaces the price of one existing regional config, and sends the full
basePlans array back (field masks cannot address a single list element).
Input | Type | Required | Notes |
| string | yes | |
| string | yes | |
| string | yes | |
| string | yes | must already exist in the base plan's |
| object | yes |
|
| string | no |
|
| enum | no |
|
| boolean | no | default |
Output:
{ packageName, productId, basePlanId, regionCode, basePlanState, before: {price, priceText}, requested: {price, priceText}, after: {price, priceText}, updateMask, regionsVersion }.
Safety checks performed before any write: base plan must exist; the region must already be
configured; the currency must match; ACTIVE base plans are refused unless allowActive
is set. Adding regions, changing availability, or changing base plan state is out of scope.
Security notes
Do not commit key files.
.gitignoreexcludes*.json,*.pem,*.p12,.env*.Run the server on the machine that holds the key, and connect clients over stdio (for example through SSH) so that the key never leaves that machine.
Consider restricting the set of callable tools on the client side (an allow-list) when exposing this server to automated agents.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read subscriptions, subscribers and orders; manage renewals, billing skips and payment links.
Read products, sales, subscribers and offer codes; verify, enable and disable product licenses.
Server-side purchase verification and entitlements for Google Play and Apple App Store over MCP.
Set up and inspect app paywalls, subscriptions, offerings and analytics from your AI agent.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables reading and replying to Google Play Store reviews using the Android Publisher API, with no extra functionality to limit security risk.2MIT
- AlicenseNot gradedqualityDmaintenanceEnables to interact with Google Play Console, allowing release management, app vitals monitoring, and APK/AAB deployment via a service account.MIT
- AlicenseNot gradedqualityBmaintenanceEnables end-to-end Android app publishing to Google Play via the Developer API, including readiness checks, releases, promotions, reviews, and subscriptions.2MIT
- AlicenseAqualityAmaintenanceEnables MCP clients to inspect Google Play releases, reviews, Android vitals, and scoped bulk reports, and to prepare explicitly authorized changes using locally supplied service-account credentials. Reads are default, while optional writes and sensitive reads require explicit configuration and single-use execution.41342 PyPIAGPL 3.0