Skip to main content
Glama
oussch702

safe-meta-ads-mcp

by oussch702

safe-meta-ads-mcp

test Node.js 20 or later Two runtime dependencies MIT license

safe-meta-ads-mcp lets Claude build Meta ad campaigns that stay paused until you type the phrase that allows spend.

An MCP server for Meta ads. It lets Claude, or any other MCP client, read your ad accounts and build campaigns, ad sets, creatives and ads through Meta's official Marketing API, with guards that keep an agent from turning on spend by accident.

Everything it creates starts paused, whatever the agent asks for. Pausing is always allowed. Turning anything on needs the exact phrase ACTIVATE AND ALLOW SPEND, which the agent is told to ask you for, and when your MCP client can show a form, the server also asks you there, with the daily budget at stake, before anything goes live. Set a daily budget ceiling and it refuses anything that would take a campaign above it. The access token stays inside the server: no tool returns it, and it is stripped from every result and every error.

We built it for the launches we run. One build for a real product launch created 21 ad sets, 456 creatives and 455 ads, and every ad set and ad was created paused, waiting for a person to say go. It uploaded 563 images and videos on the way. Two of the videos came back with HTTP 413, too large to send in a single request, so this server uploads video in chunks, the way Meta's own SDK does, and resumes an interrupted upload where it stopped. The write-up, with how the guards work and how to keep the token out of the chat: Meta ads MCP: Claude builds the campaign, and nothing spends until you say go.

See it in under a minute

https://github.com/user-attachments/assets/dc779ea4-b847-49ff-b29d-0416a158fe8c

Related MCP server: meta-ads-mcp

Quick start

You need Node.js 20 or later and a Meta access token with the ads_management permission. The FAQ explains how to get one.

Claude Code. On a Mac, keep the token in the Keychain. The first command asks for it and does not echo it.

security add-generic-password -s safe-meta-ads-mcp -a meta -w
claude mcp add meta-ads -- npx -y github:oussch702/safe-meta-ads-mcp --keychain safe-meta-ads-mcp --max-daily-budget 5000

Elsewhere, pass the token from your shell's environment instead:

claude mcp add meta-ads -e META_ACCESS_TOKEN="$META_ACCESS_TOKEN" -- npx -y github:oussch702/safe-meta-ads-mcp --max-daily-budget 5000

Claude Desktop. Open Settings, then Developer, then Edit Config, and add the server to claude_desktop_config.json:

{
  "mcpServers": {
    "meta-ads": {
      "command": "npx",
      "args": ["-y", "github:oussch702/safe-meta-ads-mcp", "--keychain", "safe-meta-ads-mcp", "--max-daily-budget", "5000"]
    }
  }
}

Without the Keychain, drop the two --keychain arguments and add "env": { "META_ACCESS_TOKEN": "your token" } next to args. Restart Claude Desktop afterwards.

The first start downloads the server and its two dependencies. If your client gives up while that happens, run npx -y github:oussch702/safe-meta-ads-mcp --version once in a terminal, then start it again.

Then ask Claude to run meta_diagnose. It reports what the token can do, the state of your ad account, and the Facebook Pages you can advertise with.

What it does

  • Reads your accounts. Ad accounts, campaigns, ad sets and ads with their status, budget and spend, and insights for any period, split by day, level or breakdowns such as age, gender, country or placement.

  • Builds campaigns, paused. It creates campaigns, ad sets, creatives and ads, and duplicates ads. The create tools have no status input, and the server sets PAUSED on every campaign, ad set, ad and copy it creates, so nothing an agent passes can start delivery.

  • Turns things on only with the phrase. meta_set_status pauses anything at once. Activating needs confirm set to exactly ACTIVATE AND ALLOW SPEND, and when the client supports MCP elicitation, a yes from you in a form that shows the ID and the daily budget at stake, never text the agent wrote. With --max-daily-budget, the server first reads from Meta what the campaign would spend per day once the object is on, and refuses when that is above your ceiling.

  • Uploads media. Images go up in one request. Videos go up in chunks, with the progress saved after each one, so an interrupted upload resumes from the last chunk Meta confirmed, even after a restart. The tool then waits until Meta has processed the video. It only sends files that are images or videos by their content, not just by their name.

  • Respects Meta's rate limits. It reads the usage headers on Meta's answers, slows down as usage climbs, waits out a limit for as long as Meta says it lasts (up to --max-wait), and retries the errors Meta marks as temporary, except when something is being created.

  • Explains errors. Meta's error codes come back as a plain sentence followed by Meta's own message, for example: Meta rejected the access token: it has expired. Create a new token, then restart the server.

Tools

Read tools, always available:

Tool

What it does

meta_list_ad_accounts

The ad accounts the token can use, with status, currency and time zone.

meta_list_campaigns

Campaigns with status, budget, and spend and impressions for a period.

meta_list_ad_sets

Ad sets of an account or a campaign, with budget, optimization goal and spend.

meta_list_ads

Ads of an account, campaign or ad set, with review feedback and delivery issues.

meta_get_insights

Spend, reach, clicks, costs and actions for a date range, by level, by day or by breakdown.

meta_diagnose

What the token can do: permissions, account status, payment method, and the Pages it can advertise with.

Write tools, left out with --read-only:

Tool

What it does

meta_create_campaign

Creates a campaign, paused, with an optional campaign budget.

meta_create_ad_set

Creates an ad set with targeting, budget and optimization goal, paused.

meta_create_creative

Creates a website-link creative from one image or one video, posted as your Facebook Page, with an optional Instagram account.

meta_create_ad

Creates an ad from an ad set and a creative, paused.

meta_upload_image

Uploads an image to the ad account and returns its hash.

meta_upload_video

Uploads a video in chunks, resumes after an interruption, and waits for processing.

meta_duplicate_ad

Copies an ad into the same ad set or another one, paused.

meta_set_status

Pauses anything. Activates only with the phrase and under the budget ceiling, and asks you directly when the client can.

Example session

An example, with made-up names and IDs, on a server started with --max-daily-budget 5000:

You     Set up a traffic campaign for the spring sale: 20 USD a day, people in the
        US aged 25 and over, with hero.jpg from the ads folder.

Claude  meta_create_campaign   "Spring sale", OUTCOME_TRAFFIC, daily_budget 2000
          campaign 2001, PAUSED
        meta_create_ad_set     campaign 2001, "US 25+", LINK_CLICKS, US, age_min 25
          ad set 2002, PAUSED
        meta_upload_image      ads/hero.jpg
          image_hash 6f1c09e2
        meta_create_creative   Page 3001, https://example.com/spring, image 6f1c09e2
          creative 2003
        meta_create_ad         ad set 2002, creative 2003
          ad 2004, PAUSED
        meta_set_status        campaign 2001, ACTIVE
          Not activated. No confirmation phrase was given. Turning this on can spend
          money, so the person has to approve it: ask them to type ACTIVATE AND ALLOW
          SPEND, then call again with confirm set to exactly that. Nothing was changed.

        Everything is built and paused. To start spending 20 USD a day, type
        ACTIVATE AND ALLOW SPEND.

You     ACTIVATE AND ALLOW SPEND

Claude  meta_set_status        campaign 2001, ACTIVE, confirm "ACTIVATE AND ALLOW SPEND"
          ACTIVE, daily budget 2000 checked against the ceiling of 5000
        meta_set_status        ad set 2002, ACTIVE, confirm "ACTIVATE AND ALLOW SPEND"
        meta_set_status        ad 2004, ACTIVE, confirm "ACTIVATE AND ALLOW SPEND"
          The ad goes live once Meta has reviewed it.

Options

The token comes from the META_ACCESS_TOKEN environment variable, unless --keychain names a Keychain item.

Option

What it does

--ad-account <id>

Default ad account, with or without act_. Every tool can still name another one.

--read-only

Registers only the six read tools. Nothing can be created or changed.

--max-daily-budget <n>

Refuses to create anything with a daily budget above n, and to turn on anything that would take a campaign above n a day: its campaign budget, or the total of its active ad sets. It is not a cap on the whole account. Budgets are in the currency's smallest unit, as Meta counts them: 5000 is 50.00 USD, or 5,000 JPY. Lifetime budgets and campaigns with scheduled budget increases are refused while it is set; increases scheduled on a single ad set are not counted. Meta may spend up to 75% over a daily budget on a given day and balances it over the week, so the ceiling limits the budget, not a single day's spend.

--keychain <service>

Reads the token from this macOS Keychain item.

--graph-version <v>

Graph API version. Default v26.0, the current one.

--max-wait <seconds>

How long one call may wait out a rate limit or video processing before it returns. Default 120.

--state-dir <dir>

Where interrupted video uploads keep their progress. Default ~/.safe-meta-ads-mcp.

What it cannot do

  • Delete anything. No tool deletes or archives a campaign, ad set, ad or file.

  • Edit what already exists, apart from pausing and activating. Budgets, targeting and creatives of existing objects are changed in Ads Manager.

  • Build every ad format. Creatives are website-link ads with one image or one video. Carousels, collections, catalog ads, lead forms and dynamic creative are not covered.

  • Stop an agent that ignores its instructions, on every client. The phrase is a deliberate step, not a password. When your client supports MCP elicitation, the server asks you directly and the agent cannot answer for you. Otherwise, Claude Desktop and Claude Code still ask you before each tool call unless you have allowed that tool permanently, so keep meta_set_status on ask, and use --read-only when you only need reports.

  • Run very large reports. Insights use Meta's synchronous endpoint. Meta's asynchronous report jobs are not supported.

  • Retry a create after a lost connection or a temporary error. Either way the object may exist or not. The server says so instead of retrying, and the agent should list before trying again. Rate limits are the exception: Meta refuses those calls outright, so they are retried.

  • Touch billing or business settings. Payment methods, spending limits and Business Manager permissions stay in Meta's own tools.

FAQ

Can an AI agent spend my ad budget? Not by accident. Everything an agent creates here starts paused, and the create tools have no way to ask for anything else. The one tool that turns ads on refuses unless it receives the exact phrase ACTIVATE AND ALLOW SPEND, which the agent is instructed to ask you for, and clients that support MCP elicitation also show you a yes or no before anything goes live. With --max-daily-budget, activation is refused whenever it would take a campaign above your ceiling, phrase or not. If you only want reports, --read-only removes every write tool.

Does it work with Instagram ads? Yes. Instagram ads use the same campaigns, ad sets and ads. Leave publisher_platforms out of the ad set's targeting and Meta uses all its default platforms, Instagram included, or set it to ["instagram"] to run on Instagram only. Pass instagram_user_id when you create the creative to show your Instagram account on those placements.

How do I get a Meta access token? Use a system user, the kind of account Meta provides for software that calls its API.

  1. In Meta for Developers, create an app and connect it to your business portfolio.

  2. In Meta Business Suite, open Business settings, then Users, then System users. Add a system user and assign it your ad account and the Facebook Page your ads run as, with permission to advertise.

  3. Generate a token for the system user and your app, with the ads_management, ads_read and pages_read_engagement permissions.

  4. Store it in the macOS Keychain or in META_ACCESS_TOKEN, then run meta_diagnose to see what it can do.

If Meta answers that your app is still in Development mode, switch it to Live in Meta for Developers before you create creatives.

Is this official? No. It is an independent open-source project by AI Strike Force, not made or endorsed by Meta or Anthropic. It calls Meta's official Marketing API with your own token, so Meta's terms and limits apply as they would to any app you build.

Contributing

Issues and pull requests are welcome. Run npm test before sending a change. The tests run against a fake Graph API and never call Meta.

License

MIT


Built by AI Strike Force, an AI automation agency. We publish the tools and findings that come out of the systems we run.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides read-only access to Meta Ads data and optionally creates paused ads, with safety features like OAuth and validation.
    1,161 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server for the Meta Marketing API enabling ad performance reports and operational adjustments like pause/resume and budget changes on client ad accounts, with strict allowlist and read-only safeguards.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables running marketing platforms like Google Ads, Meta Ads, GA4, Search Console, Tag Manager, and WordPress from any MCP client to read performance, audit wasted spend, build reports, and launch campaigns (created paused until you say otherwise).
    1
    MIT