pabal-store-api-mcp 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,19 +102,27 @@ export function parseAppStoreScreenshots(screenshotsBaseDir, locale) {
102
102
  unknown: unknownDeviceTypes,
103
103
  };
104
104
  }
105
+ /**
106
+ * Sort screenshot filenames by numeric order
107
+ * e.g., phone-1.png, phone-2.png, phone-10.png (not phone-1, phone-10, phone-2)
108
+ */
109
+ function sortByNumericOrder(files, prefix) {
110
+ return files.sort((a, b) => {
111
+ const numA = parseInt(a.replace(prefix, "").replace(".png", ""), 10);
112
+ const numB = parseInt(b.replace(prefix, "").replace(".png", ""), 10);
113
+ return numA - numB;
114
+ });
115
+ }
105
116
  export function parseGooglePlayScreenshots(screenshotsBaseDir, locale) {
106
117
  const localeDir = `${screenshotsBaseDir}/${locale}`;
107
118
  const files = getLocaleScreenshotFiles(screenshotsBaseDir, locale);
119
+ const phoneFiles = files.filter((f) => f.startsWith("phone-") && f.endsWith(".png"));
120
+ const tablet7Files = files.filter((f) => f.startsWith("tablet7-") && f.endsWith(".png"));
121
+ const tablet10Files = files.filter((f) => f.startsWith("tablet10-") && f.endsWith(".png"));
108
122
  return {
109
- phone: files
110
- .filter((f) => f.startsWith("phone-") && f.endsWith(".png"))
111
- .map((f) => `${localeDir}/${f}`),
112
- tablet7: files
113
- .filter((f) => f.startsWith("tablet7-") && f.endsWith(".png"))
114
- .map((f) => `${localeDir}/${f}`),
115
- tablet10: files
116
- .filter((f) => f.startsWith("tablet10-") && f.endsWith(".png"))
117
- .map((f) => `${localeDir}/${f}`),
123
+ phone: sortByNumericOrder(phoneFiles, "phone-").map((f) => `${localeDir}/${f}`),
124
+ tablet7: sortByNumericOrder(tablet7Files, "tablet7-").map((f) => `${localeDir}/${f}`),
125
+ tablet10: sortByNumericOrder(tablet10Files, "tablet10-").map((f) => `${localeDir}/${f}`),
118
126
  featureGraphic: files.includes("feature-graphic.png")
119
127
  ? `${localeDir}/feature-graphic.png`
120
128
  : null,
@@ -273,26 +273,14 @@ export class AppStoreService {
273
273
  skippedLocales.push(locale);
274
274
  continue;
275
275
  }
276
- console.error(`[AppStore] 📤 Uploading screenshots for ${locale}...`);
277
- // Upload screenshots
278
- for (const screenshot of screenshotsToUpload) {
279
- try {
280
- await client.uploadScreenshot({
281
- imagePath: screenshot.path,
282
- screenshotDisplayType: screenshot.displayType,
283
- locale,
284
- });
285
- console.error(`[AppStore] ✅ ${screenshot.filename}`);
286
- }
287
- catch (uploadError) {
288
- const msg = uploadError instanceof Error
289
- ? uploadError.message
290
- : String(uploadError);
291
- console.error(`[AppStore] ❌ ${screenshot.filename}: ${msg}`);
292
- }
293
- }
276
+ console.error(`[AppStore] 📤 Uploading screenshots for ${locale} (batch mode - will replace existing)...`);
277
+ // Use batch upload method - deletes existing and uploads new
278
+ const uploadResult = await client.uploadScreenshotsForLocale({
279
+ locale,
280
+ screenshots: screenshotsToUpload,
281
+ });
282
+ console.error(`[AppStore] ✅ Screenshots for ${locale}: ${uploadResult.uploaded} uploaded, ${uploadResult.deleted} deleted, ${uploadResult.failed} failed`);
294
283
  uploadedLocales.push(locale);
295
- console.error(`[AppStore] ✅ Screenshots uploaded for ${locale}`);
296
284
  }
297
285
  catch (error) {
298
286
  console.error(`[AppStore] ❌ Failed to upload screenshots for ${locale}: ${error instanceof Error ? error.message : String(error)}`);
@@ -231,47 +231,21 @@ export class GooglePlayService {
231
231
  skippedLocales.push(locale);
232
232
  continue;
233
233
  }
234
- console.error(`[GooglePlay] 📤 Uploading screenshots for ${locale}...`);
235
- // Upload phone screenshots (phone-*.png)
236
- for (const imagePath of screenshots.phone) {
237
- await client.uploadScreenshot({
238
- imagePath,
239
- imageType: "phoneScreenshots",
240
- language: locale,
241
- });
242
- console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()}`);
243
- }
244
- // Upload 7-inch tablet screenshots as phone
245
- for (const imagePath of screenshots.tablet7) {
246
- await client.uploadScreenshot({
247
- imagePath,
248
- imageType: "phoneScreenshots",
249
- language: locale,
250
- });
251
- console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()} (as phone)`);
252
- }
253
- // Upload 10-inch tablet screenshots as tablet (optional)
254
- if (screenshots.tablet10.length > 0) {
255
- for (const imagePath of screenshots.tablet10) {
256
- await client.uploadScreenshot({
257
- imagePath,
258
- imageType: "tenInchScreenshots",
259
- language: locale,
260
- });
261
- console.error(`[GooglePlay] ✅ ${imagePath.split("/").pop()} (as tablet)`);
262
- }
263
- }
264
- // Upload feature graphic (optional)
265
- if (screenshots.featureGraphic) {
266
- await client.uploadScreenshot({
267
- imagePath: screenshots.featureGraphic,
268
- imageType: "featureGraphic",
269
- language: locale,
270
- });
271
- console.error(`[GooglePlay] ✅ feature-graphic.png`);
272
- }
234
+ console.error(`[GooglePlay] 📤 Uploading screenshots for ${locale} (batch mode - will replace existing)...`);
235
+ // Use batch upload method - deletes existing and uploads new in single edit session
236
+ // Combine phone and tablet7 screenshots as phoneScreenshots (Google Play accepts both sizes)
237
+ const phoneScreenshotPaths = [
238
+ ...screenshots.phone,
239
+ ...screenshots.tablet7,
240
+ ];
241
+ const uploadResult = await client.uploadScreenshotsForLocale({
242
+ language: locale,
243
+ phoneScreenshots: phoneScreenshotPaths,
244
+ tenInchScreenshots: screenshots.tablet10,
245
+ featureGraphic: screenshots.featureGraphic || undefined,
246
+ });
247
+ console.error(`[GooglePlay] ✅ Screenshots uploaded for ${locale}: ${uploadResult.uploaded.phoneScreenshots} phone, ${uploadResult.uploaded.tenInchScreenshots} tablet`);
273
248
  uploadedLocales.push(locale);
274
- console.error(`[GooglePlay] ✅ Screenshots uploaded for ${locale}`);
275
249
  }
276
250
  catch (error) {
277
251
  console.error(`[GooglePlay] ❌ Failed to upload screenshots for ${locale}: ${error instanceof Error ? error.message : String(error)}`);
@@ -99,6 +99,32 @@ export declare class AppStoreClient {
99
99
  * Commit AppScreenshot after upload
100
100
  */
101
101
  private commitAppScreenshot;
102
+ /**
103
+ * Delete a single screenshot
104
+ */
105
+ private deleteScreenshot;
106
+ /**
107
+ * Delete all screenshots in a screenshot set
108
+ */
109
+ private deleteAllScreenshotsInSet;
110
+ /**
111
+ * Upload multiple screenshots for a locale, replacing existing ones
112
+ * 1. Find or create screenshot sets for each display type
113
+ * 2. Delete existing screenshots in each set
114
+ * 3. Upload new screenshots in order
115
+ */
116
+ uploadScreenshotsForLocale(options: {
117
+ locale: string;
118
+ screenshots: Array<{
119
+ path: string;
120
+ displayType: string;
121
+ filename: string;
122
+ }>;
123
+ }): Promise<{
124
+ uploaded: number;
125
+ deleted: number;
126
+ failed: number;
127
+ }>;
102
128
  private getApi;
103
129
  private normalizeEndpoint;
104
130
  private requestCollection;
@@ -753,6 +753,130 @@ export class AppStoreClient {
753
753
  return await this.handleSdkError(error);
754
754
  }
755
755
  }
756
+ /**
757
+ * Delete a single screenshot
758
+ */
759
+ async deleteScreenshot(screenshotId) {
760
+ const appScreenshotsApi = await this.getApi(AppScreenshotsApi);
761
+ try {
762
+ await appScreenshotsApi.appScreenshotsDeleteInstance({
763
+ id: screenshotId,
764
+ });
765
+ }
766
+ catch (error) {
767
+ return await this.handleSdkError(error);
768
+ }
769
+ }
770
+ /**
771
+ * Delete all screenshots in a screenshot set
772
+ */
773
+ async deleteAllScreenshotsInSet(screenshotSetId) {
774
+ const screenshotsResponse = await this.listScreenshots(screenshotSetId);
775
+ const screenshots = screenshotsResponse.data || [];
776
+ let deletedCount = 0;
777
+ for (const screenshot of screenshots) {
778
+ try {
779
+ await this.deleteScreenshot(screenshot.id);
780
+ deletedCount++;
781
+ }
782
+ catch (error) {
783
+ console.error(`[AppStore] Warning: Failed to delete screenshot ${screenshot.id}: ${error instanceof Error ? error.message : String(error)}`);
784
+ }
785
+ }
786
+ return deletedCount;
787
+ }
788
+ /**
789
+ * Upload multiple screenshots for a locale, replacing existing ones
790
+ * 1. Find or create screenshot sets for each display type
791
+ * 2. Delete existing screenshots in each set
792
+ * 3. Upload new screenshots in order
793
+ */
794
+ async uploadScreenshotsForLocale(options) {
795
+ const { locale, screenshots } = options;
796
+ const { readFileSync, statSync, existsSync } = await import("node:fs");
797
+ const { basename } = await import("node:path");
798
+ const result = { uploaded: 0, deleted: 0, failed: 0 };
799
+ if (screenshots.length === 0) {
800
+ return result;
801
+ }
802
+ try {
803
+ // Get app and version info
804
+ const appId = await this.findAppId();
805
+ const versionsResponse = await this.listAppStoreVersions(appId, {
806
+ platform: APP_STORE_PLATFORM,
807
+ limit: DEFAULT_VERSIONS_FETCH_LIMIT,
808
+ });
809
+ const version = sortVersions(versionsResponse.data || [])[0];
810
+ if (!version)
811
+ throw new Error("App Store version not found.");
812
+ // Find or create localization
813
+ const localizationsResponse = await this.listAppStoreVersionLocalizations(version.id, locale);
814
+ let localizationId;
815
+ if (localizationsResponse.data?.[0]) {
816
+ localizationId = localizationsResponse.data[0].id;
817
+ }
818
+ else {
819
+ const createResponse = await this.createAppStoreVersionLocalization(version.id, locale, {});
820
+ localizationId = createResponse.data.id;
821
+ }
822
+ // Group screenshots by display type
823
+ const byDisplayType = new Map();
824
+ for (const screenshot of screenshots) {
825
+ if (!byDisplayType.has(screenshot.displayType)) {
826
+ byDisplayType.set(screenshot.displayType, []);
827
+ }
828
+ byDisplayType.get(screenshot.displayType).push({
829
+ path: screenshot.path,
830
+ filename: screenshot.filename,
831
+ });
832
+ }
833
+ // Process each display type
834
+ for (const [displayType, screenshotList] of byDisplayType) {
835
+ console.error(`[AppStore] Processing ${displayType} (${screenshotList.length} screenshots)...`);
836
+ // Find or create screenshot set
837
+ const screenshotSetId = await this.findOrCreateScreenshotSet(localizationId, displayType);
838
+ // Delete existing screenshots in this set
839
+ const deletedCount = await this.deleteAllScreenshotsInSet(screenshotSetId);
840
+ if (deletedCount > 0) {
841
+ console.error(`[AppStore] 🗑️ Deleted ${deletedCount} existing screenshots`);
842
+ result.deleted += deletedCount;
843
+ }
844
+ // Upload new screenshots in order
845
+ for (const screenshot of screenshotList) {
846
+ if (!existsSync(screenshot.path)) {
847
+ console.error(`[AppStore] ⚠️ File not found: ${screenshot.filename}`);
848
+ result.failed++;
849
+ continue;
850
+ }
851
+ try {
852
+ const fileBuffer = readFileSync(screenshot.path);
853
+ const fileSize = statSync(screenshot.path).size;
854
+ // Create screenshot with upload operation
855
+ const screenshotData = await this.createAppScreenshot(screenshotSetId, screenshot.filename, fileSize);
856
+ // Upload file
857
+ if (screenshotData.uploadOperations &&
858
+ screenshotData.uploadOperations.length > 0) {
859
+ const uploadOp = screenshotData.uploadOperations[0];
860
+ await this.uploadFileToUrl(uploadOp.url, fileBuffer, uploadOp.method);
861
+ }
862
+ // Commit screenshot
863
+ await this.commitAppScreenshot(screenshotData.id);
864
+ console.error(`[AppStore] ✅ ${screenshot.filename}`);
865
+ result.uploaded++;
866
+ }
867
+ catch (error) {
868
+ console.error(`[AppStore] ❌ ${screenshot.filename}: ${error instanceof Error ? error.message : String(error)}`);
869
+ result.failed++;
870
+ }
871
+ }
872
+ }
873
+ return result;
874
+ }
875
+ catch (error) {
876
+ console.error(`[AppStore] Screenshot upload failed for ${locale}: ${error instanceof Error ? error.message : String(error)}`);
877
+ throw error;
878
+ }
879
+ }
756
880
  async getApi(apiClass) {
757
881
  if (!this.apiCache.has(apiClass)) {
758
882
  this.apiCache.set(apiClass, this.sdk.create(apiClass));
@@ -5,7 +5,7 @@
5
5
  * API Documentation: https://developers.google.com/android-publisher
6
6
  */
7
7
  import type { GooglePlayAsoData, GooglePlayMultilingualAsoData, GooglePlayReleaseNote } from "../../../packages/configs/aso-config/types.js";
8
- import type { GooglePlayClientConfig, AppAccessInfo, LatestReleaseInfo, ReleaseUpdateResult, CreateReleaseOptions, UploadScreenshotOptions, UpdateReleaseNotesOptions, AppDetailsData } from "./types.js";
8
+ import type { GooglePlayClientConfig, AppAccessInfo, LatestReleaseInfo, ReleaseUpdateResult, CreateReleaseOptions, UploadScreenshotOptions, BatchUploadScreenshotsOptions, BatchUploadScreenshotsResult, UpdateReleaseNotesOptions, AppDetailsData } from "./types.js";
9
9
  export declare class GooglePlayClient {
10
10
  private auth;
11
11
  private androidPublisher;
@@ -49,6 +49,12 @@ export declare class GooglePlayClient {
49
49
  private updateListing;
50
50
  private listImages;
51
51
  private uploadImage;
52
+ private deleteAllImages;
53
+ /**
54
+ * Upload multiple screenshots for a locale in a single edit session
55
+ * Deletes existing screenshots before uploading new ones
56
+ */
57
+ uploadScreenshotsForLocale(options: BatchUploadScreenshotsOptions): Promise<BatchUploadScreenshotsResult>;
52
58
  private getTrack;
53
59
  private updateTrack;
54
60
  private listTracks;
@@ -606,6 +606,188 @@ export class GooglePlayClient {
606
606
  }
607
607
  return { data: uploadData.image };
608
608
  }
609
+ async deleteAllImages(session, language, imageType) {
610
+ await this.androidPublisher.edits.images.deleteall({
611
+ auth: session.auth,
612
+ packageName: session.packageName,
613
+ editId: session.editId,
614
+ language,
615
+ imageType,
616
+ });
617
+ }
618
+ /**
619
+ * Upload multiple screenshots for a locale in a single edit session
620
+ * Deletes existing screenshots before uploading new ones
621
+ */
622
+ async uploadScreenshotsForLocale(options) {
623
+ const { language, phoneScreenshots = [], sevenInchScreenshots = [], tenInchScreenshots = [], featureGraphic, } = options;
624
+ const authClient = await this.auth.getClient();
625
+ const editResponse = await this.createEdit(authClient, this.packageName);
626
+ const editId = editResponse.data.id;
627
+ const session = {
628
+ auth: authClient,
629
+ packageName: this.packageName,
630
+ editId,
631
+ };
632
+ const result = {
633
+ language,
634
+ uploaded: {
635
+ phoneScreenshots: 0,
636
+ sevenInchScreenshots: 0,
637
+ tenInchScreenshots: 0,
638
+ featureGraphic: false,
639
+ },
640
+ };
641
+ try {
642
+ // Delete existing screenshots before uploading
643
+ if (phoneScreenshots.length > 0) {
644
+ console.error(`[GooglePlayClient] Deleting existing phone screenshots for ${language}...`);
645
+ try {
646
+ await this.deleteAllImages(session, language, "phoneScreenshots");
647
+ }
648
+ catch (e) {
649
+ // Ignore if no images exist
650
+ if (e.code !== 404) {
651
+ console.error(`[GooglePlayClient] Warning: Failed to delete phone screenshots: ${e.message}`);
652
+ }
653
+ }
654
+ }
655
+ if (sevenInchScreenshots.length > 0) {
656
+ console.error(`[GooglePlayClient] Deleting existing 7-inch screenshots for ${language}...`);
657
+ try {
658
+ await this.deleteAllImages(session, language, "sevenInchScreenshots");
659
+ }
660
+ catch (e) {
661
+ if (e.code !== 404) {
662
+ console.error(`[GooglePlayClient] Warning: Failed to delete 7-inch screenshots: ${e.message}`);
663
+ }
664
+ }
665
+ }
666
+ if (tenInchScreenshots.length > 0) {
667
+ console.error(`[GooglePlayClient] Deleting existing 10-inch screenshots for ${language}...`);
668
+ try {
669
+ await this.deleteAllImages(session, language, "tenInchScreenshots");
670
+ }
671
+ catch (e) {
672
+ if (e.code !== 404) {
673
+ console.error(`[GooglePlayClient] Warning: Failed to delete 10-inch screenshots: ${e.message}`);
674
+ }
675
+ }
676
+ }
677
+ if (featureGraphic) {
678
+ console.error(`[GooglePlayClient] Deleting existing feature graphic for ${language}...`);
679
+ try {
680
+ await this.deleteAllImages(session, language, "featureGraphic");
681
+ }
682
+ catch (e) {
683
+ if (e.code !== 404) {
684
+ console.error(`[GooglePlayClient] Warning: Failed to delete feature graphic: ${e.message}`);
685
+ }
686
+ }
687
+ }
688
+ // Upload phone screenshots
689
+ for (let i = 0; i < phoneScreenshots.length; i++) {
690
+ const imagePath = phoneScreenshots[i];
691
+ if (!existsSync(imagePath)) {
692
+ console.error(`[GooglePlayClient] Warning: Phone screenshot not found: ${imagePath}`);
693
+ continue;
694
+ }
695
+ const imageBuffer = readFileSync(imagePath);
696
+ const fileName = imagePath.split("/").pop() || `phone-${i + 1}.png`;
697
+ await this.androidPublisher.edits.images.upload({
698
+ auth: session.auth,
699
+ packageName: session.packageName,
700
+ editId: session.editId,
701
+ language,
702
+ imageType: "phoneScreenshots",
703
+ media: {
704
+ mimeType: "image/png",
705
+ body: imageBuffer,
706
+ },
707
+ });
708
+ console.error(`[GooglePlayClient] ✅ Uploaded ${fileName}`);
709
+ result.uploaded.phoneScreenshots++;
710
+ }
711
+ // Upload 7-inch tablet screenshots
712
+ for (let i = 0; i < sevenInchScreenshots.length; i++) {
713
+ const imagePath = sevenInchScreenshots[i];
714
+ if (!existsSync(imagePath)) {
715
+ console.error(`[GooglePlayClient] Warning: 7-inch screenshot not found: ${imagePath}`);
716
+ continue;
717
+ }
718
+ const imageBuffer = readFileSync(imagePath);
719
+ const fileName = imagePath.split("/").pop() || `tablet7-${i + 1}.png`;
720
+ await this.androidPublisher.edits.images.upload({
721
+ auth: session.auth,
722
+ packageName: session.packageName,
723
+ editId: session.editId,
724
+ language,
725
+ imageType: "sevenInchScreenshots",
726
+ media: {
727
+ mimeType: "image/png",
728
+ body: imageBuffer,
729
+ },
730
+ });
731
+ console.error(`[GooglePlayClient] ✅ Uploaded ${fileName}`);
732
+ result.uploaded.sevenInchScreenshots++;
733
+ }
734
+ // Upload 10-inch tablet screenshots
735
+ for (let i = 0; i < tenInchScreenshots.length; i++) {
736
+ const imagePath = tenInchScreenshots[i];
737
+ if (!existsSync(imagePath)) {
738
+ console.error(`[GooglePlayClient] Warning: 10-inch screenshot not found: ${imagePath}`);
739
+ continue;
740
+ }
741
+ const imageBuffer = readFileSync(imagePath);
742
+ const fileName = imagePath.split("/").pop() || `tablet10-${i + 1}.png`;
743
+ await this.androidPublisher.edits.images.upload({
744
+ auth: session.auth,
745
+ packageName: session.packageName,
746
+ editId: session.editId,
747
+ language,
748
+ imageType: "tenInchScreenshots",
749
+ media: {
750
+ mimeType: "image/png",
751
+ body: imageBuffer,
752
+ },
753
+ });
754
+ console.error(`[GooglePlayClient] ✅ Uploaded ${fileName}`);
755
+ result.uploaded.tenInchScreenshots++;
756
+ }
757
+ // Upload feature graphic
758
+ if (featureGraphic && existsSync(featureGraphic)) {
759
+ const imageBuffer = readFileSync(featureGraphic);
760
+ await this.androidPublisher.edits.images.upload({
761
+ auth: session.auth,
762
+ packageName: session.packageName,
763
+ editId: session.editId,
764
+ language,
765
+ imageType: "featureGraphic",
766
+ media: {
767
+ mimeType: "image/png",
768
+ body: imageBuffer,
769
+ },
770
+ });
771
+ console.error(`[GooglePlayClient] ✅ Uploaded feature-graphic.png`);
772
+ result.uploaded.featureGraphic = true;
773
+ }
774
+ // Commit all changes
775
+ console.error(`[GooglePlayClient] Committing screenshots for ${language}...`);
776
+ await this.commitEdit(session);
777
+ console.error(`[GooglePlayClient] ✅ Screenshots committed for ${language}`);
778
+ return result;
779
+ }
780
+ catch (error) {
781
+ console.error(`[GooglePlayClient] Rolling back screenshot upload for ${language}...`);
782
+ try {
783
+ await this.deleteEdit(session);
784
+ }
785
+ catch {
786
+ // Ignore deletion failure
787
+ }
788
+ throw error;
789
+ }
790
+ }
609
791
  async getTrack(session, track) {
610
792
  const response = await this.androidPublisher.edits.tracks.get({
611
793
  auth: session.auth,
@@ -108,6 +108,31 @@ export interface UploadScreenshotOptions {
108
108
  imageType: "phoneScreenshots" | "sevenInchScreenshots" | "tenInchScreenshots" | "tvScreenshots" | "wearScreenshots" | "featureGraphic";
109
109
  language?: string;
110
110
  }
111
+ /**
112
+ * Batch Upload Screenshots Options
113
+ * Internal type for uploading multiple screenshots in a single edit session
114
+ * Replaces existing screenshots (deletes all before upload)
115
+ */
116
+ export interface BatchUploadScreenshotsOptions {
117
+ language: string;
118
+ phoneScreenshots?: string[];
119
+ sevenInchScreenshots?: string[];
120
+ tenInchScreenshots?: string[];
121
+ featureGraphic?: string;
122
+ }
123
+ /**
124
+ * Batch Upload Screenshots Result
125
+ * Internal type for tracking batch upload results
126
+ */
127
+ export interface BatchUploadScreenshotsResult {
128
+ language: string;
129
+ uploaded: {
130
+ phoneScreenshots: number;
131
+ sevenInchScreenshots: number;
132
+ tenInchScreenshots: number;
133
+ featureGraphic: boolean;
134
+ };
135
+ }
111
136
  /**
112
137
  * Update Release Notes Options
113
138
  * Internal type for updating release notes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pabal-store-api-mcp",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "MCP server for App Store / Play Store ASO workflows",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",