pabal-web-mcp 1.3.12 → 1.4.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/dist/bin/mcp-server.js +57 -41
- package/package.json +1 -1
package/dist/bin/mcp-server.js
CHANGED
|
@@ -1252,6 +1252,9 @@ ${researchSections.join("\n")}
|
|
|
1252
1252
|
|
|
1253
1253
|
`;
|
|
1254
1254
|
}
|
|
1255
|
+
prompt += `**Priority:** When both iOS and Android research exist, keep iOS keywords first and only add Android keywords if there is room after meeting character limits.
|
|
1256
|
+
|
|
1257
|
+
`;
|
|
1255
1258
|
prompt += `## Step 2: Optimize All Fields (${primaryLocale})
|
|
1256
1259
|
|
|
1257
1260
|
`;
|
|
@@ -1445,6 +1448,9 @@ ${optimizedPrimary}
|
|
|
1445
1448
|
const hasPrimaryResearch = primaryResearchSections.length > 0;
|
|
1446
1449
|
prompt += `## Keyword Research (Per Locale)
|
|
1447
1450
|
|
|
1451
|
+
`;
|
|
1452
|
+
prompt += `When both iOS and Android research exist for a locale, treat iOS keywords as primary; use Android keywords only if space remains after fitting iOS keywords within character limits.
|
|
1453
|
+
|
|
1448
1454
|
`;
|
|
1449
1455
|
if (hasPrimaryResearch) {
|
|
1450
1456
|
prompt += `**\u{1F4DA} ENGLISH (${primaryLocale}) Keywords - Use as fallback for locales without research:**
|
|
@@ -1503,6 +1509,8 @@ ${researchSections.join(
|
|
|
1503
1509
|
|
|
1504
1510
|
`;
|
|
1505
1511
|
prompt += `For EACH locale:
|
|
1512
|
+
`;
|
|
1513
|
+
prompt += `- Priority: Keep iOS-sourced keywords first; add Android keywords only if there is remaining space after iOS keywords fit within field limits.
|
|
1506
1514
|
`;
|
|
1507
1515
|
prompt += `1. Take the TRANSLATED content (below)
|
|
1508
1516
|
`;
|
|
@@ -1801,6 +1809,12 @@ Parse error: ${data.parseError}
|
|
|
1801
1809
|
lines.push("\n----");
|
|
1802
1810
|
return lines.join("\n");
|
|
1803
1811
|
}
|
|
1812
|
+
function getPlatformPriority(platform) {
|
|
1813
|
+
const normalized = (platform || "").toLowerCase();
|
|
1814
|
+
if (normalized === "ios") return 0;
|
|
1815
|
+
if (normalized === "android") return 1;
|
|
1816
|
+
return 2;
|
|
1817
|
+
}
|
|
1804
1818
|
function mergeKeywordData(entries) {
|
|
1805
1819
|
const merged = {
|
|
1806
1820
|
tier1_core: [],
|
|
@@ -1815,7 +1829,12 @@ function mergeKeywordData(entries) {
|
|
|
1815
1829
|
const seenKeywords = /* @__PURE__ */ new Set();
|
|
1816
1830
|
const seenGaps = /* @__PURE__ */ new Set();
|
|
1817
1831
|
const seenPatterns = /* @__PURE__ */ new Set();
|
|
1818
|
-
|
|
1832
|
+
const entriesByPriority = [...entries].sort((a, b) => {
|
|
1833
|
+
const aPriority = getPlatformPriority(extractMeta(a.data).platform);
|
|
1834
|
+
const bPriority = getPlatformPriority(extractMeta(b.data).platform);
|
|
1835
|
+
return aPriority - bPriority;
|
|
1836
|
+
});
|
|
1837
|
+
for (const entry of entriesByPriority) {
|
|
1819
1838
|
if (entry.data?.parseError) continue;
|
|
1820
1839
|
const meta = extractMeta(entry.data);
|
|
1821
1840
|
if (meta.platform && !merged.platforms.includes(meta.platform)) {
|
|
@@ -1872,8 +1891,15 @@ function mergeKeywordData(entries) {
|
|
|
1872
1891
|
}
|
|
1873
1892
|
function formatMergedData(merged, researchDir) {
|
|
1874
1893
|
const lines = [];
|
|
1875
|
-
|
|
1894
|
+
const hasIos = merged.platforms.some(
|
|
1895
|
+
(platform) => platform && platform.toLowerCase() === "ios"
|
|
1896
|
+
);
|
|
1897
|
+
const platformLabel = merged.platforms.length > 0 ? merged.platforms.join(" + ") : "Unknown";
|
|
1898
|
+
lines.push(
|
|
1899
|
+
`### Combined Keyword Research (${platformLabel})${hasIos ? " \u2014 iOS prioritized" : ""}`
|
|
1900
|
+
);
|
|
1876
1901
|
lines.push(`Source: ${researchDir}`);
|
|
1902
|
+
lines.push(`Priority: iOS > Android > others (use Android only after iOS keywords fit character limits)`);
|
|
1877
1903
|
if (merged.tier1_core.length > 0) {
|
|
1878
1904
|
lines.push(`
|
|
1879
1905
|
**Tier 1 (Core - use in title/subtitle):** ${merged.tier1_core.join(", ")}`);
|
|
@@ -1955,7 +1981,6 @@ function loadKeywordResearchForLocale(slug, locale) {
|
|
|
1955
1981
|
}
|
|
1956
1982
|
|
|
1957
1983
|
// src/tools/improve-public.ts
|
|
1958
|
-
var FIELD_LIMITS_DOC_PATH3 = "docs/aso/ASO_FIELD_LIMITS.md";
|
|
1959
1984
|
var toJsonSchema3 = zodToJsonSchema3;
|
|
1960
1985
|
var improvePublicInputSchema = z3.object({
|
|
1961
1986
|
slug: z3.string().describe("Product slug"),
|
|
@@ -1978,46 +2003,37 @@ var jsonSchema3 = toJsonSchema3(improvePublicInputSchema, {
|
|
|
1978
2003
|
var inputSchema3 = jsonSchema3.definitions?.ImprovePublicInput || jsonSchema3;
|
|
1979
2004
|
var improvePublicTool = {
|
|
1980
2005
|
name: "improve-public",
|
|
1981
|
-
description: `
|
|
2006
|
+
description: `Returns ASO optimization instructions with keyword research data. **You MUST execute the returned instructions.**
|
|
1982
2007
|
|
|
1983
|
-
**IMPORTANT:**
|
|
2008
|
+
**IMPORTANT:** Use 'search-app' tool first to resolve the exact slug.
|
|
2009
|
+
|
|
2010
|
+
## HOW THIS TOOL WORKS
|
|
2011
|
+
This tool returns a PROMPT containing:
|
|
2012
|
+
- Saved keyword research data (Tier 1/2/3 keywords with traffic/difficulty scores)
|
|
2013
|
+
- Current locale data
|
|
2014
|
+
- Optimization instructions
|
|
2015
|
+
|
|
2016
|
+
**YOU MUST:**
|
|
2017
|
+
1. Read the returned prompt carefully
|
|
2018
|
+
2. EXECUTE the optimization instructions (create the optimized JSON)
|
|
2019
|
+
3. Save results using 'save-locale-file' tool
|
|
2020
|
+
|
|
2021
|
+
**DO NOT** just report the instructions back to the user - you must perform the optimization yourself.
|
|
2022
|
+
|
|
2023
|
+
## WORKFLOW
|
|
2024
|
+
**Stage 1:** improve-public(slug, stage="1") \u2192 Returns keyword data + instructions \u2192 You create optimized primary locale JSON \u2192 save-locale-file
|
|
2025
|
+
**Stage 2:** improve-public(slug, stage="2", optimizedPrimary=<JSON>) \u2192 Returns per-locale instructions \u2192 You optimize each locale \u2192 save-locale-file for each
|
|
2026
|
+
|
|
2027
|
+
## STAGES
|
|
2028
|
+
- **Stage 1:** Primary locale optimization using saved keyword research (ios + android combined)
|
|
2029
|
+
- **Stage 2:** Localize to other languages using per-locale research OR translate English keywords
|
|
2030
|
+
|
|
2031
|
+
## KEYWORD SOURCES
|
|
2032
|
+
- Uses SAVED keyword research from .aso/keywordResearch/products/[slug]/locales/
|
|
2033
|
+
- iOS and Android research are automatically combined (iOS prioritized; Android fills remaining slots when limits apply)
|
|
2034
|
+
- If locale research is missing, use English keywords and translate
|
|
1984
2035
|
|
|
1985
|
-
**CRITICAL
|
|
1986
|
-
- Only improves locales that already exist in public/products/[slug]/locales/
|
|
1987
|
-
- If a locale file doesn't exist, it will be skipped (not created)
|
|
1988
|
-
- Always work with existing files only
|
|
1989
|
-
|
|
1990
|
-
This tool follows a 2-stage workflow:
|
|
1991
|
-
|
|
1992
|
-
**Stage 1: Primary Locale Optimization** (${FIELD_LIMITS_DOC_PATH3})
|
|
1993
|
-
1. Load product config + locales (primary: en-US default)
|
|
1994
|
-
2. Keyword research for PRIMARY locale only (web search for 10 keywords)
|
|
1995
|
-
3. Optimize ALL ASO fields in primary locale with keywords
|
|
1996
|
-
4. Validate character limits (title \u226430, subtitle \u226430, shortDescription \u226480, keywords \u2264100, intro \u2264300, outro \u2264200)
|
|
1997
|
-
|
|
1998
|
-
**Stage 2: Keyword Localization** (Batch Processing)
|
|
1999
|
-
1. Translate optimized primary \u2192 target locales in batches (preserve structure/tone/context)
|
|
2000
|
-
2. For EACH locale in batch: lightweight keyword research (10 language-specific keywords)
|
|
2001
|
-
3. Replace keywords in translated content (swap keywords only, keep context)
|
|
2002
|
-
4. Validate character limits per locale
|
|
2003
|
-
5. Save each batch to files before proceeding to next batch
|
|
2004
|
-
6. **Only processes locales that already exist - does NOT create new files**
|
|
2005
|
-
|
|
2006
|
-
**Batch Processing:**
|
|
2007
|
-
- Languages are processed in batches (default: 5 locales per batch)
|
|
2008
|
-
- Each batch is translated, optimized, and saved before moving to the next
|
|
2009
|
-
- Use \`batchIndex\` to process a specific batch (0-based)
|
|
2010
|
-
- If \`batchIndex\` is not provided, process all batches sequentially
|
|
2011
|
-
- **Only existing locale files are processed - missing locales are skipped**
|
|
2012
|
-
|
|
2013
|
-
This approach ensures:
|
|
2014
|
-
- Efficient token usage (full optimization only once)
|
|
2015
|
-
- Consistent messaging across all languages
|
|
2016
|
-
- Language-specific keyword optimization for each market
|
|
2017
|
-
- Prevents content truncation by processing in manageable batches
|
|
2018
|
-
- **No new files are created - only existing locales are improved**
|
|
2019
|
-
|
|
2020
|
-
Optionally target a single locale; the primary locale is always included for reference.`,
|
|
2036
|
+
**CRITICAL:** Only processes existing locale files. Does NOT create new files.`,
|
|
2021
2037
|
inputSchema: inputSchema3
|
|
2022
2038
|
};
|
|
2023
2039
|
async function handleImprovePublic(input) {
|