Koskamo

AppGoat MCP

AppGoat provides App Store and Google Play intelligence for AI agents, enabling live data access for apps, reviews, keywords, charts, and competitors. It allows agents to automate ASO tasks like keyword research, competitor monitoring, review analysis, and Apple Ads bid management, with human approval for listing changes.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

AppGoat MCP logo, by AppGoatVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by AppGoat
You need:Create a free account (the Free plan comes with 250 credits a month, no credit card)open API keys in the dashboard and create a keyKeys start with ag_
MCP endpoint (Streamable HTTP)
https://api.appgoat.ai/mcp
Vendor documentation

What you can do with it

  • Monitor competitor app rankings and metadata changes
  • Analyze user reviews to identify bugs and sentiment
  • Research keywords and rewrite app store listings
  • Manage Apple Ads bids based on target CPI

Source and maintenance

Vendor evidenceRegistry 0.2.0

Protocol and capabilities

Server
appgoat 0.2.0
MCP protocol
2025-06-18
Tools
26 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
9 advertised
Server-advertised capabilities
{
  "tools": {},
  "prompts": {}
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

AppGoat is live App Store and Google Play data for ASO and app growth: apps, reviews, keywords and ranks, competitors, charts, App Audits, and watches that turn store changes into events. First use: call list_watches. If there are none, offer to set AppGoat up: find the user's app (search_apps, or the store URL they give), watch it (watch kind app), watch its competitors (get_competitors, then watch kind competitor_set with the ones the user picks) and run audit_app (the first audit of an organization is free). Ask before creating watches: they are free but use plan slots. The get_started prompt walks through this. Watches check every day and the user gets a daily email digest of what changed. Read changes with get_events (since = the newest created_at already handled). Changes to the user's own listings, review replies and Apple Ads are drafted with propose_action (a dry run): show the diff and guardrail flags, and call apply_action only after the user approves. App Store Connect, Google Play Console and Apple Ads accounts are connected at https://dash.appgoat.ai/connections. Playbooks (list_playbooks, also MCP prompts) are step-by-step recipes for common ASO jobs.

Tools

26 advertised

get_app — Get App
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Look up one App Store or Google Play app: title, subtitle, developer, category, price, rating and histogram, installs (Play), version and dates, description, languages, and the same app in the other store. Accepts any id, bundle id, package, store URL or a name. Reads stored data (refreshed from the store only when older than max_age, default 7 days) for one country (default us); add include sections for markets, versions, IAP, privacy, estimates and chart positions. Cost: 1 + 1 per country refreshed from the store (max 10) credits.

get_app input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "wait": {
      "type": "boolean",
      "description": "Block up to ~25 s for a refresh (default). false = answer immediately from cache with a job id."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "ISO country code(s): `us` (default), a comma list (paid plans), or `all` (Studio). Example: us,de"
    },
    "include": {
      "type": "array",
      "items": {
        "enum": [
          "markets",
          "iap",
          "versions",
          "privacy",
          "estimates",
          "charts"
        ],
        "type": "string"
      },
      "description": "Extra sections: markets (every storefront), iap, versions (history with release notes), privacy (App Store labels), estimates (modelled downloads/revenue), charts (current top-chart positions)"
    },
    "max_age": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Refresh from the store when our data is older than this many seconds (0 = always). Default 604800 (7 days)."
    },
    "full_text": {
      "type": "boolean",
      "description": "Return long text (description, release notes, review bodies) in full instead of cut short"
    }
  }
}
get_app annotations
{
  "title": "Get App",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_reviews — Get Reviews
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Read an app's user reviews, newest first, up to 100 per page: rating, title, text, version, date, developer reply and AI tags (sentiment, intent, severity, topic) where tagged. Filter by stars (rating='1-2' for complaints), version, date range, text (q) or AI tags (intent='bug,crash'; tag filters skip untagged reviews). Page with cursor. Cost: 1 per page + 1 if the US reviews are refreshed credits.

get_reviews input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "q": {
      "type": "string",
      "description": "Case-insensitive text search in the title and body. Example: crash"
    },
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "limit": {
      "type": "integer",
      "maximum": 100,
      "minimum": 1,
      "description": "Max items to return. Default: 50."
    },
    "since": {
      "type": "string",
      "description": "Only items at or after this ISO date / datetime. Example: 2026-10-01"
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "topic": {
      "type": "string",
      "description": "AI topic filter (comma list of topic labels, case-insensitive, or topic ids)."
    },
    "until": {
      "type": "string",
      "description": "Only reviews created before this ISO date / datetime."
    },
    "cursor": {
      "type": "string",
      "description": "`meta.next_cursor` from the previous page."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "intent": {
      "type": "string",
      "description": "AI intent filter (comma list): bug, crash, feature_request, pricing, ux, praise, spam, other. Example: bug,crash"
    },
    "rating": {
      "type": "string",
      "description": "Star rating filter, `1`, `1,2` or a range `1-3`. Example: 1-2"
    },
    "country": {
      "type": "string",
      "description": "ISO country code(s): `us` (default), a comma list (paid plans), or `all` (Studio). Example: us,de"
    },
    "max_age": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Refresh the latest US reviews when older than this many seconds. Default 86400 (1 day)."
    },
    "version": {
      "type": "string",
      "description": "Only reviews written for this app version."
    },
    "full_text": {
      "type": "boolean",
      "description": "Return long text (description, release notes, review bodies) in full instead of cut short"
    },
    "sentiment": {
      "type": "string",
      "description": "AI sentiment filter (comma list): positive, neutral, negative. Example: negative"
    }
  }
}
get_reviews annotations
{
  "title": "Get Reviews",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_app_history — Get App History
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

An app's daily metric history per country: rating, ratings count, reviews count, installs (Play), star histogram and price, one row per day a value changed (default the last 90 days), with the change over the period. Use it to chart growth or spot rating drops after a release. Cost: 1 + 1 per country refreshed (max 10) credits.

get_app_history input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "to": {
      "type": "string",
      "description": "End date (ISO), default today."
    },
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "from": {
      "type": "string",
      "description": "Start date (ISO), default 90 days before `to`."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "ISO country code(s): `us` (default), a comma list (paid plans), or `all` (Studio). Example: us,de"
    }
  }
}
get_app_history annotations
{
  "title": "Get App History",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_app_changes — Get App Changes
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

What changed in an app's store listing, newest first, with old and new values: version, release notes, title, subtitle, description, screenshots, icon, price, IAP, privacy, in-app events, badges, featuring, installs, content rating. Use it to monitor competitors ("what did X change this month?"). Cost: 1 + 1 if the US listing is refreshed credits.

get_app_changes input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "field": {
      "type": "string",
      "description": "Only these fields (comma list), e.g. `version,title,subtitle`."
    },
    "limit": {
      "type": "integer",
      "maximum": 200,
      "minimum": 1,
      "description": "Max items to return. Default: 50."
    },
    "since": {
      "type": "string",
      "description": "Only items at or after this ISO date / datetime. Example: 2026-10-01"
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "cursor": {
      "type": "string",
      "description": "`meta.next_cursor` from the previous page."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Only changes seen in these storefronts (comma list). Default all storefronts."
    }
  }
}
get_app_changes annotations
{
  "title": "Get App Changes",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_app_keywords — Get App Keywords
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

The search terms an app ranks for in a country, best rank first, with popularity (5–100) and difficulty (0–100): from the weekly keyword universe plus your tracked keywords. Call it for the app and a competitor to find keyword gaps. Cost: 1 credits.

get_app_keywords input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "limit": {
      "type": "integer",
      "maximum": 500,
      "minimum": 1,
      "description": "Max items to return. Default: 100."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "cursor": {
      "type": "string",
      "description": "`meta.next_cursor` from the previous page."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Two-letter country code (default 'us')."
    },
    "max_rank": {
      "type": "integer",
      "maximum": 500,
      "minimum": 1,
      "description": "Only terms where the app ranks at or above this position."
    }
  }
}
get_app_keywords annotations
{
  "title": "Get App Keywords",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_competitors — Get Competitors
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

An app's competitors, best first, scored from search terms both apps rank for (shared keywords) plus the store's similar-apps list. Feed the app ids into get_app or get_app_changes for a competitor digest. Cost: 1 credits.

get_competitors input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "limit": {
      "type": "integer",
      "maximum": 100,
      "minimum": 1,
      "description": "Max items to return. Default: 20."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Two-letter country code (default 'us')."
    }
  }
}
get_competitors annotations
{
  "title": "Get Competitors",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
search_apps — Search Apps
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Find apps by name or id in AppGoat's catalog of both stores (~5M apps): exact title matches first, then prefix, then substring, most-rated first. Returns store, app_id, title, developer, category, rating, ratings and price; pass the app_id to the other tools. Cost: 1 credits.

search_apps input schema
{
  "type": "object",
  "required": [
    "q"
  ],
  "properties": {
    "q": {
      "type": "string",
      "description": "App name (≥ 2 characters) or exact id. Example: photo editor"
    },
    "limit": {
      "type": "integer",
      "maximum": 100,
      "minimum": 1,
      "description": "Max items to return. Default: 20."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Limit to one store: 'apple' or 'play'. Omit for both."
    },
    "cursor": {
      "type": "string",
      "description": "`meta.next_cursor` from the previous page."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "category": {
      "type": "string",
      "description": "Store category name, e.g. `Photo & Video` (App Store) or `PHOTOGRAPHY` (Play)."
    }
  }
}
search_apps annotations
{
  "title": "Search Apps",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_charts — Get Charts
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

A top free, paid or grossing chart for a store, country and category, today or on a past date: rank, app, developer, rating and the move since the previous capture (new entries marked), plus apps that dropped out. Charts are captured daily for every country and category. Cost: 1 credits.

get_charts input schema
{
  "type": "object",
  "properties": {
    "date": {
      "type": "string",
      "description": "The chart as of this date (ISO). Default the latest capture."
    },
    "chart": {
      "enum": [
        "free",
        "paid",
        "grossing"
      ],
      "type": "string",
      "description": "'free' (default), 'paid' or 'grossing'."
    },
    "limit": {
      "type": "integer",
      "maximum": 200,
      "minimum": 1,
      "description": "How many ranks to return (default 100, max 200)."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "'apple' (default) or 'play'."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Two-letter country code (default 'us')."
    },
    "category": {
      "type": "string",
      "description": "App Store genre id (`36` or `all` = all apps, `6014` = games, …) or Play category (`GAME_PUZZLE`; `APPLICATION` = all apps)."
    }
  }
}
get_charts annotations
{
  "title": "Get Charts",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
keyword_research — Keyword Research
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Keyword metrics and research for App Store / Google Play search terms: popularity (5–100), difficulty (0–100), result count and the #1 result's estimated daily downloads. include adds related terms with metrics, the store's autocomplete and the current top 10 apps; app adds that app's rank and metadata relevance per term (the core of an ASO keyword audit). Unmeasured terms are measured live (a few per call) or come back pending. Cost: 1 per keyword; 5 per seed with include=related or suggestions credits.

keyword_research input schema
{
  "type": "object",
  "required": [
    "terms"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier (as in `{app}`); adds `app.rank` and `app.relevance` per term."
    },
    "wait": {
      "type": "boolean",
      "description": "Block up to ~25 s for a refresh (default). false = answer immediately from cache with a job id."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Required unless `app` is given."
    },
    "terms": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "maxItems": 25,
      "minItems": 1,
      "description": "Search terms, 1–25 (at most 5 with include related or suggestions)"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Two-letter ISO country code (storefront), e.g. us, gb, de. Default: us."
    },
    "include": {
      "type": "array",
      "items": {
        "enum": [
          "related",
          "suggestions",
          "top_apps"
        ],
        "type": "string"
      },
      "description": "related (~10 related terms with metrics), suggestions (store autocomplete), top_apps (current top 10). related/suggestions cost 5 credits per term"
    }
  }
}
keyword_research annotations
{
  "title": "Keyword Research",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_keyword_ranks — Get Keyword Ranks
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Ranking history of a watched keyword: per capture the top 10 app ids, or with app, that app's rank over time (best, worst, latest). Default the last 90 days. The id is a keyword slot of a keyword watch (list_watches and watch show the slot ids). Cost: 1 credits.

get_keyword_ranks input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Keyword slot id (from a keyword watch)"
    },
    "to": {
      "type": "string",
      "description": "End date or datetime (ISO), default now."
    },
    "app": {
      "type": "string",
      "description": "Store app id; returns `rank` per point instead of the full id list."
    },
    "from": {
      "type": "string",
      "description": "Start, ISO date or datetime (default 90 days ago)"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
get_keyword_ranks annotations
{
  "title": "Get Keyword Ranks",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
watch — Watch
Advertised by the server during the last successful anonymous check.
Open-world

Watch an app, a set of competitors or a set of keywords; significant changes become events (get_events, webhooks, daily email). kind app {app}: new versions, metadata and price changes, featuring, rating drops, review and ratings spikes, chart entries. kind competitor_set {competitors, app?}: the same for every competitor. kind keyword {terms, store or app}: the app's rank moves per term and new apps in the top N. Watched apps count against the plan's watch limit, keyword watches use one keyword slot per term × store × country; over a limit nothing changes (plan_limit). With id, changes that watch instead (send only what changes; settings are merged; active=false pauses it). Cost: 0 credits.

watch input schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "maximum": 9007199254740991,
      "description": "Watch id to change (from list_watches). Omit to create a watch",
      "exclusiveMinimum": 0
    },
    "app": {
      "type": "string",
      "description": "Any app id, bundle id, package, store URL or name. kind app: the app (required); competitor_set: your own app (optional); keyword: the app whose ranks to report (optional)"
    },
    "kind": {
      "enum": [
        "app",
        "keyword",
        "competitor_set"
      ],
      "type": "string",
      "description": "'app' (one app), 'competitor_set' (several apps) or 'keyword' (search terms). Required when creating"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "A label for the watch"
    },
    "store": {
      "enum": [
        "apple",
        "play",
        "both"
      ],
      "type": "string",
      "description": "'apple', 'play' or 'both' (keyword watches without app; default both). Also disambiguates app inputs"
    },
    "terms": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 500,
      "description": "kind keyword: search terms, e.g. ['habit tracker', 'streaks']"
    },
    "active": {
      "type": "boolean",
      "description": "false pauses the watch, true resumes it"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "settings": {
      "type": "object",
      "properties": {
        "depth": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Keyword watches: results kept per ranking (Apple ≤ 250, Play ≤ 30)."
        },
        "rank_move": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "chart_top_n": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "rating_drop": {
          "type": "number",
          "description": "Stars over 7 days. Default: 0.1."
        },
        "email_digest": {
          "type": "boolean",
          "description": "Include in the daily email digest. Default: true."
        },
        "significance": {
          "type": "number",
          "maximum": 1,
          "minimum": 0,
          "description": "Minimum significance for an event: Jev's probability that an analyst would want the alert (AI on), or a fixed per-type score. Default: 0.5."
        },
        "spike_factor": {
          "type": "number"
        },
        "keyword_top_n": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "cadence_minutes": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Keyword watches: minutes between re-ranks (360…10080)."
        }
      },
      "description": "Thresholds: significance (0–1, default 0.5, minimum for an event), rank_move (default 5), keyword_top_n (10), chart_top_n (100), rating_drop (stars over 7 days, 0.1), spike_factor (3), email_digest (true), depth and cadence_minutes (keyword watches)"
    },
    "countries": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z]{2}$"
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "Two-letter country codes to watch in (default ['us'])"
    },
    "competitors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 50,
      "description": "kind competitor_set: the apps to watch (any identifiers), up to 50"
    },
    "event_types": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "enum": [
              "new_version",
              "metadata_change",
              "price_change",
              "featured",
              "in_app_event",
              "installs_milestone",
              "rating_drop",
              "ratings_spike",
              "review_spike",
              "negative_review_spike",
              "chart_enter",
              "chart_leave",
              "rank_change",
              "keyword_entrant"
            ],
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ],
      "description": "Only these event types (default: every type of the kind)"
    }
  }
}
watch annotations
{
  "title": "Watch",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
unwatch — Unwatch
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Stop watches by id (from list_watches or watch): no new events, and their watched apps and keyword slots are freed. Past events are kept. To pause instead, call watch with id and active=false. Cost: 0 credits.

unwatch input schema
{
  "type": "object",
  "required": [
    "ids"
  ],
  "properties": {
    "ids": {
      "type": "array",
      "items": {
        "type": "integer",
        "maximum": 9007199254740991,
        "exclusiveMinimum": 0
      },
      "maxItems": 100,
      "minItems": 1,
      "description": "Watch ids"
    }
  }
}
unwatch annotations
{
  "title": "Unwatch",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
list_watches — List Watches
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Your watches (apps, competitor sets, keyword sets), newest first, with id, apps, terms, countries, event types and whether they are paused, plus watched apps and keyword slots used vs the plan's limits. Filter by kind or by an app they include. Cost: 0 credits.

list_watches input schema
{
  "type": "object",
  "properties": {
    "app": {
      "type": "string",
      "description": "Only watches that include this app (any id, bundle id, package, URL or name)."
    },
    "kind": {
      "enum": [
        "app",
        "keyword",
        "competitor_set"
      ],
      "type": "string",
      "description": "Only this kind: 'app', 'competitor_set' or 'keyword'."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
list_watches annotations
{
  "title": "List Watches",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_events — Get Events
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Significant changes on your watched apps and keywords, newest first: type, one-line title, AI summary, significance (0–1), app, country and the key payload fields (version, changes old → new, rating drop, rank move, chart rank…). Filter by type, app, watch, since and min_significance. To check for news, pass since = the created_at of the newest event already handled. Cost: 0 credits.

get_events input schema
{
  "type": "object",
  "properties": {
    "app": {
      "type": "string",
      "description": "Only events of this app (any id, bundle id, package, URL or name)."
    },
    "type": {
      "type": "string",
      "description": "Comma list of event types, e.g. 'new_version,rating_drop'. Types: new_version, metadata_change, price_change, featured, in_app_event, installs_milestone, rating_drop, ratings_spike, review_spike, negative_review_spike, chart_enter, chart_leave, rank_change, keyword_entrant."
    },
    "limit": {
      "type": "integer",
      "maximum": 200,
      "minimum": 1,
      "description": "Max items to return. Default: 50."
    },
    "since": {
      "type": "string",
      "description": "Only items at or after this ISO date / datetime. Example: 2026-10-01"
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "watch": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Only events of this watch id."
    },
    "cursor": {
      "type": "string",
      "description": "`meta.next_cursor` from the previous page."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "min_significance": {
      "type": "number",
      "maximum": 1,
      "minimum": 0,
      "description": "Only events at least this significant (0–1)."
    }
  }
}
get_events annotations
{
  "title": "Get Events",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_developer — Get Developer
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

A developer's profile: name, website, country, app count, total ratings and installs, all their apps (most-rated first) and the same company in the other store. get_app shows the developer id as dev <store>:<id>. Cost: 1 credits.

get_developer input schema
{
  "type": "object",
  "required": [
    "dev"
  ],
  "properties": {
    "dev": {
      "type": "string",
      "description": "`apple:<artist id>`, `play:<developer id>`, a numeric Apple artist id, a Play developer id (often the name), or the website domain (`spotify.com`). Example: apple:324684583"
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
get_developer annotations
{
  "title": "Get Developer",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_job — Get Job
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Poll a background store fetch that another call started (its output said refreshing or still being fetched, with a job id): status, per-country progress. When it is done, repeat the original call. Cost: 0 credits.

get_job input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "`meta.freshness.job_id`, e.g. `fetch_123`."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
get_job annotations
{
  "title": "Get Job",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
list_connections — List Connections
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

The user's connected App Store Connect, Play Console and Apple Ads accounts: connection id, provider, mode (actions or read_only), status and the linked apps. Start here before read_connection or propose_action; secrets are never returned. No connections yet: the user adds them at https://dash.appgoat.ai/connections. Cost: 0 credits.

list_connections input schema
{
  "type": "object",
  "properties": {
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "provider": {
      "enum": [
        "asc",
        "play_console",
        "apple_ads"
      ],
      "type": "string",
      "description": "Only this provider: 'asc' (App Store Connect), 'play_console' or 'apple_ads'."
    }
  }
}
list_connections annotations
{
  "title": "List Connections",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
read_connection — Read Connection
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Read live data from one of the user's connected accounts. what='reviews' (asc, play_console): the app's own reviews with reply status, unanswered=true for those without a developer reply; their review_id feeds propose_action review.reply (Play only returns reviews from the last 7 days). what='listing' (asc, play_console): the current listing text for one locale with lengths and which fields are editable right now (App Store name, subtitle, description, keywords and what's new need a version in Prepare for Submission). what='ads' (apple_ads): view=campaigns → ad_groups (campaign_id) → keywords (campaign_id, ad_group_id) gives the ids the ads.* actions take, view=negatives lists negative keywords, view=report with level=campaigns|adgroups|keywords|searchterms returns impressions, taps, installs, spend, CPT and CPA for start..end (default the last 7 days). Cost: 1 credits.

read_connection input schema
{
  "type": "object",
  "required": [
    "id",
    "what"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Connection id (con_…) from list_connections"
    },
    "app": {
      "type": "string",
      "description": "A linked app (App Store id or package name); required for reviews and listing"
    },
    "end": {
      "type": "string",
      "description": "ads report: end date YYYY-MM-DD (default yesterday, UTC)"
    },
    "view": {
      "enum": [
        "campaigns",
        "ad_groups",
        "keywords",
        "negatives",
        "report"
      ],
      "type": "string",
      "description": "ads: 'campaigns' (default), 'ad_groups', 'keywords', 'negatives' or 'report'"
    },
    "what": {
      "enum": [
        "reviews",
        "listing",
        "ads"
      ],
      "type": "string",
      "description": "'reviews', 'listing' or 'ads' (Apple Ads)"
    },
    "level": {
      "enum": [
        "campaigns",
        "adgroups",
        "keywords",
        "searchterms"
      ],
      "type": "string",
      "description": "ads report: 'campaigns' (default), 'adgroups', 'keywords' or 'searchterms'"
    },
    "limit": {
      "type": "integer",
      "maximum": 1000,
      "minimum": 1,
      "description": "Max rows: reviews up to 200 (default 100), ads up to 1000 (default 200)"
    },
    "start": {
      "type": "string",
      "description": "ads report: start date YYYY-MM-DD (default 7 days before end)"
    },
    "cursor": {
      "type": "string",
      "description": "reviews: next_cursor from the previous page"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "locale": {
      "type": "string",
      "description": "listing: locale such as en-US, de-DE (default en-US)"
    },
    "rating": {
      "type": "string",
      "description": "reviews: star filter, '1', '1,2' or '1-3'"
    },
    "country": {
      "type": "string",
      "description": "reviews: App Store territory filter (two-letter code)"
    },
    "full_text": {
      "type": "boolean",
      "description": "Return long text (description, release notes, review bodies) in full instead of cut short"
    },
    "unanswered": {
      "type": "boolean",
      "description": "reviews: only reviews without a developer reply"
    },
    "ad_group_id": {
      "type": "string",
      "description": "ads: ad group id (needed for keywords; optional for negatives)"
    },
    "campaign_id": {
      "type": "string",
      "description": "ads: campaign id (needed for ad_groups, keywords, negatives and every report level except campaigns)"
    }
  }
}
read_connection annotations
{
  "title": "Read Connection",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
propose_action — Propose Action
Advertised by the server during the last successful anonymous check.
Open-world

Prepare a change to the user's connected account as a DRY RUN: nothing is written. AppGoat reads the live account and returns the before → after diff, guardrail results (AI probabilities for store policy, tone and risky claims, plus checks such as character limits and bid jumps) and an action id. ALWAYS show the diff and any guardrail flags to the user and get their go-ahead before calling apply_action. Types and params (app = a linked App Store id or package name, locale like en-US): review.reply {app, review_id, text} (review ids from read_connection what=reviews; Play replies ≤ 350 chars); listing.update {app, locale, fields: {name|title, subtitle, description, promotional_text, whats_new, marketing_url, support_url, privacy_policy_url}} (Play: title, short_description, full_description, video); keywords.set {app, locale, keywords: [..] or 'a,b,c', mode?: replace|add|remove} (App Store, 100 bytes comma-joined); screenshots.upload {app, locale, display_type: APP_IPHONE_67… (asc) or image_type: phoneScreenshots… (play), images: [{url}], replace?}; ads.keyword.bid {campaign_id, ad_group_id, keywords: [{id, bid?, status?: ENABLED|PAUSED}], max_increase?}; ads.keyword.add {campaign_id, ad_group_id, keywords: [{text, match_type?: EXACT|BROAD, bid?}]}; ads.negative.add {campaign_id, ad_group_id?, keywords: [{text, match_type?}]} (Apple Ads ids from read_connection what=ads). Cost: 0 credits.

propose_action input schema
{
  "type": "object",
  "required": [
    "type",
    "params"
  ],
  "properties": {
    "type": {
      "enum": [
        "review.reply",
        "listing.update",
        "keywords.set",
        "screenshots.upload",
        "ads.keyword.bid",
        "ads.keyword.add",
        "ads.negative.add"
      ],
      "type": "string",
      "description": "What to change: review.reply, listing.update, keywords.set, screenshots.upload, ads.keyword.bid, ads.keyword.add or ads.negative.add"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "params": {
      "type": "object",
      "description": "Params for the type (see the tool description)",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "playbook": {
      "type": "string",
      "maxLength": 80,
      "minLength": 1,
      "description": "The playbook proposing this, e.g. 'reply-to-every-review' (shown to approvers); omit outside a playbook"
    },
    "connection": {
      "type": "string",
      "description": "Connection id from list_connections; optional when exactly one active connection fits the type and app"
    }
  }
}
propose_action annotations
{
  "title": "Propose Action",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
apply_action — Apply Action
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Go ahead with an action from propose_action, after the user has seen its diff and agreed. Outcomes: applied (written to the store / Apple Ads account, 1 credit; when the org has an auto-apply rule the guardrail score clears, or allows agents to approve); pending_approval (a person must approve it in the AppGoat dashboard: give the user the approve link, nothing is written until then); needs a person (it was already pending and agents may not approve: hand over the link, do not retry); changed (the account changed since the dry run: the new diff is shown; show it to the user and call again with force=true only if they accept it, or propose_action again). Cost: 1 credit when applied, else 0 credits.

apply_action input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Action id (act_…) from propose_action"
    },
    "force": {
      "type": "boolean",
      "description": "Apply the recomputed diff even though the account changed since the dry run. Only after the user has seen the new diff"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
apply_action annotations
{
  "title": "Apply Action",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": true
}
get_action — Get Action
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

One action from propose_action: its status (draft, pending_approval, approved, applied, failed, rejected), diff, guardrail scores, the provider result or error, the approve link and the audit trail. Use it to check whether a pending action was approved and applied. Cost: 0 credits.

get_action input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Action id (act_…)"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
get_action annotations
{
  "title": "Get Action",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
reject_action — Reject Action
Advertised by the server during the last successful anonymous check.
Open-world

Discard a draft or pending action the user does not want; nothing is written to the account. Cost: 0 credits.

reject_action input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Action id (act_…)"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "reason": {
      "type": "string",
      "description": "Why (shown in the audit log)"
    }
  }
}
reject_action annotations
{
  "title": "Reject Action",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
audit_app — Audit App
Advertised by the server during the last successful anonymous check.
Open-world

Run an App Audit of one app in one country: a 0–100 score, prioritised ASO actions with evidence, title / subtitle / keyword rewrites within the store character limits, and findings from listing, ratings, reviews, keywords and competitors, plus a shareable report page. Takes 1–3 minutes: waits about 25 s, then returns the audit id to pass to get_audit. An audit of the same app, country and mode from the last 24 h is returned again for free unless fresh=true; failed audits are not charged. The first audit of an organization is free (free_only=true runs only that one). Cost: 100 credits.

audit_app input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "mode": {
      "enum": [
        "full",
        "lite"
      ],
      "type": "string",
      "description": "lite = cached data, fewer reviews and keywords (cheaper and faster for us; same price). Default: full."
    },
    "fresh": {
      "type": "boolean",
      "description": "Run again even if a recent audit exists. Default: false."
    },
    "label": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ],
      "description": "Your label for the audit list, e.g. the client or prospect name."
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "Two-letter country code, one storefront (default 'us')."
    },
    "free_only": {
      "type": "boolean",
      "description": "Only run when it is the free first audit (402 free_audit_used otherwise). Default: false."
    },
    "white_label": {
      "type": "boolean",
      "description": "Studio: the shareable report shows the organization's branding (set in the dashboard under Settings → Report branding) instead of AppGoat's, e.g. for client or prospect reports."
    }
  }
}
audit_app annotations
{
  "title": "Audit App",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_audit — Get Audit
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Check on an App Audit that audit_app started (by its id, e.g. aud_3fK9aQ2mXc81LpRt): waits up to about 25 s for it to finish, then returns the report (score, actions, metadata rewrites, findings, report page) or its status. Cost: 0 credits.

get_audit input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Audit id from audit_app, e.g. aud_3fK9aQ2mXc81LpRt"
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    }
  }
}
get_audit annotations
{
  "title": "Get Audit",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_insights — Get Review Insights
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

What an app's users praise and complain about, from the AI tags on its reviews: top issues (topics behind negative, bug, crash, UX and pricing reviews) with last-30-days vs previous-30-days counts and sample reviews, topics, what each recent version changed in rating, sentiment and topics, and weekly sentiment. Use it for "what do users complain about since v2.3?" before reading individual reviews with get_reviews. Cost: 25 credits.

get_insights input schema
{
  "type": "object",
  "required": [
    "app"
  ],
  "properties": {
    "app": {
      "type": "string",
      "description": "Any app identifier: App Store id (`284882215`, `id284882215`), Play package (`com.spotify.music`), Apple bundle id (`com.spotify.client`), store URL (URL-encoded), `apple:<id>` / `play:<id>`, or a name (`spotify`). Example: com.spotify.music"
    },
    "store": {
      "enum": [
        "apple",
        "play"
      ],
      "type": "string",
      "description": "Disambiguates `{app}` (a bundle id vs a Play package, or a name)."
    },
    "format": {
      "enum": [
        "markdown",
        "json"
      ],
      "type": "string",
      "description": "'markdown' (default): compact tables for reading. 'json': the API's raw { data, meta }"
    },
    "country": {
      "type": "string",
      "description": "One storefront; omit for every storefront we hold reviews for."
    },
    "versions": {
      "type": "integer",
      "maximum": 20,
      "minimum": 1,
      "description": "How many of the latest versions to break down. Default: 6."
    },
    "since_days": {
      "type": "integer",
      "maximum": 730,
      "minimum": 7,
      "description": "How many days of reviews to analyse, 7–730 (default 180)."
    }
  }
}
get_insights annotations
{
  "title": "Get Review Insights",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
list_playbooks — List Playbooks
Advertised by the server during the last successful anonymous check.
Advertised read-only

AppGoat playbooks: step-by-step recipes (which tools to call, credit budget, decision rules, output format) for app audits, app idea research, ASO metadata rewrites, weekly competitor digests, turning reviews into GitHub issues, and, on connected accounts, replying to every review, optimizing Apple Ads and pushing localized listings. Without name, lists them; with name, returns the full playbook to follow. Also offered as MCP prompts. Free.

list_playbooks input schema
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "description": "A playbook name from the list, e.g. 'app-audit-lite'"
    }
  }
}
list_playbooks annotations
{
  "title": "List Playbooks",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

9 advertised

get_started — Get started with AppGoat

Advertised by the server during the last successful anonymous check.

Set AppGoat up for the user's app: watch it and its competitors, run a first App Audit, explain the daily digest and approvals, and suggest playbooks to run next.

app
Your app: name or store URL (asked for when missing)
app-audit-lite — App audit (lite)

Advertised by the server during the last successful anonymous check.

Runs a quick App Store / Google Play audit of one app with live AppGoat data - listing quality, ratings trend, recent complaints, keyword rankings, competitors and their recent changes - and ends with a prioritized fix list. Use when the user says "audit my app", "review my App Store listing", "why are my downloads dropping", "how does my app compare to competitors", "ASO check" or pastes an App Store / Google Play link and asks what to improve.

app
The app: store URL, App Store id, Play package, bundle id or name (required)
country
Two-letter storefront code (default 'us')
apple-ads-optimizer — Apple Ads optimizer

Advertised by the server during the last successful anonymous check.

Optimizes the user's Apple Ads (Search Ads) campaigns through their connected Apple Ads account - reads the last 14 days of keyword and search term reports, raises bids on keywords that convert under the target CPA (capped +30% per run), lowers or pauses keywords that spend without installs, adds converting search terms as exact keywords and wasteful ones as negatives - every change a dry run with a diff the user approves. Use when the user says "optimize my Apple Ads", "Apple Search Ads bids", "which keywords are wasting money", "add negative keywords", "harvest search terms", "lower my CPA" or sets up a weekly ads review.

campaign
Apple Ads campaign name or id (default: every enabled campaign)
target_cpa
Target cost per install in the campaign currency, e.g. 2.50 (asked for when missing)
aso-keywords-metadata-rewrite — ASO keywords → metadata rewrite

Advertised by the server during the last successful anonymous check.

Researches App Store / Google Play keywords for one app with live AppGoat data (current ranks, competitor keyword gaps, popularity, difficulty, relevance) and rewrites the title, subtitle, keyword field and description within the store character limits. Use when the user says "improve my ASO", "rewrite my app title / subtitle", "which keywords should I target", "fill my keyword field", "optimize my App Store listing", "ASO for <app>" or prepares a new version's metadata.

app
The app: store URL, App Store id, Play package, bundle id or name (required)
country
Two-letter storefront code (default 'us')
competitor-digest — Competitor digest

Advertised by the server during the last successful anonymous check.

Writes a weekly competitor digest for one App Store / Google Play app from an AppGoat competitor watch - what each competitor changed (title, subtitle, description, screenshots, icon), price and in-app purchase changes, new versions with release-note summaries, rating and chart moves, keyword gains and losses against the user's app, keyword gaps and review themes - and ends with 3 recommended actions linked to other playbooks. Sets up or reuses the competitor_set watch. Use when the user says "what did my competitors change", "weekly competitor report", "competitor digest", "monitor my competitors", "spy on competitor apps", "did anyone change their subtitle" or sets up a weekly competitor summary.

app
The app: store URL, App Store id, Play package, bundle id or name (required)
competitors
Comma list of competitor apps, any identifier (default: the competitor watch, else the top 5 competitors)
country
Two-letter storefront code (default 'us')
find-app-ideas — Find app ideas

Advertised by the server during the last successful anonymous check.

Finds underserved App Store / Google Play niches with live AppGoat data - search demand (keyword popularity) against weak supply (low ratings, abandoned incumbents, few strong apps) - and returns a ranked shortlist of app ideas with evidence and user pain points. Use when the user says "find me an app idea", "what app should I build", "underserved niches", "app opportunities in <category>", "is there demand for a <type> app" or wants to validate an idea before building.

niche
A niche or seed idea, e.g. 'habit tracker for ADHD' (default: let the playbook pick from the charts)
store
'apple' or 'play' (default both or the playbook's choice)
country
Two-letter storefront code (default 'us')
localization-push — Localization push

Advertised by the server during the last successful anonymous check.

Localizes the user's own App Store / Google Play listing into new languages through their connected App Store Connect or Play Console account - picks target locales from markets with demand, researches the keywords people actually search in each country with AppGoat, writes a localized name, subtitle, keyword field and promotional text (Play title, short and full description) within the store limits, and pushes each locale as a dry run with a before/after diff the user approves. Use when the user says "localize my app listing", "translate my App Store page", "add German / Japanese metadata", "which languages should my app support", "push keywords for other countries" or "localization push".

app
The app: store URL, App Store id, Play package, bundle id or name (required)
locales
Comma list of locales, e.g. de-DE,fr-FR,ja (default: suggested from markets with demand)
reply-to-every-review — Reply to every review

Advertised by the server during the last successful anonymous check.

Drafts a reply to every unanswered App Store and Google Play review of the user's own app, in the app's voice, through their connected App Store Connect / Play Console account - each reply is a dry run with a before/after diff and AppGoat guardrail scores (policy, tone, claims), and only the replies the user approves are posted. Use when the user says "reply to my reviews", "answer every review", "respond to unanswered reviews", "draft review replies", "clear the review backlog" or sets up daily review replies.

app
The app: store URL, App Store id, Play package, bundle id or name
since
ISO date to start from (default: the playbook default window)
reviews-to-github-issues — Reviews → GitHub issues

Advertised by the server during the last successful anonymous check.

Turns recent negative App Store / Google Play reviews into deduplicated GitHub issues - one issue per problem topic, with linked and quoted reviews, new reviews added as comments to the existing issue instead of duplicates. Uses AppGoat review data and the gh CLI (or the GitHub MCP server). Use when the user says "turn reviews into issues", "file bugs from app reviews", "what are users complaining about, make tickets", "sync App Store reviews to GitHub" or sets up a daily review triage.

app
The app: store URL, App Store id, Play package, bundle id or name (required)
repo
GitHub repository as owner/name (required)
since
ISO date to start from (default: the playbook default window)

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
450 ms
95th percentile latency
450 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 450 ms · metadata changed · 26 tool(s), 9 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http appgoat-mcp https://api.appgoat.ai/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add appgoat-mcp --url https://api.appgoat.ai/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable appgoat-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "appgoat-mcp": {
      "url": "https://api.appgoat.ai/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "appgoat-mcp": {
      "type": "streamableHttp",
      "url": "https://api.appgoat.ai/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start appgoat-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "appgoat-mcp": {
      "type": "http",
      "url": "https://api.appgoat.ai/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http appgoat-mcp https://api.appgoat.ai/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "appgoat-mcp": {
      "url": "https://api.appgoat.ai/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "appgoat-mcp": {
      "serverUrl": "https://api.appgoat.ai/mcp"
    }
  }
}

Let your agent find its tools

Find servers like AppGoat MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run AppGoat MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing