upload_artifact
Upload APK or AAB files to create releases on Google Play Console tracks, enabling controlled app distribution to internal, alpha, beta, or production users.
Instructions
Upload an APK or AAB and create a release on the given track.
File type auto-detected from extension (.apk/.aab). Upload and track assignment are atomic.
Args: package_name: Package name, e.g. com.example.myapp file_path: Absolute local path to the APK or AAB. track: "internal" (default), "alpha", "beta", or "production". status: "draft" (default), "inProgress", or "completed". rollout_percentage: Rollout % when status is "inProgress". Default 10%. release_name: Optional human-readable name. release_notes: Optional {lang: text} dict, e.g. {"en-US": "Initial release"}.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| package_name | Yes | ||
| file_path | Yes | ||
| track | No | internal | |
| status | No | draft | |
| rollout_percentage | No | ||
| release_name | No | ||
| release_notes | No |
Implementation Reference
- src/google_play_mcp/server.py:413-447 (handler)MCP tool registration and wrapper for upload_artifact, which delegates to the underlying publisher client.
@mcp.tool() def upload_artifact( package_name: str, file_path: str, track: str = "internal", status: str = "draft", rollout_percentage: float = 10.0, release_name: str = "", release_notes: Optional[dict] = None, ) -> str: """Upload an APK or AAB and create a release on the given track. File type auto-detected from extension (.apk/.aab). Upload and track assignment are atomic. Args: package_name: Package name, e.g. com.example.myapp file_path: Absolute local path to the APK or AAB. track: "internal" (default), "alpha", "beta", or "production". status: "draft" (default), "inProgress", or "completed". rollout_percentage: Rollout % when status is "inProgress". Default 10%. release_name: Optional human-readable name. release_notes: Optional {lang: text} dict, e.g. {"en-US": "Initial release"}. """ try: notes = _notes_from_dict(release_notes) result = _publisher().upload_artifact( package_name=package_name, file_path=file_path, track=track, rollout_percentage=rollout_percentage if status == "inProgress" else None, release_name=release_name or None, release_notes=notes, status=status, ) - src/google_play_mcp/client.py:305-360 (handler)Actual implementation of the upload_artifact logic, handling the file upload and track assignment process.
def upload_artifact( self, package_name: str, file_path: str, track: str, rollout_percentage: Optional[float] = None, release_name: Optional[str] = None, release_notes: Optional[List[Dict[str, str]]] = None, status: str = "draft", ) -> Dict[str, Any]: """Upload an APK or AAB and create a release on the given track. File type is inferred from the extension (.apk or .aab). Everything (upload + track assignment) happens in a single edit. """ ext = os.path.splitext(file_path)[1].lower() if ext == ".apk": mime = APK_MIME artifact_type = "apk" elif ext == ".aab": mime = BUNDLE_MIME artifact_type = "bundle" else: raise ValueError(f"Unrecognized file extension '{ext}'. Use .apk or .aab.") media = MediaFileUpload(file_path, mimetype=mime, resumable=True) edit_id = self._create_edit(package_name) try: if artifact_type == "apk": artifact = self.service.edits().apks().upload( packageName=package_name, editId=edit_id, media_body=media ).execute() else: artifact = self.service.edits().bundles().upload( packageName=package_name, editId=edit_id, media_body=media ).execute() version_code = artifact["versionCode"] release: Dict[str, Any] = { "versionCodes": [str(version_code)], "status": status, } if status == "inProgress" and rollout_percentage is not None: if rollout_percentage >= 100: release["status"] = "completed" else: release["userFraction"] = round(rollout_percentage / 100.0, 4) if release_name: release["name"] = release_name if release_notes: release["releaseNotes"] = release_notes updated_track = self._update_track( package_name, edit_id, track, {"track": track, "releases": [release]} ) commit = self._commit_edit(package_name, edit_id)