MCP server
Apogee MCP server
A remote Model Context Protocol server with 80 tools: an AI assistant launches your creatives on Meta, TikTok and Snapchat the Apogee way (the interview, the recap, your yes), reads performance and prepares changes, each confirmed by you.
Connect
| Server URL | https://app.apogee.ad/mcp |
|---|---|
| Transport | Streamable HTTP, stateless: every request is a POST answered with JSON. GET and DELETE answer 405 (no SSE stream, no session). |
| Sign-in | OAuth 2.1 with PKCE, discovered from the server (Claude, ChatGPT and the assistants of the quickstart), or an API key: Authorization: Bearer apk_… (authentication). |
| Server | apogee version 1.1.0, with instructions that tell the assistant how to launch (below). |
| Plans | Pro and Scale (plans). Each tool's cost: credits. |
Steps for Claude, ChatGPT, Claude Code, Cursor, VS Code, Gemini CLI and the others: quickstart.
How a launch works
- Pick the ad account.
list_ad_accounts(withplatformfor TikTok or Snapchat). The assistant asks which one when there are several. - The interview.
get_launch_questionsreturns the questions the app asks before every launch, in order, with the choices read from your account and a recommended answer. The assistant asks them one topic at a time, in your language, and never answers for you: starting point, campaign, upload structure, creatives, nomenclature, ads and formats, identity, audience, tracking, destination, texts, Advantage+ enhancements, catalog, budget and launch status. - The creatives. Files on your computer:
get_upload_urls, an upload per file,confirm_uploads. A Frame.io, Dropbox or Google Drive link:import_link+import_status. A Drive folder:list_drive_folder. Then the interview reads the file names with your naming convention and proposes the ads: one creative in 9:16, 4:5 and 1:1 is ONE ad. Snapchat and TikTok take videos and images (on TikTok an image runs as a carousel), from Apogee storage: a Drive file goes throughimport_linkfirst. On TikTok, an existing post can also run as a Spark Ad (list_tiktok_posts). - The texts. A primary text, a headline and a description per ad (from each video's transcript when it can), in the language of the targeted market, for you to validate. A copied ad brings its own.
- The recap.
prepare_launchcreates nothing. It refuses while a question is open (ready: falseand what to ask), applies only the app's documented defaults and lists them, checks with Meta (validate_only) the ads made from existing posts, and returns the whole recap with aplan_id. - Your explicit yes. The assistant shows the whole recap (settings, ads and files, texts, Advantage+ choices, defaults applied) and waits for your yes. Any change means a new
prepare_launch. - The launch.
launch(plan_id, confirm: true), thenlaunch_statusuntil it is finished. Ads are created paused unless you chose otherwise. A plan launches once, within 24 hours.
The same rule for every change: an action tool (pause, budgets, duplicates, targeting, a new campaign…) only prepares it and answers what will change; execute_action runs it after the user's OK, once, within 24 hours. A Bridge transfer works like a launch: prepare_bridge_transfer, the recap, then bridge_transfer.
Kinds of tools
Each tool carries MCP annotations (readOnlyHint, destructiveHint…) that assistants read to decide what needs a confirmation:
| Kind | What it does | Tools |
|---|---|---|
| Read only | Reads only: nothing is changed, in Apogee or on the ad account. | 54 |
| Prepares | Stores a plan or an action and says what it will do. Nothing changes on the ad account until it is confirmed. | 19 |
| Writes in Apogee | Changes Apogee only (imports, uploads, settings, comment syncs, AI drafts): nothing on the ad account. | 4 |
| Changes the ad account | Changes the ad account or acts as the Page, once, after the user's explicit yes. | 3 |
A connection only sees the tools of its scopes.
All the tools
80 tools in 10 groups. Credits: "Free*" = free up to the daily free reads (5,000 a day on Pro, 10,000 on Scale).
Account
Who is connected, and the ad accounts to work on.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
whoami | The Apogee account this connection acts as, the credential used (an assistant's connection or an API key) and its scopes. | read | Free* |
list_ad_accounts | The ad accounts connected to Apogee. | read | Free* |
Campaigns, ad sets and ads
Names and ids, no metrics: to find where to launch and what to copy.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
list_campaigns | The campaigns of an ad account: objective, CBO budget, status. Archived ones on request. | read | Free* |
list_adsets | The ad sets (TikTok ad groups, Snapchat ad squads) of an ad account, or of one campaign. | read | Free* |
list_ads | The ads of an ad account, a campaign or an ad set (200 at most). | read | Free* |
get_latest_in_campaign | The newest ad set and ad of a campaign, by creation time: "copy the latest ad set and ad of campaign X". Their ids go in prepare_launch copy_adset_from and copy_ad_from. | read | Free* |
get_templates | What a copy would take: from an ad set its targeting, event, bid and budget; from an ad its page, Instagram, texts, URL and call to action. | read | Free* |
list_launches | Your launches (the app's History), newest first: status, files, dates. | read | Free* |
Pages, pixels, audiences and posts
Meta only: the choices the launch interview offers.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
list_pages | The Facebook pages usable with an ad account, with their linked Instagram account. | read | Free* |
list_instagram_accounts | The Instagram account linked to a page. | read | Free* |
list_pixels | The pixels of an ad account. | read | Free* |
list_lead_forms | The instant forms of a page. | read | Free* |
list_custom_audiences | Custom and lookalike audiences, to include or exclude. | read | Free* |
search_targeting | Countries, regions and cities, interests, behaviors, life events and languages, with the keys a launch takes. | read | Free* |
list_posts | Existing posts a new ad can reuse with their likes and comments: the posts behind your ads, a page's posts, or its Instagram posts. | read | Free* |
Creatives
Bring the files in before a launch. Nothing reaches Meta at this point.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
import_link | Imports the creatives behind a Frame.io, Dropbox or Google Drive link (a file or a folder) through the account connected to Apogee. A public Frame.io share works without a Frame.io account when downloads are allowed; a password-protected share does not. | launch | Free* |
import_status | The progress of an import. Each finished file gets a ref for the launch. | read | Free* |
list_drive_folder | The videos and images of a Google Drive folder, subfolders included, each with its format. | read | Free* |
get_upload_urls | For files on your computer: one signed upload URL per file (50 per call, 500 MB per file, valid 1 hour). The assistant uploads each file with an HTTP PUT. | launch | Free* |
confirm_uploads | Checks each uploaded file arrived and is not empty. | launch | Free* |
Launch
The interview, the recap, your yes, then the launch.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
get_launch_questions | The questions the app asks before every launch, in order, with the choices read from your account and a recommended answer (TikTok's and Snapchat's own with platform). Called again with the files (it reads their names with your naming convention and proposes the ads) and with the answers so far. | read | Free* |
prepare_launch | Prepares the launch without creating anything: the whole recap and a plan_id, valid 24 hours. Refuses while a question is open. Starts from scratch, a copied ad set and ad, or saved templates; the ads are new files (grouped by your naming convention or by hand), or existing ads reused with their post ID. | launch | Free* |
launch | Launches a prepared plan (Meta, TikTok or Snapchat: the plan knows), once, after your explicit yes to its recap. | launch | 15 per ad |
launch_status | Follows a launch until it is finished. interrupted means an Apogee deploy cut it: check Ads Manager before launching again. | read | Free* |
create_campaign | Prepares a new campaign, always created paused: name, objective, budget per ad set (ABO) or per campaign (CBO, with its bid strategy). execute_action creates it after your OK. | launch | Free* |
- Ads grouped by hand: Each ad lists its own files: the formats of one creative, one file per format, never a video with an image, no naming convention needed. Two ads never share a name. An ad without a concept gets its own ad set, or "Group 1" once other ads have one.
- Ad sets chosen by hand: Which ad goes into which new ad set, each ad in exactly one, on top of One Adset One Ad, One Concept One Adset or All in One; every ad set takes the plan's ad set settings. Not with Insert in Adset,
adset_variantsor existing ads. Without it, the structure follows your naming convention. - Duplicate with post ID: each new ad set its own ads: With existing ads, each new ad set lists its ads, by ad name or source ad id. Left out everywhere: every ad in every ad set. Given on one: every ad set needs its list, and every ad must be in one at least.
- Copy the latest ad set and ad of a campaign:
get_latest_in_campaignreturns them (REST:GET /ad-accounts/{acc}/campaigns/{id}/latest); the launch interview also offers them as a starting point once the campaign is chosen.
Performance
The same reads as Apogee's Autopilot, with the same numbers as the app. Ad names follow your naming convention: ask per concept or per hook.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
get_account_overview | Spend, impressions, clicks, CTR, CPC, ROAS and conversions of the ad account for a period. | read | Free* |
get_campaigns | The campaigns with their budget, spend and results. | read | Free* |
get_adsets | The ad sets with their targeting, budget and metrics. | read | Free* |
get_ads | The ads with their creative and metrics. | read | Free* |
get_top_performers | The best and the worst campaigns, ad sets or ads by ROAS, CPA, CTR or spend: what to scale, what to cut. | read | Free* |
get_daily_breakdown | Spend, ROAS, CPA and add to carts day by day. | read | Free* |
get_ad_performance_by_placement | Results by placement (Feed, Stories, Reels…). | read | Free* |
get_ad_performance_by_age_gender | Results by age and gender. | read | Free* |
get_ad_performance_by_device | Results by device. | read | Free* |
get_creative_fatigue_metrics | Frequency, CTR trend and CPC over time; flags tired creatives. | read | Free* |
get_video_metrics | Hook rate, hold rate, completion and ThruPlay per video ad. | read | Free* |
get_ad_creatives | The images, videos and texts of the ads of an ad set or a campaign. | read | Free* |
get_audience_insights | The targeting and estimated audience size of ad sets. | read | Free* |
get_account_spend_limit | The account's spend cap, amount spent and balance. | read | Free* |
get_campaign_budget_optimization | Whether a campaign uses a campaign budget (CBO), and that budget. | read | Free* |
Brand and research
Context for creative strategy: your business profile, your comments, reviews and competitors.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
get_business_profile | What Apogee knows about the brand of this ad account: website, margin, targets (CAC, ROAS). | read | Free* |
update_business_profile | Saves what you told the assistant about the brand, so it does not ask again. Apogee's data only. | actions | Free* |
fetch_website_content | Reads the brand's website: voice, positioning, persona, claims. | read | 150 (0 if cached) |
fetch_ad_comments | The comments of your ads, as Comment Analysis stores them. | read | Free* |
trigger_comment_sync | Fetches fresh comments from Meta (1 to 5 minutes). | read | 10 |
fetch_customer_reviews | Public reviews of the brand, positive or negative. | read | Free* |
search_reddit | Reddit threads on a topic: the customers' own words and pain points. | read | Free* |
search_meta_ad_library | Competitors' ads in the Meta Ad Library (texts only). | read | Free* |
load_reference | Loads one of Apogee's reference documents (audit frameworks, checklists, benchmarks). | read | Free* |
Actions
Each tool only prepares: it returns an action_id and what will change. Nothing changes until execute_action, after your explicit OK, within 24 hours. Created objects are paused unless you ask otherwise.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
pause_ad | Pauses ads. | actions | Free* |
pause_adset | Pauses ad sets. | actions | Free* |
activate_ad | Turns paused ads back on. | actions | Free* |
activate_adset | Turns paused ad sets back on. | actions | Free* |
update_budget | Sets new daily budgets for ad sets. | actions | Free* |
scale_budget | Scales ad set budgets by a percentage (+100% at most per change). | actions | Free* |
update_campaign_status | Pauses or turns on a whole campaign. | actions | Free* |
update_adset_targeting | Changes an ad set's targeting. | actions | Free* |
duplicate_ad | Copies an ad into other ad sets of the same ad account, keeping the same post (likes, comments, shares). | actions | Free* |
duplicate_adset | Copies an ad set with its ads, each keeping its post; created paused. | actions | Free* |
duplicate_campaign | Copies a campaign with its ad sets and ads; created paused. | actions | Free* |
create_adset | A new ad set in an existing campaign, from scratch or copying another ad set's targeting and conversion; created paused. | actions | Free* |
create_ad | A new ad on an existing post or creative; created paused. | actions | Free* |
create_ad_from_post | A new ad on an existing Facebook or Instagram post, which keeps its likes and comments, with every Advantage+ enhancement explicit; paused by default. | actions | Free* |
execute_action | Runs a prepared action (or a prepared campaign), once, after your explicit OK. Returns what was created. | launch or actions | 2 |
TikTok and Snapchat
list_ad_accounts, list_campaigns, list_adsets, list_ads, get_launch_questions and prepare_launch take platform: "tiktok" or "snapchat" (default "meta"); launch and launch_status follow the plan whatever its platform: the same interview, the same recap, the same explicit yes. The tools below read their numbers and change their status and budgets, one platform at a time: money in the ad account's currency, days in its time zone, TikTok and Snapchat never added up.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
get_platform_overview | One TikTok or Snapchat ad account's totals over a period: spend, impressions, clicks, CTR, CPC, CPM, reach, purchases, revenue, ROAS, CPA, add to carts. For Meta: get_account_overview. | read | Free* |
get_platform_performance | One row per campaign, ad set (TikTok ad group, Snapchat ad squad) or ad, with its status, daily budget and metrics, sorted by spend by default. TikTok's Smart+ ads included. | read | Free* |
get_platform_daily_breakdown | Day by day (92 days at most, every day listed) for the ad account or one campaign, ad set or ad, with the period's totals. For Meta: get_daily_breakdown. | read | Free* |
get_platform_top_performers | The best and the worst ads, ad sets or campaigns by a metric, among those that spent: what to scale, what to cut. For Meta: get_top_performers. | read | Free* |
list_targeting | TikTok interests, behaviors and languages, Snapchat interests and countries, with the launch field their ids go in. Meta's targeting: search_targeting. | read | Free* |
list_tiktok_posts | TikTok Spark Ads: the existing posts a launch can run as ads, keeping their likes and comments. source: "account" (default): the video posts of one of the brand's TikTok accounts (the first one, or identity_id from the launch interview), a page at a time; source: "authorized": the posts creators authorized for this ad account. Each post says whether it can run and gives its spark_post for prepare_launch. | read | Free* |
list_tiktok_music | TikTok carousels (image ads run with a music): the music of TikTok's carousel library a launch can use. q: a keyword (e.g. "upbeat"); without one, the music this ad account used. Each gives its music_id for prepare_launch (tiktok.ad_settings.music_id); none given, TikTok picks one for each carousel at the launch. | read | Free* |
list_platform_templates | TikTok and Snapchat: the Quick Bulk Edit templates saved in the Apogee app ("Save as template" in the ad group / ad squad and ad params), per ad account. level: "adgroup": an ad group's (TikTok) or an ad squad's (Snapchat) settings; level: "ad": an ad's (TikTok account, texts, URL, call to action…). prepare_launch uses one as its base: tiktok.adgroup_template_id / tiktok.ad_template_id, snapchat.adsquad_template_id / snapchat.ad_template_id. Saving and deleting templates stay in the app. | read | Free* |
set_platform_status | Prepares pausing or turning on TikTok or Snapchat campaigns, ad sets or ads; execute_action runs it after your OK. TikTok GMV Max and legacy Smart+ campaigns, and the ads TikTok generates inside Smart+ ad groups, are changed in TikTok Ads Manager. | actions | Free* |
set_platform_daily_budget | Prepares a new daily budget for a TikTok or Snapchat campaign or ad set, in the ad account's currency; execute_action runs it after your OK. Refused above the safety cap, on a lifetime budget, on an ad set whose campaign holds the budget, and on TikTok Smart+ budgets. | actions | Free* |
- TikTok: The ad account is the advertiser id (digits). A new campaign goes under
tiktok.new_campaign: a Sales campaign, ABO or CBO with a daily or a lifetime budget (a lifetime budget runs totiktok.end_dateandtiktok.end_time, asked when missing), Standard unless Smart+ (below). TikTok's ad group and ad settings undertiktok.adgroup_settingsandtiktok.ad_settings(identity, website, call to action). Ad groups by hand:adgroups(new, or an existing one), each ad in exactly one.copy_adset_from/copy_ad_fromalso take"latest". In a Standard ad group, one video per ad, its texts inads[].copy.primary_texts(one TikTok ad per text); images run as carousels (below). Spark Ads: an existing TikTok post runs as the ad withads[].spark_post(fromlist_tiktok_posts) instead of files; its caption is the text and only its destination is asked. Checked before anything: 50 ads per Standard ad group. Not through the MCP and the API yet: binding a creator's Spark code (done in the app); GMV Max campaigns are refused. - TikTok Smart+:
tiktok.new_campaign.smart_plus: truecreates an Upgraded Smart+ Sales campaign, as the app's Create Campaign. An existing Smart+ campaign takes new ad groups where TikTok and Apogee allow it (list_campaigns:can_create_adgroup), and its ad groups take new ads (existing_adset_ids, oradgroupsby hand); Smart+ and Standard ad groups never share a launch. One Smart+ ad per creative: its texts (5 at most) rotate inside it. TikTok's dynamic call to action:tiktok.ad_settings.cta_language(en, fr, de, es, it, nl, pt, pl, sv) andtiktok.ad_settings.cta_texts(the calls to action kept among the ones TikTok offers). TikTok's automations, each off unless you turn it on:tiktok.ad_settings.automations(auto_add, andenhancements:TRANSLATE_AND_DUB,MUSIC_REFRESH,VIDEO_QUALITY,IMAGE_QUALITY,IMAGE_RESIZE). Checked before anything: 30 ads per ad group, 30 ad groups per campaign, no 13-17 age group, no Spark post. - TikTok carousels: Images (JPG or PNG) in a TikTok plan run as carousels, TikTok's image ads, with a music.
tiktok.carousel_mode:"single"(the default: each image ad is a carousel of its image) or"by_concept"(a concept's images make one carousel ad named after the concept, 35 images at most; not with ad groups made by hand). The music:tiktok.ad_settings.music_id, fromlist_tiktok_music(REST:GET /ad-accounts/{acc}/tiktok-music?q=); none given, TikTok picks one at the launch. A carousel runs on the TikTok placement only: its ad group needs it. - Snapchat: The ad account is its id (a UUID). A new campaign goes under
snapchat.new_campaign; the ad squad and ad settings undersnapchat.adsquad_settings(pixel, countries, ages, genders) andsnapchat.ad_settings(public profile, website, UTM, brand name);snapchat.time_zonefor a scheduled launch. Ad squads by hand:adsquads. One vertical video per ad, one Snap ad per headline inads[].copy.headlines(34 characters). Daily budgets: 5 at least per ad squad, 20 per campaign budget. "latest" is not available: Snapchat gives no creation dates. - Saved templates (Quick Bulk Edit): The templates saved in the Apogee app (Quick Bulk Edit, "Save as template" in the ad group / ad squad and ad params) are a plan's base:
tiktok.adgroup_template_id,tiktok.ad_template_id,snapchat.adsquad_template_id,snapchat.ad_template_id, fromlist_platform_templates(REST:GET /ad-accounts/{acc}/platform-templates?platform=&level=). The plan's own settings go over the template's. A template or a copy, not both: not withcopy_adset_from/copy_ad_from. Saving and deleting templates stay in the app. - Files: From Apogee storage: your uploads (
get_upload_urls+confirm_uploads) or imports (import_link+import_status). Snapchat takes videos and images (image ads); TikTok takes videos and images (JPG or PNG, run as carousels). A Google Drive file goes throughimport_linkfirst. On TikTok, an existing post can run instead of a file (ads[].spark_post).
Bridge
Ads of one platform launched on another (Meta → TikTok or Snapchat, and back), or a Meta → Meta copy between two ad accounts. Prepared, shown in full, then run after your explicit yes; a plan runs once, within 24 hours.
| Tool | What it does | Scope | Credits |
|---|---|---|---|
prepare_bridge_transfer | Prepares a transfer without transferring anything: the source ads (or a Meta ad set's or campaign's ads), the destination campaign and its existing ad set / ad group / ad squad or a new one copied from a template. Returns the recap and a plan_id; ready: false lists what to ask (a TikTok identity, a Snapchat public profile, a website…), then prepare again with extra_fields. Incompatibilities are listed: your yes accepts them. For a Meta → Meta copy, the destination's fields go in mapping. | launch | Free* |
bridge_transfer | Runs a prepared transfer, once, after your explicit yes; the plan is checked again first. Answers with the outcome (completed, partial, failed…) within about 25 seconds, or running. A Meta → Meta copy reuses each ad's post (likes, comments) when Meta lets the destination use it, and copies it as a new post otherwise. | launch | 15 per ad |
bridge_transfer_status | Where a transfer is: running, completed, partial (with the failures), failed, not run, or unknown (check the destination before running it again). | read | Free* |
list_bridge_transfers | The ads already bridged from a source ad account, newest first, with where each one went. | read | Free* |
get_bridge_stats | The Bridge's Stats tab: each creative bridged from a Meta ad account, its Meta ad next to its TikTok and Snapchat copies, with their spend and results over the period (7-day click attribution everywhere), each platform in its own currency. | read | Free* |
get_bridge_daily_stats | The Bridge's Daily tab: day by day, per platform, the spend, revenue, ROAS, impressions, link clicks and purchases of every creative bridged from a Meta ad account (366 days at most). Platforms are never added up. | read | Free* |
Prompt templates
Copy one, replace the [brackets] with your own names, and paste it in your assistant. Each ends with a safety reminder: everything created paused and the full recap first, or each change shown and approved before it is made.
Launch a folder from your computer
Every creative of a folder on your computer, in a new ad set of your testing campaign, with the settings of the last ad set and the last ad launched there.
Take every creative in [folder] on my computer and launch them in a NEW ad set in my [testing campaign] campaign of [ad account]. Reuse the settings of the latest ad set and the latest ad launched in that campaign. Create everything paused, and show me the full recap before you create anything. Needs an assistant that can run commands on your computer to upload the files. In Claude or ChatGPT on the web, put the folder on Google Drive, Dropbox or Frame.io and use the link template.
What the assistant asks you
- Which ad account, when you have several.
- The ads it reads from your file names with your naming convention: one ad per creative, its 9:16, 4:5 and 1:1 files together. Confirm or correct them.
- The new ad set's name.
- What it copies from the latest ad set (audience, conversion event, bid, budget) and the latest ad (page, Instagram, URL, call to action, texts), and whether anything should change.
- Which Advantage+ enhancements to turn on: every one you don't pick stays off.
- Whether to show products from your catalog, when the account has one.
- The whole recap, then your explicit yes.
What gets created
- Your files uploaded to Apogee. Nothing reaches Meta before your yes.
- One new ad set in the campaign, paused, with the copied settings.
- One ad per creative, paused, with the copied page, URL, call to action and texts.
Launch from a Frame.io, Google Drive or Dropbox link
The same launch from a link: no download, no upload on your side.
Take every creative in [link] and launch them in a NEW ad set in my [testing campaign] campaign of [ad account]. Reuse the settings of the latest ad set and the latest ad launched in that campaign. Create everything paused, and show me the full recap before you create anything. Works in every assistant. Google Drive, Dropbox and Frame.io links go through the account you connected in Apogee; a public Frame.io share works without one when downloads are allowed (reading it takes 20 to 30 seconds), a password-protected one does not.
What the assistant asks you
- Which ad account, when you have several.
- The files it found behind the link, then the ads it reads from their names: one ad per creative in all its formats. Confirm or correct them.
- The new ad set's name, and what it copies from the latest ad set and ad.
- Which Advantage+ enhancements to turn on.
- The whole recap, then your explicit yes.
What gets created
- The files imported into Apogee.
- One new ad set in the campaign, paused, with the copied settings.
- One ad per creative, paused.
Black Friday on all your ad platforms from one link
Your Black Friday creatives from one Frame.io, Google Drive or Dropbox link, launched as new campaigns on Meta, TikTok and Snapchat, each platform with its own settings, budget and currency.
Take my creatives in [link] and create my Black Friday campaigns on all my ad platforms: Meta ([Meta ad account]), TikTok ([TikTok ad account]) and Snapchat ([Snapchat ad account]). One new campaign per platform named [campaign name], a daily budget of [budget] on each, the offer is [offer] and it sends to [landing page]. Create everything paused, and show me the full recap before you create anything. Images run on every platform: image ads on Meta and Snapchat, carousels on TikTok. A public Frame.io share works without a Frame.io account when downloads are allowed.
What the assistant asks you
- Which ad account on each platform, when you have several.
- The files it found behind the link, then the ads it reads from their names: on Meta one ad per creative with its 9:16, 4:5 and 1:1 together, on TikTok one ad per vertical video or a carousel of images, on Snapchat one ad per vertical video or image.
- Per platform, what the new campaign needs: on Meta the objective, the pixel and its event, the page and Instagram account; on TikTok the identity and whether to use Smart+; on Snapchat the public profile, the pixel and the countries.
- The texts, written from your offer in the language of each market, for you to validate.
- One recap per platform, and your explicit yes to each.
What gets created
- The files imported into Apogee once, used on every platform.
- On Meta: the new campaign (prepared with
create_campaign, created after your OK), then its ad sets and ads, paused. - On TikTok and Snapchat: the new campaign, its ad group or ad squad and its ads, paused.
- Each platform in its own budget and currency: nothing is added up across platforms.
Split the ads into ad sets your way
The same creatives, in the structure you test with: one ad set per concept, one ad set per ad, or everything in one ad set.
Launch the creatives in [link or folder] in my [campaign] campaign of [ad account] as One Concept One Adset: one ad set per concept, read from my naming convention. Create everything paused, and show me the full recap before you create anything. What the assistant asks you
- How your naming convention reads each file (concept, iteration, format). A file nothing matched needs its concept.
- The ads: one creative in all its formats is one ad.
- Where the new ad sets' settings come from: a copied ad set, a saved template, or from scratch (countries, ages, pixel and event).
- The budget of each new ad set when the campaign has no campaign budget.
- The whole recap, then your explicit yes.
What gets created
- One Concept One Adset: one new ad set per concept, named after it, with that concept's ads.
- One Adset One Ad: one new ad set per ad, named after it.
- All in One: one new ad set with every ad.
- Everything paused.
Group ads and ad sets by hand
You decide which files make each ad and which ad goes into which ad set, whatever the file names say.
Launch the creatives in [link or folder] in my [campaign] campaign of [ad account]. Pair the 4:5 and the 9:16 of each creative into one ad. Put ads [A] and [B] in a new ad set named [ad set 1], and ad [C] in a new ad set named [ad set 2]. Create everything paused, and show me the full recap before you create anything. What the assistant asks you
- The ads it built: each creative's 4:5 and 9:16 files together, each ad with its own name. Confirm or correct the pairs.
- Which ad goes into which new ad set, as you asked: each ad in exactly one.
- Where the new ad sets' settings come from, and their budget when needed.
- The whole recap, then your explicit yes.
What gets created
- Two new ad sets, paused: the first with ads A and B, the second with ad C.
- One ad per creative, its formats together, paused.
Launch files whose names mean nothing
Files named IMG_4512.mp4 or final_v3_OK(1).mov, launched without a naming convention: you check the ads, rename them and put them in groups, one ad set per group.
Launch the videos in [folder or link] in my [campaign] campaign of [ad account]. The file names mean nothing: group the formats of each creative, show me the ads, let me rename them and put them in groups, one ad set per group. Reuse the settings of the latest ad set and ad of that campaign. Create everything paused, and show me the full recap before you create anything. A folder on your computer needs an assistant that can run commands on it (Claude Code, Cursor…). In Claude or ChatGPT on the web, use a Frame.io, Google Drive or Dropbox link.
What the assistant asks you
- Which ad account, when you have several.
- The ads it built: files whose names differ only by their format words (feed and story, 4x5 and 9x16…) are the 4:5, 9:16 and 1:1 of one creative, linked into one ad; every other file is its own ad, named after the file. Link the files of one creative, or split them.
- A name for each ad, if you want other names than the files'.
- Which ads go together in a group: each group becomes one ad set (One Concept One Adset).
- What it copies from the latest ad set and ad of the campaign, and whether anything should change.
- The whole recap, then your explicit yes.
What gets created
- One new ad set per group, paused, with the copied settings. An ad you put in no group gets its own ad set, or goes in "Group 1" once other ads have one.
- One ad per creative, its formats together, with the name you gave it, paused.
- No naming convention needed, and nothing to rename in your files.
Send a Meta ad to Snapchat or TikTok
An ad that works on Meta, sent to Snapchat or TikTok with Bridge, without exporting anything. The Meta ad is not touched.
Take my Meta ad [Meta ad] from [Meta ad account] and send it to Snapchat: campaign [campaign], ad squad [ad squad]. Create everything paused, and show me the full recap before you create anything. Videos only on Snapchat and TikTok.
What the assistant asks you
- Which Snapchat or TikTok ad account, when you have several.
- What the destination still needs and cannot take from the ads already there: a Snapchat public profile, a TikTok identity, a website, a headline.
- What cannot be carried over as is (a call to action remapped, a video that is not vertical): your yes accepts it.
- The whole recap, then your explicit yes.
What gets created
- The ad in that ad squad or ad group, paused, with the Meta ad's video and texts.
- The Meta ad is not touched.
list_bridge_transfersshows what was already bridged.
Run your TikTok posts as Spark Ads
Posts already on your TikTok account, or that creators authorized for you, run as ads: their likes, comments and views keep adding up, and nothing is uploaded.
Run my TikTok posts [posts] from [TikTok account] as Spark Ads in a NEW ad group of my [campaign] campaign on [TikTok ad account], sending to [landing page]. Create everything paused, and show me the full recap before you create anything. A creator's post needs its Spark code bound in the Apogee app first (TikTok › Ad params › Source); it then shows among the authorized posts.
What the assistant asks you
- Which TikTok ad account, and which of the brand's TikTok accounts the posts are on (or the posts creators authorized).
- The posts it found, each saying whether TikTok can run it and, if not, why.
- The new ad group's settings (copied from the latest ad group, or from scratch: pixel and event, countries, budget) and the destination: URL and call to action. The post's caption is the text: nothing to write.
- The whole recap, then your explicit yes.
What gets created
- One new ad group, paused, with one Spark Ad per post: the post itself runs as the ad.
- Nothing is posted again on TikTok and the posts are not changed.
Launch your statics on TikTok as carousels
Images run on TikTok as carousels, TikTok's image ads with a music: one carousel per image, or one per concept with all its images.
Launch the statics in [link] on TikTok ([TikTok ad account]) as carousels, one per concept, with [music], in a NEW ad group of my [campaign] campaign, sending to [landing page]. Create everything paused, and show me the full recap before you create anything. JPG or PNG images, 35 per carousel at most. A carousel runs on the TikTok placement only.
What the assistant asks you
- Which TikTok ad account, when you have several.
- The images it found behind the link, one carousel per concept read from your naming convention: confirm or correct them.
- The music: a few from TikTok's carousel library matching your words, or TikTok's own pick at the launch.
- The new ad group's settings (copied from the latest ad group, or from scratch), on the TikTok placement, and the destination: URL and call to action.
- The texts of each carousel, then the whole recap and your explicit yes.
What gets created
- The images imported into Apogee.
- One new ad group, paused, with one carousel ad per concept, named after it: its images in their order, with the music.
Create a TikTok Smart+ campaign
A new Upgraded Smart+ Sales campaign from your videos, as the app's Create Campaign: one Smart+ ad per creative, its texts rotating inside it, TikTok's dynamic call to action in the language of your market.
Create a TikTok Smart+ campaign named [campaign name] on [TikTok ad account] with the videos in [link], a daily budget of [budget], TikTok's dynamic call to action in [language], sending to [landing page]. Create everything paused, and show me the full recap before you create anything. Smart+ takes no 13-17 age group and no Spark post; 30 ads per ad group and 30 ad groups per campaign at most.
What the assistant asks you
- Which TikTok ad account, when you have several.
- The ads it reads from your file names: one Smart+ ad per creative, its texts (5 at most) rotating inside it.
- The ad group's settings: pixel and event, countries and ages (no 13-17 on Smart+), the identity and the destination.
- Which calls to action to keep among the ones TikTok offers in that language, and whether to turn on any of TikTok's automations (all off by default).
- The whole recap, then your explicit yes.
What gets created
- The files imported into Apogee.
- One new Upgraded Smart+ campaign with its ad group and one Smart+ ad per creative, paused.
Launch with a template saved in the app
TikTok or Snapchat ads launched from a Quick Bulk Edit template you saved in the Apogee app: its ad group or ad squad settings, or its ad settings, without setting them again.
Launch the videos in [link] on Snapchat ([Snapchat ad account]) in a NEW ad squad of my [campaign] campaign, with my saved template [template]. Create everything paused, and show me the full recap before you create anything. Templates are saved in the app (Quick Bulk Edit, "Save as template"): the assistant reads and uses them, it never saves or deletes one.
What the assistant asks you
- Which ad account, when you have several.
- The templates saved for that ad account, for the ad group or ad squad and for the ad: which ones to use.
- What to change over the template's settings, if anything: the plan's own settings go over it.
- The whole recap, then your explicit yes.
What gets created
- The files imported into Apogee.
- One new ad squad or ad group, paused, with the template's settings (and your changes over them) and its ads.
- Your templates are not changed.
Scale winners with their post ID
Winning ads moved into new ad sets with their post ID: their likes, comments and shares keep adding up.
Scale [these 3 winning ads] of [ad account] into 2 new ad sets in [scaling campaign], with their post IDs: cost caps of [25] and [35]. Put ads [A] and [B] in the first ad set, and all of them in the second. Create everything paused, and show me the full recap before you create anything. What the assistant asks you
- Which ads, when you described them (e.g. the best by ROAS): it shows them with their numbers.
- Which campaign, or a new one (budget per ad set, or a campaign budget whose bid strategy is cost cap).
- Which ad set the audience and conversion are copied from, and each new ad set's name and budget.
- The whole recap, then your explicit yes.
What gets created
- Two new ad sets, paused, each with its own cost cap.
- In each, new ads on the same posts as the winners (named after them, "- Copy with post ID"): likes and comments stay.
- The winners themselves are not touched.
Move ads, an ad set or a whole campaign to another Meta ad account
A Meta → Meta copy with the Bridge, between two of your ad accounts: an ad into an ad set, an ad set with its ads into a campaign, or a whole campaign with everything inside. The source is not touched.
Copy my ad [ad] from [source ad account] into the ad set [destination ad set] of [destination ad account] with the Bridge, keeping its post (likes and comments) if Meta allows it. Create everything paused, and show me the full recap before you create anything. What the assistant asks you
- Which source and which destination ad account, when you have several.
- What the destination needs and cannot take from the source: its pixel and conversion event, its page and Instagram account, an audience saved in the source account, a budget. It lists them and you give each one.
- Whether the copies start paused (the default) or take the status of the source.
- The whole recap, then your explicit yes.
What gets created
- In the destination account: the ad, the ad set with its ads, or the campaign with its ad sets and ads, paused.
- Each ad keeps its post (likes, comments, shares) when Meta lets the destination use it; otherwise it is copied as a new post, and the transfer says so.
- The source ads, ad sets and campaigns are not touched.
Weekly review: what to scale, what to cut
Your numbers read for you, and the changes proposed one by one. Nothing changes without your yes.
Look at [ad account] over the last 7 days. Which ads should I scale and which should I cut, judged on [ROAS or CPA]? Show me the numbers, then propose the changes. Show me each change and wait for my yes before you make it. What the assistant asks you
- Your targets, when Apogee does not know them yet (it can remember them in your business profile).
- Each proposed change (pause, budget up or down) with what it will change, and your OK for each one.
What gets created
- Nothing until you approve. Then only the changes you approved, within 24 hours.
Weekly report on every platform
Last week on Meta, TikTok and Snapchat, each platform on its own (its own currency, never added up): spend and results against the week before, the best and the worst ads, what the Bridge's copies did, and what to do next.
Give me my weekly report for [brand]: the last 7 days against the 7 days before, on Meta ([Meta ad account]), TikTok ([TikTok ad account]) and Snapchat ([Snapchat ad account]), each platform on its own. Spend, ROAS and CPA, the 3 best and the 3 worst ads, and what to scale or cut. Show me each change and wait for my yes before you make it. What the assistant asks you
- Your targets (ROAS or CPA) when Apogee does not know them yet: it can remember them in your business profile.
- Each proposed change (pause, budget up or down) with what it will change, and your OK for each one.
What gets created
- A report per platform, each in its own currency: nothing is added up across platforms.
- Nothing on your ad accounts until you approve a change.
Limits and errors
- 600 MCP requests per 15 minutes on Pro, 1,200 on Scale, every key and connection of the account together; past it,
429(rate limits). - A refused or failed tool call answers a tool result with
isError: trueand the reason in words (what to ask, what to fix): the assistant reads it and can correct its call. It costs nothing. - Credits, daily caps and the Meta, TikTok and Snapchat budgets work as on the REST API: credits, rate limits, errors.
- A missing or invalid credential: HTTP
401with the OAuth discovery header. A plan without the MCP: HTTP403, a JSON-RPC error with the plan's words.
Server instructions
What the server tells every assistant when it connects (MCP instructions), word for word:
The instructions (8,954 characters)
Apogee launches and manages Meta, TikTok and Snapchat ads the way the Apogee app does: an interview, a recap, the user's yes, then the launch.
GOLDEN RULES
1. Nothing is created, changed or transferred without the user's explicit yes to the WHOLE recap: prepare_launch → launch, an action tool → execute_action, prepare_bridge_transfer → bridge_transfer.
2. Ask the open questions ONE TOPIC AT A TIME, in the user's language, with the choices the tools return. Never answer for the user.
3. Ads are created paused unless the user asks otherwise.
4. platform: "meta" (default), "tiktok" or "snapchat" on list_ad_accounts, list_campaigns, list_adsets, list_ads, get_launch_questions and prepare_launch.
LAUNCH NEW CREATIVES (the core job)
1. list_ad_accounts (ask which one when there are several).
2. get_launch_questions(ad_account_id): the app's questions, in its order, with the account's choices and a recommended answer. Ask every to_ask one.
Order: starting point (duplicate an ad set / an ad / a template, or from scratch) → campaign → upload structure → creatives → nomenclature → ads and formats → identity → audience → tracking → destination (URL, UTM, CTA) → texts → Advantage+ → catalog → budget and launch status.
3. Creatives into Apogee: files on the computer → get_upload_urls, upload each file, confirm_uploads; a link (Frame.io incl. public shares, Dropbox, Drive) → import_link + import_status; a Drive folder → list_drive_folder.
4. get_launch_questions again with files (each file's format, and durationS when known): it proposes the ads. Show them (ad name ← files) and let the user link, split, rename and group them.
5. Texts: a primary text, a headline and a description per ad (from each video's transcript when you can), in the language of the targeted market; get them validated.
6. prepare_launch(all the answers). ready:false = ask what it lists, then call it again. Show the whole recap (settings, ads and files, texts, Advantage+, defaults applied), wait for the yes, then launch(plan_id, confirm: true) and launch_status until finished. Any change = prepare_launch again.
7. A launch with errors: launch_status gives what_to_do. Tell the user, in their language, what the platform refused and how to fix it (its explanation, and guide_url when there is one), then follow its rule. retry "after_fix": never launch again before the user says the cause is fixed or chooses a change that removes it; launching unchanged fails the same way. retry "once": you may launch the same ads one more time. empty_adsets: reuse them (insert_in_adset) rather than creating new ad sets.
FILE NAMES AND ADS
- One ad = one creative in all its formats (9:16, 4:5, 1:1): each ad = { ad_name, files: the formats of ONE creative (one file per format, never a video with an image), concept?: its group }.
- A saved naming convention that reads EVERY file: the ads come from it (concept, iteration, format).
- Otherwise (names that mean nothing: IMG_4512.MOV, final_v3_OK(1).mp4…): grouped by hand like the app's "Group by hand": the formats of one creative are linked when their names differ only by the format, every other file is its own ad named after the file, no nomenclature to confirm. maybe_same_creative = same length, different formats: ask before linking them.
- Send grouping_confirmed: true once the user validated the ads; nomenclature only names a saved convention in the recap.
AD SETS
- Structures: one_adset_one_ad, one_concept_one_adset (one ad set per concept; ads without a concept are their own, or "Group 1" once others have one), all_in_one (all_in_one_name), insert_in_adset (existing_adset_ids).
- By hand: adsets [{ name, ads: [ad_name…] }] (Meta), adgroups (TikTok), adsquads (Snapchat): each ad in exactly one; ad names unchanged.
- "Copy the latest ad set and ad of campaign X": get_latest_in_campaign → copy_adset_from / copy_ad_from.
DUPLICATE WITH POST ID (likes and comments kept): ads[].source_ad_id instead of files (get_launch_questions → creatives.choices.existing_ads). Nomenclature, texts, identity, destination, Advantage+ and catalog don't apply. New ad sets: structure all_in_one + adset_variants (one cost cap / bid / ROAS floor each; adset_variants[].ads = each one's own ads, by ad_name or source_ad_id). Existing ad sets: insert_in_adset. A CBO's bid strategy is set by create_campaign bid_strategy.
PERFORMANCE (the same reads as Apogee's Autopilot): get_account_overview, get_campaigns, get_adsets, get_ads, get_top_performers, get_daily_breakdown, get_ad_performance_by_placement / _by_age_gender / _by_device, get_creative_fatigue_metrics, get_video_metrics (hook / hold rates), get_ad_creatives, get_audience_insights, fetch_ad_comments, budgets and spend limit. list_* only resolve names and ids (no metrics); get_* carry the metrics. Ad names follow the account's naming convention (concept, hook, format…): group by it when the user asks per concept or hook.
TIKTOK / SNAPCHAT PERFORMANCE (platform "tiktok" or "snapchat", the platform's own ad account id): get_platform_overview, get_platform_performance (level campaign / adset / ad), get_platform_daily_breakdown, get_platform_top_performers. Their changes: set_platform_status (pause / activate) and set_platform_daily_budget, prepared then run by execute_action like Meta's. One platform at a time: never add their numbers up.
ACTIONS (pause, activate, budgets, duplicate, create ad set / ad, targeting, campaign status, create_campaign, create_ad_from_post): the tool only prepares the action and returns an action_id with what will change. Show it, wait for the explicit OK, then execute_action (within 24 hours). New ads with new creatives always go through prepare_launch → launch; a new ad on an EXISTING post goes through list_posts → create_ad_from_post; duplicate_ad keeps the same post inside the same ad account.
TIKTOK (platform "tiktok"): the same interview → recap → yes → launch. get_launch_questions gives TikTok's choices (campaigns with their family: Standard, and Upgraded Smart+ — a new one with tiktok.new_campaign.smart_plus: true, an existing one takes the new ads in its ad groups; GMV Max and SPC are not supported; the brand's TikTok accounts; pixels and events; countries). prepare_launch takes the shared answers (campaign_id, structure, existing_adset_ids = ad groups, copy_adset_from / copy_ad_from = an ad group / ad id or "latest", ads, grouping_confirmed, daily_budget, launch_status, schedule) and TikTok's own under tiktok (new_campaign, adgroup_settings, ad_settings with identity = one of the brand's TikTok accounts / show_on_profile (the app's "Also show the video on the TikTok profile", off by default) / website_url / call_to_action). One video per ad (the 9:16 file); images run as carousels (tiktok.carousel_mode single | by_concept, tiktok.ad_settings.music_id from list_tiktok_music, TikTok's pick by default); texts in ads[].copy.primary_texts (5 max, 100 characters, no emoji, one TikTok ad each, 50 TikTok ads per ad group). Spark Ads (existing TikTok posts, Standard campaigns): list_tiktok_posts, then ads[].spark_post instead of files (no texts: the post's caption runs). Custom identities are not available (TikTok refuses them on these ads). Targeting ids: list_targeting (interests, behaviors, languages). Checked like the app, then by TikTok's pre-flight (what it says TikTok may still refuse comes in the recap's warnings: tell the user, it never stops the launch). Drive files: import_link first (TikTok and Snapchat launches only take files in Apogee storage).
SNAPCHAT (platform "snapchat"): the same flow. Snapchat's own under snapchat (new_campaign, adsquad_settings with optimization_goal / pixel_id / countries / ages (18 minimum in Europe), ad_settings with profile_id (a public profile, mandatory) / website_url (https) / call_to_action / brand_name). One vertical video or image per ad; headlines in ads[].copy.headlines (34 characters, one Snap ad each). Targeting ids: list_targeting (interests, countries). Budgets per day: 5 per ad squad, 20 per CBO campaign. Checked like the app, then by Snapchat's pre-flight (the ad squads filled, the pixel's eligibility).
BRIDGE (ads of one platform launched on another, or a Meta → Meta copy across ad accounts): prepare_bridge_transfer(source { platform, ad_account_id, ad_ids | adset_ids | campaign_ids }, destination { platform, ad_account_id, campaign_id, adset_id | new_adset }) transfers nothing and returns the recap (ready:false = what to ask: extra_fields, or mapping for a Meta copy). Show the whole recap, wait for the yes, then bridge_transfer(plan_id, confirm: true) and bridge_transfer_status until finished. list_bridge_transfers shows what was already bridged; get_bridge_stats and get_bridge_daily_stats are the app's Stats and Daily tabs (each platform in its own currency: never add them up).
whoami says which Apogee account and scopes this connection has: tools outside them are not listed.