Play Store MCP Bridge
Provides tools for interacting with the Google Play Developer API, enabling management of apps, testing tracks, production releases, store listings, tester lists, reviews, billing, orders, and subscriptions.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Play Store MCP Bridgepublish the latest app bundle to production for com.example.app"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Play Store MCP Bridge
An authenticated remote MCP server for the Google Play Developer API. Self-host on Railway, then connect Claude, Codex, ChatGPT, Cursor, Gemini, or another compatible MCP client to https://your-domain/mcp using Google OAuth.
The bridge preserves all 117 original Google Play tools and their input schemas, and adds 6 tools for remote files and persistent background operations. Python/FastMCP calls the API directly; the remote service does not wrap a stdio subprocess. A separate local stdio entrypoint remains available.
Contents
Related MCP server: Google Play Developer API MCP Server
1. Authentication and access model
This project uses two separate Google authentication mechanisms:
Component | Purpose | Configuration |
Google OAuth Web client | Identifies people signing in to MCP and the file portal |
|
Google service account | Authorizes calls to the Google Play Developer API |
|
Bridge allowlist | Restricts which Google identities may use the bridge |
|
Signing in with Google does not grant the service account access to your apps. A valid service-account key also does not replace MCP OAuth sign-in. Configure both before connecting a client.
Allowed users share the configured Play service account and file library. Background-operation results are private to the submitting Google subject. This model suits an individual or a trusted team. For independent Play accounts, deploy separate instances unless you deliberately use the advanced per-request credential path described below.
For a normal remote connection, users need the server URL and their Google sign-in. They do not need to paste a service-account key into Claude or Codex.
2. Install from source
You need Git, Python 3.11+, and uv. The remote bridge also requires Redis, writable persistent storage, and a public HTTPS origin.
git clone https://github.com/quyendang/playstore-mcp.git
cd playstore-mcp
uv sync --frozenThere are two entrypoints:
Command | Behavior |
| Starts the authenticated remote HTTP bridge, including the portal and job queue |
| Starts the original local stdio server |
The Dockerfile starts the remote bridge by default. Running uvx play-store-mcp installs the upstream PyPI package, which is not the same as running this bridge from source.
For local remote-bridge development, run Redis locally and use an HTTPS tunnel. Set BRIDGE_PUBLIC_URL to the tunnel origin, register both Google callbacks in section 4, and choose a writable BRIDGE_DATA_DIR. Export the required variables before running playstore-mcp-bridge; the application does not automatically load .env files.
The shell examples below use Bash/Zsh on macOS or Linux. Replace domains, paths, email addresses, and package names with your own values.
3. Set up the Google Play service account
3.1. Enable the API
Open Google Cloud Console and create or select a project.
Go to APIs & Services → Library.
Find Google Play Android Developer API (
androidpublisher.googleapis.com) and enable it in the project containing your service account.
Google no longer requires linking your Play developer account to a Cloud project through the old API access page. See Google Play API setup.
3.2. Create the service account and JSON key
Open IAM & Admin → Service Accounts → Create service account.
Give it a name such as
playstore-mcpand finish creating it. App access is granted separately in Play Console; Cloud Project Owner is not required for that purpose.Open the account, then select Keys → Add key → Create new key → JSON → Create.
Save the downloaded file outside your repository. Note its
client_emailfor the next step.
Keep the original private_key, client_email, and token_uri values. If key creation is blocked by an organization policy, ask your administrator to review that policy. See Google's service-account key instructions.
Do not commit the key. On macOS/Linux, restrict access to the local file:
chmod 600 /absolute/path/service-account.json3.3. Grant access in Google Play Console
Open Play Console → Users and permissions → Invite new users.
Enter the service account's
client_email, not the personal email used to sign in to MCP.Under App permissions, select the relevant apps, grant the permissions you need, and invite the user.
Task | Play Console permission to consider |
Read app information | View app information (read-only) |
Publish to testing tracks | Release apps to testing tracks |
Publish production releases | Release to production, exclude devices, and use Play App Signing |
Edit tester lists | Manage testing tracks and edit tester lists |
Edit listings and products | Manage store presence |
Reply to reviews | Reply to reviews |
Billing, orders, and subscriptions | View financial data, orders, and cancellation survey responses; Manage orders and subscriptions |
Grant permissions for the intended tasks and app scope. See the Play Console permission reference; Google's API setup guide lists the two Billing permissions in the final row.
A downloaded JSON key alone is insufficient. Cloud IAM roles do not replace Play Console app permissions.
3.4. Configure the key on the server
On Railway, create a sealed variable named GOOGLE_PLAY_STORE_CREDENTIALS and paste the complete JSON file contents. Do not wrap the JSON in shell quotes in the dashboard.
For a local process:
export GOOGLE_PLAY_STORE_CREDENTIALS="$(cat /absolute/path/service-account.json)"Alternatively, set GOOGLE_APPLICATION_CREDENTIALS to an absolute JSON file path on the server. In Docker, that path must exist inside the container. Prefer one method; inline GOOGLE_PLAY_STORE_CREDENTIALS takes precedence over the file path.
4. Set up Google OAuth for MCP sign-in
4.1. Choose your public origin
For example:
https://playstore-mcp.example.comSet BRIDGE_PUBLIC_URL to this HTTPS origin, without /mcp, another path, a query, or a fragment. When changing domains, update this value and both Google redirect URIs together.
4.2. Configure the consent screen and audience
In Google Cloud, open Google Auth Platform; older interfaces may call this OAuth consent screen. Configure the app name, support email, contact information, and appropriate audience. If the app is in Testing, add the people who will sign in as test users. See Google OAuth app branding.
The bridge allowlist is a separate check: those users must also appear in BRIDGE_ALLOWED_EMAILS or match an allowed Google subject. Adding a bridge user does not automatically add a Google test user. Review Google's publishing and verification requirements before relying on a Testing configuration for long-term use.
4.3. Create a Web application OAuth client
Open Google Auth Platform → Clients → Create client.
Choose Web application.
Add these exact Authorized redirect URIs, using your own domain:
https://playstore-mcp.example.com/auth/callback
https://playstore-mcp.example.com/portal/callbackCreate the client and save its ID and secret in your hosting secrets:
GOOGLE_OAUTH_CLIENT_ID=YOUR_WEB_CLIENT_ID.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=YOUR_WEB_CLIENT_SECRET/auth/callback handles MCP authorization; /portal/callback handles browser sign-in to the file portal. Do not use /mcp as the Google redirect URI. See Google Web OAuth and OAuth client management.
The bridge requests openid email profile to identify users. Google Play API calls use the separate service account. Keep the Google OAuth client secret on the server.
5. Deploy on Railway
5.1. Create the service and storage
Create a Railway service from
quyendang/playstore-mcp, or your own fork. The repository includes a Dockerfile andrailway.json.Add Redis in the same project/environment. Keep persistence enabled so OAuth registrations and refresh tokens survive restarts.
Attach a Volume to the app at
/data. Use one app replica. The entrypoint initializes volume ownership, then drops privileges to UID 10001.Generate a Railway domain or attach a custom domain. Use it for
BRIDGE_PUBLIC_URLand both Google callbacks.
An initial deployment may be unhealthy until all required settings are present. Finish configuring the variables, then redeploy. See Railway volumes.
5.2. Set variables on the app service
Variable | Value |
|
|
| Google OAuth Web application client ID |
| Google OAuth Web client secret |
| A stable random secret of at least 32 characters |
| Comma-separated Google email addresses allowed to use the bridge |
| Admin emails; each must also be in |
|
|
| Complete service-account JSON in a sealed variable |
|
|
| Start with |
Generate a signing key locally:
python3 -c 'import secrets; print(secrets.token_urlsafe(48))'Keep it stable and back it up securely. Changing it invalidates sessions/tokens and prevents reading existing job records encrypted with the old key.
For example, set BRIDGE_ALLOWED_EMAILS to you@example.com,teammate@example.com. These are human Google identities, not the service account's client_email. Every allowed user receives access to the shared Play account and file library.
5.3. Deploy and check the endpoints
Apply the settings and redeploy. The bridge listens on 0.0.0.0, using Railway's PORT, then MCP_PORT, then port 8000. The health check in railway.json targets /ready.
curl --fail https://playstore-mcp.example.com/health
curl --fail https://playstore-mcp.example.com/ready
curl -i https://playstore-mcp.example.com/mcp/healthchecks the process and returnsservice: playstore-mcp-bridgeandoriginal_tools: 117./readychecks Redis, SQLite, and whether a Play client has initialized; success returns{"status":"ready"}. It does not verify permissions on every app.An unauthenticated
/mcprequest should require OAuth, normally with HTTP 401. Use an MCP client to complete the connection.
Open /portal and sign in with an allowed email to verify the portal callback. The bridge already protects its remote tools with OAuth; a manually configured static Bearer token is not required for normal client setup.
6. Connect MCP clients after deployment
Replace the example domain with your deployed domain. Use https://playstore-mcp.example.com/mcp, sign in to Google, and approve the bridge connection. Your email must pass both Google's app access rules and the bridge allowlist.
Claude Code
claude mcp add --scope user --transport http playstore \
https://playstore-mcp.example.com/mcp
claude mcp listOpen Claude Code, run /mcp, select the server, and complete authentication in your browser. CLI versions that support it can also run claude mcp login playstore. No custom credential header is needed. See Claude Code MCP.
Codex CLI / Codex app
codex mcp add playstore --url https://playstore-mcp.example.com/mcp
codex mcp login playstore
codex mcp listAlternatively, add this to ~/.codex/config.toml, then run the login command:
[mcp_servers.playstore]
url = "https://playstore-mcp.example.com/mcp"Complete Google sign-in and approve the bridge connection. Start a new chat after configuration changes; use /mcp in the CLI to inspect the connection. In the desktop app, configure the remote MCP server and choose Authenticate when prompted. See OpenAI's MCP documentation.
Claude Desktop
If your version offers custom remote connectors, add the /mcp URL in its connector settings and complete OAuth. Menu names and availability depend on your app version and account.
For a stdio configuration, mcp-remote can connect to the remote OAuth server. Install Node.js LTS with npx, then merge this entry into your existing configuration:
{
"mcpServers": {
"playstore": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://playstore-mcp.example.com/mcp"]
}
}
}The claude_desktop_config.json locations are documented in the MCP Desktop guide:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Quit and reopen Claude, then complete browser sign-in. If the app cannot find npx, use its absolute executable path.
Cursor
Add this entry to ~/.cursor/mcp.json or your project's MCP configuration:
{
"mcpServers": {
"playstore": {
"url": "https://playstore-mcp.example.com/mcp"
}
}
}Enable the server in MCP settings, complete OAuth when prompted, and make its tools available to the Agent. See Cursor MCP.
Gemini CLI
Merge this into mcpServers in ~/.gemini/settings.json:
{
"mcpServers": {
"playstore": {
"httpUrl": "https://playstore-mcp.example.com/mcp"
}
}
}Gemini CLI uses httpUrl for Streamable HTTP. Restart the CLI, inspect /mcp, and complete the server's OAuth flow. See Gemini CLI MCP.
ChatGPT and Gemini web
ChatGPT: add a custom MCP server/app/plugin with the
/mcpURL, choose OAuth, and complete Google sign-in. Use a connection with the appropriate tool capabilities for write actions. Labels and availability depend on your account; see OpenAI custom MCP.Gemini web: under Connected Apps → Custom apps, enter the same URL and authorize it. Server compatibility cannot enable an account feature that is unavailable to you. See Google's custom-app instructions.
The Google OAuth client ID and secret belong on the server. Do not paste them into the client examples above. Client-to-bridge callbacks are handled by MCP OAuth; the two Google redirect URIs in section 4 remain the bridge callbacks.
7. Verify your setup and troubleshoot
After the client reports a successful connection:
Ask: “Use Play Store MCP to validate the package name
com.yourcompany.yourapp.”validate_package_nameverifies tool access, without calling Google Play.Ask: “Use
get_releasesto read releases forcom.yourcompany.yourapp. Do not change anything.” Replace this with a real app accessible to your service account.Open
/portaland test file upload if you need remote deployment tools.
/mcp exposes 117 original tools plus 6 bridge tools. It does not collapse them into three meta-tools. Connect to /mcp-code separately if you want code mode.
Symptom | Check |
| Use |
| Match scheme, hostname, and both Google callbacks exactly; verify the Web client ID |
Google denies access while the app is in Testing | Check the OAuth audience and Google test-user list |
Account is not on the allowlist | Add the verified human Google email to |
Admin email must also be allowed | Include every admin email in |
| Check Redis, the SQLite volume, and Play credential initialization in deployment logs |
| Verify service-account |
App not found / Google returns 404 | Use the actual application ID and grant access to that app |
| Complete OAuth through the MCP client; a service-account JSON key is not a bridge Bearer token |
Origin-related HTTP 403 | Check the Origin sent by the client/proxy against |
| Match the public domain/Host to the hostname in |
Laptop file path is not found | Upload through |
Google Play writes are blocked | Set |
Tokens/job records fail after a deployment | Check for signing-key changes, Redis persistence, and the |
An operation has status | Check Google Play before submitting a new operation |
Exclude service-account JSON, OAuth secrets, signing keys, and token-bearing download links when sharing logs.
8. Upload and download files
Files attached to a conversation are not automatically uploaded to this server. Open https://your-domain/portal, sign in, upload an APK/AAB/image, and copy its asset://ID reference.
The portal uploads in chunks. To resume, enter the upload ID and select the same original file. Compare SHA-256 when verifying a resumed artifact.
The original file_path, apk_path, bundle_path, and image_path parameters accept asset://ID. Generated/system APK downloads retain destination_path as the output filename and add asset_id and a temporary download_url. Use get_asset to obtain a fresh link after expiry. Responses stream bytes and support HTTP range downloads; transfer size and storage quotas are enforced.
Remote file paths are confined to the asset directory. The local stdio entrypoint retains its original file behavior.
For CI/API uploads, authenticate with a bridge OAuth Bearer token:
POST /api/assetswith{"name":"app.aab","size":12345}.PUT /api/assets/ID/chunks?offset=0with raw chunk bytes, within the configured chunk limit. Continue at the offset returned by the server.POST /api/assets/ID/completewith{}or{"sha256":"expected-hash"}.Use the returned asset reference in an original tool.
Do not put a service-account key in a URL. Browser mutations using a session cookie require a same-origin request. Download links carry temporary authorization and should be kept private.
9. Run background operations
start_operation(tool_name, arguments, idempotency_key) queues any original tool for durable execution using the shared Play account configured on the server. Use it for large artifacts, long deployments, downloads, or batches so a client request timeout does not cancel the operation.
Example arguments for start_operation:
{
"tool_name": "deploy_app",
"arguments": {
"package_name": "com.example.app",
"track": "internal",
"file_path": "asset://YOUR_ASSET_ID"
},
"idempotency_key": "com.example.app-internal-build-42"
}Poll get_operation(operation_id), or call list_operations() after reconnecting. The original tool result appears under result. The same owner/key/arguments return the same job; reusing a key with different arguments is rejected. Queue payloads and results are encrypted on the Volume.
Statuses are queued, running, completed, failed, and unknown. A restart during execution or an unsuccessful write result is conservatively marked unknown: check Google Play before creating a new job. In-flight writes are not automatically replayed; queued jobs resume after restart. Google edits for the same package are serialized across direct calls and jobs.
Use jobs where duplicate write submissions matter. Direct tools retain their original semantics. Jobs reject per-request credential headers so a caller's service-account key is not persisted in the queue.
10. Endpoints and configuration
Endpoint | Purpose |
| OAuth-protected Streamable HTTP with all 123 tools |
| Legacy HTTP+SSE compatibility with the same tools |
| Optional |
| Google-authenticated shared file management |
| Authenticated file management/upload API |
| Admin-only, in-memory update to shared Play credentials |
| Process and readiness probes |
All transport aliases share one OAuth resource: the public origin. OAuth registrations and tokens are encrypted in Redis. The allowlist is checked on authenticated requests.
Write permissions and code mode
PLAY_STORE_MCP_READ_ONLY=1blocks all 73 Google Play write tools. Local file uploads, downloads, and deletion remain available.To enable writes, grant the appropriate Play Console permissions, set the variable to
0, and redeploy./mcp-codecan execute multiple tools under one client approval. Prefer/mcpwhen you want the client to present individual tools.BRIDGE_CODE_MODE=0disables/mcp-code. The upstreamCODE_MODEvariable controls the separate stdio surface.
Optional limits
See .env.example for the complete example configuration.
Variable | Default / purpose |
| Optional comma-separated Google subject IDs allowed to connect |
| 8 GiB per file |
| 8 MiB per chunk |
| 32 GiB reserved file storage; adjust to your actual Volume capacity |
| 100 |
| 900 seconds |
|
|
Per-request credentials and key rotation
Direct tools still support X-Google-Credentials / X-Google-Credentials-Base64 after bridge OAuth authorization. This advanced path is not needed for normal client connections. Base64 contains the complete private key; send it only to a trusted server over HTTPS. Background operations always use the shared credentials and reject these headers.
POST /credentials accepts the original JSON/Base64 payload formats, but requires an identity in BRIDGE_ADMIN_EMAILS. It updates shared credentials in memory only; update the Railway secret to persist a change across restarts. The upstream PLAY_STORE_MCP_ADMIN_TOKEN does not replace bridge OAuth admin access.
Local stdio compatibility
After exporting your Google Play credentials:
CODE_MODE=0 uv run --frozen play-store-mcp --read-onlyA stdio client starts this command itself; Redis and bridge OAuth are not required. Use uv --directory /absolute/path/playstore-mcp run --frozen play-store-mcp --read-only when the client's working directory differs. See UPSTREAM_README.md for upstream/local behavior.
11. Development and attribution
Original tool group | Count |
Publishing and batch deploy | 8 |
Listings and images | 7 |
Reviews and testers | 5 |
Products, options, subscription catalogs/plans/offers | 47 |
Purchases, orders, and external transactions | 16 |
Users/grants, data safety, device tiers, app recovery | 16 |
APK/AAB, expansion/deobfuscation, generated/system APK, internal sharing | 15 |
Validation | 3 |
Original total | 117 |
The six bridge tools are start_operation, get_operation, list_operations, list_assets, get_asset, and delete_asset. The test suite checks the tool manifest against the original implementation, including input schemas and write guards.
uv sync --frozen --extra dev
uv run --frozen pytest -q -o addopts='' --ignore=tests/test_integration.py --ignore=tests/test_live_api.py
uv run --frozen ruff check src/ tests/ docker_entrypoint.py
uv run --frozen ruff format --check src/ tests/ docker_entrypoint.py
uv run --frozen mypy src/
uv buildLive Google tests are opt-in. Bridge tests use mocked Google calls and in-memory Redis. This README describes the authenticated remote bridge; docs/ and UPSTREAM_README.md retain upstream/local documentation.
Based on lusky3/play-store-mcp, source snapshot aebcd31, under the original MIT License. The original Google API implementation and tests are retained. See also FastMCP OAuth.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read and edit GA4, Search Console and Google Tag Manager from any MCP client. 29 tools.
Remote MCP for Android CLI agent build gate, structured receipts, audit logs, and reviewer-ready evi
Remote MCP for AI Studio Android release gate MCP, structured receipts, audit logs, and reviewer-rea
- TieruxOAuthcom.tierux
Server-side purchase verification and entitlements for Google Play and Apple App Store over MCP.
Related MCP Servers
- AlicenseCqualityBmaintenanceThe complete MCP server for Google Play, offering 150 tools to fully control Android Publisher API v3 and Play Developer Reporting API v1beta1.10069 npm7MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for managing Google Play app deployment and in-app products via the Android Publisher API v3.23 npm4MIT
- AlicenseAqualityCmaintenanceAn MCP server that drives Google Play releases: bundle upload, track releases (internal/closed/open/production), listing metadata, store graphics, and review replies.8MIT
- AlicenseNot gradedqualityBmaintenanceEnables publishing Android apps to the Google Play Console from monorepos by exposing commands as MCP tools that handle AAB uploads, store listings, testers, and setup via the Google Play Developer API, returning structured JSON results.MIT