Changelog
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Planned
- Consolidate and reduce the MCP tool surface (now 117 tools) by grouping related operations, to lower per-request tool-list overhead — with no planned loss of functionality.
Changed
- Breaking: APK/AAB downloads are now always confined to a directory —
there is no "write anywhere" mode. The base directory is
PLAY_STORE_MCP_DOWNLOAD_DIRwhen set, otherwise the server's current working directory; adestination_paththat resolves outside it is rejected. SetPLAY_STORE_MCP_DOWNLOAD_DIRto download somewhere other than the working directory. Network transports (--transport sse/streamable-http) additionally requirePLAY_STORE_MCP_DOWNLOAD_DIRto be set explicitly and refuse to start without it.
Security
- Download-destination confinement lives in
PlayStoreClientand applies to both the temporary.partfile and the final file: the destination is canonicalized and verified to stay within the (always-present) base directory before anything is written — closing the path-traversal / arbitrary-file-overwrite vector (SonarCloudS2083) for both local and network use.
0.5.0 - 2026-07-06
Adds opt-in code-mode, migrates the server onto the standalone fastmcp
package, hardens shared-client concurrency, and removes the non-functional Vitals
tools.
Breaking — Vitals tools removed.
get_vitals_overviewandget_vitals_metricsno longer exist (see Removed); they returned placeholder data and never called an API.
Added
- Experimental code-mode (opt-in): set
CODE_MODE=1to expose tools through FastMCP's code-mode transform (search/get_schema/executemeta-tools with a sandboxed executor) instead of the full tool list, reducing per-request tool-list token overhead. Off by default; requires theplay-store-mcp[code-mode]extra (Monty sandbox) for theexecutetool. This is the first step of the tool-surface reduction noted under Planned.
Changed
- Migrated the server framework from the official MCP SDK's
FastMCP(mcp.server.fastmcp) to the standalonefastmcppackage (v3). Behavior is unchanged — all 117 tools, the/healthand/credentialsroutes, per-request header credentials, admin-token auth, read-only mode, and DNS-rebinding protection (PLAY_STORE_MCP_DISABLE_DNS_REBINDING) are preserved. This unblocks the upcoming code-mode capability, which lives only infastmcp.
Removed
- Breaking: removed the non-functional
get_vitals_overviewandget_vitals_metricstools. They never called an API and returned hardcoded placeholder data; Android Vitals requires the separate Play Developer Reporting API, which is out of scope for this server.
Fixed
get_order/batch_get_ordersnow read the real v3Orderresource: product IDs fromlineItems[].productId(exposed asproduct_ids/line_items) and status from thestatestring enum. Previously they read non-existent top-levelproductId/purchaseStatefields, so those values were always null against the live API and order state was lost.list_in_app_productsnow followstokenPagination.nextPageTokeninstead of returning only the first page (apps with many SKUs were silently truncated).get_reviewsandlist_voided_purchasesnow paginate tomax_resultsacross pages viatokenPagination, rather than returning a single page.delete_subscription_offernow returns the parentproduct_idinstead of mislabeling the deletedoffer_idasproduct_id.- Media downloads (
download_generated_apk/download_system_apk_variant) now acquire the client's transport lock per chunk, closing a gap in the shared-client thread-safety fix: a download concurrent with another call on the shared client no longer races on the non-thread-safehttplib2transport (which could corrupt the downloaded file or raiseResponseNotReady). - The shared (env /
/credentials) client now serializes its HTTP transport with a per-client lock, so concurrent tool calls under network transports no longer race on the non-thread-safehttplib2connection (which could interleave requests or deliver a response to the wrong caller). Per-request header-auth clients each get their own client and stay fully concurrent.
Security
- APK/AAB downloads (
download_generated_apk,download_system_apk_variant) now write to a temporary file and atomically rename on success, so a failed or unauthorized download can no longer truncate an existing file or leave a partial one at the destination. - Optional
PLAY_STORE_MCP_DOWNLOAD_DIRconfines download destinations to an allowlisted directory — recommended for network-exposed deployments so a caller cannot write outside it (path traversal / arbitrary-file overwrite). Unset (the default, single-user local case) allows any path, preserving existing behavior. - Documented that the server-side credential fallback
(
GOOGLE_PLAY_STORE_CREDENTIALS//credentials) is a process-global client shared by every request that omits a credential header; multi-tenant deployments should leave it unset so a missing header fails closed rather than running under a shared identity. - Recommend pairing code-mode with
--read-only/PLAY_STORE_MCP_READ_ONLY=1unless writes are needed: oneexecutecan invoke up to 50 tool calls (including mutations) behind a single approval. Read-only enforcement still applies inside the sandbox.
0.4.0 - 2026-07-02
Major feature expansion: grows from ~24 to 119 MCP tools, adding broad coverage of the Google Play Developer API, plus reliability/security hardening and a full dependency refresh.
Note — write endpoints are beta. The new write/mutating tools in this release are covered by unit tests (mocked), but only read-only paths have been exercised against the live Play API. Treat create/update/patch/delete/upload/ purchase-action/migrate tools as beta and open an issue for any problems. Run with
--read-only/PLAY_STORE_MCP_READ_ONLY=1to disable all write operations.Note — tool count. 119 tools is a large surface for a single MCP server: it increases per-request token usage and some clients cap/truncate large tool lists. A follow-up release will reduce this.
Added
- Purchases & orders: in-app product purchases (
get/acknowledge/consume); purchase management (refund_order,cancel/defer/revoke_subscription_purchase,get_product_purchase_v2);get_review,batch_get_orders. - Monetization catalog: in-app products, subscriptions, subscription base plans (incl. price migration), subscription offers, one-time products, and one-time product purchase options & offers.
- Artifacts & uploads: edit upload pipeline (APKs, app bundles, deobfuscation and expansion files); store-listing images; generated APK list + download; system APK variants; internal app sharing uploads.
- Account & configuration: external transactions (alternative billing); device tier configs; app data safety labels; app recovery actions; Play Console account access (users & grants).
- Read-only mode:
--read-only/PLAY_STORE_MCP_READ_ONLYdisables all write operations.
Changed
- Transient errors (429/500/503) are retried with exponential backoff on real API calls, and the retry is idempotency-aware — non-idempotent (POST) mutations are not retried on an ambiguous 5xx, to avoid duplicate side effects.
/credentialsendpoint hardened: optionalPLAY_STORE_MCP_ADMIN_TOKEN(constant-time bearer check) for deployments behind a reverse proxy; blocking credential validation moved off the event loop.- Consistent error contract: read methods raise
PlayStoreClientErrorinstead of leaking rawHttpError, and edit transactions are always cleaned up on failure. - List endpoints now follow
nextPageToken— fixes silent truncation (including the account-access user list). - CI: PyPI publish gated on tests/lint/type-check; least-privilege Docker workflow
permissions; pinned
uv.
Fixed
list_app_recoveriesnow sends the API-requiredversionCode(previously rejected).__version__is single-sourced from package metadata (was a stale0.2.0).- Case-insensitive
.aabdetection. - Subscription
start_time/expiry_timepopulated from the v2 response.
Security
pyjwt[crypto]>=2.12.0is now a declared dependency so the CVE-2026-32597 fix reaches installs, not just the lockfile.- Credential-update error responses no longer leak exception text.
Dependencies
- Refreshed all dependencies to latest, including the majors mypy 2.x and protobuf 7.x. Validated: 697 tests / 100% branch coverage, ruff/mypy clean, pip-audit clean, and a live read-only API smoke.
0.3.0 - 2026-06-19
Security hardening, dependency upgrades, and CI improvements.
Added
- Configurable DNS-rebinding protection via the
PLAY_STORE_MCP_DISABLE_DNS_REBINDINGenvironment variable (for cloud / reverse-proxy deployments).
Changed
- Upgraded
mcp1.26.0 → 1.28.0 andcryptography46.0.7 → 49.0.0. - Hardened CI workflows, suppressed scanner false positives, and addressed code-review findings.
[0.2.0] and earlier
See the GitHub Releases page.