General MCP
Project data, App Store Connect, website editing, reviews, revenue, analytics, and more.
For video-specific automation, including .ksvideo creation, narration, 3D devices, and movie export, use the Video MCP documentation.
What is MCP?
The Model Context Protocol (MCP) is an open standard that lets AI assistants interact with external tools. Kickstart includes a bundled MCP helper that exposes project data - revenue, reviews, TestFlight builds, competitors, websites, and more - so AI tools can read and act on it directly.
This means you can ask Claude, Codex, Gemini, or another MCP client questions such as "How is my app performing this month?" or "Create a new subscription group", and they can use your real Kickstart data to answer.
How to Set Up
Kickstart ships with a KickstartMCP command-line helper bundled inside the app. MCP clients invoke it directly over stdio - no server to start, no port to configure.
- Make sure Kickstart is installed in
/Applications. - Open Kickstart at least once so your data is populated.
- Add the following to your MCP client's configuration.
Claude Code
claude mcp add kickstart -- /Applications/Kickstart.app/Contents/Helpers/KickstartMCP
Codex
codex mcp add kickstart -- /Applications/Kickstart.app/Contents/Helpers/KickstartMCP
Cursor, Gemini, and Other MCP Clients
Point your MCP client at the helper binary:
/Applications/Kickstart.app/Contents/Helpers/KickstartMCP
After adding the configuration, restart your AI tool so it picks up the new MCP server. You can also find the path in Kickstart's Settings > General.
Protocol Endpoints
Kickstart uses stdio transport with JSON-RPC 2.0 and supports MCP protocol version 2025-06-18 with compatibility for 2024-11-05.
initialize- Negotiates the protocol version and returns supported capabilities and server info.notifications/initialized- Completes the MCP handshake afterinitialize. This is a notification, so it does not return a response body.notifications/cancelled- Cancel an in-flight call by itsrequestId; no response is sent for the cancelled request. Other requests remain available. Useget_search_ads_request_recoveryto retrieve retained cancellation evidence across helper restarts; read resources independently before retrying.ping- Simple health check endpoint. Kickstart accepts this even before initialization completes.tools/list- Returns the full catalog of tool definitions, including each tool's description and JSON input schema.tools/call- Invokes a tool by name with arguments and returns structured tool output.
Kickstart accepts both single JSON-RPC requests and batch arrays. Operational methods other than ping require the full initialize -> notifications/initialized handshake first.
Raw Client Flow
Most users should let Claude, Codex, Cursor, Gemini, or another MCP client handle this automatically. If you are building a client yourself, this is the expected request sequence:
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_projects","arguments":{}}}
Usage Notes
tools/listis the authoritative source for exact input schemas and should be preferred over hand-written client assumptions.- Every tool that accepts
projectNameuses case-insensitive matching. - Website tools default
websiteNameto the first website on the project when you omit it, exceptpublish_website, which requires a website name when the project has multiple websites. - Only call
publish_websitewhen the user explicitly requests publishing. It builds and uploads the saved website to its configured GitHub repository, replacing the site on thegh-pagesbranch and configuring GitHub Pages. GitHub credentials and the repository must already be configured in Kickstart. Editing website content or setting a blog post’sisPublishedflag does not deploy it. sectionIndex,itemIndex, andblogPostIndexare zero-based values returned byget_website.- Use
list_refresh_scopesbeforerefresh_project_datato discover which project data can be refreshed programmatically in the current build. refresh_project_datareports a per-scope status ofrefreshed,partial,skipped,unsupported, orfailed; inspectdetailsbefore trusting apartialrefresh as complete.- Several workflows require IDs returned by earlier read calls, such as TestFlight group/build/localization IDs and Search Ads campaign IDs.
- Use
get_keyword_data_modeto read the installation's fetching mode (localOnly,serverBacked, orunselected). Useset_keyword_data_modewithmode: "localOnly"ormode: "serverBacked"only when the user requests or approves that choice. Both modes require Kickstart Pro, and the choice applies across all projects in the app and MCP. Server-backed mode uploads tracked keywords from all projects and supports rankings, Difficulty, Popularity, and history. Local-only queries Apple directly without Popularity and stops further tracked-list uploads; it does not delete previously uploaded data. The app also allows changing the mode in Settings > General > Keyword Data. See the privacy policy for data handling. tools/callreturns structured tool output with acontentarray; Kickstart currently returns text content there.
Agent Operating Loop
A capable agent should treat Kickstart as a stateful source of truth. Do not guess IDs, indexes, or tool availability; discover them, call the narrowest tool that does the job, then read back the result.
- Start every session with
initialize,notifications/initialized, thentools/list. Hide or skip workflows whose tools are not listed. - Call
list_projectsbefore project-specific work and use the returned project name when calling other tools. Matching is case-insensitive, but exact names make logs easier to audit. - Read before writing. For example, call
get_websitebefore changing website sections,list_subscription_groupsbefore subscription edits, andget_testflight_summarybefore build-localization work. - Preserve IDs and indexes returned by read tools. App Store Connect IDs, Search Ads campaign IDs, TestFlight IDs, section indexes, item indexes, and blog post indexes should be copied from Kickstart responses.
- After a mutating call, read back the same resource if another call depends on the updated state. This avoids stale indexes after section reordering, deletion, or item insertion.
- Prefer small, reversible operations. Destructive tools such as
delete_project,delete_subscription,delete_event, andremove_blog_postshould only be used when the user explicitly asks for that outcome. - Summarize important tool results to the user, especially public App Store actions such as review responses, in-app events, nominations, subscriptions, and offer-code generation.
Response Handling
Kickstart returns normal MCP responses. The actual tool payload is usually JSON encoded as text inside the first content item, so external clients should parse that text before deciding what happened.
Successful tool response
Look for result.content[0].type == "text", then parse result.content[0].text as JSON. Most read tools return arrays or objects with fields such as projects, tasks, reviews, sections, items, or summary. Mutating tools usually include a status message and enough updated state to plan the next call.
Tool-level errors
If result.isError is true, the MCP call reached Kickstart but the requested operation failed. Show the error to the user, then recover using a read call when possible. Common causes include missing projects, missing App Store Connect credentials, unavailable Pro-only tools, invalid website indexes, App Store API failures, or a tool schema mismatch.
JSON-RPC errors
If the top-level response contains error, the client sent an invalid MCP request, called an unknown method, skipped initialization, passed malformed JSON, or used an unknown tool name. Re-run tools/list and rebuild the call using the schema returned there.
Common General Workflows
Analyze an app launch
- Call
list_projects, thenget_projectfor the selected app. - If the user wants fresh upstream data, call
list_refresh_scopes, thenrefresh_project_datafor the relevant available scopes before reading summaries. - Call
get_todays_agenda,get_task_stats, andlist_tasksto assess operational work. - Call
get_revenue_summary,get_app_analytics,get_review_stats, andget_reviewswhen App Store Connect data is configured. - Call
get_optimization_scores,get_optimization_suggestions,list_localizations, andget_localization_statsfor App Store listing quality. - Return a concise written analysis with concrete next actions, and only mutate data if the user requested changes.
Edit a generated website
- Call
get_websiteand keep the returnedsectionIndex,itemIndex, andblogPostIndexvalues. - Call
list_website_section_typesif you need to add a new section, because section type names and field names must match Kickstart's schema. - Use
add_website_section,update_website_section,add_section_items,remove_section_item, orreorder_website_sectionsfor page content. - Use
add_blog_post,update_blog_post, orremove_blog_postfor blog work. - Use
update_website_settingsfor site-level styling, navigation, footer, custom domain, analytics, and privacy settings. - Call
get_websiteagain after structural changes so follow-up calls use fresh indexes.
Work with App Store Connect data
- Call the relevant list or summary tool first:
get_testflight_summary,list_events,list_nominations,list_subscription_groups,list_offer_codes, orget_reviews. - Copy exact IDs from the response into update, delete, submit, response, localization, and generation calls.
- For public-facing text, write complete production copy in the tool call. Do not rely on Kickstart to expand placeholders.
- After any create, update, submit, or delete call, read the same resource again so the user can verify the resulting App Store state.
Research competitors and keywords
Check get_keyword_data_mode first. If a mode is needed but unselected, explain both options and use set_keyword_data_mode with the user's choice. Do not switch to server analysis automatically to satisfy a tool requirement.
- Use
search_appsto find App Store IDs, thenadd_competitorto track apps selected by the user. - Use
list_competitors,get_competitor_analysis,get_search_rankings,get_keyword_popularity,check_keyword_rankings, anddiscover_keywords_for_appfor analysis. Keyword discovery requires Server-backed mode. - Use
track_keywordandremove_tracked_keywordto maintain the project's tracked keyword set.
Raw Tool Call Examples
These examples are intentionally plain JSON-RPC so any client, including Gemini, Claude, Codex, Cursor, or a custom script, can reproduce them. Always compare with tools/list in the running app before sending production mutations.
List projects
{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"list_projects","arguments":{}}}
Create a project
{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"create_project","arguments":{"name":"Example App","tagline":"Plan, launch, and improve faster.","description":"A focused planning app for indie developers.","launchDate":"2026-06-01"}}}
Read and update website settings
{"jsonrpc":"2.0","id":12,"method":"tools/call","params":{"name":"get_website","arguments":{"projectName":"Example App"}}}
{"jsonrpc":"2.0","id":13,"method":"tools/call","params":{"name":"update_website_settings","arguments":{"projectName":"Example App","siteName":"Example App","customDomain":"www.example.com","primaryColor":"#34C759","colorScheme":"dark","headerBrandName":"Example App","footerTagline":"Build better launches."}}}
Respond to a review
{"jsonrpc":"2.0","id":14,"method":"tools/call","params":{"name":"get_reviews","arguments":{"projectName":"Example App","limit":10}}}
{"jsonrpc":"2.0","id":15,"method":"tools/call","params":{"name":"respond_to_review","arguments":{"projectName":"Example App","reviewID":"REVIEW_ID_FROM_GET_REVIEWS","responseBody":"Thanks for the thoughtful feedback. We have passed this to the team and will keep improving the experience."}}}
Recovery Notes
- If a tool is missing from
tools/list, the installed Kickstart build may be older, the feature may be gated, or the user may not have the required entitlement. Do not fabricate calls to missing tools. - If a project is not found, call
list_projectsagain and let the user choose from the returned names. - If an index-based website call fails, call
get_websiteand rebuild the operation from the latest returned structure. - If an App Store Connect, Search Ads, or analytics call fails, report the failing upstream service and keep local project data work separate from network-backed work.
- If a mutation partially succeeds upstream but the follow-up read fails, ask the user before retrying a public action such as responding to a review, submitting a nomination, or generating offer codes.
Available General Tools
The general MCP surface covers the non-video categories below. Use tools/list for the discoverable catalog. Every tool that accepts a projectName parameter uses case-insensitive matching.
Projects (5)
list_projects- Lists all projects with their basic info (name, tagline, launch date, App Store ID, task completion stats).get_project- Gets detailed information about a specific project including all metadata and press kit info.create_project- Creates a new project in Kickstart.update_project- Updates an existing project's metadata.delete_project- Deletes a project and all its associated data. Cannot be undone.
Project Data Refresh (2)
list_refresh_scopes- Lists refreshable project data scopes, including availability and unsupported app-layer-only refreshes.refresh_project_data- Refreshes selected scopes such as App Store optimization metadata, localizations, revenue details, reviews, keywords, TestFlight, and crash signatures.
Tasks (5)
list_tasks- Lists tasks for a project. Filter by status (today/overdue/upcoming/completed/all) and category (product/distribution/feedback/intelligence/operations).get_task_stats- Gets task completion statistics by category and overall progress.complete_task- Marks a task as completed.uncomplete_task- Marks a completed task as incomplete.get_todays_agenda- Gets today's agenda: tasks due today, overdue tasks, and upcoming tasks for the next 7 days.
Journal (4)
list_journal_entries- Lists all journal entries sorted by creation date (newest first).add_journal_entry- Creates a new custom journal entry for a project.update_journal_entry- Updates an existing journal entry's body text by title match.delete_journal_entry- Deletes a journal entry by title match.
Revenue and Subscriptions (2)
get_revenue_summary- Gets revenue summary including total revenue, units sold, and breakdowns by territory, device, and product type.get_subscription_analytics- Gets subscription analytics including active subscribers, churn rates, and subscription events.
App Analytics (1)
get_app_analytics- Gets app analytics including impressions, downloads, installations, sessions, crashes, and breakdowns by territory, source, and device.
Reviews (4)
get_reviews- Gets customer reviews with rating, title, body, and response status.respond_to_review- Posts a developer response to a customer review, visible on the App Store.delete_review_response- Deletes a developer response from a review.get_review_stats- Gets review statistics: average rating, rating distribution, and recent trends.
TestFlight (8)
get_testflight_summary- Gets TestFlight summary including builds, groups, and tester counts.get_testflight_feedback- Gets feedback from beta testers including screenshots and crash reports.list_beta_testers- Lists beta testers for a specific group.get_beta_app_localizations- Gets beta app localizations (feedback email, description, URLs) for each locale.update_beta_app_localization- Updates a beta app localization's feedback email, description, or URLs.get_beta_build_localizations- Gets build-level localizations ("What to Test") for a specific build.update_beta_build_localization- Updates or creates the "What to Test" text for a build in a specific locale.get_beta_tester_metrics- Gets usage metrics (sessions, crashes, feedback) for beta testers in a group.
Optimization (2)
get_optimization_scores- Gets App Store Optimization scores for title, subtitle, keywords, and description with an overall weighted score.get_optimization_suggestions- Gets detailed optimization suggestions organized by severity for improving your App Store listing.
Localizations (2)
list_localizations- Lists all App Store localizations with completion status and character counts.get_localization_stats- Gets localization statistics: completion rates, missing locales, and suggested markets.
In-App Events (4)
list_events- Lists in-app events with state, badge type, schedule, and localization info.create_event- Creates a new in-app event.update_event- Updates an existing in-app event.delete_event- Deletes an in-app event.
Editorial Nominations (5)
list_nominations- Lists editorial nominations with state and details.create_nomination- Creates a new editorial nomination.update_nomination- Updates an existing nomination.submit_nomination- Submits a draft nomination for editorial review.delete_nomination- Deletes (archives) a nomination.
Competitors (6)
list_competitors- Lists tracked competitor apps with cached info.add_competitor- Adds a competitor app by App Store ID.remove_competitor- Removes a tracked competitor app.search_apps- Searches the App Store for apps matching a query.get_search_rankings- Checks App Store search rankings for a keyword and reports where tracked competitors appear.get_competitor_analysis- Gets competitive analysis: pricing, ratings, and keyword analysis.
Keywords (8)
get_keyword_data_mode- ReturnslocalOnly,serverBacked, orunselectedfor this installation.set_keyword_data_mode- SetsmodetolocalOnlyorserverBackedacross all projects. Requires Pro and the user's choice; existing tracked keywords are validated before enabling server analysis.list_tracked_keywords- Lists keywords being tracked for a project.get_keyword_popularity- Gets Apple's exact relative Popularity from 0 to 100 for tracked or supplied keywords in Server-backed mode.track_keyword- Adds a keyword to track and optionally fetches current rankings.remove_tracked_keyword- Stops tracking a keyword for a project.check_keyword_rankings- Fetches keyword ranking data and reports ranks, Difficulty, available Popularity, and history.discover_keywords_for_app- Finds shared keywords where an App Store app currently ranks. This requires Server-backed mode.
Keyword Insights (9)
Every tool in this group requires an active Kickstart Pro subscription, including reads of cached results. Use a linked projectName; App Store Connect credentials are not needed for ranking discovery or history. Ranking tools respect the installation's existing Server-backed mode and never change that choice, add tracked keywords, update a manifest, or request Apple fetching.
discover_app_keyword_history- Finds keywords this app appeared in during the previous 90 complete UTC days of Kickstart's captured search corpus. Returns at most 100 entries from one complete prepared list. PassnextOffsetand the samepublicationIDto continue; restart at offset 0 if the publication changes.get_app_keyword_history- Gets one discovered keyword's ranks and explicit coverage across up to 90 UTC dates.startDateandendDateare inclusive. The discovery response'swindow.endis exclusive, so the latest available date is the previous UTC day. No observation, absent app, partial legacy evidence, and a numeric rank remain distinct.get_app_keyword_timeline- Lists at most 100 events with effective dates, observed dates, provenance, scope, and old/new values. Optional storefront, device, and date filters restrict the timeline.nextOffsetcontinues the list.add_app_keyword_annotation- Adds a dated manual marker, optionally scoped to a storefront, device, or locale. It does not publish metadata or affect tracking.correct_app_keyword_event- Corrects a marker's title, note, or effective date while retaining its provenance and original observed time. Omitted note/date preserve existing values;clearEffectiveDate: trueremoves an incorrectly known effective date.delete_app_keyword_annotation- Deletes a manual marker. Captured source events can be corrected but cannot be deleted with this tool.get_app_keyword_impact- Compares one fixed keyword and matching Detailed acquisition data around an event, using seven UTC dates before and after by default. OptionalpageIDrestricts acquisition to a CPP. The event date is excluded. Incomplete windows withhold summaries; they are never shifted to fill missing dates. Reports include nearby events and do not claim causality.list_custom_product_page_insights- Lists captured CPP IDs, most recent names and publication/deletion states, the default page ID, and available exact Analytics filter values. Use these IDs and filters for page analytics.get_custom_product_page_analytics- Gets CPP page views, downloads, and downloads divided by page views for up to 90 dates. Exact app/date-scoped name history resolves renamed or deleted pages; ambiguous matches stay unresolved. Optional territory, device, and source filters apply to the same underlying Apple rows.
Start with discovery, select a keyword, then request its history. A fresh local list avoids another discovery download. New discovery network starts are paced at one per second across calls within the MCP process. Daily history downloads have no rate or volume quota and share the Core downloader's six concurrent request slots. Cancellation stops the request's pending work; completed encrypted data can be reused later.
Timeline and CPP analytics tools can use locally retained App Store Connect data in either keyword mode. They still require Pro. The rank impact tool additionally requires Server-backed mode because it reads ranking history. Missing Analytics does not prevent ranking history; refresh Analytics in Kickstart to populate acquisition comparisons. Detailed metrics are kept separate from Standard totals. App Store Search includes Search Ads and must not be described as organic-only traffic.
Downloaded discovery/history, derived ranks, and timeline data stay encrypted in the app/MCP shared local storage. MCP intentionally returns readable requested results to its authorized caller. The local discovery pacing is cooperative, not a server-enforced scraping restriction.
Subscription Management (5)
list_subscription_groups- Lists all subscription groups and their subscriptions, including pricing, state, and localizations.create_subscription_group- Creates a new subscription group for an app.create_subscription- Creates a new subscription within a group.update_subscription- Updates an existing subscription's properties.delete_subscription- Removes a subscription from sale and deletes it. Cannot be undone.
Offer Codes (4)
list_offer_codes- Lists all offer code configurations organized by subscription group and subscription.create_offer_code- Creates a new offer code configuration for a subscription.generate_offer_codes- Generates a batch of one-time use offer codes. Returns the code values.list_offer_code_generations- Lists past offer code generation batches including the generated codes.
Release Checklists (5)
list_checklist_templates- Lists release checklist templates.create_checklist_template- Creates a new checklist template with categories and items.create_checklist_instance- Creates a checklist instance from a template for tracking a release.get_checklist_instance- Gets a checklist instance with all categories, items, and statuses.update_checklist_item- Updates the status of a checklist item.
Press Kit (1)
get_press_kit- Gets press kit content including markdown description, contact info, and configuration.
Website Builder (14)
publish_website- Builds and publishes a website to its configured GitHub repository. Returns the site URL and any Pages configuration warning.get_website- Returns the full website state: metadata, theme, header, footer, blog posts, and every section with nested items.list_website_section_types- Returns a catalog of all 18 section types with descriptions, fields, and item schemas.create_website- Creates a new website with default header and footer.add_website_section- Adds a new section with field values and optional inline nested items.update_website_section- Partially updates section-level fields by index.remove_website_section- Removes a section by index.add_section_items- Adds nested items to an existing section (FAQ questions, features, testimonials, etc.).add_blog_post- Adds a blog post to the website. The first paragraph becomes the summary used on the blog index and RSS feed.update_blog_post- Partially updates a blog post by itsblogPostIndexfromget_website.remove_blog_post- Removes a blog post by itsblogPostIndexfromget_website.remove_section_item- Removes a nested item from a section by index.update_website_settings- Updates site metadata, theme, header, footer, custom domain, privacy, and code injection.reorder_website_sections- Moves a section from one position to another.
Apple Ads
Start with list_search_ads_accounts or search_ads_credential_doctor, then use the resource and query tools below. Before constructing an unfamiliar request, call describe_apple_ads_tool with its exact toolName. It returns complete argument guidance, filter/sort tables, detailed output schemas, and Apple endpoint links without credentials or Pro. Discovery keeps compact output-envelope types. tools/list retains argument structure, constraints, and safety guidance; established valid requests still work directly. Queries return one page of Apple's complete JSON. Preserve null values as unavailable evidence and follow the returned pagination. Numeric resource identifiers accept positive 64-bit integers or decimal strings. Opaque product-page identifiers remain strings. Money amounts, including draft budgets and target CPA, must be positive decimal strings such as "1.25", with explicit uppercase currencies.
Write startTime/endTime values use UTC strings such as 2026-09-21T10:00:00.000, without Z or an offset. Milliseconds may be omitted and are normalized to .000. Zoned values are rejected locally: convert the instant to UTC first, rather than removing the offset. Explicit endTime: null still clears an expiration.
API create and update tools require the Apple request in body and return the complete Apple JSON response. MCP 2.0.0 removes the deprecated flat arguments. Runtime validation rejects missing bodies and unknown wrapper arguments before HTTP. New campaigns, ad groups, ads, and targeting keywords default to paused. Every mutation requires confirm: true and uses the selected account. Bulk bodies expose allowPartialSuccess and per-item correlation IDs. A timeout or cancellation can leave a remote change in progress: read back before retrying.
Do not assume % is a wildcard in LIKE filters. September 18, 2026 probes matched campaign and supported-language names without %, while adding surrounding % returned no matches. Guidance includes this caution on every endpoint advertising LIKE; other endpoints have not been verified. Successful queries containing % in LIKE filter values return LIKE_PERCENT_LITERAL warnings. Filter values and Apple responses remain unchanged. Apple rejected promotedObjectId NOT_IN despite its documentation; NOT_EQUALS worked. campaignId IN worked for ad groups and ads. Keyword queries still require campaignId EQUALS when that filter is supplied; IN support has not been verified for keywords. Campaign-level negatives require campaignId EQUALS plus adGroupId IS_NULL, without a value.
RUNNING is not proof of delivery. Cross-check future startTime, expired endTime, the account time zone and current daypart, parent state, and reports. Report rows use totalMetrics and granularMetrics; missing metrics remain unavailable evidence.
Reads retry supported transient transport failures and HTTP 408/500/502/503/504 up to twice. Reads and writes refresh authentication once after 401 and retry 429 with bounded pacing inside the operation deadline. Writes do not retry transient failures; reconcile uncertain writes before retrying.
The Apple Ads interface supports App Store campaign management. Apple Maps campaign management, ad-account creation/delegation administration, and asset upload/deletion are outside its scope. Selecting an account without verified App Store product support is rejected without changing the shared selection.
Results expose the same JSON envelope in text and structuredContent, including errors, warnings, outcomes, and request metadata. httpRequestCount counts all HTTP attempts, including preflight reads; attemptCount is its compatibility alias and retryCount counts retries. HTTP 200 write errors still set isError; outcome distinguishes confirmed failure from partial or unknown application. This also preserves machine-readable evidence for older MCP clients. Kickstart-generated outcome resourceID values are strings; Apple IDs inside response retain their original types. Account listing and scoped delete helpers return synthesized summaries. Multi-ID negative-keyword deletion reports one outcome item per unique ID, with separate succeeded, alreadyDeleted, failed, unknown, and unattempted counts. Individual HTTP receipts in lastWriteResponse are not workflow totals.
Inspect report warnings before describing a grouped breakdown. On 2026-09-17, campaign and ad group reports requested with countryCode, ageRange, or gender returned aggregate rows without the requested dimension metadata. REPORT_GROUPING_UNVERIFIED identifies affected dimensions and row counts. Do not interpret those rows as a single-country or demographic result. A single row containing the requested dimension is valid; an empty report provides no grouping evidence.
On 2026-09-17, impression share, search-term popularity, and target CPA suggestions each reported RateLimit-Limit: 5. This is per reported window, not a fixed daily limit. Check requestMetadata.attempts[].rateLimitHeaders, particularly RateLimit-Remaining, RateLimit-Reset, and Retry-After; limits can change. Long windows allow a small burst shared by helper processes while quota is ample, then resume sustained pacing. Low or exhausted quota and Retry-After can cause waits or a rateLimitWait error when the operation deadline would be exceeded. Avoid parallel research loops.
Known immutable update fields are rejected locally, including campaign account/app identity and billing event, ad group pricing model, keyword identity, ad parent/creative IDs, and creative type/destination. Additional Apple fields remain accepted. Apple only soft-deletes resources, so a deleted record remains after cleanup. On 2026-09-17, a confirmed dailyBudget change was absent from change history and its field-level details; read budgets back directly rather than treating missing history as proof they were unchanged.
Kickstart's shared credential vault uses an AES-GCM envelope whose keys come from constants shipped in the app. It provides obfuscation rather than protection from someone who can read the vault and the binary. Credential sync copies the same wrapped blob to iCloud. File protection and iCloud account security remain separate protections.
Writes must use the selected account. A mismatched accountID is not an instruction to change the shared selection; if the user wants another shared account, select_search_ads_account verifies APPSTORE_APP_MANUAL and refuses unsupported accounts. During credential validation, a failed details refresh for the same selected account preserves previously verified product features, currency, and time zone where unavailable. Credential Doctor reports this warning; current ACL roles and membership still apply.
HTTP 200 recommendation validation errors with no result rows can be definite atomic rejections: every input is failed and noChangesApplied is true when all detail codes are recognized and identifiers are consistent. Mixed or conflicting evidence remains uncertain. Error strings summarize HTTP status, codes, fields, and guidance; complete payloads remain in response, outcome, and partialResult, including for text-only MCP 2024-11-05 clients. Delete annotations advertise idempotence; budget-order creation is marked destructive because it changes the shared spending limit.
Unknown wrapper arguments are rejected before any request. Use accountID, with that exact spelling. Account-scoped responses identify the account used. Query schemas describe endpoint-specific fields, operators, and sorting without restricting additional Apple payload fields. Impression-share pages support up to 10,000 rows. Search-term popularity and report pages support up to 5,000.
HTTP 403 responses preserve Apple's error and direct you to search_ads_credential_doctor to refresh stored permissions; check permissionsPersisted and warnings. list_search_ads_accounts with refresh: true lists current access without saving permissions. App and MCP writes revalidate stale permissions and check the shared credentials and account selection immediately before submission. Search Ads Basic (APPSTORE_APP_AUTOMATED) lacks the APPSTORE_APP_MANUAL capability required by App Store campaign endpoints.
Create, update, and delete tools accept the applicable expectedCampaignID, expectedAdGroupID, or expectedAppID guards. A mismatch prevents the entire request from being submitted. Atomic bulk rejections identify every unapplied input. Partial failures set isError and preserve successful IDs and every outcome; retry only confirmed failed items. Parent assertions remain all-or-nothing even with allowPartialSuccess. Scoped updates validate IDs in bounded queries. Repeat deletes report an already-deleted resource only after readback confirms its deleted state. For the plural negative-delete helper, already-deleted items do not count as new successes. A preflight rejection with no new deletions reports outcome.status: failed in either ID order; only actual successful deletions make a batch with failed or unattempted items partial.
Always verify important changes with an independent read. Changing campaign countries, including replacing one country with another, can remove ad-group geographic targeting. Accepted or uncertain changes preserve warnings with the previous targeting; definite rejections do not report targeting side effects. To clear maximum age, use maxAge: null; maxAge: {"include": null} and an empty include array are rejected locally because Apple has returned success without clearing the limit. Reverting Maximize Conversions to Manual CPT requires bid: null inside bidStrategy to clear the target CPA. For owned-app discovery, continue until an empty or short page, detecting repeated pages, because totalCount can describe only one page.
Creative queries use the accountID wrapper for account selection; Apple rejects an adAccountId filter. For example, find custom-page creatives with a supported filter, then match their destination.parameters.adamId to your app:
{"name":"query_search_ads_creatives","arguments":{"query":{"filters":[{"field":"creativeType","operator":"EQUALS","value":"CUSTOM_PRODUCT_PAGE"}],"pagination":{"offset":0,"pageSize":100}}}}
Follow an asset reference from a localization response using its UUID:
{"name":"get_search_ads_asset","arguments":{"assetID":"A426EE92-E6D3-41F9-9BA8-AF990C00D3D1"}}
Before changing a keyword, use identifiers from your own reads. This example requires the keyword to belong to campaign 42 and ad group 7 before applying the change:
{"name":"update_search_ads_keyword","arguments":{"keywordID":123,"expectedCampaignID":42,"expectedAdGroupID":7,"body":{"status":"PAUSED"},"confirm":true}}
Tool discovery remains stable if Pro access changes. Calls still enforce Pro access and explain whether the shared entitlement is missing, inactive, expired, or unreadable. Development and production apps store their entitlement snapshots separately.
search_ads_credential_doctor- Validate credentials and persist the same account roles used for writes.list_search_ads_accounts- List accessible accounts and refresh permissions when requested.select_search_ads_account- Confirm and save an accessible account selection, optionally checking the previous selection.delete_search_ads_negative_keywords- Verify the whole batch's scope before deleting; report completed IDs if a later deletion fails.delete_search_ads_ad- Delete an ad where Apple permits it; product-page restrictions can prevent individual deletion.get_search_ads_access- Read accessible ad accounts and API roles. No account selection is required.get_search_ads_user- Read the authenticated API user and organization IDs. No account selection is required.get_search_ads_organization- Read an organization returned by get_search_ads_user or get_search_ads_access.get_search_ads_advertiser_resources- Read advertiser resources by resourceType. No account selection is required.query_search_ads_supported_languages- Query the ad-supported languages in countries and regions.search_ads_apps- Search App Store apps by app or developer name, content provider IDs, or ownership.search_ads_geo_locations- Find geographic targeting IDs by name, country, and entity type. supplySource defaults to APPSTORE.query_search_ads_geo_locations- Look up geographic targeting locations by entity type and ID using GeoSearchPostRequest.get_search_ads_legacy_app_status- Read country-specific reasons a legacy app campaign has limited delivery.create_search_ads_keyword- Create one targeting keyword using the complete Apple KeywordCreate body.update_search_ads_keyword- Update one targeting keyword using the complete Apple KeywordUpdate body.create_search_ads_negative_keyword- Create one negative keyword. Set exactly one of campaignId for campaign scope or adGroupId for ad group scope. Negative keywords default to ENABLED.update_search_ads_negative_keyword- Update one negative keyword using the complete Apple NegativeKeywordUpdate body.delete_search_ads_negative_keyword- Delete one negative keyword by its account-wide ID. Read it first to verify its campaign or ad group.create_search_ads_keywords- Bulk-create targeting keywords. body exposes allowPartialSuccess and each item correlationId. Returns every item outcome.update_search_ads_keywords- Bulk-update targeting keywords. body exposes allowPartialSuccess and each item correlationId. Returns every item outcome.create_search_ads_negative_keywords- Bulk-create negative keywords with explicit scopes. body exposes allowPartialSuccess and item correlationId.update_search_ads_negative_keywords- Bulk-update negative keywords. body exposes allowPartialSuccess and item correlationId. Inspect every item outcome.create_search_ads_creative- Create a creative using the full CreativeCreate body. App Store creative deletion may be unsupported; reuse an existing creative when possible.update_search_ads_creative- Update a creative name or spec using the full CreativeUpdate body.create_search_ads_ad- Create an ad using the full AdCreate body. Defaults to PAUSED.update_search_ads_ad- Update an ad using the full AdUpdate body.create_search_ads_campaign- Create a campaign using Apple's complete CampaignCreate body, including dates, placement, targeting, and bidStrategy. Status defaults to PAUSED. On 2026-09-17, omitting startTime produced 2026-09-17T00:00:00.000, the start of that UTC day, rather than activation time. Supply startTime when timing matters.update_search_ads_campaign- Update a campaign using Apple's complete CampaignUpdate body, including schedule, targeting, and bidStrategy. Placement is read-only: Apple returns HTTP 400 even when resending the current value, so supplyPlacement is rejected locally. Changing countries, including single-country replacements, can clear ad-group geo targeting. Changes that put existing geo targeting at risk return warnings with saved targeting and independent readback results.create_search_ads_ad_group- Create an ad group using Apple's complete AdGroupCreate body, including campaignId, dates, audiences, Search Match, and bidStrategy. Status defaults to PAUSED.update_search_ads_ad_group- Update an ad group using Apple's complete AdGroupUpdate body, including targeting, dates, Search Match, and bidStrategy.query_search_ads_campaigns- Query complete campaign resources with Apple filters and pagination, including deleted campaigns when requested. On 2026-09-17, displayStatus and systemStatus RUNNING coexisted with schedules preventing delivery. Check daypart, start/end times, and reports.query_search_ads_ad_groups- Query complete ad groups. Filter campaignId to scope inventory.query_search_ads_keywords- Query complete targeting keywords. Filter campaignId or adGroupId to scope inventory.query_search_ads_negative_keywords- Query complete negative keywords. Filter campaignId and adGroupId; use adGroupId IS_NULL for campaign-level exclusions.query_search_ads_ads- Query complete ads and serving state. Filter campaignId or adGroupId to scope inventory.query_search_ads_creatives- Query complete creatives. FiltercreativeTypewhen needed, then matchdestination.parameters.adamIdin the returned rows to select an app.list_search_ads_owned_apps- List apps owned by the ad account, including app IDs needed by suggestions, eligibility, reports, and campaign creation. Supports offset, limit (maximum 50), and storefronts.get_search_ads_app- Read complete app details and advertising capabilities.query_search_ads_app_eligibility- Query full placement, market, and device eligibility. Filter adamId using EQUALS and a numeric app ID; optionally countryOrRegion or supplyPlacement.get_search_ads_account- Retrieve the full selected or specified ad account.get_search_ads_campaign- Retrieve all fields of one campaign. On 2026-09-17, displayStatus and systemStatus RUNNING coexisted with schedules preventing delivery. Check daypart, start/end times, and reports.get_search_ads_ad_group- Retrieve all fields of one ad group.get_search_ads_keyword- Retrieve one targeting keyword.get_search_ads_negative_keyword- Retrieve one negative keyword.get_search_ads_ad- Retrieve all fields of one ad.get_search_ads_creative- Retrieve the full creative and destination. Creative get/query responses omitted eligibility on 2026-09-17; projecting eligibility returned HTTP 400 INVALID_INPUT. Use query_search_ads_app_eligibility for placement, market, and device eligibility.query_search_ads_assets- Query App Store asset metadata and variants. Asset get/query responses omitted eligibility on 2026-09-17; use query_search_ads_app_eligibility for placement, market, and device eligibility.get_search_ads_asset- Follow an asset UUID returned by app or product-page localizations. Eligibility was absent on 2026-09-17; use query_search_ads_app_eligibility for placement, market, and device eligibility.query_search_ads_budget_orders- Query budget orders for Line of Credit accounts.get_search_ads_budget_order- Read a budget order, its amount, schedule, and assigned account.create_search_ads_budget_order- Create a Line of Credit budget order for the selected account.update_search_ads_budget_order- Update an order after verifying its assigned account; changes can affect all campaigns drawing from it.delete_search_ads_budget_order- Delete an order where Apple permits, after checking its assigned account.get_search_ads_product_page- Retrieve an existing product page. Product pages are edited in App Store Connect.query_search_ads_campaign_report- Query full campaign performance, including attribution splits, granular metrics, and dimensions. Filter id (not campaignId) to select campaigns. On 2026-09-17, campaign/ad-group groupBy [ageRange, gender] returned HTTP 400: "GroupBy only allows one field for age/geo/gender".query_search_ads_ad_group_report- Query full ad group performance and supported audience breakdowns. Scope with a campaignId filter.query_search_ads_keyword_report- Query all returned keyword metrics, including unsuccessful keywords. Scope with a campaignId filter.query_search_ads_search_term_report- Query actual matched search terms. A campaignId filter is required. Use ORTZ; HOURLY and EMPTY_METRICS are unsupported. Privacy-suppressed terms are not zero traffic.query_search_ads_ad_report- Query full ad performance, creative metadata, and destinations. Scope with a campaignId filter. HOURLY is unsupported.query_search_ads_impression_share- Query paid impression share. Filter promotedObjectId with IN and an array of app IDs; use UTC and DAILY or WEEKLY_SUN_SAT. options.impressionShareReportType selects FIRST_SLOT or ALL_SLOTS.query_search_ads_search_term_popularity- Query relative search demand by country, genre, and term. Genre uses Apple's uppercase enum, such as EDUCATION, rather than the app's localized genre name. Use UTC and WEEKLY_SUN_SAT or MONTHLY. Popularity is not absolute search volume.query_search_ads_keyword_suggestions- Query keyword suggestions. Filter promotedObjectId and promotedObjectType; optionally countriesOrRegions and terms. Without seed terms, suggestions can be generic and unrelated to the promoted app. Apple documents popularity from 0 to 100. Seeded and unseeded ranges differed on 2026-09-17; compare values only within one response.query_search_ads_phrase_suggestions- Query phrase suggestions or search known phrases. Put queryType in filters: SUGGESTION uses promotedObjectId/type; SEARCH uses phrase with IN or LIKE and has returned Maps entities in observed responses. Prefer keyword suggestions for App Store keyword ideas; Apple documents App Store SUGGESTION support, but sampled requests failed server-side.query_search_ads_category_suggestions- Query category suggestions or search categories. Put queryType in filters: SUGGESTION uses promotedObjectId/type; SEARCH uses category with IN or LIKE and has returned Maps entities in observed responses. Apple documents App Store SUGGESTION support, but availability depends on Apple.query_search_ads_target_cpa_suggestion- Read the new-campaign target CPA suggestion. Filter on promotedObjectId, promotedObjectType APPSTORE_APP, and optional countryOrRegion. Sorting and pagination are also advertised. A null result means no suggestion is available.query_search_ads_daily_budget_recommendations- Query Apple daily-budget recommendations and forecasts. Filter promotedObjectId and promotedObjectType; optionally campaignId and state.query_search_ads_target_cpa_recommendations- Query target CPA recommendations for Maximize Conversions campaigns. Filter promotedObjectId and promotedObjectType.apply_search_ads_daily_budget_recommendations- Apply explicit Apple daily-budget recommendations. Changes spending; returns applied history and per-item outcomes.dismiss_search_ads_daily_budget_recommendations- Dismiss explicit daily-budget recommendations. This changes recommendation state permanently.apply_search_ads_target_cpa_recommendations- Apply explicit target CPA recommendations. Changes spending; the applied target is returned in recommendation history.dismiss_search_ads_target_cpa_recommendations- Dismiss explicit target CPA recommendations. This changes recommendation state permanently.query_search_ads_product_pages- Query product pages returned by Apple. Default pages may be absent; use app localizations for default-page metadata. Filter adamId to select the app.query_search_ads_product_page_localizations- Query localized product-page metadata and assets. Filter productPageId (required); optionally language or languageCode.query_search_ads_app_localizations- Query localized default product-page metadata and assets for an app.query_search_ads_rejection_reasons- Query app creative rejection reasons using Apple filters.get_search_ads_rejection_reason- Retrieve one app creative rejection reason.query_search_ads_change_history- Query change history. Filters on eventTime and entityType are required. Use entityType IN Campaign, AdGroup, Keyword, or another Apple entity type. On 2026-09-17, Apple enforced a 183-day lookback from the current time; six calendar months can exceed it. options.metadata accepts none (default), latest, or snapshot. Apple can return current state for historical snapshots and metadata even with none; use field-level change details for event evidence. Keyword events may be missing, so read resources independently.get_search_ads_change_detail- Retrieve field-level before/after values using a detailId from change history. Supports offset and limit.delete_search_ads_campaign- Delete a campaign. Requires explicit confirmation.delete_search_ads_ad_group- Delete an ad group. Requires explicit confirmation.delete_search_ads_keyword- Delete a targeting keyword. Requires explicit confirmation.delete_search_ads_creative- Delete a creative where Apple supports the resource type. Apple can reject deletion of App Store product-page creatives. Requires explicit confirmation.
Cancellation recovery is available by default. The following campaign workflows require the helper launch argument --apple-ads-workflows; the app's campaign planner remains available:
get_search_ads_request_recovery- Retrieve the latest cancellation snapshots, optionally filtered by the cancelled tools/call JSON-RPCidasrequestID. Integer IDs and their string spellings match the same records; each record preserves its originalrequestID, so distinct or reused IDs can return multiple records. Credential-free snapshots survive helper restarts for 24 hours, up to 256 records and 1 MiB, with oldest-first eviction. Use optionalsessionIDto distinguish helpers. The latest 64 records retain richer session evidence. Persisted snapshots omit bodies, raw Apple responses, resource names, and free-form errors. Without filters, the lookup covers all helper sessions using this local store. Inspectwarnings,storageAvailable,historyIncomplete, and each record'struncatedflag. Damaged stores are archived before repair. Valid records are salvaged from inputs up to 4 MiB, then normal expiry and size limits apply; larger inputs are archived without salvage, with an explicit warning. New snapshots can be saved. The incomplete-history warning survives restarts and expires 24 hours after the latest repair. Existing plain-text markers use their original modification time. Owner-only archives are retained for up to seven days, with at most eight per store; cleanup runs on store access after successful updates. Marker read, migration, save, and deletion failures and archive cleanup failures produce warnings without blocking a writable snapshot store. Repair archive timestamps preserve the 24-hour warning across restarts if the marker cannot be saved. A known expired marker stops affectinghistoryIncompleteeven if deletion fails; unreadable metadata keeps history completeness unverified. Empty results do not prove that nothing was submitted. Read back before retrying.build_search_ads_campaign_draft- Build a draft using project data and heuristics. SupplyprojectNameor bothappIDand a realappName; use decimal strings fordailyBudgetandtargetCPA. A supplied custom product page must belong to that app and report an available state (PUBLISHED or VISIBLE).apply_search_ads_campaign_draft- Create and verify the paused entities in a reviewed draft.start_search_ads_campaign- Enable a verified campaign and its explicitly supplied entities.
Draft application rechecks edited amounts, names, IDs, markets, and custom product pages before creating resources. The draft builder does not validate Apple eligibility or suggestions and does not provide evidence for keyword exclusions. Review its proposed fields and use the query tools to validate the draft before applying it. Agents can also compose research, campaign changes, and measurement from the API tools.
Compact discovery and workflow opt-in
MCP 2.0.0 includes compact discovery and optional campaign workflows. This release removes legacy read aliases and flat write arguments; follow the migration guide below. Refresh tools/list after upgrading. The default catalog contains 85 Apple Ads tools. To continue using build_search_ads_campaign_draft, apply_search_ads_campaign_draft, or start_search_ads_campaign, add --apple-ads-workflows to the helper's launch arguments and restart it. This enables all three workflow tools, for 88 Apple Ads tools. Draft money values must use the current amount and currency object contract. Otherwise, compose planning and execution from the query and mutation primitives.
For full endpoint guidance, use:
{"name":"describe_apple_ads_tool","arguments":{"toolName":"query_search_ads_campaigns","section":"all"}}
The optional section can be request, response, examples, or all. The examples section points to this guide. Cache results by contentVersion. Full schemas retain Apple's open nested bodies and unrestricted response JSON. Safety checks and runtime validation are unchanged.
Write permissions now require separate ACL/role and product-feature verification within 24 hours. Kickstart refreshes expired permissions before writes; an unavailable refresh can block the write. Account-detail failures preserve previously verified metadata without renewing its verification time. Selected-account read denials trigger a permission check, but endpoint-specific denial alone does not revoke fresh permissions. Authentication and permission refresh can update the shared cache and vault. APPSTORE_APP_AUTOMATED-only accounts lack manual campaign support; refreshing credentials cannot add that capability. Credential Doctor reports the verification timestamps and permissionStaleReason. Do not change the shared account selection to resolve such errors.
Recovery lookups can now return snapshots from previous helper processes. Match the original requestID, sessionID, and recoveryID; integer and string spellings may identify multiple records. Records are cancellation evidence rather than final write outcomes. Recovery evidence is captured after signaling cancellation. Snapshots from older helpers whose cancellation ordering cannot be verified retain their resource IDs, but report conservative noChangesSubmitted: false and noChangesApplied: false with a message requiring readback. Read back uncertain resources before retrying.
Migrating to MCP 2.0.0
MCP 2.0.0 removes ten read aliases. Replace them with the following tools, supplying Apple's request object in query:
| Removed command | Replacement |
|---|---|
get_search_ads_campaigns |
query_search_ads_campaigns |
get_search_ads_ad_groups |
query_search_ads_ad_groups |
get_search_ads_keywords |
query_search_ads_keywords |
get_search_ads_negative_keywords |
query_search_ads_negative_keywords |
get_search_ads_ads |
query_search_ads_ads |
get_search_ads_creatives |
query_search_ads_creatives |
check_search_ads_app_eligibility |
query_search_ads_app_eligibility |
get_campaign_report |
query_search_ads_campaign_report |
get_keyword_report |
query_search_ads_keyword_report |
get_search_ads_report |
query_search_ads_campaign_report, query_search_ads_ad_group_report, query_search_ads_keyword_report, query_search_ads_search_term_report, or query_search_ads_ad_report, according to the report level |
Move read filters into query.filters, dates into query.timeRange, and pagination into query.pagination. Resolve projectName to an App Store app ID before querying; use the endpoint's documented app filter. Creative queries return account pages: match destination.parameters.adamId yourself and follow pagination.
These eleven write names remain, but accept only the Apple body contract: create_search_ads_campaign, update_search_ads_campaign, create_search_ads_ad_group, update_search_ads_ad_group, create_search_ads_keywords, update_search_ads_keywords, create_search_ads_negative_keywords, update_search_ads_negative_keywords, create_search_ads_creative, create_search_ads_ad, and update_search_ads_ad.
Use each tool's published body schema rather than nesting the old flat arguments unchanged. Apple field names and structures differ: for example, dailyBudget becomes body.dailyBudget.value with an amount and currency, and keyword batches use body.items. Keep accountID, the update's resource ID, confirm, and applicable expected…ID guards outside body. Parent IDs for creation belong inside the Apple body. For example:
{"name":"update_search_ads_campaign","arguments":{"campaignID":42,"body":{"name":"Renamed campaign"},"confirm":true}}
Refresh the MCP tool catalog or restart the client after upgrading. Supported MCP wire protocol versions remain 2024-11-05 and 2025-06-18; the server contract version is separate.
Achievements (1)
list_achievements- Lists celebrated milestones including revenue, download, rating, and review milestones.
Requirements
- Kickstart installed in
/Applications. - Kickstart opened at least once so it can populate local data.
- App Store Connect API keys configured in Kickstart for App Store Connect-backed tools.
- Search Ads credentials configured in Kickstart for Search Ads tools.
- Network access for App Store, Search Ads, competitor lookup, ranking, and analytics requests.