Skip to main content
Glama
shinypebble

openai-ads-mcp

by shinypebble

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
MCP_HOSTNoBind address for http transport.127.0.0.1
MCP_PORTNoBind port for http transport.8000
READ_ONLYNoWhen true, write tools are not registered and cannot be called.false
MCP_TRANSPORTNostdio or http.stdio
OPENAI_ADS_API_KEYYesAdvertiser API key; identifies the single ad account.
OPENAI_ADS_BASE_URLNoAPI base URL.https://api.ads.openai.com/v1

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
extensions
{
  "io.modelcontextprotocol/ui": {}
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
account_healthA

Validate the API key and report the account's currency, timezone, and write mode.

Call this first. read_only tells you whether write tools are available this session; currency and timezone apply to all spend figures and date windows.

account_overviewA

Compact campaign -> ad group -> ad tree with statuses and roll-up counts.

Use this instead of trying to "list all ads": the API has no global ad list, so this walks the hierarchy for you. Archived objects are never returned by the list endpoints (they're only retrievable by id), so the tree shows active/paused objects only. Each node has a derived serving flag: a child of a paused campaign/ad group stays active but does not serve, with serving_issues naming the paused ancestor.

ad_performanceA

Per-ad performance over an inclusive YYYY-MM-DD window, flagging weak ads.

Returns impressions/clicks/spend with derived CTR/CPC/CPM and joined conversions & cost-per-conversion. Each row's flag is dead (enough impressions, ~no clicks), underperforming (very low CTR), or ok. Rows are sorted worst-first. Same-day data is partial; today is handled but may be incomplete.

copy_auditA

Find near-identical ad copy + length issues, and return all copy in scope.

Near-identical pairs use normalized token overlap (Jaccard 0..1) — a cheap, deterministic screen for mechanical near-duplicates (reworded/reordered text), NOT same-angle paraphrases. For semantic "these say the same thing" dedup, reason over the returned copies list yourself. Scope defaults to the whole account; narrow with campaign_id or ad_group_id.

context_hints_auditC

Flag ad groups whose context_hints are missing or thin (fewer than 3).

get_insightsA

Escape hatch for raw insight rows at a given aggregation level.

aggregation_level is one of ad_account/campaign/ad_group/ad. If fields is omitted, sensible defaults for that level are used (fields must match the level, e.g. campaign.impressions not ad.impressions). The until == today quirk is handled for you. Prefer ad_performance for the common 'find weak ads' task.

get_campaignB

Fetch one campaign by id, with serving_issues normalized to a list.

serving_issues is undocumented and returned by by-id reads only (list endpoints omit it); it is empty when nothing blocks delivery. A campaign has no parent, so there is nothing to derive — its issues are whatever the API reports.

get_ad_groupA

Fetch one ad group by id; backfills its parent campaign_id and serving issues.

The API omits campaign_id and (when the parent is paused) the parent-not-active serving issue on by-id reads, so this walks the campaign→ad-group tree once to fill both.

get_adA

Fetch one ad by id — use to diagnose non-serving ads.

Backfills the parent ad_group_id and the effective serving_issues (the API's own undocumented codes plus parent-not-active derived from the tree), since a paused parent campaign/ad group leaves an ad active but not serving. Both require one walk of the account tree; an archived ad is absent from that walk, so its parents stay blank.

pause_adsA

Pause many ads at once (reversible). Failures are reported per id, not fatal.

archive_adsA

Archive many ads. IRREVERSIBLE and removes them from list views — pass confirm=true.

Prefer pause_ads unless you are certain. Failures are reported per id.

set_statusA

Apply a single lifecycle transition to a campaign, ad group, or ad.

Note: pausing a campaign or ad group does NOT change its children's status (they stay 'active' but stop serving). archive is IRREVERSIBLE and removes the object from all list views — it requires confirm=true (matching archive_ads); prefer action="pause" unless you are certain.

update_ad_copyA

Update an ad's creative copy. Pass only the fields you want to change.

Re-sends the full creative (which the API requires on ad updates) for you. Title must be 3-50 chars, body <= 100. Aim for a headline near 16 chars and body near 32, and make variants take a distinct angle rather than rephrasing.

create_ad_variantA

Create a new ad: upload the creative image, then create the ad in one step.

Provide the image as image_url (preferred) or base64 in image_file_b64. Defaults to paused so you can review before it serves. Use a specific landing page (target_url), not a generic homepage.

create_campaignA

Create a campaign. bidding_type is immutable post-creation (default impressions/CPM).

Set exactly one budget — daily_spend_limit_micros OR lifetime_spend_limit_micros (a campaign carries a single budget mode; one is required). Limits are in micros (1_000_000 = one currency unit). country_codes are ISO codes for location targeting.

create_ad_groupA

Create an ad group under a campaign.

max_bid_micros is 1..100_000_000. Add 3-5 conversational context_hints describing the questions/needs users bring (not just keywords).

update_campaignB

Update a campaign. Budget and targeting are full-object replaces when provided.

update_ad_groupC

Update an ad group — including adding/replacing conversational context_hints.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
openai-ads-optimizer/SKILL.mdUse when optimizing an OpenAI Ads (ChatGPT Ads) account through the `openai-ads` MCP server — auditing campaigns/ad groups/ads, finding dead or underperforming ads, detecting near-identical ad copy, auditing ad-group context hints, and (when writes are enabled) pausing/archiving dead ads, rewriting copy, adjusting context hints, and creating new ad variants. Invoke for any performance-marketing task on an OpenAI Ads account.
openai-ads-optimizer/_manifestFile listing for openai-ads-optimizer

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shinypebble/openai-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server