aso-mcp 1.3.0 → 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/README.md +3 -2
- package/build/cache/sqlite-cache.d.ts +15 -0
- package/build/cache/sqlite-cache.d.ts.map +1 -1
- package/build/cache/sqlite-cache.js +68 -5
- package/build/cache/sqlite-cache.js.map +1 -1
- package/build/server.js +2 -0
- package/build/server.js.map +1 -1
- package/build/tools/get-ranking-history.d.ts +3 -0
- package/build/tools/get-ranking-history.d.ts.map +1 -0
- package/build/tools/get-ranking-history.js +147 -0
- package/build/tools/get-ranking-history.js.map +1 -0
- package/build/tools/suggest-keywords.d.ts.map +1 -1
- package/build/tools/suggest-keywords.js +6 -1
- package/build/tools/suggest-keywords.js.map +1 -1
- package/build/tools/track-ranking.d.ts.map +1 -1
- package/build/tools/track-ranking.js +7 -1
- package/build/tools/track-ranking.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ npm install -g aso-mcp
|
|
|
23
23
|
|
|
24
24
|
## Why aso-mcp?
|
|
25
25
|
|
|
26
|
-
- **
|
|
26
|
+
- **20 specialized ASO tools**: from keyword discovery and ranking trends to App Store Connect metadata management
|
|
27
27
|
- **Real App Store data**: live search results, ratings, reviews, and suggestions
|
|
28
28
|
- **Custom scoring engine**: proprietary algorithm independent of Apple Search Ads API issues
|
|
29
29
|
- **No API key needed**: zero configuration, install and go
|
|
@@ -97,7 +97,8 @@ Any MCP-compatible client (ChatGPT, Cursor, Windsurf, etc.) can connect via stdi
|
|
|
97
97
|
| `analyze_competitors` | Metadata comparison of top apps for a keyword + keyword gap |
|
|
98
98
|
| `optimize_metadata` | Title/subtitle/keyword field suggestions with character limit checks |
|
|
99
99
|
| `analyze_reviews` | Sentiment analysis, complaint and feature request extraction |
|
|
100
|
-
| `track_ranking` | App's ranking position across multiple keywords |
|
|
100
|
+
| `track_ranking` | App's ranking position across multiple keywords (each run saves a local snapshot) |
|
|
101
|
+
| `get_ranking_history` | Position trends over time from saved snapshots: daily positions, change, improving/declining per keyword |
|
|
101
102
|
| `keyword_gap` | Keyword difference between two apps + opportunity analysis |
|
|
102
103
|
|
|
103
104
|
### Phase 3: Localization & Reporting
|
|
@@ -9,4 +9,19 @@ export declare function getCacheStats(): {
|
|
|
9
9
|
maxEntries: number;
|
|
10
10
|
dbPath: string;
|
|
11
11
|
};
|
|
12
|
+
export interface RankingSnapshotInput {
|
|
13
|
+
keyword: string;
|
|
14
|
+
position: number | null;
|
|
15
|
+
totalResults: number;
|
|
16
|
+
topApp: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RankingHistoryRow {
|
|
19
|
+
keyword: string;
|
|
20
|
+
position: number | null;
|
|
21
|
+
totalResults: number;
|
|
22
|
+
topApp: string | null;
|
|
23
|
+
recordedAt: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function recordRankingSnapshots(appId: string, country: string, entries: RankingSnapshotInput[]): void;
|
|
26
|
+
export declare function getRankingHistory(appId: string, country: string, days: number, keywords?: string[]): RankingHistoryRow[];
|
|
12
27
|
//# sourceMappingURL=sqlite-cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-cache.d.ts","sourceRoot":"","sources":["../../src/cache/sqlite-cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sqlite-cache.d.ts","sourceRoot":"","sources":["../../src/cache/sqlite-cache.ts"],"names":[],"mappings":"AAYA,wBAAgB,SAAS,IAAI,IAAI,CAsDhC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAevD;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAa,GACxB,IAAI,CAiBN;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,wBAAgB,aAAa,IAAI;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAgBA;AAuBD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,EAAE,GAC9B,IAAI,CAmBN;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,iBAAiB,EAAE,CA8BrB"}
|
|
@@ -4,6 +4,7 @@ import os from "os";
|
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
const MAX_CACHE_ENTRIES = 5000;
|
|
6
6
|
const SIZE_CHECK_INTERVAL = 100;
|
|
7
|
+
const HISTORY_RETENTION_DAYS = 400;
|
|
7
8
|
let db;
|
|
8
9
|
let writesSinceLastCheck = 0;
|
|
9
10
|
export function initCache() {
|
|
@@ -19,11 +20,36 @@ export function initCache() {
|
|
|
19
20
|
key TEXT PRIMARY KEY,
|
|
20
21
|
value TEXT NOT NULL,
|
|
21
22
|
expires_at INTEGER NOT NULL,
|
|
22
|
-
created_at INTEGER DEFAULT (strftime('%s', 'now'))
|
|
23
|
+
created_at INTEGER DEFAULT (strftime('%s', 'now')),
|
|
24
|
+
last_accessed INTEGER DEFAULT (strftime('%s', 'now'))
|
|
23
25
|
)
|
|
24
26
|
`);
|
|
25
|
-
//
|
|
27
|
+
// Migration: pre-1.4.0 databases lack last_accessed (eviction was FIFO).
|
|
28
|
+
const cols = db.prepare("PRAGMA table_info(cache)").all();
|
|
29
|
+
if (!cols.some((c) => c.name === "last_accessed")) {
|
|
30
|
+
db.exec("ALTER TABLE cache ADD COLUMN last_accessed INTEGER DEFAULT 0");
|
|
31
|
+
db.exec("UPDATE cache SET last_accessed = created_at WHERE last_accessed = 0");
|
|
32
|
+
}
|
|
33
|
+
// Ranking history: durable snapshots written by track_ranking, read by
|
|
34
|
+
// get_ranking_history. Lives in the same DB but is NOT part of the cache:
|
|
35
|
+
// clear_cache and LRU eviction never touch it.
|
|
36
|
+
db.exec(`
|
|
37
|
+
CREATE TABLE IF NOT EXISTS ranking_history (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
app_id TEXT NOT NULL,
|
|
40
|
+
keyword TEXT NOT NULL,
|
|
41
|
+
country TEXT NOT NULL,
|
|
42
|
+
position INTEGER,
|
|
43
|
+
total_results INTEGER NOT NULL DEFAULT 0,
|
|
44
|
+
top_app TEXT,
|
|
45
|
+
recorded_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
46
|
+
);
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_ranking_history_lookup
|
|
48
|
+
ON ranking_history (app_id, country, keyword, recorded_at);
|
|
49
|
+
`);
|
|
50
|
+
// Clean up expired entries and stale history
|
|
26
51
|
db.exec(`DELETE FROM cache WHERE expires_at < strftime('%s', 'now')`);
|
|
52
|
+
db.prepare("DELETE FROM ranking_history WHERE recorded_at < strftime('%s', 'now') - ?").run(HISTORY_RETENTION_DAYS * 86400);
|
|
27
53
|
// Enforce size limit on startup
|
|
28
54
|
enforceSizeLimit();
|
|
29
55
|
}
|
|
@@ -31,11 +57,15 @@ export function getFromCache(key) {
|
|
|
31
57
|
const row = db
|
|
32
58
|
.prepare("SELECT value FROM cache WHERE key = ? AND expires_at > strftime('%s', 'now')")
|
|
33
59
|
.get(key);
|
|
60
|
+
if (row) {
|
|
61
|
+
// Touch for LRU eviction ordering
|
|
62
|
+
db.prepare("UPDATE cache SET last_accessed = strftime('%s', 'now') WHERE key = ?").run(key);
|
|
63
|
+
}
|
|
34
64
|
return row?.value ?? null;
|
|
35
65
|
}
|
|
36
66
|
export function setCache(key, value, ttlSeconds = 3600) {
|
|
37
67
|
const expiresAt = Math.floor(Date.now() / 1000) + ttlSeconds;
|
|
38
|
-
db.prepare("INSERT OR REPLACE INTO cache (key, value, expires_at) VALUES (?, ?,
|
|
68
|
+
db.prepare("INSERT OR REPLACE INTO cache (key, value, expires_at, last_accessed) VALUES (?, ?, ?, strftime('%s', 'now'))").run(key, value, expiresAt);
|
|
39
69
|
// Throttle: only check size every SIZE_CHECK_INTERVAL writes (avoids O(N) COUNT per write).
|
|
40
70
|
writesSinceLastCheck++;
|
|
41
71
|
if (writesSinceLastCheck >= SIZE_CHECK_INTERVAL) {
|
|
@@ -71,11 +101,44 @@ function enforceSizeLimit() {
|
|
|
71
101
|
db.exec(`DELETE FROM cache WHERE expires_at < strftime('%s', 'now')`);
|
|
72
102
|
const count = db.prepare("SELECT COUNT(*) as count FROM cache").get().count;
|
|
73
103
|
if (count > MAX_CACHE_ENTRIES) {
|
|
74
|
-
// Remove
|
|
104
|
+
// Remove least recently used entries to get back under limit
|
|
75
105
|
const toRemove = count - MAX_CACHE_ENTRIES;
|
|
76
106
|
db.prepare(`DELETE FROM cache WHERE key IN (
|
|
77
|
-
SELECT key FROM cache ORDER BY created_at ASC LIMIT ?
|
|
107
|
+
SELECT key FROM cache ORDER BY last_accessed ASC, created_at ASC LIMIT ?
|
|
78
108
|
)`).run(toRemove);
|
|
79
109
|
}
|
|
80
110
|
}
|
|
111
|
+
export function recordRankingSnapshots(appId, country, entries) {
|
|
112
|
+
if (entries.length === 0)
|
|
113
|
+
return;
|
|
114
|
+
const insert = db.prepare(`INSERT INTO ranking_history (app_id, keyword, country, position, total_results, top_app)
|
|
115
|
+
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
116
|
+
const insertAll = db.transaction((rows) => {
|
|
117
|
+
for (const r of rows) {
|
|
118
|
+
insert.run(appId, r.keyword.trim().toLowerCase(), country, r.position, r.totalResults, r.topApp);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
insertAll(entries);
|
|
122
|
+
}
|
|
123
|
+
export function getRankingHistory(appId, country, days, keywords) {
|
|
124
|
+
const cutoff = Math.floor(Date.now() / 1000) - days * 86400;
|
|
125
|
+
let sql = `SELECT keyword, position, total_results, top_app, recorded_at
|
|
126
|
+
FROM ranking_history
|
|
127
|
+
WHERE app_id = ? AND country = ? AND recorded_at >= ?`;
|
|
128
|
+
const params = [appId, country, cutoff];
|
|
129
|
+
if (keywords && keywords.length > 0) {
|
|
130
|
+
const placeholders = keywords.map(() => "?").join(",");
|
|
131
|
+
sql += ` AND keyword IN (${placeholders})`;
|
|
132
|
+
params.push(...keywords.map((k) => k.trim().toLowerCase()));
|
|
133
|
+
}
|
|
134
|
+
sql += " ORDER BY keyword ASC, recorded_at ASC";
|
|
135
|
+
const rows = db.prepare(sql).all(...params);
|
|
136
|
+
return rows.map((r) => ({
|
|
137
|
+
keyword: r.keyword,
|
|
138
|
+
position: r.position,
|
|
139
|
+
totalResults: r.total_results,
|
|
140
|
+
topApp: r.top_app,
|
|
141
|
+
recordedAt: r.recorded_at,
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
81
144
|
//# sourceMappingURL=sqlite-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-cache.js","sourceRoot":"","sources":["../../src/cache/sqlite-cache.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-cache.js","sourceRoot":"","sources":["../../src/cache/sqlite-cache.ts"],"names":[],"mappings":"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"}
|
package/build/server.js
CHANGED
|
@@ -14,6 +14,7 @@ import { registerAnalyzeCompetitors } from "./tools/analyze-competitors.js";
|
|
|
14
14
|
import { registerOptimizeMetadata } from "./tools/optimize-metadata.js";
|
|
15
15
|
import { registerAnalyzeReviews } from "./tools/analyze-reviews.js";
|
|
16
16
|
import { registerTrackRanking } from "./tools/track-ranking.js";
|
|
17
|
+
import { registerGetRankingHistory } from "./tools/get-ranking-history.js";
|
|
17
18
|
import { registerKeywordGap } from "./tools/keyword-gap.js";
|
|
18
19
|
// Phase 3 tools
|
|
19
20
|
import { registerLocalizedKeywords } from "./tools/localized-keywords.js";
|
|
@@ -49,6 +50,7 @@ registerAnalyzeCompetitors(server);
|
|
|
49
50
|
registerOptimizeMetadata(server);
|
|
50
51
|
registerAnalyzeReviews(server);
|
|
51
52
|
registerTrackRanking(server);
|
|
53
|
+
registerGetRankingHistory(server);
|
|
52
54
|
registerKeywordGap(server);
|
|
53
55
|
// Register Phase 3 tools
|
|
54
56
|
registerLocalizedKeywords(server);
|
package/build/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-ranking-history.d.ts","sourceRoot":"","sources":["../../src/tools/get-ranking-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBpE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,QAyK1D"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getRankingHistory } from "../cache/sqlite-cache.js";
|
|
3
|
+
// Position used for trend math when the app is not in the top 100.
|
|
4
|
+
// Keeps "ranked 80 -> not ranked" registering as a decline instead of a gap.
|
|
5
|
+
const NOT_RANKED_POSITION = 101;
|
|
6
|
+
function toDate(unixSeconds) {
|
|
7
|
+
return new Date(unixSeconds * 1000).toISOString().slice(0, 10);
|
|
8
|
+
}
|
|
9
|
+
export function registerGetRankingHistory(server) {
|
|
10
|
+
server.tool("get_ranking_history", "Shows how an app's keyword rankings changed over time, based on snapshots saved locally by previous track_ranking runs. Returns per-keyword daily positions, best/worst, change, and trend (improving/declining/stable). Run track_ranking regularly to build history.", {
|
|
11
|
+
appId: z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.describe("App Store app ID or bundle ID (same value used in track_ranking)"),
|
|
15
|
+
country: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(2)
|
|
18
|
+
.max(5)
|
|
19
|
+
.default("tr")
|
|
20
|
+
.describe("Country code"),
|
|
21
|
+
days: z
|
|
22
|
+
.number()
|
|
23
|
+
.min(1)
|
|
24
|
+
.max(365)
|
|
25
|
+
.default(30)
|
|
26
|
+
.describe("How many days of history to include"),
|
|
27
|
+
keywords: z
|
|
28
|
+
.array(z.string().min(1))
|
|
29
|
+
.max(20)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Optional keyword filter. Omit to include all tracked keywords."),
|
|
32
|
+
}, async ({ appId, country, days, keywords }) => {
|
|
33
|
+
try {
|
|
34
|
+
const rows = getRankingHistory(appId.trim().toLowerCase(), country.toLowerCase(), days, keywords);
|
|
35
|
+
if (rows.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: JSON.stringify({
|
|
41
|
+
appId,
|
|
42
|
+
country,
|
|
43
|
+
days,
|
|
44
|
+
totalSnapshots: 0,
|
|
45
|
+
message: "No ranking history found for this app/country in the given period. Run track_ranking first; each run saves a snapshot.",
|
|
46
|
+
}, null, 2),
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Group rows by keyword, then collapse to one point per day
|
|
52
|
+
// (last snapshot of the day wins) to keep the output compact.
|
|
53
|
+
const byKeyword = new Map();
|
|
54
|
+
for (const row of rows) {
|
|
55
|
+
const list = byKeyword.get(row.keyword) ?? [];
|
|
56
|
+
list.push(row);
|
|
57
|
+
byKeyword.set(row.keyword, list);
|
|
58
|
+
}
|
|
59
|
+
const keywordHistories = [...byKeyword.entries()].map(([keyword, kwRows]) => {
|
|
60
|
+
const daily = new Map();
|
|
61
|
+
for (const r of kwRows) {
|
|
62
|
+
const date = toDate(r.recordedAt);
|
|
63
|
+
daily.set(date, {
|
|
64
|
+
date,
|
|
65
|
+
position: r.position,
|
|
66
|
+
totalResults: r.totalResults,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const points = [...daily.values()];
|
|
70
|
+
const ranked = points.filter((p) => p.position !== null);
|
|
71
|
+
const bestPosition = ranked.length > 0
|
|
72
|
+
? Math.min(...ranked.map((p) => p.position))
|
|
73
|
+
: null;
|
|
74
|
+
const worstPosition = ranked.length > 0
|
|
75
|
+
? Math.max(...ranked.map((p) => p.position))
|
|
76
|
+
: null;
|
|
77
|
+
const first = points[0];
|
|
78
|
+
const last = points[points.length - 1];
|
|
79
|
+
const eff = (p) => p ?? NOT_RANKED_POSITION;
|
|
80
|
+
let trend;
|
|
81
|
+
let positionChange = null;
|
|
82
|
+
if (points.length < 2) {
|
|
83
|
+
trend = "insufficient-data";
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
positionChange = eff(first.position) - eff(last.position);
|
|
87
|
+
trend =
|
|
88
|
+
positionChange > 0
|
|
89
|
+
? "improving"
|
|
90
|
+
: positionChange < 0
|
|
91
|
+
? "declining"
|
|
92
|
+
: "stable";
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
keyword,
|
|
96
|
+
snapshots: points,
|
|
97
|
+
latestPosition: last.position,
|
|
98
|
+
firstPosition: first.position,
|
|
99
|
+
bestPosition,
|
|
100
|
+
worstPosition,
|
|
101
|
+
positionChange,
|
|
102
|
+
trend,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
// Best mover: largest positive change
|
|
106
|
+
const movers = keywordHistories.filter((k) => k.positionChange !== null && k.positionChange > 0);
|
|
107
|
+
const bestMover = movers.length > 0
|
|
108
|
+
? movers.sort((a, b) => b.positionChange - a.positionChange)[0]
|
|
109
|
+
: null;
|
|
110
|
+
const result = {
|
|
111
|
+
appId,
|
|
112
|
+
country,
|
|
113
|
+
days,
|
|
114
|
+
totalSnapshots: rows.length,
|
|
115
|
+
keywordsTracked: keywordHistories.length,
|
|
116
|
+
summary: {
|
|
117
|
+
improving: keywordHistories.filter((k) => k.trend === "improving")
|
|
118
|
+
.length,
|
|
119
|
+
declining: keywordHistories.filter((k) => k.trend === "declining")
|
|
120
|
+
.length,
|
|
121
|
+
stable: keywordHistories.filter((k) => k.trend === "stable").length,
|
|
122
|
+
insufficientData: keywordHistories.filter((k) => k.trend === "insufficient-data").length,
|
|
123
|
+
bestMover: bestMover
|
|
124
|
+
? {
|
|
125
|
+
keyword: bestMover.keyword,
|
|
126
|
+
improvedBy: bestMover.positionChange,
|
|
127
|
+
latestPosition: bestMover.latestPosition,
|
|
128
|
+
}
|
|
129
|
+
: null,
|
|
130
|
+
},
|
|
131
|
+
keywords: keywordHistories,
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
content: [
|
|
135
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
142
|
+
isError: true,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=get-ranking-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-ranking-history.js","sourceRoot":"","sources":["../../src/tools/get-ranking-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-keywords.d.ts","sourceRoot":"","sources":["../../src/tools/suggest-keywords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAapE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"suggest-keywords.d.ts","sourceRoot":"","sources":["../../src/tools/suggest-keywords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAapE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,QA+GxD"}
|
|
@@ -54,7 +54,11 @@ export function registerSuggestKeywords(server) {
|
|
|
54
54
|
const uniqueKeywords = [
|
|
55
55
|
...new Set(Object.values(allKeywords).flat()),
|
|
56
56
|
];
|
|
57
|
-
const
|
|
57
|
+
const SCORE_LIMIT = 30;
|
|
58
|
+
const scoredKeywords = await batchGetScores(uniqueKeywords.slice(0, SCORE_LIMIT), country);
|
|
59
|
+
const truncationNote = uniqueKeywords.length > SCORE_LIMIT
|
|
60
|
+
? `Scored the first ${SCORE_LIMIT} of ${uniqueKeywords.length} unique keywords. The rest are listed unscored under 'strategies'.`
|
|
61
|
+
: undefined;
|
|
58
62
|
// Sort by traffic
|
|
59
63
|
scoredKeywords.sort((a, b) => b.traffic - a.traffic);
|
|
60
64
|
const scoresSource = summarizeScoresSource(scoredKeywords);
|
|
@@ -63,6 +67,7 @@ export function registerSuggestKeywords(server) {
|
|
|
63
67
|
country,
|
|
64
68
|
scoresSource,
|
|
65
69
|
scoresNote: scoresSourceNote(scoresSource),
|
|
70
|
+
truncationNote,
|
|
66
71
|
strategies: allKeywords,
|
|
67
72
|
scoredKeywords,
|
|
68
73
|
totalUniqueKeywords: uniqueKeywords.length,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-keywords.js","sourceRoot":"","sources":["../../src/tools/suggest-keywords.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"suggest-keywords.js","sourceRoot":"","sources":["../../src/tools/suggest-keywords.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-ranking.d.ts","sourceRoot":"","sources":["../../src/tools/track-ranking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"track-ranking.d.ts","sourceRoot":"","sources":["../../src/tools/track-ranking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,QA4HrD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { searchApps } from "../data-sources/app-store.js";
|
|
3
|
-
import { getFromCache, setCache } from "../cache/sqlite-cache.js";
|
|
3
|
+
import { getFromCache, setCache, recordRankingSnapshots, } from "../cache/sqlite-cache.js";
|
|
4
4
|
import { CACHE_TTL } from "../utils/constants.js";
|
|
5
5
|
export function registerTrackRanking(server) {
|
|
6
6
|
server.tool("track_ranking", "Finds an app's ranking position for specific keywords. Shows the app's position within the top 100 results for each keyword.", {
|
|
@@ -67,6 +67,10 @@ export function registerTrackRanking(server) {
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
}));
|
|
70
|
+
// Persist snapshots for trend analysis (get_ranking_history).
|
|
71
|
+
// Failed searches are not data points, so they are skipped.
|
|
72
|
+
const validRankings = rankings.filter((r) => r.topApp !== "Error");
|
|
73
|
+
recordRankingSnapshots(appId.trim().toLowerCase(), country.toLowerCase(), validRankings);
|
|
70
74
|
// Summary
|
|
71
75
|
const found = rankings.filter((r) => r.position !== null);
|
|
72
76
|
const top10 = found.filter((r) => r.position <= 10);
|
|
@@ -88,6 +92,8 @@ export function registerTrackRanking(server) {
|
|
|
88
92
|
? found.sort((a, b) => a.position - b.position)[0].keyword
|
|
89
93
|
: null,
|
|
90
94
|
},
|
|
95
|
+
snapshotsRecorded: validRankings.length,
|
|
96
|
+
historyHint: "Snapshots saved locally. Use get_ranking_history to see position trends over time.",
|
|
91
97
|
};
|
|
92
98
|
const resultText = JSON.stringify(result, null, 2);
|
|
93
99
|
setCache(cacheKey, resultText, CACHE_TTL.SEARCH_RESULTS);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-ranking.js","sourceRoot":"","sources":["../../src/tools/track-ranking.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"track-ranking.js","sourceRoot":"","sources":["../../src/tools/track-ranking.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,8HAA8H,EAC9H;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,2DAA2D,CAAC;QACxE,QAAQ,EAAE,CAAC;aACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aACxB,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,QAAQ,CAAC,oCAAoC,CAAC;QACjD,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC;aACN,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,cAAc,CAAC;KAC5B,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACrC,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;aAClC,IAAI,EAAE;aACN,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,MAAM,QAAQ,GAAG,WAAW,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAClG,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QAChE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAExD,+DAA+D;YAC/D,oEAAoE;YACpE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC7B,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;oBAExD,mEAAmE;oBACnE,IAAI,QAAQ,GAAkB,IAAI,CAAC;oBACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAQ,CAAC;wBACjC,MAAM,cAAc,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;wBAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;wBACzC,MAAM,WAAW,GACf,CAAC,CAAC,cAAc,IAAI,cAAc,KAAK,kBAAkB,CAAC;wBAC5D,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,QAAQ,KAAK,YAAY,CAAC;wBAC5D,IAAI,WAAW,IAAI,OAAO,EAAE,CAAC;4BAC3B,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC;4BACjB,MAAM;wBACR,CAAC;oBACH,CAAC;oBAED,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAQ,CAAC;oBACpC,OAAO;wBACL,OAAO;wBACP,QAAQ;wBACR,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,SAAS;wBACrC,YAAY,EAAE,OAAO,CAAC,MAAM;qBAC7B,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO;wBACL,OAAO;wBACP,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,OAAO;wBACf,YAAY,EAAE,CAAC;qBAChB,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CACH,CAAC;YAEF,8DAA8D;YAC9D,4DAA4D;YAC5D,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;YACnE,sBAAsB,CACpB,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAC1B,OAAO,CAAC,WAAW,EAAE,EACrB,aAAa,CACd,CAAC;YAEF,UAAU;YACV,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAS,IAAI,EAAE,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAS,IAAI,EAAE,CAAC,CAAC;YAErD,MAAM,MAAM,GAAG;gBACb,KAAK;gBACL,OAAO;gBACP,aAAa,EAAE,QAAQ,CAAC,MAAM;gBAC9B,QAAQ;gBACR,OAAO,EAAE;oBACP,cAAc,EAAE,KAAK,CAAC,MAAM;oBAC5B,SAAS,EAAE,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;oBACzC,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC;wBAC5B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC;wBAC5C,CAAC,CAAC,IAAI;oBACR,WAAW,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC;wBAC3B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAS,GAAG,CAAC,CAAC,QAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;wBAC5D,CAAC,CAAC,IAAI;iBACT;gBACD,iBAAiB,EAAE,aAAa,CAAC,MAAM;gBACvC,WAAW,EACT,oFAAoF;aACvF,CAAC;YAEF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACnD,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;YAEzD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QACpE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBACrE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|