Overt over MCP.
Overt runs a Model Context Protocol server, so Claude, Cursor or any other MCP client can drive it directly — search the App Store, score a listing, track keywords and read daily rank history, by asking in plain English rather than opening a dashboard.
There are 20 tools, listed in full below. Agent access itself is included on every plan, Free included, and an agent is held to exactly the same plan limits you are — it cannot exceed your app or keyword allowance.
The one exception is generate_metadata, which needs a paid plan to run from an agent. On Free it returns an explanation and spends nothing; the account’s generation allowance is unchanged and can still be used in the dashboard. Every other tool here — search, scores, ranks, keyword difficulty, competitors, charts — works on Free.
Getting a key
Create an API key under Settings → API. The key is shown once, when you create it. Treat it like a password: anything holding it can read and change what your account tracks. Revoking a key stops it working on the very next call.
Connecting a client
The server speaks streamable HTTP at a single endpoint:
https://overt.live/api/mcp
For Claude Desktop, add this to claude_desktop_config.json and restart the app. Cursor and most other clients take the same object in their own MCP settings.
{
"mcpServers": {
"overt": {
"type": "http",
"url": "https://overt.live/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Replace YOUR_API_KEY with the key you created. Authentication is a bearer token on every request, and there is no session to keep alive.
Connecting a client that uses OAuth
Some clients discover authentication rather than taking a pasted key. Overt publishes protected-resource metadata at /.well-known/oauth-protected-resource, and its unauthenticated replies carry a WWW-Authenticate header pointing at it, so a client can find the authorization server on its own.
The authorization server is Clerk, not Overt. Overt never sees your password, never issues a token and never stores one — it only verifies the token you present and checks on every request that it has not been revoked or expired. Revoking access in Clerk stops the next call, not the one after some cache expires.
What an agent can do
Each tool below shows the parameters it takes, a prompt that would reach for it, and the response it really returns. Tool output is plain text rather than JSON, because agents read it more reliably.
One thing worth knowing before reading the rank tools: rank is a position, so a smaller number is better — a keyword going from #40 to #12 improved. A rank reported as not in top 200 means the app was checked and genuinely not found, which is different from a day with no check at all. The server tells clients this in its own instructions, so a competent agent gets the direction right without being reminded.
search_app_store — Search the App Store
Search Apple's App Store by name or keyword and return matching apps with their App Store ids. Use this to find the numeric id an app must be referred to by elsewhere.
| Parameter | Required | Description |
|---|---|---|
term | Yes | Search term, e.g. an app name or a keyword. |
country | No | App Store storefront. One of: us, gb, ca, au, de, fr, es, it, nl, se, jp, kr, in, br, mx. Defaults to us. |
Ask
Find the App Store id for Loopwell.
Returns
1. Loopwell — Habit Tracker — Loopwell Studio (App Store id: 6443218870) 2. Loopwell Focus — Loopwell Studio (App Store id: 6501120043) 3. Habit Loop — Northbend (App Store id: 1544820117)
score_listing — Score an app's listing
Compute Overt's listing health score (0-100) for any App Store app, with a breakdown of title, description, screenshots and reputation, and what to improve. Works on any app, including competitors — it reads only public App Store data.
| Parameter | Required | Description |
|---|---|---|
appStoreId | Yes | Numeric App Store id, from search_app_store. |
country | No | App Store storefront. One of: us, gb, ca, au, de, fr, es, it, nl, se, jp, kr, in, br, mx. Defaults to us. |
Ask
How strong is Loopwell's listing? Compare it to Momentum's.
Returns
Loopwell — Habit Tracker — Loopwell Studio Overall listing health: 84/100 Title: 95/100 Description: 90/100 Screenshots: 50/100 — Only 2 screenshot(s) — the App Store supports up to 10; more visual real estate converts better. Reputation: 85/100 — Average rating is 3.9 — below 4.0 measurably hurts conversion in App Store search. Freshness: 95/100
list_tracked_apps — List tracked apps and ranks
List the apps this account tracks, with every tracked keyword, its storefront, its latest rank and its movement since the previous check.
Takes no parameters.
Ask
What am I ranking for?
Returns
Loopwell — Habit Tracker (App Store id: 6443218870, app id: lw_84210) "habit tracker" [US] — #14 (up 6 since the previous check), last checked 2026-07-29 (keyword id: kw_9f21) "daily routine" [US] — #38 (down 2 since the previous check), last checked 2026-07-29 (keyword id: kw_7a02) "streak app" [US] — not in top 200, last checked 2026-07-29 (keyword id: kw_3b88)
get_rank_history — Get a keyword's rank history
Daily rank history for one tracked keyword, oldest first. A rank of 'not in top 200' means checked and not found, which is different from a date with no entry at all.
| Parameter | Required | Description |
|---|---|---|
keywordId | Yes | Keyword id, from list_tracked_apps. |
days | No | How far back to look. Defaults to 90. |
Ask
Has “habit tracker” been improving over the last two weeks?
Returns
"habit tracker" [US] — 14 checks 2026-07-16: #16 2026-07-17: #15 2026-07-18: #14 2026-07-19: #13 2026-07-20: #14 2026-07-21: #12 2026-07-22: #11 2026-07-23: #10 2026-07-24: #9 2026-07-25: #9
list_competitor_changes — List competitor listing changes
Recent metadata changes Overt detected on the apps this account watches — the day a competitor rewrote a title or subtitle, changed price, or swapped screenshots.
| Parameter | Required | Description |
|---|---|---|
days | No | How far back to look. Defaults to 30. |
Ask
Did any of my competitors change their listing this week?
Returns
2026-07-24 — app 1234567890, subtitle was: Daily Habits & Routines now: Habit Tracker, Streaks & Goals 2026-07-21 — app 1234567890, price was: 0 now: 2.99
suggest_keywords — Suggest keywords to track
Suggest keywords worth tracking for one of this account's apps, mined from the listings of its competitors and the apps already ranking for its keywords. Ranked by how many of those apps use each phrase. This is not search volume — Apple does not publish that, so it is not estimated here.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id, from list_tracked_apps or track_app. |
limit | No | How many suggestions to return. Defaults to 25. |
Ask
What keywords should I be tracking for Loopwell?
Returns
"daily routine" — used by 7 apps (Momentum — Daily Habits, Streaks, Routinery) "habit streaks" — used by 5 apps (Streaks, Loop Habit Tracker, Done) "morning routine" — used by 4 apps (Routinery, Fabulous, Momentum — Daily Habits)
get_keyword_difficulty — Score how hard a keyword is
Score how hard it would be to rank for a keyword, from 0 to 100, where HIGHER means HARDER — the opposite direction to a listing health score. Measured from how established the apps already at the top are and how many of them target the phrase in their name. Works for any keyword, tracked or not. Pass appId to also learn where that app already ranks for it, which is the best available signal for whether a keyword is worth taking.
| Parameter | Required | Description |
|---|---|---|
keyword | Yes | The search term to score. |
country | No | App Store storefront. One of: us, gb, ca, au, de, fr, es, it, nl, se, jp, kr, in, br, mx. Defaults to us. |
appId | No | Optional Overt app id. When given, also reports where that app currently ranks for the term. |
Ask
How hard would it be to rank for “habit tracker”?
Returns
"habit tracker" [US] — 74/100 (Hard). Higher is harder. Incumbent strength: The typical app in the top 10 has 14,009 ratings. Title targeting: 8 of the top 10 put “habit tracker” in their app name.
compare_with_competitor — Compare a listing against a competitor's
Compare one of this account's apps against a competitor it watches, field by field — title, description length, screenshots, rating, ratings, price and version — from the daily snapshots already stored. Only fields with a defensible direction report who is ahead; price and version never do.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id, from list_tracked_apps. |
competitorAppStoreId | Yes | Numeric App Store id of a competitor already watched for that app. |
Ask
How does Loopwell stack up against Momentum?
Returns
Loopwell — Habit Tracker vs Momentum — Daily Habits Captured 2026-07-29 and 2026-07-29. Title: Loopwell — Habit Tracker | Momentum — Daily Habits Title length: 24 chars | 26 chars Description: 812 chars | 340 chars (you are ahead) Screenshots: 4 | 8 (they are ahead) Rating: 4.6 | 4.8 (they are ahead) Ratings: 2,412 | 18,905 (they are ahead) Price: Free | Free Version: 2.1.0 | 4.7.2
get_top_chart — Read an App Store top chart
Read Apple's top-app chart for a country and optionally a single category, and report where one of this account's apps sits on it. Category charts are far more meaningful than the overall chart, which almost no app competes in. Not appearing on a chart is the ordinary result, not an error.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id, from list_tracked_apps. |
feed | No | Which chart. One of: topfreeapplications, toppaidapplications, topgrossingapplications. Defaults to topfreeapplications. |
category | No | App Store category name. Omit for the overall chart across all categories. |
limit | No | How many chart entries to list. Defaults to 20. |
Ask
Where does Loopwell sit in the Health & Fitness chart?
Returns
Health & Fitness — topfreeapplications [US] This account's app is #38 on this chart. 1. MyFitnessPal — MyFitnessPal, Inc. 2. Calm — Calm.com, Inc. 3. Strava — Strava, Inc. 4. Flo Period & Pregnancy Tracker — Flo Health, Inc. 5. Planet Fitness Workouts — Planet Fitness
track_app — Track an app
Start tracking an App Store app on this account, so its keyword ranks are checked daily. Subject to the account's plan limit on number of apps.
| Parameter | Required | Description |
|---|---|---|
appStoreId | Yes | Numeric App Store id, from search_app_store. |
country | No | App Store storefront. One of: us, gb, ca, au, de, fr, es, it, nl, se, jp, kr, in, br, mx. Defaults to us. |
Ask
Start tracking Loopwell in the US store.
Returns
Now tracking Loopwell — Habit Tracker (app id: lw_84210). Add keywords with track_keyword.
track_keyword — Track a keyword
Track a keyword for one of this account's apps, in a specific storefront. The same keyword can be tracked in several storefronts independently. First rank appears after the next daily check. Subject to the account's plan limit on number of keywords.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id, from list_tracked_apps or track_app. |
keyword | Yes | The search term to track. |
country | No | App Store storefront. One of: us, gb, ca, au, de, fr, es, it, nl, se, jp, kr, in, br, mx. Defaults to us. |
Ask
Track “habit streaks” and “routine builder” for Loopwell.
Returns
Tracking "habit streaks" [US] (keyword id: kw_5e13). Its first position appears after the next rank check.
untrack_keyword — Stop tracking a keyword
Stop tracking a keyword. Its recorded rank history is removed with it and cannot be recovered, so confirm with the user before calling this.
| Parameter | Required | Description |
|---|---|---|
keywordId | Yes | Keyword id, from list_tracked_apps. |
Ask
Stop tracking “streak app” — it’s never going to rank.
Returns
Keyword removed, along with its rank history.
Destructive. Clients that honour tool annotations will ask you to confirm before running this one. Rank history accumulates a day at a time and cannot be backfilled, so removing it is permanent.
untrack_app — Stop tracking an app
Stop tracking an app. This also removes every keyword tracked for it, all of their recorded rank history, and the competitors watched against it. None of that can be recovered or backfilled. Always confirm with the user before calling this.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id, from list_tracked_apps. |
Ask
I’ve pulled Loopwell Focus from the store — stop tracking it.
Returns
Stopped tracking Loopwell Focus. 6 keywords and their rank history were removed with it.
Destructive. Clients that honour tool annotations will ask you to confirm before running this one. Rank history accumulates a day at a time and cannot be backfilled, so removing it is permanent.
add_competitor — Watch a competitor
Start watching a competitor's App Store listing against one of this account's apps. Their metadata is snapshotted daily, so list_competitor_changes reports the day they rewrite a title, subtitle or description. Subject to the account's plan limit on number of competitors.
| Parameter | Required | Description |
|---|---|---|
appId | Yes | Overt app id to watch this competitor against. |
competitorAppStoreId | Yes | Numeric App Store id of the competitor, from search_app_store. |
Ask
Watch HabitKit against Loopwell.
Returns
Now watching HabitKit (competitor id: 4f2a91e0). Their first metadata snapshot is taken on the next daily run, and changes appear in list_competitor_changes from the following day.
remove_competitor — Stop watching a competitor
Stop watching a competitor. Metadata changes already recorded for them are kept; only future snapshots stop.
| Parameter | Required | Description |
|---|---|---|
competitorId | Yes | Competitor id, from list_competitors. |
Ask
Stop watching HabitKit.
Returns
Competitor removed. Changes already recorded for them are kept.
Destructive. Clients that honour tool annotations will ask you to confirm before running this one. Rank history accumulates a day at a time and cannot be backfilled, so removing it is permanent.
list_competitors — List watched competitors
List the competitors this account watches, with the id each must be referred to by in remove_competitor and the app each is watched against.
Takes no parameters.
Ask
Who am I watching?
Returns
HabitKit (App Store id: 1573497225, competitor id: 4f2a91e0) — watched against app 9c1f... Streaks (App Store id: 963034692, competitor id: 7b30ca44) — watched against app 9c1f...
generate_metadata — Generate App Store metadata
Generate App Store listing metadata for an app: ranked title/subtitle candidates with the reasoning behind each, plus a full store description. Every field is measured against Apple's real limits (30 characters for title and subtitle, 100 BYTES for the keyword field, 4000 characters for the description) and anything over is flagged. Claims are grounded in features evidenced by the app's own listing, because Apple rejects metadata that misrepresents what an app does. This SPENDS one of the account's monthly generation credits and costs real money — confirm with the user before calling it, and call get_plan_usage first if you need to know how many remain. How many candidates come back, and whether the keyword field is included, depend on the account's plan. Generating from an agent requires a paid plan. On the free plan this returns an explanation instead and spends nothing — the account can still generate in the Overt dashboard, so do not tell the user that generation is unavailable to them.
| Parameter | Required | Description |
|---|---|---|
appStoreId | Yes | Numeric App Store id of the app to write metadata for. |
seedKeyword | Yes | The search term to optimise for. Its top-ranking apps become the competitive set the generation reasons against, so pick the phrase the app should be found by. |
Ask
Rewrite Loopwell’s listing for “habit tracker”.
Returns
Loopwell — Habit Tracker — metadata generated for "habit tracker"
Generation 3 of 5 this month.
Candidate 0:
Title (28/30 chars): Loopwell: Habit Tracker
Subtitle (31/30 chars): Build daily routines that stick
Why: "habit tracker" is absent from the current title, and it is the term with the
highest search volume this app already ranks in the top 60 for.
OVER LIMIT — subtitle is 31 characters against Apple's 30. Not auto-trimmed:
cutting prose mid-word produces garbage. Edit it before shipping.
Description (2841/4000 chars):
Loopwell turns the habits you keep meaning to start into ones you actually keep…
Keyword gaps this was built from: streak, daily routine, habit builder
On the Free plan, 2 more candidates and the keyword field Apple indexes are not
included. The full result was generated and stored either way — upgrading reveals
it without regenerating.
Recorded as generation a81c…. Once the user publishes one of these, call
mark_shipped with that id so Overt can measure what it did to rank.list_generations — List past generations
List metadata generations already produced for this account, newest first, with the id each must be referred to by in mark_shipped and whether it has been shipped. Costs no credit — it reads what was already generated.
| Parameter | Required | Description |
|---|---|---|
appId | No | Optional Overt app id to narrow to one app. Omit for all apps. |
limit | No | How many to return. Defaults to 10. |
Ask
What listings have I generated?
Returns
2026-07-28 — Loopwell, seeded with "habit tracker" (generation id: a81c4d2f) Shipped 2026-07-29, candidate 0. [0] Loopwell: Habit Tracker — Build routines that stick [1] Loopwell — Daily Habits — Track streaks, build routines 2026-07-14 — Loopwell, seeded with "routine" (generation id: 3e90b17a) Not marked as shipped, so its effect cannot be measured. [0] Loopwell — Daily Routine — Small habits, every day
mark_shipped — Mark a generation as shipped
Record which candidate from a past generation was actually put live on the App Store. This is what closes the loop: Overt then compares rank in the seven days before shipping against the days after, so the user can see whether the rewrite worked. Only call this once the user confirms they have actually published the change.
| Parameter | Required | Description |
|---|---|---|
suggestionId | Yes | Generation id, from list_generations. |
chosenCandidate | Yes | Which candidate was shipped, numbered from 0 as listed in list_generations. |
Ask
I published the first option — record that.
Returns
Recorded "Loopwell: Habit Tracker" / "Build routines that stick" as shipped today. Overt compares the seven days before against the days after — the after-window starts tomorrow, because Apple's indexing lag means same-day movement still reflects the old listing.
get_plan_usage — Check plan usage and limits
Report where this account stands against its plan: apps, keywords and competitors used versus allowed, generation credits left this month, how often ranks refresh, and how much of a generation this plan returns. Call this BEFORE bulk tracking or generating, so you can tell the user what will fit instead of hitting a limit part-way through.
Takes no parameters.
Ask
How much of my plan have I used?
Returns
Plan: Free Apps: 1 of 1 used — full Keywords: 7 of 10 used (3 free) Competitors: 1 of 1 used — full Generations this month: 3 of 5 used (2 free) Rank refresh: weekly Generation returns 1 candidate, without the keyword field. Tracking the same keyword in two storefronts uses two keyword slots.
Prompts
As well as tools, Overt publishes 5 prompts — ready-made workflows that appear in your client’s prompt picker. They exist so someone who has just connected Overt has somewhere to start without first learning 20 tool names. Each one expands into instructions the agent then carries out with the tools above.
| Prompt | Arguments | What it does |
|---|---|---|
audit_listing | app | Score an app's listing, explain what is weakest, and say what to change first. Read-only — spends no generation credit. |
plan_keywords | appId | Look at an app's current keywords and ranks, suggest new ones, and score how hard each would be to win. Read-only — spends no generation credit. |
review_competitors | days | Summarise recent competitor metadata changes and what they imply. Read-only — spends no generation credit. |
rewrite_listing | app seedKeyword | Generate new title, subtitle and description candidates for a tracked app. SPENDS one generation credit — asks for confirmation first. |
check_progress | appId | Review shipped listing changes against what ranks did next. Read-only — spends no generation credit. |
Only rewrite_listing can cost anything, and it is written to make the agent check your remaining credits and ask before it generates.
Rate limits
The tools that reach Apple — search_app_store, score_listing, track_app, add_competitor, get_keyword_difficulty, get_top_chart and generate_metadata— spend from Apple’s public API budget of roughly 20 requests a minute, which is shared across all of Overt and is the same budget that runs daily rank checks for every paying customer. They are throttled per credential, so an agent looping over a list gets slowed down rather than being allowed to starve everyone’s rank checks for the day. An API key and an OAuth token draw on separate buckets and cannot exhaust each other. The tools that only read your tracked data are not affected.
Generation costs money
generate_metadata is the one tool here that spends something. Each call uses one of your monthly generation credits and makes a real model call, so it is deliberately not marked idempotent — a client must never silently retry it, because a retry spends a second credit and returns different text. Call get_plan_usage first if you want to know how many you have left.
The ceiling is enforced in Postgres before any model call, and the claim is atomic — an agent calling in a loop is refused at the limit rather than running up a bill. If a generation fails after the credit is claimed, the credit is returned. How many candidates come back, and whether the keyword field is included, depend on your plan; when something is withheld the response says so rather than quietly returning less.
Troubleshooting
- 401 Unauthorized — the key is missing, malformed, or revoked. Confirm the header is
Authorization: Bearer <key>and mint a fresh key if unsure. - An agent reports a keyword has “no rank” — check whether the response said
not in top 200(checked, not found) ornot checked yet(tracked, but the next daily check has not run). They mean different things. - A write fails on a plan limit — an agent cannot raise your app or keyword allowance. The limit is the one on your plan.
Create an API key to get started, or try Overt in the browser first — it is free, with no card.