asomaster-mcp
This MCP server connects AI agents to the local ASOMaster desktop ASO app to inspect, manage, and publish app-store optimization work.
Track apps as owned, competitor, or brainstorm projects; organize folders; search stores; inspect console apps, competitor facts, versions, and listings.
Read ASO intelligence: project overviews, keyword boards, keyword/market details, rank alerts, rival changes, ratings, audits, estimate accuracy, and market lists.
Manage keywords: add, edit, hide, delete, localize, set market-specific phrases, get AI suggestions, and discover popular App Store searches.
Run rank checks and fetch real popularity from Apple Ads, Google Ads Keyword Planner, or imported files after connecting sources.
Use local AI providers for brainstorming, keyword ideas, listing optimization, screenshot headings/translations, and in-app assistant conversations.
Build listing options, compare/choose/localize drafts, edit locales, set What's New/links, preview changes, and publish only with explicit owner approval.
Inspect screenshot design state and write/translate screenshot headings; rendering/export/upload remain app-side.
Connect, test, or disconnect developer consoles and popularity credentials via local file paths/keychain storage.
Import/export data, update settings, choose/test AI providers, acknowledge alerts, and stop/clear/wait for background jobs.
Fetches real keyword popularity data from Apple Ads for App Store demand analysis.
Provides ASO tools for App Store listings, including keyword boards, rank history, ratings, audit scores, listing drafts/localization, and publishing workflows via App Store Connect.
Fetches real keyword popularity data from Google Ads Keyword Planner and reports popularity connection/status separately from ASOMaster estimates.
Provides ASO tools for Google Play listings, including keyword boards, rank history, ratings, listing drafts/localization, and publishing workflows.
ASOMaster MCP server
asomaster-mcp connects AI agents (Claude Code, Codex, Cursor, Claude Desktop, Windsurf, OpenCode or any
stdio MCP client) to ASOMaster, a desktop ASO app for the App Store and Google Play.
Your agent can read keyword boards, check ranks, find and localize keywords, fetch real Apple Ads or Google Ads popularity, watch rivals and run the listing studio, with every change showing up live in the app. The bridge talks to the app over a private local socket (a named pipe on Windows); nothing goes through our servers.
Full docs: https://asomaster.app/docs/mcp/ (Markdown for agents: https://asomaster.app/docs/mcp.md)
Install
asomaster-mcp ships inside the ASOMaster app (this repository is its source). Download ASOMaster for macOS
(Windows beta), activate a license, then either:
From the app: Settings › MCP clients › Install, for Claude Code, Codex, OpenCode, Cursor, Claude Desktop or Windsurf.
By hand: point your client at the bridge.
System | Bridge path |
macOS |
|
Windows |
|
Claude Code:
claude mcp add --scope user asomaster -- /Applications/ASOMaster.app/Contents/MacOS/asomaster-mcpCursor, Claude Desktop, Windsurf and other JSON configs (examples/mcp.json):
{
"mcpServers": {
"asomaster": {
"command": "/Applications/ASOMaster.app/Contents/MacOS/asomaster-mcp",
"args": []
}
}
}Codex (~/.codex/config.toml):
[mcp_servers.asomaster]
command = "/Applications/ASOMaster.app/Contents/MacOS/asomaster-mcp"
args = []The app doesn't need to be open; the bridge starts it. Supported MCP protocol versions: 2024-11-05, 2025-03-26, 2025-06-18 and 2025-11-25.
Related MCP server: @applyra/mcp-server
What agents can do
Read: apps, keyword boards per market, keyword detail (rank history, apps ranking), rank alerts, audit score, ratings, rival listing changes (
get_overview,get_project_board,get_term_detail,list_rank_alerts,list_rival_changes,get_audit,get_ratings).Keywords: suggest, add, localize, edit and remove keywords; popular App Store searches around a seed word (
add_keywords,edit_keyword,popular_searches).Demand: real popularity from Apple Ads or Google Ads Keyword Planner, kept separate from ASOMaster's own estimates (
connect_popularity,get_popularity_status).Audit: run the store listing audit per country, read the score, issues and competitors, and dismiss competitors that don't fit (
run_audit,get_audit,dismiss_audit_competitor).Listings: draft, compare, choose and localize titles, subtitles, keyword fields and descriptions; run a final review after translating, undo edits, keep a don't-target list and preview changes (
get_optimizer,optimizer_review,get_publish_preview).Pricing: read App Store and Google Play prices per country and plan new ones, with local price suggestions (
get_pricing,plan_pricing).Screenshots: edit slides, import store screenshots, write and translate headings, render and export a fastlane layout (
get_screenshots,screenshots_render,screenshots_export).Jobs: store searches and AI runs are queued;
wait_for_jobswaits until they finish.
Safety
Anything that changes a live store page (publishing a listing, prices, screenshots or a replacement app name) needs your go-ahead twice: the agent must pass your explicit approval, and the app shows a native confirmation only you can answer. Nothing is submitted for review.
Credentials are passed as file paths, stored in the OS keychain and never returned by a tool.
Local only: owner-only Unix socket on macOS, per-user named pipe with a token on Windows.
Source, Linux build and Docker
This repository holds the bridge's source (Rust, MIT). cargo build --release builds it; cargo test
runs its tests. The Dockerfile builds and runs it so MCP directories can check that the
server starts and lists its tools. ASOMaster itself runs on macOS and Windows; without the app the
bridge still answers initialize and tools/list, and every tool call returns app_unavailable.
Requirements
ASOMaster with an active license (subscription: 15.99 EUR per month or 49 EUR per year). Without one,
tools answer license_required.
Support
Questions and bug reports: open an issue here or see https://asomaster.app/support/.
ASOMaster is made by Cressu OÜ.
Available Tools
92 toolsacknowledge_alertsMark alerts read / clearADestructiveIdempotent
Mark rank alerts as read (given ids, or all when ids is omitted). With clear:true, delete all alerts instead.
Inputs: ids, clear.
add_appTrack an appA
Start tracking an app as a project: your own app (kind mine) or a competitor. Accepts an App Store / Play id, bundle / package name or store URL (find it with search_store). Imports the live listing and seeds keywords in the background; the new project appears in get_overview when the job finishes.
Inputs: app (required), kind (required), store (required), ai, +4 more.
add_console_appsTrack all console appsA
Track every app visible in the connected developer console account(s) for a store as 'mine' projects (skips ones already tracked).
Inputs: store (required).
add_keywordsAdd keywordsA
Add one or more keywords (search phrases) to a project. section 'listing' = phrases the listing targets now; 'idea' = candidates to evaluate (default). localize=true asks the AI to translate each phrase into every tracked market's search language (otherwise the same phrase is used everywhere). New keywords have no ranks until run_rank_check. market (one of the project's markets) also tracks each phrase exactly as written there, e.g. a term from get_search_terms; an existing keyword then only gains that market's phrase.
Inputs: keywords (required), projectId (required), market, section, +1 more.
apply_assistant_changesApply assistant proposalsAIdempotent
Apply changes the assistant proposed in one of its messages (ids from get_assistant_thread, e.g. "c0"; omit changeIds for every still-proposed change). Already applied or dismissed changes are skipped. Only apply what the owner agreed to.
Inputs: messageId (required), projectId (required), changeIds.
ask_assistantAsk the ASO assistantA
Send a message to the in-app ASO assistant for a project (keywords or optimizer scope). It PROPOSES keyword / listing changes (status proposed) but applies nothing by itself; review them with the owner, then call apply_assistant_changes or dismiss_assistant_changes. Background job; read the reply with get_assistant_thread after wait_for_jobs.
Inputs: text (required), scope (required), projectId (required), ai.
brainstorm_projectBrainstorm a new app ideaA
Create a brainstorm project for an app that does not exist yet: the AI proposes keywords from a short brief and checks them in the chosen markets. Requires a ready AI provider.
Inputs: brief (required), store (required), markets.
clear_assistantClear assistant conversationBDestructiveIdempotent
Delete the assistant conversation history of a project.
Inputs: projectId (required).
clear_jobsClear finished jobsADestructiveIdempotent
Remove finished, failed and stopped jobs from the job list. Queued and running jobs are kept; their results (rankings, options, ...) are not affected.
Inputs: no named parameters.
connect_consoleConnect developer consoleA
Connect an App Store Connect API key (apple: keyId, issuerId, private key .p8) or a Google Play service account (google: service-account JSON, optional package names; connecting the same service account again ADDS its package names to the saved ones). Google Play cannot list a developer's apps, so to add an app to an already connected Play account pass store google, accountId and packageNames WITHOUT a key: the app checks each package with the stored key and links the owner's app. Pass FILE PATHS (privateKeyPath / serviceAccountPath; files must be .p8/.pem/.json/.txt in the owner's Downloads, Desktop or Documents folder) so secrets never enter the conversation; the bridge reads them locally and the app stores them in the OS keychain. Credentials are never returned. Needed for console apps, publishing and own-app metadata.
Inputs: store (required), keyId, label, issuerId, +6 more.
connect_popularityConnect popularity sourceA
Connect a source of REAL keyword popularity: apple_ads (Apple Ads API: clientId, teamId, keyId, private key, optional orgId), google_ads_planner (Google Ads Keyword Planner through the owner's own Google Cloud project at Basic access: customerId, refreshToken, oauthClientId, oauthClientSecret, optional loginCustomerId; the owner can also sign in from Settings › Popularity instead) or imported (a popularity export file at filePath). Prefer file paths for keys. Secrets go to the OS keychain and are never returned. Then call fetch_popularity.
Inputs: source (required), keyId, orgId, store, +11 more.
disconnect_consoleDisconnect console accountADestructiveIdempotent
Remove a console account and delete its stored key from the keychain. Ask the owner first.
Inputs: accountId (required).
disconnect_popularityDisconnect popularity sourceADestructiveIdempotent
Disconnect a popularity source and delete its stored credentials. Ask the owner first.
Inputs: source (required).
dismiss_assistant_changesDismiss assistant proposalsAIdempotent
Mark changes the assistant proposed in one of its messages as dismissed (omit changeIds for every still-proposed change). Nothing in the project changes.
Inputs: messageId (required), projectId (required), changeIds.
dismiss_audit_competitorDismiss or restore an audit competitorAIdempotent
Leave an app out of the audit's competitor lists and the AI's evidence (it still counts in rankings and competition), or bring it back with restore. appId is the store id from get_audit competitors[].app.id.
Inputs: appId (required), projectId (required), restore.
dont_targetDon't target a phraseAIdempotent
Put a phrase on the project's "don't target" list (with an optional note, e.g. a rival's brand), or take it off with remove:true. Listed phrases are left out of every AI step (suggestions, listing options, localization, screenshot headings) and of drafts; a tracked keyword with that label is hidden. get_project_board lists them under dontTarget.
Inputs: phrase (required), projectId (required), note, remove.
draft_review_replyDraft a review replyA
Queue an AI draft of the public reply to one review (reviewId from get_reviews): in the reviewer's language, within the store's limit (App Store 5,970 characters, Google Play 350), polite and specific, no refunds promised, no personal data, no links except the owner's support link. The draft is saved on the review for the owner to edit; nothing is posted. Only the owner can send a reply, in the app. Then wait_for_jobs and get_reviews.
Inputs: reviewId (required), projectId (required), ai, directions.
edit_keywordEdit keywordAIdempotent
Rename a keyword and/or hide it (hidden keywords stay tracked but leave the active board) or unhide it.
Inputs: keywordId (required), label, hidden.
export_dataExport board / history / optimizer / auditAIdempotent
Export a project's board, rank history, optimizer drafts or audit as CSV or JSON. By default returns the content (cut at maxChars); with saveToFile:true writes the file into the app's exports folder instead. format fastlane (what optimizer only) always writes a zip of fastlane deliver / supply metadata to the exports folder.
Inputs: what (required), format (required), projectId (required), maxChars, +1 more.
fetch_popularityFetch real popularityA
Pull REAL search popularity for the project's keywords from the connected source (Apple Ads popularity or Google Ads Keyword Planner). Separate from rank checks and from ASOMaster's estimates; requires a connected source (get_popularity_status).
Inputs: projectId (required), markets.
get_ai_statusAI providersARead-onlyIdempotent
Status of the local AI providers the app uses for brainstorming, suggestions, the optimizer and the assistant: installed / signed in / ready, current model and the next setup step when not ready.
Inputs: no named parameters.
get_app_factsCompetitor factsARead-onlyIdempotent
For App Store ids (e.g. competitors from get_board) in one store: first release date, date of the current version, version, price, rating count and ratings per day since release (how fast the app gathers reviews; a fresh update and high ratings/day mean an active rival). Google Play answers an empty list (its page has no reliable dates). Ids missing from the answer are not in that store. At most 50 ids.
Inputs: ids (required), store (required), country (required).
get_assistant_threadAssistant conversationARead-onlyIdempotent
Recent messages of the in-app ASO assistant for a project (keywords or optimizer scope), including keywords it mentioned and the changes it proposed with their status (proposed / applied / dismissed / failed).
Inputs: scope (required), projectId (required), lastMessages.
get_auditApp auditARead-onlyIdempotent
Where the app stands per tracked country and overall, 0-100 (countries weighted by market potential): rankings (visibility of each checked phrase's rank, weighted by demand), listing (how well the country's own listing holds the searched words; localized says whether it is in the country's language), competition (how beatable the apps ranked above are), a verdict (pivot = change keywords, localize = the listing shown is in another language and misses the searches, align = fine-tune, fine), deterministic issues with the step that fixes each (action: keywords, names, names_localize, copy, copy_localize, screens, screens_localize, store), the top-10 and gap phrases, main competitors, and the AI conclusions (headline, reason, takeaways) of the last run_audit plus a cross-country summary. One country is returned in full (country, default the main one); the others as one line each. Demand is real popularity when connected (demandSource), else estimated volume.
Inputs: projectId (required), country.
get_change_impactDid a change work?ARead-onlyIdempotent
Before vs after each change of the app: listing text published through ASOMaster, the app's own listing text changing when re-read, a new App Store version (its release day), and markers the owner added ("new screenshots"). For each change and market: tracked keywords ranked / in the top 10 / top 3 and their median rank (same keywords in both windows), the biggest risers and fallers, store traffic per day and conversion (downloads / page views; coverage says when the store has not reported every day yet: App Store Connect lags 1-2 days, Google Play posts monthly) and the average rating, with a verdict: improved, worse, no_clear_change, too_early (the after window has not passed), not_enough_data or waiting_for_release (App Store text sent for a version Apple has not released yet; once released, day is the release day, liveDay says so and sentDay keeps the day it was sent). The change day itself is left out; overlaps lists other changes within the window, whose effects mix in. It shows what happened around a change, not proof that the change caused it. All changes come back as one line each; the one picked by eventId (default the newest) in full with every market as one line, or one market in full with market.
Inputs: projectId (required), days, market, eventId.
get_next_versionNext app versionBRead-onlyIdempotent
The editable app version on the developer console (if any) and the version string the app would suggest for publishing.
Inputs: projectId (required).
get_optimizerOptimizer stateARead-onlyIdempotent
Listing optimizer state for a project: step, current live listing, generated listing options (with reach/difficulty, covered phrases and validation problems), the chosen option, core phrases and per-locale drafts with translation candidates. Descriptions are cut unless full is true.
Inputs: projectId (required), full, locale.
get_overviewOverviewARead-onlyIdempotent
Start here. Lists every tracked project (id, store, kind, markets, keyword and top-10 counts, searches checked vs never checked, audit step, last check), folders, running and recently finished jobs, key settings, license state and unread rank alerts. Use the ids it returns with every other tool.
Inputs: kind, store, folderId.
get_popularity_statusPopularity sourcesARead-onlyIdempotent
Which REAL popularity sources (Apple Ads, Google Ads Keyword Planner, imported files) are connected, for which store, and when they last fetched. Credentials are never returned.
Inputs: no named parameters.
get_pricingLocal pricing planBRead-onlyIdempotent
The app's subscriptions / in-app purchases (App Store) or base plans / one-time purchase options (Google Play) with today's price in the base country, which are selected, and for selected ones the plan per country: today, scheduled, proposed (decimal local prices), share of the base price, changed, overridden, skipped reasons. Also the method spread previews (min/median/max % of base), data sources and the last publish report. Reads App Store Connect / Play Console (cached 10 min; refresh re-reads). Never writes.
Inputs: projectId (required), country, refresh.
get_project_boardProject keyword boardARead-onlyIdempotent
Keyword x market grid for one project, summarised per market: for each keyword its id, label, row summary and, per shown market, rank / previous rank, ESTIMATED volume & difficulty (estVol/estDiff), REAL popularity (pop, only when a provider is connected), verdict and opportunity. Also the top competitors. With more than 4 tracked markets only the main market is shown unless you pass markets. Hidden keywords are excluded unless section is hidden/all.
Inputs: projectId (required), sort, limit, markets, +1 more.
get_publish_previewWhat publishing changesARead-onlyIdempotent
Before publish_listing: reads the live listing fresh from App Store Connect / Play Console and returns, per language the publish writes, each field it changes as from -> to, isNew for a language the app does not have yet, and the languages that already match (unchanged). source is console (fresh read) or stored (no console answered). Tell the owner what changes before publishing.
Inputs: projectId (required).
get_ratingsApp ratings historyARead-onlyIdempotent
The app's average rating and rating count per market over the last days (recorded after each rank check; App Store per storefront, Google Play global): latest values, ratings added over the range (newRatings), change of the average (ratingChange) and the daily points.
Inputs: projectId (required), days.
get_reviewsStore reviews inboxARead-onlyIdempotent
Customer reviews of one of the owner's apps, read from App Store Connect / Google Play Console by sync_reviews and kept locally (Google Play only shares about the last 7 days, so history builds up with each sync). Returns the summary for the period (count, average stars, unreplied, reviews per star, frequent phrases in 1-2 star vs 4-5 star reviews), markets (App Store countries or Play reviewer languages), keyword ideas (frequent review phrases no tracked keyword covers; add winners with add_keywords section idea), and the reviews matching the filters: stars, title, text, market, app version, current reply and the owner's draft. state says whether reviews were synced (not_loaded, ready, error with message, disconnected). Replies are sent only by the owner in the app.
Inputs: projectId (required), days, limit, stars, +3 more.
get_screenshotsScreenshot designer stateARead-onlyIdempotent
The project's screenshot design: slides (heading in the main locale, image per device), theme, headings per locale, render status per locale/device/slot, devices drawn in landscape (design.landscape; sizes swapped), and checks (errors block export and upload; warnings do not: missing images, headings over the limit, stale or missing translations, low text contrast, images that will be cropped, the same image on several slides). Plain slides show their image as it is, with no heading. Write headings with screenshots_write_headings / screenshots_translate, change slides with screenshots_edit_slide / screenshots_set_theme, add images with screenshots_import_store / screenshots_add_image, then screenshots_render, screenshots_export and (with the owner's go-ahead) screenshots_upload.
Inputs: projectId (required).
get_search_termsApple Ads search termsARead-onlyIdempotent
REAL search terms people typed in the App Store that showed the owner's own app in its Apple Ads campaigns, per country, as keyword ideas. Without market: a summary of the markets with the most impressions (totals, lowVolume, termCount, avoidedCount, the top 5 terms); call again with market for that market's full rows: impressions, taps, installs, ttr (taps / impressions), the bid keyword and match type that triggered each term, tracked (a keyword already has this phrase in that market) and avoided (on the don't-target list). lowVolume totals the terms Apple hides for privacy (too few searches to name). Cached by the app: a period the owner loaded once is refreshed at most once a day while Apple Ads is connected (weekly while no campaign promotes the app); fetchedAt / stale / nextRefreshAt say how old it is, warning names campaigns that failed. state: ready, no_campaigns (no Apple Ads campaign promotes the app), not_loaded (the owner has not loaded this period in the app), not_connected (connect Apple Ads first) or unsupported (Google Play, rivals, app ideas). To track a term, call add_keywords with market set to its country (localize true when the market's search language isn't English).
Inputs: projectId (required), days, limit, market, +1 more.
get_term_detailKeyword detail in one marketARead-onlyIdempotent
Everything about one keyword in one market: the current cell (rank, estimates, real popularity, verdict), rank/estimate history by day, and the apps currently ranking for it (position, rating count, installs, whether the phrase matches their title/subtitle).
Inputs: market (required), keywordId (required), projectId (required), topApps, +1 more.
get_volume_calibrationEstimate accuracyARead-onlyIdempotent
How well the estimated volume tracks real popularity, over every tracked phrase that has both (Apple Ads / Google Ads / imported): pairs, spearman rank correlation (-1..1, null under 10 pairs), meanAbsError on 0-100 and bandAgreement (share in the same low/medium/high band). Use it to judge how far to trust estimates where real popularity is missing.
Inputs: no named parameters.
import_fileImport keywords fileA
Import an Astro export or a CSV of apps / keywords from a local path (must be a .csv/.tsv/.txt/.json file in the owner's Downloads, Desktop or Documents folder). format astro without path reads Astro's own database on this Mac: its popularity becomes real popularity and each Astro app's phrases join the tracked app with the same App Store id. previewOnly:true just reports what would be imported (rows, apps, keywords, countries). With projectId the phrases are added as keywords of that project; otherwise apps become projects (optionally in folderId). Background job.
Inputs: format (required), path, store, folderId, +2 more.
link_released_appLink an app idea to its released appA
An app idea (a brainstorm project, no store app yet) is now published: link it to its App Store id / Play package / store URL. It becomes kind mine (or competitor), keeps every keyword and history, and the store listing replaces the idea's name. Fails for projects that already have an app or when the app is already tracked.
Inputs: app (required), kind (required), projectId (required).
list_console_appsDeveloper console appsARead-onlyIdempotent
Connected developer console accounts for a store (App Store Connect / Google Play Console) and the apps they can see, with whether each app is already tracked.
Inputs: store (required).
list_marketsMarketsBRead-onlyIdempotent
Markets (countries) available for a store with search language, listing locales and a 0-10 potential score. Use the country codes as market ids.
Inputs: store (required), featuredOnly.
list_rank_alertsRank alertsARead-onlyIdempotent
Rank-change alerts raised by checks (keyword, market, from -> to rank), newest first.
Inputs: limit, projectId, unreadOnly.
list_rival_changesRival listing changesARead-onlyIdempotent
Name and subtitle changes of tracked rivals (kind competitor), noticed when their listing is re-read (every rank check), newest first: app, locale, field (title or subtitle), from -> to, read. A rival renaming around a phrase is a signal to re-check that phrase.
Inputs: no named parameters.
localize_keywordLocalize keywordA
Have the AI translate a keyword into the search language of each market (or the given markets), replacing non-overridden per-market phrases.
Inputs: keywordId (required), markets.
move_projectMove projectAIdempotent
Move a project into a folder (null = top level), optionally placing it before another project.
Inputs: folderId (required), projectId (required), beforeId.
optimizer_chooseChoose listing optionAIdempotent
Pick the listing option to ship and the core phrases it must carry into every locale. Next step: optimizer_localize.
Inputs: optionId (required), projectId (required), corePhrases (required).
optimizer_edit_localeEdit a locale draftBIdempotent
Change fields of one locale's draft listing (empty string clears a field).
Inputs: fields (required), locale (required), projectId (required).
optimizer_localizeLocalize chosen listingA
Write per-locale drafts of the chosen listing: the core phrases are translated, candidate local phrasings are measured in each locale's test market, and the best are used. A locale that fails does not stop the others; get_optimizer lists failedLocales and lastError. Background job.
Inputs: projectId (required), scope, locales, remaining, +1 more.
optimizer_more_optionsMore listing optionsC
Generate additional listing options next to the existing ones.
Inputs: count (required), projectId (required), directions.
optimizer_pick_phrasePick local phrasingBIdempotent
In one locale draft, use a different measured candidate phrase for a core phrase (from that locale's candidates in get_optimizer).
Inputs: locale (required), phrase (required), keyword (required), projectId (required).
optimizer_remove_optionRemove listing optionBDestructiveIdempotent
Delete one listing option (generated or custom) from the optimizer.
Inputs: optionId (required), projectId (required).
optimizer_resetReset optimizerADestructiveIdempotent
Discard all options, the choice and every locale draft for the project.
Inputs: projectId (required).
optimizer_reviewFinal review of the listingA
Review the localized listing: names and subtitles of every language against the approved main listing (wrong meaning, dropped topic, doubled word, wrong regional variant or script, stray English, over the limit), a rejection-risk scan of keyword fields and copy (vulgar words, other brands, medical claims, price/free words, missing features, wrong script, changed links) and rule checks. Fixes are applied most severe first when they fit; the rest are listed as looks. Runs by itself after optimizer_localize; get_optimizer shows review.changes / review.looks. Never blocks publishing. Background job.
Inputs: projectId (required), parts.
optimizer_review_undoUndo a review changeBIdempotent
Put one final-review change back (changeId from get_optimizer review.changes).
Inputs: changeId (required), projectId (required).
optimizer_save_optionAdd or edit a listing optionA
Add your own listing option (omit optionId) or replace the listing of an existing option. The app re-scores it and reports validation problems (length limits, repeated words) in get_optimizer.
Inputs: listing (required), projectId (required), label, optionId.
optimizer_set_linksWhat's New and listing linksAIdempotent
Set What's New and the listing links written by the next publish. Apple: whatsNew, marketingUrl, supportUrl, privacyUrl for the main language (or every published language with allLanguages). Google Play: marketingUrl is the contact website, plus contactEmail. Omitted fields stay; empty strings clear. publish must be true for publish_listing to write them. Links must start with https://.
Inputs: projectId (required), publish, whatsNew, privacyUrl, +4 more.
optimizer_startGenerate listing optionsA
Start the listing optimizer for a project: scouts the board's keywords in the main locale and has the AI write several complete listing options (title, subtitle/short description, keyword field, description) scored for reach and difficulty. Replaces previous options. Background job; then read get_optimizer.
Inputs: locale (required), projectId (required), ai, directions.
plan_pricingEdit the pricing planAIdempotent
Change the saved pricing plan (nothing is written to the store): select products, pick a method (tiers = five income tiers, purchasing_power = GNI PPP, income = GNI Atlas, blended = both, equal = the store's own conversion), floor / ceiling as percent of the base price (floor 5-100, ceiling 100-300), prefer local price endings, a product's base price, one country's own price (override) or reset all overrides of a product, the start date (YYYY-MM-DD, empty = earliest; App Store only), whether existing subscribers keep their price (default true) and whether in-app purchases change at once. Returns the updated get_pricing summary.
Inputs: projectId (required), iapNow, method, select, +8 more.
popular_searchesPopular searches around a seedARead-onlyIdempotent
What people search in one App Store market around a seed word, from the store's own autocomplete (suggestions are ordered by search volume): the seed, the seed plus a space and plus common next letters are asked and merged in order of first appearance (position 1 = most searched). tracked marks phrases already in the project. Google Play answers supported:false (no public source). Good for finding high-demand phrases to add with add_keywords.
Inputs: seed (required), store (required), country (required), projectId.
publish_listingPublish listing to the storeADestructive
DESTRUCTIVE / LIVE: pushes the chosen listing and every ready locale draft to App Store Connect or Google Play Console, changing what real users see. Only call after the owner has reviewed the exact listing text and explicitly told you to publish in this conversation; never on your own initiative and never as part of a larger plan they approved in general terms. Requires a connected console. The app then shows the owner a confirmation dialog listing the store, app, version, locales and fields; nothing is published unless they click Publish there (no answer within ~2 minutes = denied, error code not_approved). Background job once approved; follow with wait_for_jobs and report the outcome.
Inputs: approval (required), projectId (required), ownerApproved (required), versionString.
publish_pricingPublish prices to the storeADestructive
DESTRUCTIVE / LIVE: writes the plan's changed prices for the selected products (or productIds) to App Store Connect or Google Play Console; real customers then pay them. Only call after the owner has seen the per-country before/after (get_pricing) and explicitly told you to publish in this conversation. The app shows the owner a confirmation dialog listing products, countries and the start date; nothing is written unless they confirm there (no answer within ~2 minutes = denied, code not_approved). App Store subscriptions keep existing subscribers on their price by default (a price increase never reaches them); Google Play never moves existing subscribers. Background job; follow with wait_for_jobs, then get_pricing for the report.
Inputs: approval (required), projectId (required), ownerApproved (required), productIds.
remove_folderDelete folderADestructiveIdempotent
Delete a folder. Its projects are kept and move to the top level.
Inputs: folderId (required).
remove_keywordsDelete keywordsADestructiveIdempotent
Permanently delete keywords and their rank history. Prefer edit_keyword hidden:true unless the owner wants them gone.
Inputs: keywordIds (required).
remove_projectDelete projectADestructiveIdempotent
Permanently delete a project with its keywords, rank history and optimizer drafts. Only when the owner asked for this exact project: pass its name (from get_overview) as confirmName; a mismatch deletes nothing.
Inputs: projectId (required), confirmName (required).
resume_jobResume a job paused for AI usageAIdempotent
A job whose AI ran out of usage waits (aiPause in get_overview / wait_for_jobs) and resumes by itself at aiPause.resumesAt. This tries again now, on provider when given (switch AI; pay-per-use API providers can only be chosen in the app).
Inputs: jobId (required), provider.
resync_projectRefresh app metadataA
Re-import the app's live listing / metadata from the store (and console when connected).
Inputs: projectId (required).
run_auditRun the app auditA
Queue an audit run: optionally re-read the store listing (refetch), let the AI research more keywords (moreKeywords, steered by note, else toward the main competitors), check phrases (only never-checked ones unless recheck), then write AI conclusions for the main country first and the other picked countries, and a cross-country summary. Countries left out keep their last audit. Results are saved per country as they finish; an interrupted run resumes when the app restarts. Then wait_for_jobs and get_audit.
Inputs: projectId (required), options.
run_rank_checkCheck ranksA
Search the store for every keyword in the project's markets and record ranks, estimated volume/difficulty and competitors. Runs as a background job (the store is rate-limited, so large boards take minutes). Results already checked today are reused unless force is true.
Inputs: projectId (required), force, markets.
save_folderCreate or rename folderA
Create a folder (omit folderId) or rename an existing one.
Inputs: name (required), folderId.
screenshots_add_imageAdd a screenshot imageAIdempotent
Put a PNG or JPEG from the user's Downloads, Desktop or Documents folder on a slide for one device (and locale; default main, which every locale shares). Use the raw app screenshot taken on that device, not a finished store image.
Inputs: path (required), device (required), slideId (required), projectId (required), +1 more.
screenshots_edit_slideEdit a screenshot slideAIdempotent
Change one slide of the screenshot design (or add a slide at the end when slideId is omitted): heading (word highlights; at most 34 characters, 40 for scripts without case), subheading, plain (show the image as it is), layout (centered, bleed, zoomed, duo, tilted), per-slide style (background / gradient / text color / text size), device position and a notification card; style, device and notification change only the fields given. Texts go to locale (default the main locale); other locales get their own translation. Read get_screenshots for slide ids, then render with screenshots_render.
Inputs: projectId (required), plain, style, device, +7 more.
screenshots_exportExport screenshotsA
Write the complete rendered set as a zip into the app's exports folder: layout "zip" (a folder per locale plus manifest.json) or "fastlane" (deliver / supply folders). Returns the file path. Every screenshot must be rendered for the current design.
Inputs: projectId (required), layout.
screenshots_import_storeImport live store screenshotsA
Download the screenshots on the app's live store page for a locale (default main) and put them on slides in order, each image once (new slides are plain: they already carry their text). Play images are sorted into phone and tablet by shape (the tablet is switched on when there are tablet images); in the main locale a device whose store images are landscape is turned to landscape. Returns how many images were placed, repeats left out and devices turned.
Inputs: projectId (required), locale.
screenshots_renderRender screenshotsA
Ask the open ASOMaster window to draw every screenshot still missing for the current design (bundled fonts, every locale and device). Returns at once; poll get_screenshots until every target is done. A heading too long to fit is reported in the app and stops that render.
Inputs: projectId (required).
screenshots_set_themeSet the screenshot themeAIdempotent
Change the look shared by every slide (any subset): background, backgroundEnd (null = solid), backgroundAngle, textColor, accent (highlighted words), font (inter, poppins, playfair, nunito, barlow), caps, position (top, bottom), frame (none, dark, light), layout, textSize; and/or the devices to render in store order; and/or landscape, the devices drawn in landscape (iPhone 2868×1320, iPhone 6.5″ 2778×1284, iPad 13″ 2752×2064, iPad 12.9″ 2732×2048, iPad 11″ 2388×1668, Play phone 1920×1080, Play 10″ tablet 2560×1600; [] = all portrait; Mac, Watch and the feature graphic have one shape). Then render with screenshots_render.
Inputs: projectId (required), theme, devices, landscape.
screenshots_translateTranslate screenshot headingsA
Adapt the main screenshot headings to the project's other languages (or only locales), reusing each language's own search words. Every slide needs a main heading first. Subheadings and notification texts are adapted too. Background job; then read get_screenshots (locales show translated / stale / missing).
Inputs: projectId (required), ai, locales.
screenshots_uploadUpload screenshots to the storeADestructive
LIVE: replaces the screenshots of the editable App Store version or the Play listing with the rendered set (unchanged sets are skipped; nothing is submitted for review). locales uploads only those languages (e.g. just the main one; only their screenshots must be rendered) and leaves the others as they are in the store. Only call after the owner has seen the screenshots and told you to upload them in this conversation. The app then shows the owner a confirmation dialog; nothing is sent unless they approve there (no answer in ~2 minutes = denied, error not_approved). dryRun checks everything without changing the store and needs no dialog. Background job; follow with wait_for_jobs.
Inputs: approval (required), projectId (required), ownerApproved (required), dryRun, +1 more.
screenshots_write_headingsWrite screenshot headingsA
Have the AI write the one-line heading printed on each screenshot slide, in the main locale (verb first, one benefit, at most 34 characters; 40 for scripts without case). Slides that already have a heading are kept unless overwrite is true or slideId names one slide. When the AI can see images it looks at each slide's screenshot. Background job; then read get_screenshots.
Inputs: projectId (required), ai, slideId, overwrite, +1 more.
search_storeSearch the storeARead-onlyIdempotent
Live store search in one market (10 apps unless limit asks for more: up to 200 on the App Store; Google Play returns about 30 at most). Accepts a search term or a pasted store URL. Apps already tracked carry trackedAs {projectId, kind}. Use it to find app ids before add_app.
Inputs: term (required), store (required), country (required), limit.
set_ai_providerChoose AI providerAIdempotent
Select the local AI provider (and optionally model) the app uses for generation. Check readiness with get_ai_status first.
Inputs: provider (required), model.
set_market_phraseSet phrase for one marketAIdempotent
Override the exact search phrase used for a keyword in one market (e.g. a better local wording). An empty phrase removes the override.
Inputs: market (required), phrase (required), keywordId (required).
set_project_marketsSet tracked marketsAIdempotent
Replace the list of markets (countries) tracked for a project. New markets are empty until run_rank_check runs for them.
Inputs: markets (required), projectId (required).
stop_jobStop a jobAIdempotent
Stop a queued or running background job (rank check, AI generation, import, ...). Work already done is kept.
Inputs: jobId (required).
suggest_keywordsAI keyword suggestionsA
Ask the AI for new keyword ideas for a project based on its listing, brief and current board; they land in the 'idea' section.
Inputs: projectId (required), hint, count.
sync_reviewsSync store reviewsA
Queue a background read of new customer reviews (and their current replies) from the developer console of one of the owner's apps. The app also does this by itself once a day. Then wait_for_jobs and get_reviews.
Inputs: projectId (required).
test_ai_providerTest AI providerARead-onlyIdempotent
Send a tiny test prompt through a provider and record latency / errors (see get_ai_status). Refused for providers that bill an API key; the user runs those tests in the app.
Inputs: provider (required).
test_consoleTest console accountAIdempotent
Verify a connected console account still works (updates its status in list_console_apps).
Inputs: accountId (required).
update_projectEdit projectBIdempotent
Rename a project, change its brief (context used by the AI) or its automatic rank-check schedule.
Inputs: projectId (required), name, brief, autoCheck.
update_settingsUpdate settingsAIdempotent
Change app settings; only the keys you pass change. Use set_ai_provider for the AI provider/model.
Inputs: settings (required).
upload_app_nameUpload a replacement nameADestructive
DESTRUCTIVE / LIVE: App Store Connect refused a language's name because another app uses it (get_optimizer renames: locale, the refused name and up to 3 AI proposals; the rest of that language was already uploaded). Nothing is renamed automatically. Show the owner the proposals, let them pick or edit one, and only after they told you which name to use in this conversation call this with that exact name (≤ 30 characters). The app then asks the owner to confirm in a native dialog. Background job; a name that is taken too is reported (renames.tried) and the job fails with conflict. App Store only; never submits for review.
Inputs: name (required), locale (required), approval (required), projectId (required), +1 more.
wait_for_jobsWait for background workARead-onlyIdempotent
Block until background work changes state: returns as soon as a job finishes (done / failed / stopped), or when nothing is queued or running, or after timeoutSeconds (max 50). With jobId, waits for that job only; with projectId, for that project's jobs. Call it repeatedly after any tool that queued work until idle is true, then read the results. Reports progress of jobs still running.
Inputs: jobId, projectId, timeoutSeconds.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 92 tools
Despite 92 tools, purposes are mostly separable: projects (add_app/update_project/remove_project), keywords (add/edit/remove/set_market_phrase/localize), analysis (get_project_board, get_term_detail, get_audit, get_change_impact), and pipeline steps (optimizer_*, screenshots_*) are clearly scoped. A few near-pairs remain (optimizer_more_options vs optimizer_save_option, optimizer_reset vs removing single options, fetch_popularity vs run_rank_check, screenshots_render/export/upload) that could be mispicked, but descriptions disambiguate them.
Names are uniformly snake_case and mostly verb_noun with stable namespace prefixes (optimizer_, screenshots_, get_/list_/add_/set_/remove_/run_/publish_/connect_). Minor deviations: some are noun-first or verb-less (popular_searches, dont_target, plan_pricing, get_volume_calibration) and the prefix convention is not applied to every family (project tools lack a project_ prefix).
92 tools is far beyond a comfortable surface for an agent, even for a broad ASO suite spanning keywords, ranks, popularity, audits, AI optimizers, screenshot design, pricing, reviews, console connections, jobs and import/export. Many sub-domains justify a few tools each, but the total is heavy and forces multi-hop discovery (get_overview → board → detail → action).
Coverage is exceptional: full project/keyword/folder lifecycle, markets, rank checks, real and estimated popularity, audits with competitor management, listing optimizer through publish, screenshot design-to-upload, pricing planning-to-publish, reviews sync and AI drafts, console connections, job control, settings and import/export. Intentional read-only boundaries (replies, submission for review) are documented rather than gaps.
Maintenance
Related MCP Connectors
App Store and Google Play ASO: keyword rankings, competitors, reviews, audits and an action queue.
ASO for App Store and Google Play: keyword research, rank tracking, in-app feedback and analytics.
ASO for your AI: keywords, rankings, competitors and ads across 2.5M+ App Store apps.
ASO tools for AI agents: keyword research, rank tracking, competitor analysis (iOS & Android).
Related MCP Servers
AlicenseAqualityCmaintenanceProvides App Store Optimization tools for AI agents, enabling app lookup, keyword research, ASO audit, review mining, and revenue estimation across iOS and Google Play.43123 npmMIT- AlicenseAqualityBmaintenanceConnects App Store and Google Play keyword data to AI assistants, enabling ASO tasks like rank tracking, keyword analysis, competitor visibility, and top charts through natural language.30334 npmMIT
- AlicenseBqualityBmaintenanceStorelift's MCP server lets Claude, ChatGPT, Cursor or any MCP client read your App Store and Google Play keyword ranks, rivals, reviews, store pages, charts and AI visibility from your Storelift workspace. The remote server is included on every plan, including Free (1 app, 25 keywords in each of 2 storefronts, no end date); the local server and public API come with Pro and Studio.85173 npm1MIT

AppmanAi MCPofficial
AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query live App Store and Google Play data — keyword demand, rank history, top charts, competitor sets, reviews and ratings — across 100+ countries, directly inside a chat instead of a dashboard. Exposes 35 read-only tools covering app search, ASO keyword profiling, ranking trajectories, and worldwide market comparisons through a remote OAuth-authenticated endpoint.3MIT