Skip to main content
Glama
google-play-developer-mcp

google-play-developer-mcp

by devinwang

google-play-developer-mcp

The complete Model Context Protocol (MCP) server for Google Play. 157 tools. Full Android Publisher API v3 + Play Developer Reporting API v1beta1. No deprecated endpoints. Works with Claude, Cursor, VS Code Copilot, Gemini CLI, or any MCP client.

npm version npm downloads CI License: MIT Node Tools: 157 API: v3 Reporting: v1beta1 MCP TypeScript

See also: app-store-connect-mcp — the same philosophy for Apple's App Store Connect.


Table of Contents


Related MCP server: Google Play Developer API MCP Server

Why this exists

Google Play Console has an API, but its surface is wide and moves fast. Existing community MCPs each cover a slice — one does store listings, another does releases, a third does reviews — and all lag behind Google's deprecations.

google-play-developer-mcp is the one that covers everything.

Property

This server

Typical community MCP

Android Publisher API v3

✅ Full

Partial

Play Developer Reporting API

✅ Full

❌ Missing

monetization.onetimeproducts (post-2025 catalog)

✅

Uses deprecated inappproducts

purchases.subscriptionsv2 / productsv2

✅

Often still on v1

2026 features (OfferPhase, cancel/defer, priceStepUp)

✅

❌

Multi-account

✅

Usually one

Credential safety

No keys in repo, strict .gitignore

Varies

Public release under semver

✅ v1.0.0

Mostly pre-1.0

If you drive Google Play Console with an AI assistant — release automation, review triage, subscription catalog management, crash triage — this gives the assistant a full toolbox in one install.


Feature matrix

157 tools across 33 groups. Every non-deprecated endpoint in both APIs.

Group

Tools

Covers

accounts_*

6

Local registry — add / list / switch / remove / update multiple Play Console accounts

auth_*

1

Verify the service account can acquire a token

apps_*

2

List every app the service account can see, get app details

edits_*

5

Managed-publishing transactions: insert, get, validate, commit, delete

details_*

3

App-level contact email / phone / website, default language

country_availability_*

1

Per-country availability within an edit

listings_*

6

Per-locale title / short description / full description / video. Includes delete_all

images_*

4

Icon, feature graphic, promo graphic, phone/tablet/TV/wear screenshots. List, upload, delete, delete-all

bundles_*

2

Upload and list Android App Bundles (AAB)

apks_*

3

Upload / list APKs + register externally-hosted APK (enterprise)

deobfuscation_files_*

1

Upload ProGuard / native code mapping

expansion_files_*

4

OBB — get / upload / update / patch

tracks_*

5

internal, alpha, beta, production, plus custom closed-testing tracks. List, get, update, patch, create

testers_*

3

Google Groups allowlists for internal / closed tracks

onetime_products_*

17

✨ New monetization catalog for non-subscription products. Three-level hierarchy: product → purchase option → offer. Complete CRUD + batch on all three levels

subscriptions_*

8

Subscription catalog: list, create, update, delete, archive, batch-get, batch-update

subscription_base_plans_*

7

Monthly/annual plans. Activate, deactivate, migrate prices, batch migrate, batch update + states

subscription_offers_*

10

Free trials / introductory prices. Create, update, delete, activate, deactivate + batch flavours

monetization_convert_region_prices

1

Compute comparable region prices from one input price

purchases_products_v2_*

1

Verify one-time-product purchases (supports multiple purchase options + offers)

purchases_products_*

2

Acknowledge / consume one-time purchases (productsv2 only exposes get)

purchases_subscriptions_v2_*

4

Get, revoke, cancel, defer. Includes 2026 OfferPhase, outOfAppPurchaseContext, priceStepUp consent, item-based refund

purchases_subscriptions_acknowledge

1

v1 acknowledge (retained — still the right call for acknowledging initial purchase)

purchases_voided_list

1

Refund / chargeback feed

orders_*

5

List, get, batch-get, refund, review refund (get + batch-get added 2025-05, review_refund added 2026-07 for collaborative chargebacks)

external_transactions_*

3

Alternative Billing (Korea / EU) — get / create / refund

reviews_*

3

List, get, reply

users_* + grants_*

7

Team members & per-app grants

device_tier_configs_*

3

Device-tier targeting for AAB

app_recovery_*

5

Recovery actions: list, create, deploy, cancel, add targeting

generated_apks_*

2

List and download generated APKs from an AAB

system_apks_variants_*

4

System APK variants for preload scenarios

internal_app_sharing_*

2

Upload APK or AAB for internal link sharing

Group

Tools

Covers

reports_apps_*

2

search, fetch_release_filter_options

reports_anomalies_list

1

Detected anomalies across all metric sets

reports_crash_rate_*

2

Crash rate — metadata + time-series query

reports_anr_rate_*

2

ANR rate

reports_slow_start_rate_*

2

Slow start (cold launch)

reports_slow_rendering_rate_*

2

Slow rendering (jank)

reports_excessive_wakeup_rate_*

2

Battery — excessive wake-ups

reports_stuck_background_wake_lock_rate_*

2

Battery — stuck wake locks

reports_lmk_rate_*

2

Low-memory killer rate

reports_anon_rss_swap_memory_*

2

Anonymous RSS + swap memory usage

reports_bitmap_memory_*

2

Bitmap memory usage

reports_errors_counts_*

2

Aggregate error counts

reports_errors_issues_search

1

Grouped ErrorIssue search

reports_errors_reports_search

1

Raw ErrorReport search


Quick start

npm install -g google-play-developer-mcp

Then in your MCP client config (e.g. ~/.config/claude/config.json, Cursor MCP config, or VS Code mcp.json):

{
  "mcpServers": {
    "google-play-developer": {
      "command": "google-play-developer-mcp"
    }
  }
}

Next, tell the server which Play Console account to use — see the setup guide below.


Step-by-step setup

1. Create a Google Cloud service account

  1. Open the Google Cloud Console.

  2. Select or create a project (any project — this is just where the service account lives).

  3. APIs & Services → Library — enable both of these:

    • Google Play Android Developer API

    • Google Play Developer Reporting API

  4. IAM & Admin → Service Accounts → Create service account.

  5. Once created, open the account → Keys → Add key → JSON. Download the JSON file.

  6. Move the JSON file somewhere safe and outside any git repo. A good location: ~/.config/google-play-developer-mcp/service-account.json.

2. Authorize the service account in Play Console

  1. Open Play Console.

  2. Users and permissions → Invite new user. Paste the service account email (it looks like name@project-id.iam.gserviceaccount.com).

  3. Assign permissions:

    • Admin (all permissions) for full access.

    • Or narrower combinations (View app information, Manage store presence, Manage orders and subscriptions, etc.) if you want to restrict what the MCP can do.

  4. Wait up to 24 hours. Play Console takes time to propagate the new authorization — this is a common gotcha. If early API calls return PERMISSION_DENIED, this is usually why.

3. Register the account with the MCP server

Launch any MCP client that has the server configured, then run:

accounts_add --name my-app \
  --keyFile /Users/you/.config/google-play-developer-mcp/service-account.json \
  --description "My company's Play Console"

(Or manually create ~/.google-play-developer-mcp/accounts.json — see the file format below.)

4. Verify

auth_status

Should return { ok: true, email: "..." }.

apps_list

Lists the apps the service account can see.


Register with your MCP client

Claude Desktop

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "google-play-developer": {
      "command": "google-play-developer-mcp"
    }
  }
}

Claude Code

claude mcp add google-play-developer google-play-developer-mcp

Or edit ~/.claude.json:

{
  "mcpServers": {
    "google-play-developer": {
      "command": "google-play-developer-mcp"
    }
  }
}

Cursor

Settings → MCP → Add new MCP server:

{
  "google-play-developer": {
    "command": "google-play-developer-mcp"
  }
}

VS Code (GitHub Copilot agent mode)

.vscode/mcp.json:

{
  "servers": {
    "google-play-developer": {
      "type": "stdio",
      "command": "google-play-developer-mcp"
    }
  }
}

Gemini CLI / Codex CLI / Windsurf / Continue

Any MCP-compliant client accepts the same command entry — point it at the globally installed google-play-developer-mcp binary (or at node /path/to/dist/index.js if running from source).

Running from source (no npm install -g)

git clone https://github.com/devinwang/google-play-developer-mcp.git
cd google-play-developer-mcp
npm install
npm run build

Then in your MCP client config:

{
  "mcpServers": {
    "google-play-developer": {
      "command": "node",
      "args": ["/absolute/path/to/google-play-developer-mcp/dist/index.js"]
    }
  }
}

Usage examples

Release a new build to internal testing

accounts_switch --name my-app

# Open an edit, upload bundle, route it to the internal track, commit.
edits_insert --packageName com.example.app
# → { id: "EDIT_ID", expiryTimeSeconds: "..." }

bundles_upload --packageName com.example.app --editId EDIT_ID \
  --file /path/to/app-release.aab
# → { versionCode: 47, sha256: "..." }

tracks_update --packageName com.example.app --editId EDIT_ID \
  --track internal \
  --releases '[{"versionCodes":["47"],"status":"completed","releaseNotes":[{"language":"en-US","text":"Fixes a crash on startup."}]}]'

edits_commit --packageName com.example.app --editId EDIT_ID

Promote a release from beta to production with staged rollout

edits_insert --packageName com.example.app
# → EDIT_ID

# Promote the beta versionCodes to production with 10% staged rollout.
tracks_update --packageName com.example.app --editId EDIT_ID \
  --track production \
  --releases '[{"versionCodes":["47"],"status":"inProgress","userFraction":0.1}]'

edits_commit --packageName com.example.app --editId EDIT_ID

Reply to reviews

reviews_list --packageName com.example.app --maxResults 50
# → { reviews: [{ reviewId, authorName, comments, ... }] }

reviews_reply --packageName com.example.app --reviewId REVIEW_ID \
  --replyText "Thanks for the feedback! The crash is fixed in v1.2 — please update."

Create a subscription with a free-trial offer

# 1. Create the subscription (product)
subscriptions_create --packageName com.example.app --productId plus_monthly \
  --subscription '{"listings":[{"languageCode":"en-US","title":"Plus","benefits":["All premium features"]}],"taxAndComplianceSettings":{"taxTier":"TAX_TIER_UNSPECIFIED"}}'

# 2. Create a base plan
subscription_base_plans_batch_update --packageName com.example.app --productId plus_monthly \
  --requests '[{"basePlan":{"basePlanId":"monthly","autoRenewingBasePlanType":{"billingPeriodDuration":"P1M","accountHoldDuration":"P30D"},"state":"DRAFT","regionalConfigs":[{"regionCode":"US","price":{"currencyCode":"USD","units":"9","nanos":990000000}}]},"updateMask":"autoRenewingBasePlanType,regionalConfigs"}]'

# 3. Activate the base plan
subscription_base_plans_activate --packageName com.example.app \
  --productId plus_monthly --basePlanId monthly

# 4. Create a 7-day free-trial offer
subscription_offers_create --packageName com.example.app --productId plus_monthly \
  --basePlanId monthly --offerId new-user-trial \
  --offer '{"phases":[{"duration":"P7D","regionalConfigs":[{"regionCode":"US","free":true}]}],"state":"DRAFT"}'

subscription_offers_activate --packageName com.example.app \
  --productId plus_monthly --basePlanId monthly --offerId new-user-trial

Verify a purchase token server-side (backend use case)

# For a one-time product (consumable or non-consumable)
purchases_products_v2_get --packageName com.example.app --token PURCHASE_TOKEN

# For a subscription — includes 2026 OfferPhase, priceChangeState, etc.
purchases_subscriptions_v2_get --packageName com.example.app --token PURCHASE_TOKEN

Triage crashes

reports_crash_rate_query \
  --name "apps/com.example.app/crashRateMetricSet" \
  --dimensions '["versionCode","countryCode"]' \
  --metrics '["crashRate","distinctUsers"]' \
  --timelineSpec '{"aggregationPeriod":"DAILY","startTime":{"year":2026,"month":4,"day":1},"endTime":{"year":2026,"month":4,"day":8}}'

reports_errors_issues_search --parent "apps/com.example.app" \
  --filter "errorIssueType = \"CRASH\""

Tool reference

All tools use snake_case names following the resource_action convention, consistent with the Android Publisher URL structure. See the Feature matrix for the full group breakdown.

Each tool accepts a JSON object of arguments — inspect the schema from your MCP client (Claude Code: /mcp tools, Claude Desktop: show tool list in chat, Cursor: MCP panel) to see the exact shape.

Complex body arguments (e.g. subscription, offer, appRecoveryAction, subscription releases) accept the Google-documented JSON schema directly — see the official reference.


Security

This repo ships with zero credentials. You bring a service-account JSON key; the server records only the path.

What is and isn't on disk:

Where

What

~/.google-play-developer-mcp/accounts.json

Account name + key-file path + description. No secrets. Created with 0600 permissions.

~/.config/…/service-account.json (you place it)

The actual Google Cloud service-account JSON. Never committed. Never emitted by any tool.

Repo contents

Code only.

.gitignore blocks

  • *.json.key, *service-account*.json, *service_account*.json, *-sa.json, *-sa-key.json

  • gcp-key*.json, google-credentials*.json, play-credentials*.json

  • .env, .env.* (but keeps .env.example)

  • accounts.json, credentials/, keys/, secrets/

  • *.pem, *.p12, *.pfx, *.key, id_rsa*

  • Keep your service-account JSON outside any git repo on your machine.

  • Grant the service account the narrowest role that your workflow needs. Full admin grants the MCP permission to delete app metadata — give it only what you need.

  • Rotate the service-account key yearly: delete the old key in Google Cloud Console, create a new one, run accounts_update --keyFile <newPath>.

  • auth_status never returns the actual token; only a boolean and the service-account email.

Audit trail

Every write operation on the Android Publisher API is logged by Google Cloud IAM under the service account's identity. If you ever suspect misuse, IAM → Audit Logs in the Cloud Console will show which endpoints were called.


Design notes

  • Edit-session-aware. Every write on the Android Publisher API runs inside an edit. The server exposes edits_insert / edits_commit / edits_delete directly so you can hold an edit open across many tool calls — the most common multi-step flow. If you forget to commit, nothing ships. Safe by default.

  • Multi-account. One server process can manage many Play Console accounts. Switch with accounts_switch. State lives in ~/.google-play-developer-mcp/accounts.json.

  • No deprecated endpoints. Catalogue endpoints use monetization.onetimeproducts (not the deprecated inappproducts). Purchase verification uses purchasesV2 / subscriptionsV2.

  • Forward-compatible types. Where Google ships an API feature faster than the googleapis TypeScript typings, we cast through publisherAny() / reportingAny(). The HTTP calls are identical — only TypeScript's static check is skipped on the known-drifting surfaces.

  • Good error messages. Every Google API error is translated — 401 becomes "your token is wrong", 403 becomes "permission not propagated, wait 24h", 429 becomes "quota exhausted", etc.

  • Stateless transport. Server is stdio, no network listener, no persistent state beyond the accounts file.

  • Zero telemetry. The server never phones home.


Contributing

PRs welcome. Before you submit:

  • npm run typecheck passes (CI will also run this)

  • Never include a service-account key or token in an issue or PR. If you need to share a reproduction, redact the token (X-Goog-Api-Client: ...REDACTED...).

  • New tools follow the resource_action naming convention.

  • If you add a tool that hits a new API surface, add it to the Feature matrix so the doc stays in sync.


Version history

0.2.0 — 2026-10-21

  • 157 MCP tools (+7). New: orders_review_refund, purchases_products_acknowledge, purchases_products_consume, reports_anon_rss_swap_memory_{get,query}, reports_bitmap_memory_{get,query}.

  • Upgraded googleapis 171 → 187.

0.1.0 — 2026-04-20 (first public release)

  • 150 MCP tools covering the full Android Publisher API v3 and Play Developer Reporting API v1beta1.

  • Latest-generation endpoints only. Uses monetization.onetimeproducts (replaces deprecated inappproducts), purchases.productsv2 / subscriptionsv2 (replaces v1).

  • 2026 features. SubscriptionPurchaseV2.offerPhase, purchases.subscriptionsv2.cancel/defer, orders.batchGet, offerPhaseDetails, price step-up consent, outOfAppPurchaseContext.

  • Multi-account support with on-disk registry.

  • Zero credentials in the repository. Comprehensive .gitignore.

  • Error translation for all common Google API failure modes.


References


License

MIT — see LICENSE.

Available Tools

157 tools
accounts_addA

Register a new Play Console account. Provide a local filesystem path to a Google Cloud service-account JSON key. The key stays on disk — the MCP only records its path.

Inputs: name (required), keyFile (required), description.

accounts_currentA

Show which account is currently active. All subsequent API calls target this account.

Inputs: no named parameters.

accounts_listA

List every Play Console account registered with the MCP server (names + key-file paths, no secrets).

Inputs: no named parameters.

accounts_removeB

Remove an account from the local registry. Does NOT delete the key file.

Inputs: name (required).

accounts_switchB

Make an existing registered account the active one.

Inputs: name (required).

accounts_updateB

Change the key-file path or description of an existing account.

Inputs: name (required), keyFile, description.

apks_add_externally_hostedA

Register an APK that is hosted outside Google Play (enterprise-only, requires allowlist).

Inputs: editId (required), packageName (required), externallyHostedApk (required).

apks_listB

List all APK uploads in the edit.

Inputs: editId (required), packageName (required).

apks_uploadA

Upload a new APK. Prefer AAB via bundles_upload.

Inputs: file (required), editId (required), packageName (required).

app_recovery_add_targetingB

Add targeting (country/locale/version) to an in-progress recovery action.

Inputs: packageName (required), appRecoveryId (required), targetingUpdate (required).

app_recovery_cancelB

Cancel an in-flight app recovery action.

Inputs: packageName (required), appRecoveryId (required).

app_recovery_createD

Create an app recovery action.

Inputs: packageName (required), appRecoveryAction (required).

app_recovery_deployC

Deploy an app recovery action to users.

Inputs: packageName (required), appRecoveryId (required).

app_recovery_listC

List app recovery actions for a versionCode.

Inputs: packageName (required), versionCode (required).

apps_getA

Open a fresh edit and return the details resource (contact email/phone/website + default language) for one app.

Inputs: packageName (required).

apps_listB

List every Android app the active service account can access. Uses the Play Developer Reporting API's apps.search.

Inputs: pageSize, pageToken.

auth_statusA

Verify that the active account can acquire a Google OAuth token. Returns the service-account email plus whether a token was obtained.

Inputs: no named parameters.

bundles_listC

List all AAB uploads in the current edit.

Inputs: editId (required), packageName (required).

bundles_uploadA

Upload a new App Bundle (.aab). Returns versionCode and sha256. Commit the edit separately to publish to a track.

Inputs: file (required), editId (required), packageName (required), deviceTierConfigId, +1 more.

country_availability_getB

Fetch per-country availability for a given track within an edit.

Inputs: track (required), editId (required), packageName (required).

deobfuscation_files_uploadC

Upload a ProGuard mapping file for a specific version code. Use deobfuscationFileType='proguard' or 'nativeCode'.

Inputs: file (required), editId (required), packageName (required), apkVersionCode (required), +1 more.

details_getA

Get app-level details (contact email/phone/website + default language).

Inputs: editId (required), packageName (required).

details_patchB

Partial update — only the provided fields change.

Inputs: editId (required), packageName (required), contactEmail, contactPhone, +2 more.

details_updateB

Overwrite app-level details. Full replacement — unspecified fields are cleared.

Inputs: editId (required), packageName (required), contactEmail, contactPhone, +2 more.

device_tier_configs_createC

Create a new device-tier config.

Inputs: packageName (required), deviceTierConfig (required), allowUnknownDevices.

device_tier_configs_getC

Get a device-tier config by id.

Inputs: packageName (required), deviceTierConfigId (required).

device_tier_configs_listB

List all device-tier configs for an app.

Inputs: packageName (required), pageSize, pageToken.

edits_commitB

Commit and publish all changes in the edit. Pass changesNotSentForReview=true to skip automatic review submission.

Inputs: editId (required), packageName (required), changesNotSentForReview.

edits_deleteB

Abandon an edit. All pending changes are discarded.

Inputs: editId (required), packageName (required).

edits_getA

Fetch an existing edit — useful to check expiry before work.

Inputs: editId (required), packageName (required).

edits_insertA

Open a new edit session for an app. Returns the edit id plus its expiry. Subsequent edits.* tool calls must pass this id.

Inputs: packageName (required).

edits_validateA

Validate an edit without committing. Catches schema/media errors before you publish.

Inputs: editId (required), packageName (required).

expansion_files_getB

Get expansion file metadata for a version code.

Inputs: editId (required), packageName (required), apkVersionCode (required), expansionFileType (required).

expansion_files_patchC

Partial update of expansion file metadata.

Inputs: editId (required), packageName (required), apkVersionCode (required), expansionFileType (required), +2 more.

expansion_files_updateC

Full update of expansion file metadata.

Inputs: editId (required), packageName (required), apkVersionCode (required), expansionFileType (required), +2 more.

expansion_files_uploadC

Upload expansion file contents (OBB).

Inputs: file (required), editId (required), packageName (required), apkVersionCode (required), +1 more.

external_transactions_createC

Register a new external transaction (Alternative Billing).

Inputs: parent (required), transaction (required), externalTransactionId (required).

external_transactions_getC

Get an external transaction (Alternative Billing).

Inputs: parent (required), externalTransactionId (required).

external_transactions_refundC

Report a refund on an external transaction.

Inputs: parent (required), refund (required), externalTransactionId (required).

generated_apks_downloadA

Download a specific generated APK. downloadId is the id from generated_apks_list. Returns the binary as a base64 string.

Inputs: downloadId (required), packageName (required), versionCode (required).

generated_apks_listA

List generated (split + standalone) APKs for a given bundle versionCode.

Inputs: packageName (required), versionCode (required).

grants_createA

Grant a user access to one app. parent is developers/{dev}/users/{user}. Grant body contains packageName + appLevelPermissions.

Inputs: grant (required), parent (required).

grants_deleteC

Revoke a grant.

Inputs: name (required).

grants_updateC

Patch a grant (change appLevelPermissions).

Inputs: name (required), grant (required), updateMask.

images_deleteC

Delete a single image by id.

Inputs: editId (required), imageId (required), language (required), imageType (required), +1 more.

images_delete_allB

Delete every image of a given type in one locale.

Inputs: editId (required), language (required), imageType (required), packageName (required).

images_listB

List uploaded images for a specific type and locale.

Inputs: editId (required), language (required), imageType (required), packageName (required).

images_uploadB

Upload a new image. file is a local filesystem path. MIME is auto-detected from extension (png/jpg).

Inputs: file (required), editId (required), language (required), imageType (required), +1 more.

internal_app_sharing_upload_apkB

Upload an APK for internal app sharing. Returns a link you can distribute internally.

Inputs: file (required), packageName (required).

internal_app_sharing_upload_bundleC

Upload an AAB for internal app sharing.

Inputs: file (required), packageName (required).

listings_deleteC

Delete the listing for one locale.

Inputs: editId (required), language (required), packageName (required).

listings_delete_allA

Delete ALL locale listings in this edit. Irreversible within the edit.

Inputs: editId (required), packageName (required).

listings_getC

Get one locale's listing.

Inputs: editId (required), language (required), packageName (required).

listings_listB

List every locale listing within an edit.

Inputs: editId (required), packageName (required).

listings_patchC

Partial update — unspecified fields preserved.

Inputs: editId (required), language (required), packageName (required), title, +3 more.

listings_updateB

Full replacement update of a locale listing. Fields: title (30), shortDescription (80), fullDescription (4000), video (YouTube URL).

Inputs: editId (required), language (required), packageName (required), title, +3 more.

monetization_convert_region_pricesA

Utility: convert a price in one region to comparable prices in every other region. Use before setting prices on a base plan.

Inputs: price (required), packageName (required).

onetime_product_offers_batch_deleteC

Delete up to 100 offers.

Inputs: requests (required), productId (required), packageName (required), purchaseOptionId (required).

onetime_product_offers_batch_getC

Batch-get up to 100 offers.

Inputs: requests (required), productId (required), packageName (required), purchaseOptionId (required).

onetime_product_offers_batch_updateB

Batch-update up to 100 offers (creates or updates).

Inputs: requests (required), productId (required), packageName (required), purchaseOptionId (required).

onetime_product_offers_batch_update_statesC

Activate/deactivate/cancel up to 100 offers.

Inputs: requests (required), productId (required), packageName (required), purchaseOptionId (required).

onetime_product_offers_getB

Get one offer on a purchase option.

Inputs: offerId (required), productId (required), packageName (required), purchaseOptionId (required).

onetime_product_offers_listB

List offers attached to a purchase option. purchaseOptionId is required — use '-' to list across all options.

Inputs: productId (required), packageName (required), purchaseOptionId (required), pageSize, +1 more.

onetime_product_purchase_options_batch_deleteC

Delete up to 100 purchase options.

Inputs: requests (required), productId (required), packageName (required).

onetime_product_purchase_options_batch_updateC

Update or create up to 100 purchase options for a one-time product.

Inputs: requests (required), productId (required), packageName (required).

onetime_product_purchase_options_batch_update_statesC

Activate or deactivate up to 100 purchase options in one call.

Inputs: requests (required), productId (required), packageName (required).

onetime_products_batch_deleteC

Delete up to 100 one-time products in one call.

Inputs: requests (required), packageName (required).

onetime_products_batch_getB

Fetch up to 100 one-time products in one call.

Inputs: productIds (required), packageName (required).

onetime_products_batch_updateC

Update up to 100 one-time products in one call.

Inputs: requests (required), packageName (required).

onetime_products_createB

Create a one-time product. Pass the full OneTimeProduct body.

Inputs: product (required), productId (required), packageName (required), regionsVersion.

onetime_products_deleteC

Delete a one-time product.

Inputs: productId (required), packageName (required), latencyTolerance.

onetime_products_getB

Get a single one-time product.

Inputs: productId (required), packageName (required).

onetime_products_listC

List all one-time products.

Inputs: packageName (required), pageSize, pageToken.

onetime_products_updateC

Update a one-time product (patch semantics, with updateMask).

Inputs: product (required), productId (required), packageName (required), updateMask, +2 more.

orders_batch_getB

Get up to 100 orders in one call.

Inputs: orderIds (required), packageName (required).

orders_getB

Get one order by order id.

Inputs: orderId (required), packageName (required).

orders_listC

List orders within a time window. Returns OrderId, productId, purchase state, quantity, offerPhaseDetails.

Inputs: packageName (required), endTime, orderIds, pageToken, +2 more.

orders_refundB

Refund an order. Pass revoke=true to also cancel the entitlement (subscription) or consumable.

Inputs: orderId (required), packageName (required), revoke.

orders_review_refundA

Respond to a pending refund review (collaborative chargeback, 2026-07). Call within 24 hours of a PendingRefundReviewNotification. Supply refundPreference and optional usage evidence so Play can dispute the chargeback.

Inputs: orderId (required), packageName (required), refundPreference (required), pendingRefundToken (required), +3 more.

purchases_products_acknowledgeA

Acknowledge a one-time product purchase. Unacknowledged purchases are refunded by Play after 3 days.

Inputs: token (required), productId (required), packageName (required), developerPayload.

purchases_products_consumeA

Consume a consumable one-time product so the user can buy it again. Consuming also acknowledges the purchase.

Inputs: token (required), productId (required), packageName (required).

purchases_products_v2_getA

Get current state of a one-time product purchase. Supports multiple purchase options + offers (replaces legacy purchases.products).

Inputs: token (required), packageName (required).

purchases_subscriptions_acknowledgeB

Acknowledge a subscription purchase. 2025-11+ accepts optional externalAccountId for account-linking. (v1 endpoint retained for compatibility.)

Inputs: token (required), packageName (required), subscriptionId, developerPayload, +1 more.

purchases_subscriptions_v2_cancelC

Cancel a subscription (2025-09+). cancellationType: USER_REQUESTED, DEVELOPER_REQUESTED, or SYSTEM_INITIATED.

Inputs: token (required), packageName (required), cancellationType, cancelSurveyReason.

purchases_subscriptions_v2_deferA

Defer billing for a subscription (2026-01 supports subscriptions with add-ons too). Pass DeferralInfo with expectedExpiryTime + desiredExpiryTime.

Inputs: token (required), packageName (required), deferralInfo (required).

purchases_subscriptions_v2_getB

Get full state of a subscription purchase (SubscriptionPurchaseV2). Includes OfferPhase (2026), outOfAppPurchaseContext, latestSuccessfulOrderId, priceChangeState, priceStepUpConsentDetails.

Inputs: token (required), packageName (required).

purchases_subscriptions_v2_revokeC

Revoke a subscription (refund + terminate access). 2025-05 added itemBasedRefund option for per-item refunds.

Inputs: token (required), packageName (required), revocationContext.

purchases_voided_listB

List voided purchases (refunded/charged-back). Supports filtering by time range + voided source.

Inputs: packageName (required), type, token, endTime, +4 more.

reports_anomalies_listC

List detected anomalies across metric sets for an app.

Inputs: parent (required), filter, pageSize, pageToken.

reports_anon_rss_swap_memory_getC

Get anonymous RSS + swap memory usage metric-set metadata. Format: apps/{packageName}/anonRssAndSwapMemoryUsageMetricSet

Inputs: name (required).

reports_anon_rss_swap_memory_queryC

Query anonymous RSS + swap memory usage timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_anr_rate_getC

Get ANR-rate metric-set metadata.

Inputs: name (required).

reports_anr_rate_queryD

Query ANR-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_apps_fetch_release_filter_optionsB

List the release-filter dimensions available for an app (version codes, track, staged rollout).

Inputs: name (required).

reports_bitmap_memory_getB

Get bitmap memory usage metric-set metadata. Format: apps/{packageName}/bitmapMemoryUsageMetricSet

Inputs: name (required).

reports_bitmap_memory_queryC

Query bitmap memory usage timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_crash_rate_getA

Get crash-rate metric-set metadata (available dimensions, metrics, freshness).

Inputs: name (required).

reports_crash_rate_queryB

Query crash-rate timeline with dimensions, metrics, filter.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_errors_counts_getC

Get error-counts metric-set metadata.

Inputs: name (required).

reports_errors_counts_queryC

Query aggregated error-count timelines.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_excessive_wakeup_rate_getC

Get excessive-wake-up-rate metadata.

Inputs: name (required).

reports_excessive_wakeup_rate_queryC

Query excessive-wake-up-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_lmk_rate_getC

Get Low-Memory-Killer (LMK) rate metadata.

Inputs: name (required).

reports_lmk_rate_queryC

Query LMK-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_slow_rendering_rate_getC

Get slow-rendering-rate metadata.

Inputs: name (required).

reports_slow_rendering_rate_queryC

Query slow-rendering-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_slow_start_rate_getC

Get slow-start-rate metadata.

Inputs: name (required).

reports_slow_start_rate_queryD

Query slow-start-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reports_stuck_background_wake_lock_rate_getC

Get stuck-background-wake-lock-rate metadata.

Inputs: name (required).

reports_stuck_background_wake_lock_rate_queryC

Query stuck-background-wake-lock-rate timeline.

Inputs: name (required), filter, metrics, pageSize, +4 more.

reviews_getC

Get a single review by id.

Inputs: reviewId (required), packageName (required), translationLanguage.

reviews_listB

List reviews from the last 7 days. Use token from the previous page for pagination. Optional filters: language, translationLanguage, device.

Inputs: packageName (required), token, maxResults, startIndex, +1 more.

reviews_replyA

Post a public reply to a review. Replies can be edited by calling this again.

Inputs: reviewId (required), replyText (required), packageName (required).

subscription_base_plans_activateC

Activate a base plan — starts making it available for purchase.

Inputs: productId (required), basePlanId (required), packageName (required).

subscription_base_plans_batch_migrate_pricesB

Migrate prices on up to 100 base plans in one call.

Inputs: requests (required), productId (required), packageName (required).

subscription_base_plans_batch_updateC

Upsert up to 100 base plans.

Inputs: requests (required), productId (required), packageName (required).

subscription_base_plans_batch_update_statesC

Activate/deactivate up to 100 base plans.

Inputs: requests (required), productId (required), packageName (required).

subscription_base_plans_deactivateA

Deactivate a base plan — no new purchases; existing subscribers unaffected.

Inputs: productId (required), basePlanId (required), packageName (required).

subscription_base_plans_deleteA

Delete a base plan (must be inactive).

Inputs: productId (required), basePlanId (required), packageName (required).

subscription_base_plans_migrate_pricesC

Apply a price change to existing subscribers of a base plan in specific regions.

Inputs: productId (required), basePlanId (required), packageName (required), regionalPriceMigrations (required), +2 more.

subscription_offers_activateC

Activate an offer — starts making it available for purchase.

Inputs: offerId (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_batch_getC

Batch-get up to 100 offers.

Inputs: requests (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_batch_updateC

Upsert up to 100 offers.

Inputs: requests (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_batch_update_statesC

Activate/deactivate up to 100 offers.

Inputs: requests (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_createB

Create an offer on a base plan (free trial, intro pricing, etc.).

Inputs: offer (required), offerId (required), productId (required), basePlanId (required), +2 more.

subscription_offers_deactivateC

Deactivate an offer.

Inputs: offerId (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_deleteD

Delete an offer.

Inputs: offerId (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_getC

Get a single offer.

Inputs: offerId (required), productId (required), basePlanId (required), packageName (required).

subscription_offers_listA

List offers for a base plan. basePlanId supports '-' wildcard to list across all.

Inputs: productId (required), basePlanId (required), packageName (required), pageSize, +1 more.

subscription_offers_updateC

Patch-update an offer.

Inputs: offer (required), offerId (required), productId (required), basePlanId (required), +5 more.

subscriptions_archiveA

Archive a subscription. Archived subscriptions are hidden from new purchases but existing subscribers keep access.

Inputs: productId (required), packageName (required).

subscriptions_batch_getB

Get up to 100 subscriptions in one call.

Inputs: productIds (required), packageName (required).

subscriptions_batch_updateC

Update up to 100 subscriptions in one call.

Inputs: requests (required), packageName (required).

subscriptions_createC

Create a subscription.

Inputs: productId (required), packageName (required), subscription (required), regionsVersion.

subscriptions_deleteA

Delete a subscription. Only works on subscriptions with no active base plans/offers.

Inputs: productId (required), packageName (required), latencyTolerance.

subscriptions_getC

Get a single subscription.

Inputs: productId (required), packageName (required).

subscriptions_listC

List all subscriptions.

Inputs: packageName (required), pageSize, pageToken, showArchived.

subscriptions_updateB

Patch-update a subscription. Pass updateMask to limit the fields updated.

Inputs: productId (required), packageName (required), subscription (required), updateMask, +3 more.

system_apks_variants_createC

Create a new system APK variant for a versionCode.

Inputs: variant (required), packageName (required), versionCode (required).

system_apks_variants_downloadC

Download a built system APK variant. Returns base64.

Inputs: variantId (required), packageName (required), versionCode (required).

system_apks_variants_getC

Get a system APK variant.

Inputs: variantId (required), packageName (required), versionCode (required).

system_apks_variants_listB

List system APK variants created for a given versionCode.

Inputs: packageName (required), versionCode (required).

testers_getB

Get the current tester allowlist for a track.

Inputs: track (required), editId (required), packageName (required).

testers_patchC

Partial update of the tester allowlist.

Inputs: track (required), editId (required), packageName (required), googleGroups.

testers_updateB

Full replacement of the tester allowlist.

Inputs: track (required), editId (required), packageName (required), googleGroups.

tracks_createA

Create a brand-new custom closed-testing track. The new id is set on the server. Type can only be closedTesting.

Inputs: track (required), editId (required), packageName (required), type, +1 more.

tracks_getB

Get one track — includes all releases currently staged.

Inputs: track (required), editId (required), packageName (required).

tracks_listA

List every track visible in this edit (includes default internal/alpha/beta/production + any custom closed-testing tracks).

Inputs: editId (required), packageName (required).

tracks_patchC

Partial update of track state.

Inputs: track (required), editId (required), releases (required), packageName (required).

tracks_updateA

Full replacement of track state. releases is an array of release objects — versionCodes, status (draft|inProgress|halted|completed), userFraction (0-1 for staged rollout), inAppUpdatePriority (0-5), countryTargeting, and releaseNotes.

Inputs: track (required), editId (required), releases (required), packageName (required).

users_createB

Add a new team member to the developer account. Pass the user resource with email + roles + optional expirationTime.

Inputs: user (required), parent (required).

users_deleteB

Remove a user from the developer account.

Inputs: name (required).

users_listA

List all users on a developer account. parent is the developer account id in the form developers/{developerId} (find it in the Play Console URL).

Inputs: parent (required), pageSize, pageToken.

users_updateC

Patch-update a team member (roles, access level).

Inputs: name (required), user (required), updateMask.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.8/5.0

    Scored across 157 tools

    Disambiguation4/5

    The vast majority of tools use clear resource_action naming (e.g., subscriptions_create, tracks_patch, orders_refund), so boundaries are mostly clean. However, a few genuine overlaps exist, notably apps_list vs reports_apps_search (both 'list every app the account can access') and the dense family of subscriptions/onetime_products batch variants that an agent could easily confuse.

    Naming Consistency4/5

    Strongly consistent snake_case with a resource_prefix_action pattern across nearly all 157 tools. Minor deviations like auth_status, monetization_convert_region_prices, and mixed onetime_products_/subscriptions_ prefixes (singular vs plural asymmetry) keep it from a perfect score.

    Tool Count2/5

    157 tools is far beyond the 15-25 comfortable range and imposes heavy selection overhead even for a large API. The domain is genuinely broad so not an absolute mismatch, but the surface is bloated with many fine-grained batch/state variants that could be consolidated.

    Completeness5/5

    Coverage is remarkably thorough across accounts, apps, edits, listings, images, bundles/APKs, tracks, testers, products, subscriptions, base plans, offers, purchases, orders, reviews, users/grants, recovery, and reporting. Full CRUD plus batch and lifecycle state operations are present with few obvious dead ends.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers