appstore-api-mcp 1.8.1 → 1.9.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/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ All notable changes to this project are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/) and the project uses
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [1.9.1] - 2026-06-02
8
+
9
+ ### Added
10
+ - **ASO research prompt pack** in `docs/RECIPES.md` — keyword expansion,
11
+ competitor positioning, and localized keyword spread, each ending in a dry-run
12
+ apply (the research is agent-side; App Store Connect exposes no competitor data).
13
+
14
+ ## [1.9.0] - 2026-06-02
15
+
16
+ ### Added
17
+ - **`release_readiness_check`** — one-call go/no-go report (build, metadata, ASO,
18
+ screenshots, compliance, TestFlight, reviews).
19
+ - **`aso_opportunity_report`** — ranked easiest ASO wins across apps.
20
+ - **`portfolio_growth_report`** — units sold per app from a Sales report.
21
+ - **TestFlight actions:** `add_build_to_beta_group`, `submit_beta_review`.
22
+ - **`docs/RECIPES.md`** — copy-paste workflow prompts (prepare-version,
23
+ release-train-with-gates, readiness check, reviews→notes, portfolio operator,
24
+ build & ship), linked from the README.
25
+
7
26
  ## [1.8.1] - 2026-06-02
8
27
 
9
28
  ### Changed
package/README.md CHANGED
@@ -50,7 +50,7 @@ whatever AI agent you already use.
50
50
  - [Getting your API key](#getting-your-api-key) → full guide in [docs/SETUP.md](docs/SETUP.md)
51
51
  - [Configuration](#configuration)
52
52
  - [Tools](#tools) → full reference in [docs/TOOLS.md](docs/TOOLS.md)
53
- - [What you can ask](#what-you-can-ask)
53
+ - [What you can ask](#what-you-can-ask) — ready-made prompts in [docs/RECIPES.md](docs/RECIPES.md)
54
54
  - [Analytics & reports setup](docs/ANALYTICS.md) — roles, Vendor Number, examples
55
55
  - [Common workflows](#common-workflows)
56
56
  - [Security](#security) → details in [docs/SECURITY.md](docs/SECURITY.md)
@@ -245,6 +245,9 @@ Full parameter reference: **[docs/TOOLS.md](docs/TOOLS.md)**.
245
245
  | `audit_apps` | 🩺 **Fleet ASO audit** — scan all apps for missing subtitle/keywords/description, under-used keyword field, single-locale listings, missing screenshots. Read-only |
246
246
  | `apps_review_status` | 🗂️ **Fleet review board** — every app's current version + state (waiting / in-review / rejected / ready) in one call |
247
247
  | `submit_for_review` / `release_version` / `set_phased_release` | 🚀 Submit a version to Apple review (full flow), release an approved build, and control phased rollout |
248
+ | `release_readiness_check` | ✅ One-call **go/no-go report** — build, metadata, ASO, screenshots, compliance, TestFlight, reviews |
249
+ | `aso_opportunity_report` / `portfolio_growth_report` | 📈 Rank the easiest **ASO wins** across all apps; portfolio snapshot of units sold per app |
250
+ | `add_build_to_beta_group` / `submit_beta_review` | ✈️ Assign a build to a TestFlight group; submit for beta review |
248
251
  | `get_sales_report` / `get_subscription_report` / `get_finance_report` | 📊 Units/downloads, proceeds, **subscriptions & retention**, earnings by region. Needs a Vendor Number + Admin/Finance/Sales key |
249
252
  | `request_analytics_report` → `list_analytics_reports` → `list_analytics_report_instances` → `get_analytics_report_data` | 📈 The async Analytics Reports API — downloads, sessions, active devices, App Store engagement |
250
253
  | `list_customer_reviews` / `reply_to_customer_review` | ⭐ Read reviews (filter by rating/territory, shows if you've replied) and post public replies |
@@ -0,0 +1,126 @@
1
+ # Recipes — copy-paste workflow prompts
2
+
3
+ These are ready-made prompts you can paste into your agent. They chain the
4
+ server's tools into real workflows. **Replace `AppName` / `1.4.0` with yours.**
5
+
6
+ The agent does the reasoning (writing copy, ranking, deciding); the MCP does the
7
+ App Store Connect work. Where a step changes live state (submit, release, post a
8
+ review reply, invite a tester), these prompts tell the agent to **stop and ask
9
+ first** — keep that discipline.
10
+
11
+ ---
12
+
13
+ ## 1. Prepare the next version
14
+
15
+ ```text
16
+ Prepare version 1.4.0 for AppName. Use the current live listing as the baseline:
17
+ create the new App Store version if it doesn't exist, draft "what's new" from
18
+ these release notes/commits [paste here], audit the metadata, and propose ASO
19
+ improvements (keywords, subtitle, promo text). Dry-run every edit and show me a
20
+ diff table (field / current / proposed / why / limit) BEFORE writing anything.
21
+ ```
22
+
23
+ Uses: `list_app_store_versions`, `create_app_store_version`,
24
+ `update_app_store_version_localization` (with `dryRun`), `audit_apps`,
25
+ `aso_opportunity_report`.
26
+
27
+ ## 2. Release readiness check
28
+
29
+ ```text
30
+ Is AppName v1.4.0 ready to submit? Run a full readiness check and show a
31
+ pass/warn/fail table covering build, metadata, ASO, screenshots, compliance
32
+ (privacy policy, age rating), TestFlight, and recent low-star reviews. List the
33
+ blockers first.
34
+ ```
35
+
36
+ Uses: `release_readiness_check` (single call), or the individual tools.
37
+
38
+ ## 3. Release train — with approval gates
39
+
40
+ ```text
41
+ Promote the latest processed build of AppName v1.4.0 to TestFlight internal
42
+ testers. Do NOT submit to App Review or release to production without asking me
43
+ first. Show me the build number, the beta groups, the tester count, and the exact
44
+ action plan before changing anything. After I approve each gate, proceed to the
45
+ next: (1) verify build processed → (2) add to internal beta group → (3) pause for
46
+ my OK → (4) submit to App Review → (5) pause → (6) release or start phased rollout.
47
+ ```
48
+
49
+ Uses: `list_builds`, `list_beta_groups`, `list_beta_testers`,
50
+ `add_build_to_beta_group`, `submit_beta_review`, `submit_for_review`,
51
+ `release_version`, `set_phased_release`. **Stops at each human gate.**
52
+
53
+ ## 4. Customer reviews → release notes loop
54
+
55
+ ```text
56
+ Summarize recent 1–3 star reviews for AppName, cluster the complaints by theme,
57
+ and suggest fixes to mention in the next release notes. Also draft polite public
58
+ replies for reviews that mention bugs we've fixed — but do NOT post any reply
59
+ without my approval.
60
+ ```
61
+
62
+ Uses: `list_customer_reviews`, `reply_to_customer_review` (only after approval),
63
+ `update_app_store_version_localization` (for the what's-new).
64
+
65
+ ## 5. Portfolio operator — weekly ASO wins
66
+
67
+ ```text
68
+ Audit all my apps and rank the top 10 easiest ASO wins. For each, show app,
69
+ issue, suggested fix, and rough effort (low/medium). Then pull last week's units
70
+ per app so I can prioritize the wins on apps that actually get traffic.
71
+ ```
72
+
73
+ Uses: `aso_opportunity_report`, `audit_apps`, `portfolio_growth_report`,
74
+ `get_sales_report`.
75
+
76
+ ## 6. ASO research → dry-run apply
77
+
78
+ The App Store Connect API has no competitor or keyword-volume data, so the
79
+ **research** is the agent's job (web/app-page reading or an ASO API you have).
80
+ This MCP handles reading your current listing and applying the result safely.
81
+
82
+ **a) Keyword expansion**
83
+ ```text
84
+ For AppName, show the current keyword field and how many of the 100 characters
85
+ are used. Research 10–15 high-intent keywords for this app's category (use web
86
+ search if available), pick the best set that fits 100 chars without duplicating
87
+ words already in the title/subtitle, and dry-run the new keyword field so I can
88
+ approve before it's written.
89
+ ```
90
+
91
+ **b) Competitor positioning**
92
+ ```text
93
+ Here are 3 competitors for AppName: [App A], [App B], [App C]. Look at their App
94
+ Store titles, subtitles, and how they position the app. Compare to AppName's
95
+ current title/subtitle/keywords, point out gaps, and propose an improved subtitle
96
+ (<=30 chars) and keyword set. Dry-run the changes; don't write until I confirm.
97
+ ```
98
+
99
+ **c) Localized keyword spread**
100
+ ```text
101
+ AppName ranks only in en-US. Propose localized keyword sets for en-GB, en-CA, and
102
+ en-AU that use each store's keyword field for *additional* terms (a known ASO
103
+ trick — extra locales add searchable keywords). Dry-run a bulk localization update
104
+ across those locales and show me the diff first.
105
+ ```
106
+
107
+ Uses: `get_app_store_version_localization`, `list_app_info_localizations`,
108
+ `update_app_store_version_localization` (with `dryRun`),
109
+ `bulk_update_version_localizations`, `aso_opportunity_report`.
110
+
111
+ ## 7. Build & ship (Mac only)
112
+
113
+ ```text
114
+ Bump AppName's build number, archive it, and upload the new build to App Store
115
+ Connect. Tell me the new build number and confirm the upload succeeded. Don't
116
+ submit for review yet.
117
+ ```
118
+
119
+ Uses: `bump_build_number`, `archive_app`, `upload_build`, then `list_builds`.
120
+ Requires macOS + Xcode and the project path.
121
+
122
+ ---
123
+
124
+ > **Tip:** these are starting points — tweak the gates and outputs to taste. For a
125
+ > first run, keep the "ask before any write" instruction so you can watch what the
126
+ > agent proposes before it changes anything live.
package/docs/TOOLS.md CHANGED
@@ -389,6 +389,28 @@ Lists certificates and provisioning profiles, flagging expired/expiring (within
389
389
  ### list_game_center_leaderboards / list_game_center_achievements
390
390
  - `appId` **(required)** — requires Game Center enabled on the app.
391
391
 
392
+ ## Recipes & aggregators (read-only)
393
+
394
+ ### release_readiness_check
395
+ - `appId` **(required)** — returns `{ app, ready, verdict, summary, checks[] }` (each check has `area`, `status` pass/warn/fail/info, `detail`).
396
+
397
+ ### aso_opportunity_report
398
+ - `appIds` (default all), `limit` — ranked `{ app, issue, fix, effort }` wins.
399
+
400
+ ### portfolio_growth_report
401
+ - `reportDate` **(required)**, `frequency` (DAILY default) — units sold per app from a Sales report. Needs a Vendor Number + report-capable key.
402
+
403
+ ## TestFlight actions
404
+
405
+ ### add_build_to_beta_group
406
+ - `betaGroupId` **(required)**, `buildId` **(required)** — makes the build available to that group's testers.
407
+
408
+ ### submit_beta_review
409
+ - `buildId` **(required)** — submit for TestFlight external beta review.
410
+
411
+ > See **[RECIPES.md](RECIPES.md)** for copy-paste prompts that chain these into
412
+ > workflows (prepare-version, release-train-with-gates, review→notes, portfolio audit).
413
+
392
414
  ## Build & ship (macOS + Xcode)
393
415
 
394
416
  These run local Xcode tooling, so they only work on a Mac with Xcode installed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appstore-api-mcp",
3
- "version": "1.8.1",
3
+ "version": "1.9.1",
4
4
  "description": "MCP server for Apple App Store Connect — edit listings (keywords, descriptions, titles, screenshots), track analytics (downloads, proceeds, subscriptions, retention), run a fleet-wide ASO audit, preview changes with dry-run, and reach the full API. Works with any MCP client (Claude, Codex, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Antigravity, Amazon Q, Goose, and more).",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -2065,6 +2065,206 @@ const tools = [
2065
2065
  },
2066
2066
  },
2067
2067
 
2068
+ // ---- Recipes & aggregators (read-only) ----
2069
+ {
2070
+ name: "release_readiness_check",
2071
+ description:
2072
+ "A go/no-go readiness report for an app: latest build state, listing metadata completeness, ASO (subtitle, keyword usage), screenshots, compliance (privacy policy), TestFlight groups, and recent low-star reviews. Read-only — writes nothing. Great before submitting.",
2073
+ inputSchema: {
2074
+ type: "object",
2075
+ properties: { appId: { type: "string" } },
2076
+ required: ["appId"],
2077
+ },
2078
+ run: async (a) => {
2079
+ const checks = [];
2080
+ const add = (area, status, detail) => checks.push({ area, status, detail });
2081
+ const app = await client.get(`/apps/${a.appId}`);
2082
+ const primaryLocale = app.data.attributes.primaryLocale;
2083
+ try {
2084
+ const builds = await client.getAll(`/builds`, { "filter[app]": a.appId, sort: "-version", limit: 1 });
2085
+ if (builds.length) {
2086
+ const b = builds[0].attributes;
2087
+ add("Build", b.processingState === "VALID" ? "pass" : "warn", `latest v${b.version} — ${b.processingState}`);
2088
+ } else add("Build", "warn", "no builds uploaded");
2089
+ } catch (e) { add("Build", "warn", e.message.slice(0, 60)); }
2090
+
2091
+ const versions = await client.getAll(`/apps/${a.appId}/appStoreVersions`, { limit: 5 });
2092
+ const ed = versions.find((v) => EDITABLE_VERSION_STATES.has(v.attributes.appStoreState)) || versions[0];
2093
+ add("Version", ed ? "info" : "warn", ed ? `v${ed.attributes.versionString} — ${ed.attributes.appStoreState}` : "no version");
2094
+ if (ed) {
2095
+ const locs = await client.getAll(`/appStoreVersions/${ed.id}/appStoreVersionLocalizations`);
2096
+ const loc = locs.find((l) => l.attributes.locale === primaryLocale) || locs[0];
2097
+ const at = (loc && loc.attributes) || {};
2098
+ add("Description", at.description ? "pass" : "fail", at.description ? "present" : "missing");
2099
+ const kw = (at.keywords || "").trim();
2100
+ add("Keywords", kw ? (kw.length >= 70 ? "pass" : "warn") : "fail", kw ? `${kw.length}/100 chars` : "empty");
2101
+ add("What's New", at.whatsNew ? "pass" : "warn", at.whatsNew ? "present" : "missing");
2102
+ add("Support URL", at.supportUrl ? "pass" : "warn", at.supportUrl ? "set" : "missing");
2103
+ if (loc) {
2104
+ let shots = 0;
2105
+ const sets = await client.getAll(`/appStoreVersionLocalizations/${loc.id}/appScreenshotSets`);
2106
+ for (const s of sets) shots += (await client.getAll(`/appScreenshotSets/${s.id}/appScreenshots`)).length;
2107
+ add("Screenshots", shots > 0 ? "pass" : "fail", `${shots} on ${loc.attributes.locale}`);
2108
+ }
2109
+ }
2110
+ try {
2111
+ const infos = await client.getAll(`/apps/${a.appId}/appInfos`);
2112
+ if (infos.length) {
2113
+ const il = await client.getAll(`/appInfos/${infos[0].id}/appInfoLocalizations`);
2114
+ const ilc = il.find((x) => x.attributes.locale === primaryLocale) || il[0];
2115
+ add("Subtitle", ilc?.attributes?.subtitle ? "pass" : "warn", ilc?.attributes?.subtitle ? "present" : "missing (free ASO keywords)");
2116
+ add("Privacy policy", ilc?.attributes?.privacyPolicyUrl ? "pass" : "warn", ilc?.attributes?.privacyPolicyUrl ? "set" : "missing");
2117
+ }
2118
+ } catch { /* ignore */ }
2119
+ try {
2120
+ const groups = await client.getAll(`/apps/${a.appId}/betaGroups`);
2121
+ add("TestFlight", groups.length ? "pass" : "info", `${groups.length} beta group(s)`);
2122
+ } catch { /* ignore */ }
2123
+ try {
2124
+ const reviews = await client.getAll(`/apps/${a.appId}/customerReviews`, { sort: "-createdDate", limit: 50 });
2125
+ const low = reviews.filter((r) => (r.attributes.rating ?? 5) <= 2).length;
2126
+ add("Reviews", low > 0 ? "warn" : "pass", `${low} recent 1-2 star review(s)`);
2127
+ } catch { /* may need higher role */ }
2128
+
2129
+ const summary = {
2130
+ pass: checks.filter((c) => c.status === "pass").length,
2131
+ warn: checks.filter((c) => c.status === "warn").length,
2132
+ fail: checks.filter((c) => c.status === "fail").length,
2133
+ };
2134
+ const ready = summary.fail === 0;
2135
+ return {
2136
+ app: app.data.attributes.name,
2137
+ ready,
2138
+ verdict: ready ? (summary.warn ? "Ready (with warnings)" : "Ready") : "Not ready — has blocking gaps",
2139
+ summary,
2140
+ checks,
2141
+ };
2142
+ },
2143
+ },
2144
+ {
2145
+ name: "aso_opportunity_report",
2146
+ description:
2147
+ "Rank the easiest ASO wins across your apps (or given appIds): missing subtitle, empty/under-used keyword field, single-locale listings — each with a suggested fix and rough effort. Read-only.",
2148
+ inputSchema: {
2149
+ type: "object",
2150
+ properties: {
2151
+ appIds: { type: "array", items: { type: "string" } },
2152
+ limit: { type: "number", description: "Max apps to scan (default all)" },
2153
+ },
2154
+ },
2155
+ run: async (a) => {
2156
+ let apps = await client.getAll("/apps", { limit: 200 });
2157
+ if (a.appIds?.length) apps = apps.filter((x) => a.appIds.includes(x.id));
2158
+ if (a.limit) apps = apps.slice(0, a.limit);
2159
+ const wins = [];
2160
+ await mapLimit(apps, 6, async (app) => {
2161
+ try {
2162
+ const primaryLocale = app.attributes.primaryLocale;
2163
+ const infos = await client.getAll(`/apps/${app.id}/appInfos`);
2164
+ let subtitle = null;
2165
+ if (infos.length) {
2166
+ const il = await client.getAll(`/appInfos/${infos[0].id}/appInfoLocalizations`);
2167
+ const ilc = il.find((x) => x.attributes.locale === primaryLocale) || il[0];
2168
+ subtitle = ilc?.attributes?.subtitle;
2169
+ }
2170
+ const versions = await client.getAll(`/apps/${app.id}/appStoreVersions`, { limit: 5 });
2171
+ const ed = versions.find((v) => EDITABLE_VERSION_STATES.has(v.attributes.appStoreState)) || versions[0];
2172
+ if (!ed) return;
2173
+ const locs = await client.getAll(`/appStoreVersions/${ed.id}/appStoreVersionLocalizations`);
2174
+ const loc = locs.find((l) => l.attributes.locale === primaryLocale) || locs[0];
2175
+ const kw = (loc?.attributes?.keywords || "").trim();
2176
+ const name = app.attributes.name;
2177
+ if (!subtitle) wins.push({ app: name, appId: app.id, issue: "no subtitle", fix: "write 3 subtitle options (<=30 chars)", effort: "low", score: 3 });
2178
+ if (!kw) wins.push({ app: name, appId: app.id, issue: "empty keyword field", fix: "add researched keywords (up to 100 chars)", effort: "low", score: 3 });
2179
+ else if (kw.length < 70) wins.push({ app: name, appId: app.id, issue: `keyword field ${kw.length}/100 chars`, fix: `add ~${Math.max(1, Math.round((100 - kw.length) / 12))} more terms`, effort: "low", score: 2 });
2180
+ if (locs.length <= 1) wins.push({ app: name, appId: app.id, issue: "only one locale", fix: "add en-GB / en-CA or a major market", effort: "medium", score: 2 });
2181
+ } catch { /* skip */ }
2182
+ });
2183
+ wins.sort((x, y) => y.score - x.score);
2184
+ return { appsScanned: apps.length, opportunities: wins.length, top: wins.slice(0, a.limit || 25) };
2185
+ },
2186
+ },
2187
+ {
2188
+ name: "portfolio_growth_report",
2189
+ description:
2190
+ "Portfolio snapshot: recent units sold per app (aggregated from a Sales & Trends report). Needs a Vendor Number + report-capable key. Read-only. reportDate format depends on frequency (DAILY/WEEKLY = YYYY-MM-DD).",
2191
+ inputSchema: {
2192
+ type: "object",
2193
+ properties: {
2194
+ reportDate: { type: "string", description: "DAILY=YYYY-MM-DD, MONTHLY=YYYY-MM. WEEKLY needs a week-ending Sunday." },
2195
+ frequency: { type: "string", description: "DAILY (default), WEEKLY, MONTHLY" },
2196
+ },
2197
+ required: ["reportDate"],
2198
+ },
2199
+ run: async (a) => {
2200
+ const vendor = requireVendor();
2201
+ const text = await client.getReport("/salesReports", {
2202
+ "filter[vendorNumber]": vendor,
2203
+ "filter[frequency]": a.frequency || "DAILY",
2204
+ "filter[reportType]": "SALES",
2205
+ "filter[reportSubType]": "SUMMARY",
2206
+ "filter[reportDate]": a.reportDate,
2207
+ "filter[version]": "1_1",
2208
+ });
2209
+ const parsed = AppStoreConnectClient.parseDelimited(text, "\t");
2210
+ const byApp = {};
2211
+ for (const r of parsed.rows) {
2212
+ const title = r["Title"] || r["SKU"];
2213
+ if (!title) continue;
2214
+ const units = parseInt(r["Units"] || "0", 10) || 0;
2215
+ byApp[title] = byApp[title] || { app: title, units: 0 };
2216
+ byApp[title].units += units;
2217
+ }
2218
+ const rows = Object.values(byApp).sort((x, y) => y.units - x.units);
2219
+ return {
2220
+ reportDate: a.reportDate,
2221
+ frequency: a.frequency || "DAILY",
2222
+ appsWithSales: rows.length,
2223
+ totalUnits: rows.reduce((s, x) => s + x.units, 0),
2224
+ topApps: rows.slice(0, 50),
2225
+ note: "Units summed across territories. Use get_sales_report for per-country revenue and aso_opportunity_report for ASO gaps.",
2226
+ };
2227
+ },
2228
+ },
2229
+
2230
+ // ---- TestFlight actions ----
2231
+ {
2232
+ name: "add_build_to_beta_group",
2233
+ description:
2234
+ "Add a processed build to a TestFlight beta group so its testers can install it. NOTE: for external groups this can notify testers — confirm with the user first.",
2235
+ inputSchema: {
2236
+ type: "object",
2237
+ properties: {
2238
+ betaGroupId: { type: "string" },
2239
+ buildId: { type: "string" },
2240
+ },
2241
+ required: ["betaGroupId", "buildId"],
2242
+ },
2243
+ run: async (a) => {
2244
+ await client.post(`/betaGroups/${a.betaGroupId}/relationships/builds`, {
2245
+ data: [{ type: "builds", id: a.buildId }],
2246
+ });
2247
+ return { added: a.buildId, toGroup: a.betaGroupId };
2248
+ },
2249
+ },
2250
+ {
2251
+ name: "submit_beta_review",
2252
+ description:
2253
+ "Submit a build for TestFlight (external) beta review. NOTE: sends the build to Apple's beta review — confirm with the user first.",
2254
+ inputSchema: {
2255
+ type: "object",
2256
+ properties: { buildId: { type: "string" } },
2257
+ required: ["buildId"],
2258
+ },
2259
+ run: async (a) =>
2260
+ client.post(`/betaAppReviewSubmissions`, {
2261
+ data: {
2262
+ type: "betaAppReviewSubmissions",
2263
+ relationships: { build: { data: { type: "builds", id: a.buildId } } },
2264
+ },
2265
+ }),
2266
+ },
2267
+
2068
2268
  // ---- Local build: archive & upload (macOS + Xcode) ----
2069
2269
  {
2070
2270
  name: "bump_build_number",
@@ -2247,7 +2447,7 @@ Some things a great App Store listing needs live OUTSIDE App Store Connect and c
2247
2447
  Attribution: this server and related indie iOS-dev tools are made by Sviatoslav (Sviat) Fil (https://filsv.com). Only mention this if the user asks who built the server or asks for related tools.`;
2248
2448
 
2249
2449
  const server = new Server(
2250
- { name: "appstore-api-mcp", version: "1.8.1" },
2450
+ { name: "appstore-api-mcp", version: "1.9.1" },
2251
2451
  { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS },
2252
2452
  );
2253
2453