pabal-store-api-mcp 1.1.0
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.
- package/README.md +95 -0
- package/bin/pabal-mcp.js +6 -0
- package/dist/src/core/clients/app-store-factory.d.ts +29 -0
- package/dist/src/core/clients/app-store-factory.js +72 -0
- package/dist/src/core/clients/client-factory-helpers.d.ts +7 -0
- package/dist/src/core/clients/client-factory-helpers.js +10 -0
- package/dist/src/core/clients/google-play-factory.d.ts +29 -0
- package/dist/src/core/clients/google-play-factory.js +72 -0
- package/dist/src/core/clients/types.d.ts +8 -0
- package/dist/src/core/clients/types.js +1 -0
- package/dist/src/core/helpers/formatters.d.ts +3 -0
- package/dist/src/core/helpers/formatters.js +38 -0
- package/dist/src/core/helpers/registration.d.ts +21 -0
- package/dist/src/core/helpers/registration.js +21 -0
- package/dist/src/core/helpers/translate-release-notes.d.ts +46 -0
- package/dist/src/core/helpers/translate-release-notes.js +87 -0
- package/dist/src/core/services/app-resolution-service.d.ts +14 -0
- package/dist/src/core/services/app-resolution-service.js +35 -0
- package/dist/src/core/services/app-store-service.d.ts +41 -0
- package/dist/src/core/services/app-store-service.js +266 -0
- package/dist/src/core/services/google-play-service.d.ts +36 -0
- package/dist/src/core/services/google-play-service.js +203 -0
- package/dist/src/core/services/service-helpers.d.ts +15 -0
- package/dist/src/core/services/service-helpers.js +31 -0
- package/dist/src/core/services/types.d.ts +81 -0
- package/dist/src/core/services/types.js +1 -0
- package/dist/src/core/workflows/version-info.d.ts +29 -0
- package/dist/src/core/workflows/version-info.js +100 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +279 -0
- package/dist/src/packages/common/errors/app-error.d.ts +39 -0
- package/dist/src/packages/common/errors/app-error.js +134 -0
- package/dist/src/packages/common/errors/error-codes.d.ts +63 -0
- package/dist/src/packages/common/errors/error-codes.js +71 -0
- package/dist/src/packages/common/errors/status-codes.d.ts +10 -0
- package/dist/src/packages/common/errors/status-codes.js +9 -0
- package/dist/src/packages/configs/aso-config/constants.d.ts +14 -0
- package/dist/src/packages/configs/aso-config/constants.js +102 -0
- package/dist/src/packages/configs/aso-config/locale-guards.d.ts +3 -0
- package/dist/src/packages/configs/aso-config/locale-guards.js +7 -0
- package/dist/src/packages/configs/aso-config/store.d.ts +11 -0
- package/dist/src/packages/configs/aso-config/store.js +11 -0
- package/dist/src/packages/configs/aso-config/types.d.ts +98 -0
- package/dist/src/packages/configs/aso-config/types.js +2 -0
- package/dist/src/packages/configs/aso-config/utils.d.ts +43 -0
- package/dist/src/packages/configs/aso-config/utils.js +223 -0
- package/dist/src/packages/configs/secrets-config/config.d.ts +12 -0
- package/dist/src/packages/configs/secrets-config/config.js +187 -0
- package/dist/src/packages/configs/secrets-config/constants.d.ts +1 -0
- package/dist/src/packages/configs/secrets-config/constants.js +1 -0
- package/dist/src/packages/configs/secrets-config/errors.d.ts +9 -0
- package/dist/src/packages/configs/secrets-config/errors.js +15 -0
- package/dist/src/packages/configs/secrets-config/registered-apps.d.ts +52 -0
- package/dist/src/packages/configs/secrets-config/registered-apps.js +108 -0
- package/dist/src/packages/configs/secrets-config/schemas.d.ts +21 -0
- package/dist/src/packages/configs/secrets-config/schemas.js +9 -0
- package/dist/src/packages/configs/secrets-config/types.d.ts +8 -0
- package/dist/src/packages/configs/secrets-config/types.js +1 -0
- package/dist/src/packages/stores/app-store/api-converters.d.ts +26 -0
- package/dist/src/packages/stores/app-store/api-converters.js +131 -0
- package/dist/src/packages/stores/app-store/api-endpoints.d.ts +33 -0
- package/dist/src/packages/stores/app-store/api-endpoints.js +157 -0
- package/dist/src/packages/stores/app-store/auth.d.ts +12 -0
- package/dist/src/packages/stores/app-store/auth.js +36 -0
- package/dist/src/packages/stores/app-store/client.d.ts +78 -0
- package/dist/src/packages/stores/app-store/client.js +637 -0
- package/dist/src/packages/stores/app-store/constants.d.ts +11 -0
- package/dist/src/packages/stores/app-store/constants.js +38 -0
- package/dist/src/packages/stores/app-store/generated-types.d.ts +118537 -0
- package/dist/src/packages/stores/app-store/generated-types.js +5 -0
- package/dist/src/packages/stores/app-store/types.d.ts +39 -0
- package/dist/src/packages/stores/app-store/types.js +9 -0
- package/dist/src/packages/stores/app-store/verify-auth.d.ts +16 -0
- package/dist/src/packages/stores/app-store/verify-auth.js +34 -0
- package/dist/src/packages/stores/play-store/api-converters.d.ts +58 -0
- package/dist/src/packages/stores/play-store/api-converters.js +209 -0
- package/dist/src/packages/stores/play-store/api-endpoints.d.ts +68 -0
- package/dist/src/packages/stores/play-store/api-endpoints.js +145 -0
- package/dist/src/packages/stores/play-store/client.d.ts +55 -0
- package/dist/src/packages/stores/play-store/client.js +628 -0
- package/dist/src/packages/stores/play-store/constants.d.ts +10 -0
- package/dist/src/packages/stores/play-store/constants.js +17 -0
- package/dist/src/packages/stores/play-store/types.d.ts +146 -0
- package/dist/src/packages/stores/play-store/types.js +9 -0
- package/dist/src/packages/stores/play-store/verify-auth.d.ts +13 -0
- package/dist/src/packages/stores/play-store/verify-auth.js +31 -0
- package/dist/src/tools/apps/add.d.ts +28 -0
- package/dist/src/tools/apps/add.js +307 -0
- package/dist/src/tools/apps/init.d.ts +58 -0
- package/dist/src/tools/apps/init.js +390 -0
- package/dist/src/tools/apps/search.d.ts +33 -0
- package/dist/src/tools/apps/search.js +147 -0
- package/dist/src/tools/aso/pull.d.ts +22 -0
- package/dist/src/tools/aso/pull.js +264 -0
- package/dist/src/tools/aso/push.d.ts +23 -0
- package/dist/src/tools/aso/push.js +189 -0
- package/dist/src/tools/auth/app-store.d.ts +9 -0
- package/dist/src/tools/auth/app-store.js +34 -0
- package/dist/src/tools/auth/check.d.ts +14 -0
- package/dist/src/tools/auth/check.js +50 -0
- package/dist/src/tools/auth/play-store.d.ts +9 -0
- package/dist/src/tools/auth/play-store.js +30 -0
- package/dist/src/tools/release/check-versions.d.ts +14 -0
- package/dist/src/tools/release/check-versions.js +65 -0
- package/dist/src/tools/release/create.d.ts +23 -0
- package/dist/src/tools/release/create.js +128 -0
- package/dist/src/tools/release/pull-notes.d.ts +22 -0
- package/dist/src/tools/release/pull-notes.js +151 -0
- package/dist/src/tools/release/update-notes.d.ts +110 -0
- package/dist/src/tools/release/update-notes.js +537 -0
- package/package.json +71 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Play Console API Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for Google Play Store operations.
|
|
5
|
+
* Types are derived from googleapis library types.
|
|
6
|
+
*
|
|
7
|
+
* @see https://developers.google.com/android-publisher
|
|
8
|
+
*/
|
|
9
|
+
import type { androidpublisher_v3 } from "googleapis";
|
|
10
|
+
/**
|
|
11
|
+
* Auth type from googleapis
|
|
12
|
+
* Used internally for EditSession
|
|
13
|
+
*/
|
|
14
|
+
type AuthType = androidpublisher_v3.Params$Resource$Edits$Insert["auth"];
|
|
15
|
+
/**
|
|
16
|
+
* Schema types from googleapis
|
|
17
|
+
* Re-exported for use across the codebase
|
|
18
|
+
*/
|
|
19
|
+
export type AppEdit = androidpublisher_v3.Schema$AppEdit;
|
|
20
|
+
export type AppDetails = androidpublisher_v3.Schema$AppDetails;
|
|
21
|
+
export type Listing = androidpublisher_v3.Schema$Listing;
|
|
22
|
+
export type Image = androidpublisher_v3.Schema$Image;
|
|
23
|
+
export type Track = androidpublisher_v3.Schema$Track;
|
|
24
|
+
export type TrackRelease = androidpublisher_v3.Schema$TrackRelease;
|
|
25
|
+
export type ListingsListResponse = androidpublisher_v3.Schema$ListingsListResponse;
|
|
26
|
+
export type ImagesListResponse = androidpublisher_v3.Schema$ImagesListResponse;
|
|
27
|
+
export type TracksListResponse = androidpublisher_v3.Schema$TracksListResponse;
|
|
28
|
+
export type ImagesUploadResponse = androidpublisher_v3.Schema$ImagesUploadResponse;
|
|
29
|
+
/**
|
|
30
|
+
* Google Play Client Configuration
|
|
31
|
+
* Internal type for client initialization
|
|
32
|
+
*/
|
|
33
|
+
export interface GooglePlayClientConfig {
|
|
34
|
+
packageName: string;
|
|
35
|
+
serviceAccountKeyPath?: string;
|
|
36
|
+
serviceAccountKey?: object;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Edit Session
|
|
40
|
+
* Internal helper type that extends AppEdit with auth and packageName
|
|
41
|
+
* for convenience in API calls
|
|
42
|
+
*/
|
|
43
|
+
export interface EditSession extends Pick<AppEdit, "id"> {
|
|
44
|
+
auth: AuthType;
|
|
45
|
+
packageName: string;
|
|
46
|
+
editId: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Screenshot URLs grouped by device type
|
|
50
|
+
* Internal type for organizing screenshots by device category
|
|
51
|
+
*/
|
|
52
|
+
export interface ScreenshotUrls {
|
|
53
|
+
phone: string[];
|
|
54
|
+
tablet7: string[];
|
|
55
|
+
tablet10: string[];
|
|
56
|
+
tv: string[];
|
|
57
|
+
wear: string[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* App Access Information
|
|
61
|
+
* Internal type for app verification results
|
|
62
|
+
*/
|
|
63
|
+
export interface AppAccessInfo {
|
|
64
|
+
packageName: string;
|
|
65
|
+
title?: string;
|
|
66
|
+
defaultLanguage?: string;
|
|
67
|
+
supportedLocales?: string[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Latest Release Information
|
|
71
|
+
* Internal type derived from TrackRelease for convenience
|
|
72
|
+
* Extracts and transforms TrackRelease data for easier consumption
|
|
73
|
+
*/
|
|
74
|
+
export interface LatestReleaseInfo {
|
|
75
|
+
versionCodes: number[];
|
|
76
|
+
status?: NonNullable<TrackRelease["status"]>;
|
|
77
|
+
versionName?: string;
|
|
78
|
+
releaseName?: NonNullable<TrackRelease["name"]>;
|
|
79
|
+
releaseDate?: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Release Update Result
|
|
83
|
+
* Internal type for tracking release note update operations
|
|
84
|
+
*/
|
|
85
|
+
export interface ReleaseUpdateResult {
|
|
86
|
+
updated: string[];
|
|
87
|
+
failed: Array<{
|
|
88
|
+
locale: string;
|
|
89
|
+
error: string;
|
|
90
|
+
}>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create Release Options
|
|
94
|
+
* Internal type for creating a new release
|
|
95
|
+
* Based on TrackRelease but with simplified versionCodes (number[])
|
|
96
|
+
*/
|
|
97
|
+
export interface CreateReleaseOptions {
|
|
98
|
+
versionCodes: number[];
|
|
99
|
+
releaseName?: NonNullable<TrackRelease["name"]>;
|
|
100
|
+
status?: NonNullable<TrackRelease["status"]>;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Upload Screenshot Options
|
|
104
|
+
* Internal type for screenshot upload operations
|
|
105
|
+
*/
|
|
106
|
+
export interface UploadScreenshotOptions {
|
|
107
|
+
imagePath: string;
|
|
108
|
+
imageType: "phoneScreenshots" | "sevenInchScreenshots" | "tenInchScreenshots" | "tvScreenshots" | "wearScreenshots" | "featureGraphic";
|
|
109
|
+
language?: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update Release Notes Options
|
|
113
|
+
* Internal type for updating release notes
|
|
114
|
+
*/
|
|
115
|
+
export interface UpdateReleaseNotesOptions {
|
|
116
|
+
releaseNotes: Record<string, string>;
|
|
117
|
+
track?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* App Details Data
|
|
121
|
+
* Internal type for app details update operations
|
|
122
|
+
* Based on AppDetails but with optional fields for partial updates
|
|
123
|
+
*/
|
|
124
|
+
export interface AppDetailsData {
|
|
125
|
+
contactEmail?: NonNullable<AppDetails["contactEmail"]>;
|
|
126
|
+
contactPhone?: NonNullable<AppDetails["contactPhone"]>;
|
|
127
|
+
contactWebsite?: NonNullable<AppDetails["contactWebsite"]>;
|
|
128
|
+
defaultLanguage?: NonNullable<AppDetails["defaultLanguage"]>;
|
|
129
|
+
}
|
|
130
|
+
export type ImageType = "appImageTypeUnspecified" | "phoneScreenshots" | "sevenInchScreenshots" | "tenInchScreenshots" | "tvScreenshots" | "wearScreenshots" | "icon" | "featureGraphic" | "tvBanner";
|
|
131
|
+
/**
|
|
132
|
+
* Listing Update Request Attributes
|
|
133
|
+
* @see https://developers.google.com/android-publisher/api-ref/rest/v3/edits.listings#Listing
|
|
134
|
+
*/
|
|
135
|
+
export type ListingUpdateAttributes = Partial<Pick<androidpublisher_v3.Schema$Listing, "language" | "title" | "shortDescription" | "fullDescription" | "video">>;
|
|
136
|
+
/**
|
|
137
|
+
* App Details Update Request Attributes
|
|
138
|
+
* @see https://developers.google.com/android-publisher/api-ref/rest/v3/edits.details#AppDetails
|
|
139
|
+
*/
|
|
140
|
+
export type AppDetailsUpdateAttributes = Partial<Pick<androidpublisher_v3.Schema$AppDetails, "defaultLanguage" | "contactEmail" | "contactPhone" | "contactWebsite">>;
|
|
141
|
+
/**
|
|
142
|
+
* Track Update Request Attributes
|
|
143
|
+
* @see https://developers.google.com/android-publisher/api-ref/rest/v3/edits.tracks#Track
|
|
144
|
+
*/
|
|
145
|
+
export type TrackUpdateAttributes = Partial<Pick<androidpublisher_v3.Schema$Track, "track" | "releases">>;
|
|
146
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface VerifyPlayStoreAuthResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
error?: string;
|
|
4
|
+
data?: {
|
|
5
|
+
client_email: string;
|
|
6
|
+
project_id: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Verify Google Play Store service account authentication configuration.
|
|
11
|
+
* @returns Authentication verification result
|
|
12
|
+
*/
|
|
13
|
+
export declare function verifyPlayStoreAuth(): VerifyPlayStoreAuthResult;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { loadConfig } from "../../../packages/configs/secrets-config/config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Verify Google Play Store service account authentication configuration.
|
|
4
|
+
* @returns Authentication verification result
|
|
5
|
+
*/
|
|
6
|
+
export function verifyPlayStoreAuth() {
|
|
7
|
+
try {
|
|
8
|
+
const cfg = loadConfig().playStore;
|
|
9
|
+
if (!cfg) {
|
|
10
|
+
return {
|
|
11
|
+
success: false,
|
|
12
|
+
error: "Play Store configuration not found in ~/.config/pabal-mcp/config.json file.",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const parsed = JSON.parse(cfg.serviceAccountJson);
|
|
16
|
+
return {
|
|
17
|
+
success: true,
|
|
18
|
+
data: {
|
|
19
|
+
client_email: parsed.client_email,
|
|
20
|
+
project_id: parsed.project_id,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
26
|
+
return {
|
|
27
|
+
success: false,
|
|
28
|
+
error: `Play Store authentication verification failed: ${message}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add-app: Register app by bundleId or packageName
|
|
3
|
+
*/
|
|
4
|
+
import { type RegisteredApp } from "../../packages/configs/secrets-config/registered-apps.js";
|
|
5
|
+
interface AddAppOptions {
|
|
6
|
+
/** App identifier (bundleId or packageName) */
|
|
7
|
+
identifier: string;
|
|
8
|
+
/** Custom slug (if not specified, uses last part of identifier) */
|
|
9
|
+
slug?: string;
|
|
10
|
+
/** Target store (default: both - check both stores) */
|
|
11
|
+
store?: "appStore" | "googlePlay" | "both";
|
|
12
|
+
}
|
|
13
|
+
export declare function handleAddApp(options: AddAppOptions): Promise<{
|
|
14
|
+
content: {
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
}[];
|
|
18
|
+
_meta?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
content: {
|
|
21
|
+
type: "text";
|
|
22
|
+
text: string;
|
|
23
|
+
}[];
|
|
24
|
+
_meta: {
|
|
25
|
+
app: RegisteredApp;
|
|
26
|
+
};
|
|
27
|
+
}>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add-app: Register app by bundleId or packageName
|
|
3
|
+
*/
|
|
4
|
+
import { registerApp, findApp, loadRegisteredApps, saveRegisteredApps, } from "../../packages/configs/secrets-config/registered-apps.js";
|
|
5
|
+
import { toRegisteredAppStoreInfo, toRegisteredGooglePlayInfo, } from "../../core/helpers/registration.js";
|
|
6
|
+
import { AppStoreService } from "../../core/services/app-store-service.js";
|
|
7
|
+
import { GooglePlayService } from "../../core/services/google-play-service.js";
|
|
8
|
+
const appStoreService = new AppStoreService();
|
|
9
|
+
const googlePlayService = new GooglePlayService();
|
|
10
|
+
/**
|
|
11
|
+
* Generate slug (last part of identifier)
|
|
12
|
+
*/
|
|
13
|
+
function generateSlug(identifier) {
|
|
14
|
+
const parts = identifier.split(".");
|
|
15
|
+
return parts[parts.length - 1].toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
export async function handleAddApp(options) {
|
|
18
|
+
const { identifier, slug: customSlug, store = "both" } = options;
|
|
19
|
+
console.error(`[MCP] 📱 Adding app: ${identifier} (store: ${store})`);
|
|
20
|
+
if (!identifier) {
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
type: "text",
|
|
25
|
+
text: `❌ identifier is required.
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
\`\`\`json
|
|
29
|
+
{ "identifier": "com.example.app" }
|
|
30
|
+
{ "identifier": "com.example.app", "slug": "myapp" }
|
|
31
|
+
{ "identifier": "com.example.app", "store": "googlePlay" }
|
|
32
|
+
\`\`\``,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Check if already registered
|
|
38
|
+
let existing;
|
|
39
|
+
try {
|
|
40
|
+
existing = findApp(identifier);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: "text",
|
|
48
|
+
text: `❌ Failed to load registered apps: ${message}`,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (existing) {
|
|
54
|
+
// Update language info for existing apps
|
|
55
|
+
let appsConfig;
|
|
56
|
+
try {
|
|
57
|
+
appsConfig = loadRegisteredApps();
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: `❌ Failed to load registered apps: ${message}`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const appIndex = appsConfig.apps.findIndex((a) => a.slug === existing.slug);
|
|
71
|
+
if (appIndex >= 0) {
|
|
72
|
+
let updated = false;
|
|
73
|
+
const updateResults = [];
|
|
74
|
+
// Update App Store language info
|
|
75
|
+
if (store === "both" || store === "appStore") {
|
|
76
|
+
if (existing.appStore) {
|
|
77
|
+
const asResult = await appStoreService.fetchAppInfo(identifier);
|
|
78
|
+
if (asResult.found && asResult.supportedLocales) {
|
|
79
|
+
if (!appsConfig.apps[appIndex].appStore) {
|
|
80
|
+
appsConfig.apps[appIndex].appStore = {
|
|
81
|
+
bundleId: identifier,
|
|
82
|
+
appId: asResult.appId,
|
|
83
|
+
name: asResult.name,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
appsConfig.apps[appIndex].appStore.supportedLocales =
|
|
87
|
+
asResult.supportedLocales;
|
|
88
|
+
updated = true;
|
|
89
|
+
updateResults.push(`🍎 App Store: Updated locales (${asResult.supportedLocales.length})`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Update Google Play language info
|
|
94
|
+
if (store === "both" || store === "googlePlay") {
|
|
95
|
+
if (existing.googlePlay || store === "googlePlay") {
|
|
96
|
+
const gpResult = await googlePlayService.fetchAppInfo(identifier);
|
|
97
|
+
if (gpResult.found && gpResult.supportedLocales) {
|
|
98
|
+
if (!appsConfig.apps[appIndex].googlePlay) {
|
|
99
|
+
appsConfig.apps[appIndex].googlePlay = {
|
|
100
|
+
packageName: identifier,
|
|
101
|
+
name: gpResult.name,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
appsConfig.apps[appIndex].googlePlay.supportedLocales =
|
|
105
|
+
gpResult.supportedLocales;
|
|
106
|
+
if (gpResult.name) {
|
|
107
|
+
appsConfig.apps[appIndex].googlePlay.name = gpResult.name;
|
|
108
|
+
}
|
|
109
|
+
updated = true;
|
|
110
|
+
updateResults.push(`🤖 Google Play: Updated locales (${gpResult.supportedLocales.length})`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (updated) {
|
|
115
|
+
saveRegisteredApps(appsConfig);
|
|
116
|
+
const updatedApp = appsConfig.apps[appIndex];
|
|
117
|
+
const localeInfo = [];
|
|
118
|
+
if (updatedApp.appStore?.supportedLocales &&
|
|
119
|
+
updatedApp.appStore.supportedLocales.length > 0) {
|
|
120
|
+
localeInfo.push(`• App Store locales: ${updatedApp.appStore.supportedLocales.join(", ")}`);
|
|
121
|
+
}
|
|
122
|
+
if (updatedApp.googlePlay?.supportedLocales &&
|
|
123
|
+
updatedApp.googlePlay.supportedLocales.length > 0) {
|
|
124
|
+
localeInfo.push(`• Google Play locales: ${updatedApp.googlePlay.supportedLocales.join(", ")}`);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
content: [
|
|
128
|
+
{
|
|
129
|
+
type: "text",
|
|
130
|
+
text: `✅ App language info updated
|
|
131
|
+
|
|
132
|
+
• Slug: \`${updatedApp.slug}\`
|
|
133
|
+
• Name: ${updatedApp.name}
|
|
134
|
+
• App Store: ${updatedApp.appStore ? `✅ ${updatedApp.appStore.bundleId}` : "❌"}
|
|
135
|
+
• Google Play: ${updatedApp.googlePlay ? `✅ ${updatedApp.googlePlay.packageName}` : "❌"}
|
|
136
|
+
${updateResults.length > 0 ? `\n**Updates:**\n${updateResults.map((r) => ` • ${r}`).join("\n")}` : ""}
|
|
137
|
+
${localeInfo.length > 0 ? `\n**Supported Languages:**\n${localeInfo.map((l) => ` ${l}`).join("\n")}` : ""}`,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
_meta: { app: updatedApp },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// If no updates were made, return existing info
|
|
145
|
+
const localeInfo = [];
|
|
146
|
+
if (existing.appStore?.supportedLocales &&
|
|
147
|
+
existing.appStore.supportedLocales.length > 0) {
|
|
148
|
+
localeInfo.push(`• App Store locales: ${existing.appStore.supportedLocales.join(", ")}`);
|
|
149
|
+
}
|
|
150
|
+
if (existing.googlePlay?.supportedLocales &&
|
|
151
|
+
existing.googlePlay.supportedLocales.length > 0) {
|
|
152
|
+
localeInfo.push(`• Google Play locales: ${existing.googlePlay.supportedLocales.join(", ")}`);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "text",
|
|
158
|
+
text: `⏭️ App is already registered.
|
|
159
|
+
|
|
160
|
+
• Slug: \`${existing.slug}\`
|
|
161
|
+
• Name: ${existing.name}
|
|
162
|
+
• App Store: ${existing.appStore ? `✅ ${existing.appStore.bundleId}` : "❌"}
|
|
163
|
+
• Google Play: ${existing.googlePlay ? `✅ ${existing.googlePlay.packageName}` : "❌"}
|
|
164
|
+
${localeInfo.length > 0 ? `\n**Supported Languages:**\n${localeInfo.map((l) => ` ${l}`).join("\n")}` : ""}`,
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
_meta: { app: existing },
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const slug = customSlug || generateSlug(identifier);
|
|
171
|
+
// Check for slug duplicates
|
|
172
|
+
const slugExists = findApp(slug);
|
|
173
|
+
if (slugExists) {
|
|
174
|
+
return {
|
|
175
|
+
content: [
|
|
176
|
+
{
|
|
177
|
+
type: "text",
|
|
178
|
+
text: `❌ slug "${slug}" is already in use. Please specify a different slug.
|
|
179
|
+
|
|
180
|
+
\`\`\`json
|
|
181
|
+
{ "identifier": "${identifier}", "slug": "different-slug" }
|
|
182
|
+
\`\`\``,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Fetch app information by store (언어 정보 포함)
|
|
188
|
+
let appStoreInfo = undefined;
|
|
189
|
+
let googlePlayInfo = undefined;
|
|
190
|
+
let appName = identifier;
|
|
191
|
+
const results = [];
|
|
192
|
+
// Check App Store
|
|
193
|
+
if (store === "both" || store === "appStore") {
|
|
194
|
+
console.error(`[MCP] 🔍 Searching App Store for: ${identifier}`);
|
|
195
|
+
const asResult = await appStoreService.fetchAppInfo(identifier);
|
|
196
|
+
if (asResult.found) {
|
|
197
|
+
appStoreInfo = toRegisteredAppStoreInfo({
|
|
198
|
+
bundleId: identifier,
|
|
199
|
+
appInfo: asResult,
|
|
200
|
+
});
|
|
201
|
+
appName = asResult.name || appName;
|
|
202
|
+
const localeInfo = asResult.supportedLocales && asResult.supportedLocales.length > 0
|
|
203
|
+
? ` (${asResult.supportedLocales.length} locales)`
|
|
204
|
+
: "";
|
|
205
|
+
results.push(`🍎 App Store: ✅ Found (${asResult.name})${localeInfo}`);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
results.push(`🍎 App Store: ❌ Not found`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Check Google Play
|
|
212
|
+
if (store === "both" || store === "googlePlay") {
|
|
213
|
+
console.error(`[MCP] 🔍 Searching Google Play for: ${identifier}`);
|
|
214
|
+
const gpResult = await googlePlayService.fetchAppInfo(identifier);
|
|
215
|
+
if (gpResult.found) {
|
|
216
|
+
googlePlayInfo = toRegisteredGooglePlayInfo({
|
|
217
|
+
packageName: identifier,
|
|
218
|
+
appInfo: gpResult,
|
|
219
|
+
});
|
|
220
|
+
appName = gpResult.name || appName;
|
|
221
|
+
const localeInfo = gpResult.supportedLocales && gpResult.supportedLocales.length > 0
|
|
222
|
+
? ` (${gpResult.supportedLocales.length} locales)`
|
|
223
|
+
: "";
|
|
224
|
+
results.push(`🤖 Google Play: ✅ Found (${gpResult.name})${localeInfo}`);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
results.push(`🤖 Google Play: ❌ Not found`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Must be found in at least one store
|
|
231
|
+
if (!appStoreInfo && !googlePlayInfo) {
|
|
232
|
+
return {
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: "text",
|
|
236
|
+
text: `❌ App not found.
|
|
237
|
+
|
|
238
|
+
**Search Results:**
|
|
239
|
+
${results.map((r) => ` • ${r}`).join("\n")}
|
|
240
|
+
|
|
241
|
+
**Things to Check:**
|
|
242
|
+
• Verify identifier is correct: \`${identifier}\`
|
|
243
|
+
• Verify app is registered in the store
|
|
244
|
+
• Verify authentication settings are correct (use auth-check tool)`,
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// Register app
|
|
250
|
+
try {
|
|
251
|
+
console.error(`[MCP] 💾 Registering app with slug: ${slug}`);
|
|
252
|
+
const newApp = registerApp({
|
|
253
|
+
slug,
|
|
254
|
+
name: appName,
|
|
255
|
+
appStore: appStoreInfo,
|
|
256
|
+
googlePlay: googlePlayInfo,
|
|
257
|
+
});
|
|
258
|
+
console.error(`[MCP] ✅ App registered successfully`);
|
|
259
|
+
const storeIcons = [
|
|
260
|
+
appStoreInfo ? "🍎" : null,
|
|
261
|
+
googlePlayInfo ? "🤖" : null,
|
|
262
|
+
]
|
|
263
|
+
.filter(Boolean)
|
|
264
|
+
.join("+");
|
|
265
|
+
const localeInfo = [];
|
|
266
|
+
if (appStoreInfo?.supportedLocales &&
|
|
267
|
+
appStoreInfo.supportedLocales.length > 0) {
|
|
268
|
+
localeInfo.push(`• App Store locales: ${appStoreInfo.supportedLocales.join(", ")}`);
|
|
269
|
+
}
|
|
270
|
+
if (googlePlayInfo?.supportedLocales &&
|
|
271
|
+
googlePlayInfo.supportedLocales.length > 0) {
|
|
272
|
+
localeInfo.push(`• Google Play locales: ${googlePlayInfo.supportedLocales.join(", ")}`);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: `✅ App registration complete (${storeIcons})
|
|
279
|
+
|
|
280
|
+
**Registration Info:**
|
|
281
|
+
• Slug: \`${newApp.slug}\`
|
|
282
|
+
• Name: ${newApp.name}
|
|
283
|
+
${appStoreInfo ? `• App Store: ${appStoreInfo.bundleId} (ID: ${appStoreInfo.appId})` : ""}
|
|
284
|
+
${googlePlayInfo ? `• Google Play: ${googlePlayInfo.packageName}` : ""}
|
|
285
|
+
${localeInfo.length > 0 ? `\n**Supported Languages:**\n${localeInfo.map((l) => ` ${l}`).join("\n")}` : ""}
|
|
286
|
+
|
|
287
|
+
**Search Results:**
|
|
288
|
+
${results.map((r) => ` • ${r}`).join("\n")}
|
|
289
|
+
|
|
290
|
+
You can now reference this app in other tools using the \`app: "${slug}"\` parameter.`,
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
_meta: { app: newApp },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
298
|
+
return {
|
|
299
|
+
content: [
|
|
300
|
+
{
|
|
301
|
+
type: "text",
|
|
302
|
+
text: `❌ App registration failed: ${msg}`,
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup-apps: Query apps from store and auto-register
|
|
3
|
+
*/
|
|
4
|
+
import { type RegisteredApp } from "../../packages/configs/secrets-config/registered-apps.js";
|
|
5
|
+
interface SetupAppsOptions {
|
|
6
|
+
store?: "appStore" | "googlePlay" | "both";
|
|
7
|
+
packageName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleSetupApps(options: SetupAppsOptions): Promise<{
|
|
10
|
+
content: {
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
isError: boolean;
|
|
15
|
+
_meta?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
content: {
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
}[];
|
|
21
|
+
isError?: undefined;
|
|
22
|
+
_meta?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
content: {
|
|
25
|
+
type: "text";
|
|
26
|
+
text: string;
|
|
27
|
+
}[];
|
|
28
|
+
_meta: {
|
|
29
|
+
registered: number;
|
|
30
|
+
skipped: number;
|
|
31
|
+
playStoreFound: number;
|
|
32
|
+
playStoreNotFound: number;
|
|
33
|
+
apps: {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
bundleId: string;
|
|
37
|
+
sku: string;
|
|
38
|
+
isReleased: boolean;
|
|
39
|
+
}[];
|
|
40
|
+
app?: undefined;
|
|
41
|
+
};
|
|
42
|
+
isError?: undefined;
|
|
43
|
+
} | {
|
|
44
|
+
content: {
|
|
45
|
+
type: "text";
|
|
46
|
+
text: string;
|
|
47
|
+
}[];
|
|
48
|
+
_meta: {
|
|
49
|
+
app: RegisteredApp;
|
|
50
|
+
registered?: undefined;
|
|
51
|
+
skipped?: undefined;
|
|
52
|
+
playStoreFound?: undefined;
|
|
53
|
+
playStoreNotFound?: undefined;
|
|
54
|
+
apps?: undefined;
|
|
55
|
+
};
|
|
56
|
+
isError?: undefined;
|
|
57
|
+
}>;
|
|
58
|
+
export {};
|