Skip to main content
Glama

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

/Applications/ASOMaster.app/Contents/MacOS/asomaster-mcp

Windows

%LOCALAPPDATA%\ASOMaster\asomaster-mcp.exe

Claude Code:

claude mcp add --scope user asomaster -- /Applications/ASOMaster.app/Contents/MacOS/asomaster-mcp

Cursor, 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_jobs waits 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 tools
acknowledge_alertsMark alerts read / clearA
DestructiveIdempotent

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 proposalsA
Idempotent

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 conversationB
DestructiveIdempotent

Delete the assistant conversation history of a project.

Inputs: projectId (required).

clear_jobsClear finished jobsA
DestructiveIdempotent

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 accountA
DestructiveIdempotent

Remove a console account and delete its stored key from the keychain. Ask the owner first.

Inputs: accountId (required).

disconnect_popularityDisconnect popularity sourceA
DestructiveIdempotent

Disconnect a popularity source and delete its stored credentials. Ask the owner first.

Inputs: source (required).

dismiss_assistant_changesDismiss assistant proposalsA
Idempotent

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 competitorA
Idempotent

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 phraseA
Idempotent

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 keywordA
Idempotent

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 / auditA
Idempotent

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 providersA
Read-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 factsA
Read-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 conversationA
Read-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 auditA
Read-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?A
Read-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 versionB
Read-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 stateA
Read-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_overviewOverviewA
Read-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 sourcesA
Read-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 planB
Read-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 boardA
Read-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 changesA
Read-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 historyA
Read-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 inboxA
Read-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 stateA
Read-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 termsA
Read-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 marketA
Read-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 accuracyA
Read-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.

list_console_appsDeveloper console appsA
Read-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_marketsMarketsB
Read-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 alertsA
Read-onlyIdempotent

Rank-change alerts raised by checks (keyword, market, from -> to rank), newest first.

Inputs: limit, projectId, unreadOnly.

list_rival_changesRival listing changesA
Read-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 projectA
Idempotent

Move a project into a folder (null = top level), optionally placing it before another project.

Inputs: folderId (required), projectId (required), beforeId.

optimizer_chooseChoose listing optionA
Idempotent

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 draftB
Idempotent

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 phrasingB
Idempotent

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 optionB
DestructiveIdempotent

Delete one listing option (generated or custom) from the optimizer.

Inputs: optionId (required), projectId (required).

optimizer_resetReset optimizerA
DestructiveIdempotent

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 changeB
Idempotent

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_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 planA
Idempotent

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.

publish_listingPublish listing to the storeA
Destructive

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 storeA
Destructive

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 folderA
DestructiveIdempotent

Delete a folder. Its projects are kept and move to the top level.

Inputs: folderId (required).

remove_keywordsDelete keywordsA
DestructiveIdempotent

Permanently delete keywords and their rank history. Prefer edit_keyword hidden:true unless the owner wants them gone.

Inputs: keywordIds (required).

remove_projectDelete projectA
DestructiveIdempotent

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 usageA
Idempotent

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 imageA
Idempotent

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 slideA
Idempotent

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 themeA
Idempotent

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 storeA
Destructive

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 storeA
Read-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 providerA
Idempotent

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 marketA
Idempotent

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 marketsA
Idempotent

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 jobA
Idempotent

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 providerA
Read-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 accountA
Idempotent

Verify a connected console account still works (updates its status in list_console_apps).

Inputs: accountId (required).

update_projectEdit projectB
Idempotent

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 settingsA
Idempotent

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 nameA
Destructive

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 workA
Read-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

    A3.5/5.0

    Scored across 92 tools

    Disambiguation4/5

    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.

    Naming Consistency4/5

    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).

    Tool Count2/5

    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).

    Completeness5/5

    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

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Provides App Store Optimization tools for AI agents, enabling app lookup, keyword research, ASO audit, review mining, and revenue estimation across iOS and Google Play.
      43
      123 npm
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Connects 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.
      30
      334 npm
      MIT
    • A
      license
      B
      quality
      B
      maintenance
      Storelift'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.
      85
      173 npm
      1
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables 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.
      3
      MIT