pabal-web-mcp 0.1.0 → 0.1.1
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 +169 -43
- package/dist/bin/mcp-server.js +37 -32
- package/dist/chunk-MWXNTV3M.js +1001 -0
- package/dist/index.d.ts +24 -2
- package/dist/index.js +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,164 @@ MCP (Model Context Protocol) server for ASO (App Store Optimization) data manage
|
|
|
8
8
|
npm install pabal-web-mcp
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## 🛠️ MCP Client Installation
|
|
12
|
+
|
|
13
|
+
### Requirements
|
|
14
|
+
|
|
15
|
+
- Node.js >= 18
|
|
16
|
+
- MCP client: Cursor, Claude Code, VS Code, Windsurf, etc.
|
|
17
|
+
|
|
18
|
+
> [!TIP]
|
|
19
|
+
> If you repeatedly do ASO/store tasks, add a client rule like "always use pabal-web-mcp" so the MCP server auto-invokes without typing it every time.
|
|
20
|
+
|
|
21
|
+
### Global install (recommended)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g pabal-web-mcp
|
|
25
|
+
|
|
26
|
+
# or
|
|
27
|
+
|
|
28
|
+
yarn global add pabal-web-mcp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Install globally first for fastest starts and to avoid npm download issues (proxy/firewall/offline). You can still use `npx -y pabal-web-mcp`, but global install is recommended. After global install, set your MCP config to `command: "pabal-web-mcp"` (no `npx` needed).
|
|
32
|
+
|
|
33
|
+
<details>
|
|
34
|
+
<summary><b>Install in Cursor</b></summary>
|
|
35
|
+
|
|
36
|
+
Add to `~/.cursor/mcp.json` (global) or project `.cursor/mcp.json`:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"pabal-web-mcp": {
|
|
42
|
+
"command": "npx",
|
|
43
|
+
"args": ["-y", "pabal-web-mcp"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or if installed globally:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"pabal-web-mcp": {
|
|
55
|
+
"command": "pabal-web-mcp"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
<details>
|
|
64
|
+
<summary><b>Install in VS Code</b></summary>
|
|
65
|
+
|
|
66
|
+
Example `settings.json` MCP section:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
"mcp": {
|
|
70
|
+
"servers": {
|
|
71
|
+
"pabal-web-mcp": {
|
|
72
|
+
"type": "stdio",
|
|
73
|
+
"command": "npx",
|
|
74
|
+
"args": ["-y", "pabal-web-mcp"]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or if installed globally:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
"mcp": {
|
|
84
|
+
"servers": {
|
|
85
|
+
"pabal-web-mcp": {
|
|
86
|
+
"type": "stdio",
|
|
87
|
+
"command": "pabal-web-mcp"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
</details>
|
|
94
|
+
|
|
95
|
+
<details>
|
|
96
|
+
<summary><b>Install in Claude Code</b></summary>
|
|
97
|
+
|
|
98
|
+
> [!TIP]
|
|
99
|
+
> See the [official Claude Code MCP documentation](https://code.claude.com/docs/en/mcp#setting-up-enterprise-mcp-configuration) for detailed configuration options.
|
|
100
|
+
|
|
101
|
+
Add to Claude Code MCP settings (JSON format):
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"pabal-web-mcp": {
|
|
107
|
+
"command": "npx",
|
|
108
|
+
"args": ["-y", "pabal-web-mcp"]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Or if installed globally (`npm install -g pabal-web-mcp`):
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"mcpServers": {
|
|
119
|
+
"pabal-web-mcp": {
|
|
120
|
+
"command": "pabal-web-mcp"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
</details>
|
|
127
|
+
|
|
128
|
+
<details>
|
|
129
|
+
<summary><b>Install in Windsurf</b></summary>
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"mcpServers": {
|
|
134
|
+
"pabal-web-mcp": {
|
|
135
|
+
"command": "npx",
|
|
136
|
+
"args": ["-y", "pabal-web-mcp"]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Or if installed globally:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"pabal-web-mcp": {
|
|
148
|
+
"command": "pabal-web-mcp"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
## MCP Server
|
|
157
|
+
|
|
158
|
+
This package includes an MCP server for managing ASO data through Claude or other MCP-compatible clients.
|
|
159
|
+
|
|
160
|
+
### Available Tools
|
|
161
|
+
|
|
162
|
+
| Tool | Description |
|
|
163
|
+
| ---------------- | -------------------------------------------------- |
|
|
164
|
+
| `aso-to-public` | Convert ASO data to public config format |
|
|
165
|
+
| `public-to-aso` | Convert public config to ASO data format |
|
|
166
|
+
| `improve-public` | Improve product locale content with AI suggestions |
|
|
167
|
+
| `init-project` | Initialize a new product project structure |
|
|
168
|
+
|
|
11
169
|
## Usage
|
|
12
170
|
|
|
13
171
|
### Importing Types
|
|
@@ -60,38 +218,6 @@ console.log(asoData.appStore?.name);
|
|
|
60
218
|
console.log(asoData.googlePlay?.title);
|
|
61
219
|
```
|
|
62
220
|
|
|
63
|
-
## MCP Server
|
|
64
|
-
|
|
65
|
-
This package includes an MCP server for managing ASO data through Claude or other MCP-compatible clients.
|
|
66
|
-
|
|
67
|
-
### Available Tools
|
|
68
|
-
|
|
69
|
-
| Tool | Description |
|
|
70
|
-
|------|-------------|
|
|
71
|
-
| `aso-to-public` | Convert ASO data to public config format |
|
|
72
|
-
| `public-to-aso` | Convert public config to ASO data format |
|
|
73
|
-
| `improve-public` | Improve product locale content with AI suggestions |
|
|
74
|
-
| `init-project` | Initialize a new product project structure |
|
|
75
|
-
|
|
76
|
-
### Running the MCP Server
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npx pabal-web-mcp
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Or add to your Claude Desktop config:
|
|
83
|
-
|
|
84
|
-
```json
|
|
85
|
-
{
|
|
86
|
-
"mcpServers": {
|
|
87
|
-
"pabal-web-mcp": {
|
|
88
|
-
"command": "npx",
|
|
89
|
-
"args": ["pabal-web-mcp"]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
221
|
## Types Reference
|
|
96
222
|
|
|
97
223
|
### ASO Types
|
|
@@ -116,17 +242,17 @@ Or add to your Claude Desktop config:
|
|
|
116
242
|
## Supported Locales
|
|
117
243
|
|
|
118
244
|
| Unified | App Store | Google Play |
|
|
119
|
-
|
|
120
|
-
| en-US
|
|
121
|
-
| ko-KR
|
|
122
|
-
| ja-JP
|
|
123
|
-
| zh-CN
|
|
124
|
-
| zh-TW
|
|
125
|
-
| de-DE
|
|
126
|
-
| fr-FR
|
|
127
|
-
| es-ES
|
|
128
|
-
| pt-BR
|
|
129
|
-
| ...
|
|
245
|
+
| ------- | --------- | ----------- |
|
|
246
|
+
| en-US | en-US | en-US |
|
|
247
|
+
| ko-KR | ko | ko-KR |
|
|
248
|
+
| ja-JP | ja | ja-JP |
|
|
249
|
+
| zh-CN | zh-Hans | zh-CN |
|
|
250
|
+
| zh-TW | zh-Hant | zh-TW |
|
|
251
|
+
| de-DE | de-DE | de-DE |
|
|
252
|
+
| fr-FR | fr-FR | fr-FR |
|
|
253
|
+
| es-ES | es-ES | es-ES |
|
|
254
|
+
| pt-BR | pt-BR | pt-BR |
|
|
255
|
+
| ... | ... | ... |
|
|
130
256
|
|
|
131
257
|
## License
|
|
132
258
|
|
package/dist/bin/mcp-server.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_LOCALE,
|
|
4
4
|
appStoreToUnified,
|
|
5
|
+
getProductsDir,
|
|
6
|
+
getPublicDir,
|
|
7
|
+
getPullDataDir,
|
|
8
|
+
getPushDataDir,
|
|
5
9
|
googlePlayToUnified,
|
|
6
10
|
isAppStoreMultilingual,
|
|
7
11
|
isGooglePlayMultilingual,
|
|
@@ -9,7 +13,7 @@ import {
|
|
|
9
13
|
saveAsoToAsoDir,
|
|
10
14
|
unifiedToAppStore,
|
|
11
15
|
unifiedToGooglePlay
|
|
12
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-MWXNTV3M.js";
|
|
13
17
|
|
|
14
18
|
// src/bin/mcp-server.ts
|
|
15
19
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -28,10 +32,9 @@ import fs from "fs";
|
|
|
28
32
|
import path from "path";
|
|
29
33
|
function loadPullData(slug) {
|
|
30
34
|
const asoData = {};
|
|
35
|
+
const pullDataDir = getPullDataDir();
|
|
31
36
|
const googlePlayPath = path.join(
|
|
32
|
-
|
|
33
|
-
".aso",
|
|
34
|
-
"pullData",
|
|
37
|
+
pullDataDir,
|
|
35
38
|
"products",
|
|
36
39
|
slug,
|
|
37
40
|
"store",
|
|
@@ -50,9 +53,7 @@ function loadPullData(slug) {
|
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
const appStorePath = path.join(
|
|
53
|
-
|
|
54
|
-
".aso",
|
|
55
|
-
"pullData",
|
|
56
|
+
pullDataDir,
|
|
56
57
|
"products",
|
|
57
58
|
slug,
|
|
58
59
|
"store",
|
|
@@ -202,14 +203,14 @@ var jsonSchema = toJsonSchema(asoToPublicInputSchema, {
|
|
|
202
203
|
var inputSchema = jsonSchema.definitions?.AsoToPublicInput || jsonSchema;
|
|
203
204
|
var asoToPublicTool = {
|
|
204
205
|
name: "aso-to-public",
|
|
205
|
-
description: `Converts ASO data from
|
|
206
|
+
description: `Converts ASO data from pullData to public/products/[slug]/ structure.
|
|
206
207
|
|
|
207
208
|
**IMPORTANT:** The 'slug' parameter is REQUIRED. If the user does not provide a slug, you MUST ask them to provide it. This tool processes only ONE product at a time.
|
|
208
209
|
|
|
209
210
|
This tool:
|
|
210
|
-
1. Loads ASO data from
|
|
211
|
+
1. Loads ASO data from pullData/products/[slug]/store/ (path from ~/.config/pabal-mcp/config.json dataDir)
|
|
211
212
|
2. Generates per-locale conversion prompts to map fullDescription into structured locale JSON (template intro/outro + landing features/screenshots captions)
|
|
212
|
-
3. Next steps (manual): paste converted JSON into public/products/[slug]/locales/[locale].json and copy screenshots from
|
|
213
|
+
3. Next steps (manual): paste converted JSON into public/products/[slug]/locales/[locale].json and copy screenshots from pullData if needed
|
|
213
214
|
|
|
214
215
|
The conversion from unstructured to structured format is performed by Claude based on the conversion prompt.`,
|
|
215
216
|
inputSchema
|
|
@@ -218,7 +219,7 @@ async function handleAsoToPublic(input) {
|
|
|
218
219
|
const { slug } = input;
|
|
219
220
|
const asoData = loadPullData(slug);
|
|
220
221
|
if (!asoData.googlePlay && !asoData.appStore) {
|
|
221
|
-
throw new Error(`No ASO data found in
|
|
222
|
+
throw new Error(`No ASO data found in pullData for ${slug}`);
|
|
222
223
|
}
|
|
223
224
|
const mergedDataByLocale = /* @__PURE__ */ new Map();
|
|
224
225
|
if (asoData.googlePlay) {
|
|
@@ -270,7 +271,8 @@ async function handleAsoToPublic(input) {
|
|
|
270
271
|
).find((loc) => googlePlayToUnified(loc) === unifiedLocale);
|
|
271
272
|
if (googlePlayLocale) {
|
|
272
273
|
if (!screenshotPaths) screenshotPaths = {};
|
|
273
|
-
|
|
274
|
+
const pullDataDir2 = getPullDataDir();
|
|
275
|
+
screenshotPaths.googlePlay = `${pullDataDir2}/products/${slug}/store/google-play/screenshots/${googlePlayLocale}/`;
|
|
274
276
|
}
|
|
275
277
|
}
|
|
276
278
|
if (mergedData.appStore) {
|
|
@@ -279,7 +281,8 @@ async function handleAsoToPublic(input) {
|
|
|
279
281
|
).find((loc) => appStoreToUnified(loc) === unifiedLocale);
|
|
280
282
|
if (appStoreLocale) {
|
|
281
283
|
if (!screenshotPaths) screenshotPaths = {};
|
|
282
|
-
|
|
284
|
+
const pullDataDir2 = getPullDataDir();
|
|
285
|
+
screenshotPaths.appStore = `${pullDataDir2}/products/${slug}/store/app-store/screenshots/${appStoreLocale}/`;
|
|
283
286
|
}
|
|
284
287
|
}
|
|
285
288
|
const prompt = generateConversionPrompt(
|
|
@@ -303,7 +306,8 @@ async function handleAsoToPublic(input) {
|
|
|
303
306
|
--- ${unifiedLocale} (${sourcesText}) ---
|
|
304
307
|
${prompt}`);
|
|
305
308
|
}
|
|
306
|
-
|
|
309
|
+
const pullDataDir = getPullDataDir();
|
|
310
|
+
let responseText = `Converting ASO data from pullData to public/products/${slug}/ structure.
|
|
307
311
|
|
|
308
312
|
`;
|
|
309
313
|
responseText += `Found ${conversionTasks.length} unified locale(s) to convert.
|
|
@@ -322,7 +326,7 @@ Next steps (manual):
|
|
|
322
326
|
`;
|
|
323
327
|
responseText += ` Example: public/products/${slug}/locales/ar.json (not ar-SA.json)
|
|
324
328
|
`;
|
|
325
|
-
responseText += `2. Copy screenshots from
|
|
329
|
+
responseText += `2. Copy screenshots from ${pullDataDir}/products/${slug}/store/ to public/products/${slug}/screenshots/
|
|
326
330
|
`;
|
|
327
331
|
return {
|
|
328
332
|
content: [
|
|
@@ -413,7 +417,7 @@ function prepareAsoDataForPush(slug, configData) {
|
|
|
413
417
|
|
|
414
418
|
// src/tools/utils/public-to-aso/save-raw-aso-data.util.ts
|
|
415
419
|
function saveRawAsoData(slug, asoData, options) {
|
|
416
|
-
const rootDir = options?.rootDir ??
|
|
420
|
+
const rootDir = options?.rootDir ?? getPushDataDir();
|
|
417
421
|
saveAsoToAsoDir(slug, asoData, { rootDir });
|
|
418
422
|
const localeCounts = {};
|
|
419
423
|
if (asoData.googlePlay) {
|
|
@@ -475,8 +479,9 @@ function isLocalAssetPath(assetPath) {
|
|
|
475
479
|
import fs3 from "fs";
|
|
476
480
|
import path3 from "path";
|
|
477
481
|
function copyLocalAssetToAsoDir(assetPath, outputPath) {
|
|
482
|
+
const publicDir = getPublicDir();
|
|
478
483
|
const trimmedPath = assetPath.replace(/^\.\//, "").replace(/^public\//, "").replace(/^\/+/, "");
|
|
479
|
-
const sourcePath = path3.join(
|
|
484
|
+
const sourcePath = path3.join(publicDir, trimmedPath);
|
|
480
485
|
if (!fs3.existsSync(sourcePath)) {
|
|
481
486
|
console.warn(`\u26A0\uFE0F Local image not found: ${sourcePath}`);
|
|
482
487
|
return false;
|
|
@@ -514,9 +519,8 @@ var jsonSchema2 = toJsonSchema2(publicToAsoInputSchema, {
|
|
|
514
519
|
});
|
|
515
520
|
var inputSchema2 = jsonSchema2.definitions?.PublicToAsoInput || jsonSchema2;
|
|
516
521
|
async function downloadScreenshotsToAsoDir(slug, asoData, options) {
|
|
517
|
-
const rootDir = options?.rootDir ??
|
|
522
|
+
const rootDir = options?.rootDir ?? getPushDataDir();
|
|
518
523
|
const productStoreRoot = path4.join(
|
|
519
|
-
process.cwd(),
|
|
520
524
|
rootDir,
|
|
521
525
|
"products",
|
|
522
526
|
slug,
|
|
@@ -654,15 +658,15 @@ async function downloadScreenshotsToAsoDir(slug, asoData, options) {
|
|
|
654
658
|
}
|
|
655
659
|
var publicToAsoTool = {
|
|
656
660
|
name: "public-to-aso",
|
|
657
|
-
description: `Prepares ASO data from public/products/[slug]/ to
|
|
661
|
+
description: `Prepares ASO data from public/products/[slug]/ to pushData format.
|
|
658
662
|
|
|
659
663
|
**IMPORTANT:** The 'slug' parameter is REQUIRED. If the user does not provide a slug, you MUST ask them to provide it. This tool processes only ONE product at a time.
|
|
660
664
|
|
|
661
665
|
This tool:
|
|
662
666
|
1. Loads ASO data from public/products/[slug]/config.json + locales/
|
|
663
667
|
2. Converts to store-compatible format (removes screenshots from metadata, sets contactWebsite/marketingUrl)
|
|
664
|
-
3. Saves metadata to
|
|
665
|
-
4. Copies/downloads screenshots to
|
|
668
|
+
3. Saves metadata to pushData/products/[slug]/store/ (path from ~/.config/pabal-mcp/config.json dataDir)
|
|
669
|
+
4. Copies/downloads screenshots to pushData/products/[slug]/store/screenshots/
|
|
666
670
|
|
|
667
671
|
Before running, review ${FIELD_LIMITS_DOC_PATH} for per-store limits. This prepares data for pushing to stores without actually uploading.`,
|
|
668
672
|
inputSchema: inputSchema2
|
|
@@ -674,12 +678,13 @@ async function handlePublicToAso(input) {
|
|
|
674
678
|
throw new Error(`No ASO data found in config.json + locales/ for ${slug}`);
|
|
675
679
|
}
|
|
676
680
|
const storeData = prepareAsoDataForPush(slug, configData);
|
|
681
|
+
const pushDataRoot = getPushDataDir();
|
|
677
682
|
if (dryRun) {
|
|
678
683
|
return {
|
|
679
684
|
content: [
|
|
680
685
|
{
|
|
681
686
|
type: "text",
|
|
682
|
-
text: `Preview mode - Data that would be saved to
|
|
687
|
+
text: `Preview mode - Data that would be saved to ${pushDataRoot}:
|
|
683
688
|
|
|
684
689
|
${JSON.stringify(
|
|
685
690
|
storeData,
|
|
@@ -690,7 +695,6 @@ ${JSON.stringify(
|
|
|
690
695
|
]
|
|
691
696
|
};
|
|
692
697
|
}
|
|
693
|
-
const pushDataRoot = ".aso/pushData";
|
|
694
698
|
saveRawAsoData(slug, storeData, { rootDir: pushDataRoot });
|
|
695
699
|
await downloadScreenshotsToAsoDir(slug, configData, {
|
|
696
700
|
rootDir: pushDataRoot
|
|
@@ -708,7 +712,7 @@ ${JSON.stringify(
|
|
|
708
712
|
const locales = isAppStoreMultilingual(appStoreData) ? appStoreData.locales : { [appStoreData.locale || DEFAULT_LOCALE]: appStoreData };
|
|
709
713
|
localeCounts.appStore = Object.keys(locales).length;
|
|
710
714
|
}
|
|
711
|
-
let responseText = `\u2705 ${slug}
|
|
715
|
+
let responseText = `\u2705 ${slug} pushData files prepared from config.json + locales/ (images + metadata synced)
|
|
712
716
|
|
|
713
717
|
`;
|
|
714
718
|
if (localeCounts.googlePlay) {
|
|
@@ -741,7 +745,8 @@ import { zodToJsonSchema as zodToJsonSchema3 } from "zod-to-json-schema";
|
|
|
741
745
|
import fs4 from "fs";
|
|
742
746
|
import path5 from "path";
|
|
743
747
|
function loadProductLocales(slug) {
|
|
744
|
-
const
|
|
748
|
+
const productsDir = getProductsDir();
|
|
749
|
+
const productDir = path5.join(productsDir, slug);
|
|
745
750
|
const configPath = path5.join(productDir, "config.json");
|
|
746
751
|
const localesDir = path5.join(productDir, "locales");
|
|
747
752
|
let config = null;
|
|
@@ -1711,7 +1716,7 @@ var listSlugDirs = (dir) => {
|
|
|
1711
1716
|
};
|
|
1712
1717
|
var initProjectInputSchema = z4.object({
|
|
1713
1718
|
slug: z4.string().trim().optional().describe(
|
|
1714
|
-
"Optional product slug to focus on. Defaults to all slugs in
|
|
1719
|
+
"Optional product slug to focus on. Defaults to all slugs in pullData/products/"
|
|
1715
1720
|
)
|
|
1716
1721
|
});
|
|
1717
1722
|
var jsonSchema4 = zodToJsonSchema4(initProjectInputSchema, {
|
|
@@ -1727,14 +1732,14 @@ var initProjectTool = {
|
|
|
1727
1732
|
This tool is read-only and returns a checklist. It does not call pabal-mcp directly or write files.
|
|
1728
1733
|
|
|
1729
1734
|
Steps:
|
|
1730
|
-
1) Ensure pabal-mcp 'init' ran and
|
|
1735
|
+
1) Ensure pabal-mcp 'init' ran and pullData/products/[slug]/ exists (path from ~/.config/pabal-mcp/config.json dataDir)
|
|
1731
1736
|
2) Convert pulled ASO data -> public/products/[slug]/ using pabal-web-mcp tools (aso-to-public, public-to-aso dry run)
|
|
1732
1737
|
3) Validate outputs and next actions`,
|
|
1733
1738
|
inputSchema: inputSchema4
|
|
1734
1739
|
};
|
|
1735
1740
|
async function handleInitProject(input) {
|
|
1736
|
-
const pullDataDir = path6.join(
|
|
1737
|
-
const publicDir =
|
|
1741
|
+
const pullDataDir = path6.join(getPullDataDir(), "products");
|
|
1742
|
+
const publicDir = getProductsDir();
|
|
1738
1743
|
const pullDataSlugs = listSlugDirs(pullDataDir);
|
|
1739
1744
|
const publicSlugs = listSlugDirs(publicDir);
|
|
1740
1745
|
const targetSlugs = input.slug?.length && input.slug.trim().length > 0 ? [input.slug.trim()] : pullDataSlugs.length > 0 ? pullDataSlugs : publicSlugs;
|
|
@@ -1752,7 +1757,7 @@ async function handleInitProject(input) {
|
|
|
1752
1757
|
lines.push("");
|
|
1753
1758
|
if (targetSlugs.length === 0) {
|
|
1754
1759
|
lines.push(
|
|
1755
|
-
"No products detected. Run pabal-mcp 'init' for your slug(s) to populate
|
|
1760
|
+
"No products detected. Run pabal-mcp 'init' for your slug(s) to populate pullData/products/, then rerun this tool."
|
|
1756
1761
|
);
|
|
1757
1762
|
return {
|
|
1758
1763
|
content: [
|
|
@@ -1790,7 +1795,7 @@ async function handleInitProject(input) {
|
|
|
1790
1795
|
lines.push("");
|
|
1791
1796
|
lines.push("Step 3: Verify and prepare for push (optional)");
|
|
1792
1797
|
lines.push(
|
|
1793
|
-
"Use pabal-web-mcp 'public-to-aso' with dryRun=true to validate structure and build
|
|
1798
|
+
"Use pabal-web-mcp 'public-to-aso' with dryRun=true to validate structure and build pushData before uploading via store tooling."
|
|
1794
1799
|
);
|
|
1795
1800
|
lines.push("");
|
|
1796
1801
|
lines.push("Notes:");
|