# Meta Ads Mcp

> MCP server for Meta Ads (Facebook/Instagram) - agency multi-account, cloud-ready

- **Type:** MCP server
- **Install:** `agentstack add mcp-byadsco-meta-ads-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [byadsco](https://agentstack.voostack.com/s/byadsco)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [byadsco](https://github.com/byadsco)
- **Source:** https://github.com/byadsco/meta-ads-mcp

## Install

```sh
agentstack add mcp-byadsco-meta-ads-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Meta Ads MCP Server

> **Self-hosted Model Context Protocol (MCP) server that gives Claude, ChatGPT and other AI agents secure, multi-tenant access to the Meta Marketing API for Facebook Ads and Instagram Ads.** Built for advertising agencies managing many client ad accounts from a single AI assistant — with OAuth login, encrypted-at-rest tokens, rate-limit compliance and circuit breakers baked in.
>
> **v3.0.0 (2026-05-06)** — vocabulary aligned with Meta's official MCP server (`mcp.facebook.com/ads`). Tool names switched from `meta_ads_*` to `ads_*`, added 14 new tools (insights views, diagnostics, help search, agency macros). Breaking change — see [CHANGELOG](CHANGELOG.md) and [docs/migration-v3.md](docs/migration-v3.md).

[](LICENSE)
[](https://github.com/byadsco/meta-ads-mcp/actions/workflows/ci.yml)
[](https://nodejs.org)
[](https://www.typescriptlang.org/)
[](https://modelcontextprotocol.io)
[](https://cloud.google.com/run)

## Table of contents

- [What is Meta Ads MCP?](#what-is-meta-ads-mcp)
- [Who is this for?](#who-is-this-for)
- [Aligned with Meta's official MCP](#aligned-with-metas-official-mcp)
- [Features](#features)
- [Tools (135 total)](#tools-135-total)
- [Quick start](#quick-start)
- [Authentication — three modes](#authentication--three-modes)
- [Setting up Sign in with Meta](#setting-up-sign-in-with-meta)
- [Registering System User tokens (no expiry)](#registering-system-user-tokens-no-expiry)
- [Connecting AI clients](#connecting-ai-clients)
- [Common workflows](#common-workflows)
- [Architecture overview](#architecture-overview)
- [Meta API compliance](#meta-api-compliance)
- [Deployment](#deployment)
- [Local development](#local-development)
- [Security](#security)
- [FAQ / troubleshooting](#faq--troubleshooting)
- [Contributing](#contributing)
- [Resources](#resources)
- [License](#license)

## What is Meta Ads MCP?

**Meta Ads MCP Server** is an open-source [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the [Meta Marketing API](https://developers.facebook.com/docs/marketing-apis) — the API behind Facebook Ads and Instagram Ads — as a set of well-typed tools that any MCP-compatible AI agent can call. Drop it in front of Claude, ChatGPT, Cline, Continue or any other MCP client and your assistant can manage campaigns, ad sets, creatives, audiences, insights, leads, comments and pixels across an unlimited number of ad accounts.

It is **multi-tenant by design**. Each user signs in with **Facebook Login** on a consent page, their long-lived (60-day) Meta token is encrypted with AES-256-GCM and stored in Firestore, and every MCP request automatically picks up the right token. There is no shared PIN, no token pasting, no plaintext at rest.

It is **compliance-first**. Every Meta throttling header (`X-App-Usage`, `X-Business-Use-Case-Usage`, `x-fb-ads-insights-throttle`, `x-ad-account-usage`, reach throttle) is parsed and respected per `(token, account, use-case)` bucket. A circuit breaker stops all calls for an account on abuse signal `1996` or repeated throttles. Insights guardrails reject dangerous parameter combinations *before* they hit Graph API.

It is **deploy-ready**. Stateless Streamable HTTP transport, Docker image, GitHub Actions workflow that ships to Google Cloud Run with Workload Identity Federation, gitleaks-scanned on every push, masked health checks. Or run it via `stdio` for single-tenant local use with Claude Desktop.

## Who is this for?

- **Marketing agencies** that manage many client ad accounts and want one AI assistant that can act across all of them.
- **In-house marketing teams** with multiple users who need their own Meta token but a shared MCP endpoint.
- **Developers** building AI-powered tools, copilots or autonomous agents on top of Meta Ads.
- **Solo operators** who want to drive their own Meta account from Claude Desktop with zero infrastructure (`stdio` mode).

## Aligned with Meta's official MCP

On 2026-04-29 Meta launched a first-party remote MCP server at
`mcp.facebook.com/ads` (the "Ads AI Connectors" umbrella) with native support
for ChatGPT, Claude, and Perplexity. v3.0.0 of this project aligns its
vocabulary so the same prompts and agent patterns transfer cleanly between
both servers.

| | Meta's official MCP (`mcp.facebook.com/ads`) | This project |
|---|---|---|
| Auth model | Per-user OAuth in your AI client | **Multi-tenant**: agency operator handles N client accounts from one server |
| Tool surface | 29 tools (campaigns, ads, catalogs, 5 insight views, opportunity_score, dataset, errors, help) | **126 tools** including the official 29-equivalent + audiences, lookalikes, lead forms, automated rules, A/B studies, async reports, billing invoices, custom conversions, asset uploads, comment moderation, cross-account macros, and full WhatsApp Business management (templates, phone numbers, flows, QR codes) |
| Hosting | Hosted by Meta | Self-hosted on Cloud Run / your infra; tokens encrypted at rest in Firestore |
| Cross-account | Per-user, single Meta login | Yes — `ads_portfolio_summary` aggregates across N accounts |
| Token control | Lives in your AI client | Server-side System User token registry per agency operator |
| Naming | `ads_create_campaign`, `ads_update_entity`, `ads_insights_*` | **Same naming**, plus all the tools the official MCP doesn't ship |

When to use which:

- **Single advertiser running their own ads from Claude/ChatGPT** → Meta's
  official MCP. Zero setup, first-party.
- **Agency operating across many client accounts**, internal staff that should
  not have direct Facebook login to every client, custom workflow / governance
  needs, integration with internal stack → this project.

## Features

- **135 tools** covering campaign management, creatives, targeting, audiences, reporting, comments, billing, invoices, tokens, Instagram workflows, WhatsApp Business management, rate-limit observability, semantic insight views, diagnostics, help-center search, competitor research via the public Meta Ad Library, and agency-tier cross-account macros.
- **Aligned vocabulary** with Meta's official MCP server so agents transfer cleanly between both.
- **Sign in with Meta (Facebook Login)** — replaces shared PINs. Each user lands their own long-lived (60-day) Meta token.
- **System User token registry** — for tokens that don't expire, register them per user from the consent UI.
- **Encrypted persistence** — Meta tokens stored AES-256-GCM in Firestore; survive restarts so connections never drop.
- **Email / domain / FB-id allowlist** — public repo, private deployment: only listed identities can sign in.
- **Multi-account support** — each request carries its own Meta access token via `AsyncLocalStorage` request context.
- **Cloud-ready** — Streamable HTTP transport, stateless, Docker-ready, Google Cloud Run reference deploy.
- **Stdio support** — for local development with MCP clients like Claude Desktop.
- **Compliance-first rate limiting** — per-`(token, ad-account, use-case)` bucketing of every throttle signal Meta publishes; reacts to `estimated_time_to_regain_access` instead of blind backoff.
- **Circuit breaker** — abuse-signal (subcode 1996), temporary-block and repeated-throttle events stop all calls for the affected account, following Meta's explicit *"stop making API calls"* rule.
- **Preventive write pacing** — Ads Management `POST`/`DELETE` are paced against the hourly BUC quota so bursts from agents never blow the limit.
- **Insights guardrails** — dangerous parameter combinations (account-level + high-cardinality breakdowns, lifetime + breakdowns in sync, `time_range` > 37 months) are rejected *before* hitting Meta.
- **Async reports with safe polling** — `ads_run_report_and_wait` one-shot with 5 s-min / 60 s-max backoff, proper `Job Failed` / `Job Skipped` handling.
- **Retry logic** — exponential backoff on truly transient errors only (never on throttled requests).

## Tools (135 total)

Ads tools use the `ads_*` naming convention, aligned with Meta's official MCP server; WhatsApp Business tools use `whatsapp_*`. Read tools declare `readOnlyHint: true`; mutating tools declare `destructiveHint` / `idempotentHint` and prefix descriptions with a `⚠️` warning.

| Category | Tools | Description |
|---|---|---|
| Accounts | 3 | `ads_get_ad_accounts`, `ads_get_account_info`, `ads_get_pages_for_business` |
| Campaigns | 5 | CRUD + status management |
| Ad Sets | 6 | CRUD + clone bundle (native ad-copy, 100% creative-type coverage incl. dynamic/Advantage+) |
| Ads | 6 | CRUD with creative assignment, UTM (`url_tags`) editing |
| Creatives | 9 | List, details, create/update, image/video library and uploads |
| Creative media | 1 | `ads_get_creative_media` — downloads an ad's images (incl. carousel cards and video thumbnails) and returns them as inline MCP image blocks for visual analysis; videos come with a signed source URL for external download |
| Generic entity helpers | 3 | `ads_get_ad_entities`, `ads_update_entity`, `ads_activate_entity` (mirror official MCP) |
| Insights — power tool | 1 | `ads_get_insights` — full control over breakdowns, attribution, time series |
| Insights views | 5 | `performance_trend`, `anomaly_signal`, `auction_ranking_benchmarks`, `industry_benchmark`, `advertiser_context` |
| Targeting | 7 | Interest / behavior / demographic / geo search, audience estimation, targeting description |
| Budget | 1 | Budget schedule management |
| Leads | 4 | Lead forms and lead retrieval |
| Audiences | 8 | Custom audiences, lookalikes, and cross-account sharing |
| Previews | 2 | Ad previews before launch |
| Pixels | 5 | Pixel details, events, custom conversions |
| Comments | 4 | Ad comment moderation |
| Rules | 5 | Automated rules and rule details |
| A/B Testing | 3 | Ad study creation and inspection |
| Reports | 4 | Async report creation, status, retrieval, and one-shot run+wait |
| Billing | 4 | Billing info, spend limits, and invoices (`ads_get_invoices`) |
| Diagnostics | 3 | `ads_get_opportunity_score`, `ads_get_dataset_quality`, `ads_get_errors` |
| Help search | 1 | `ads_get_help_article` — curated Meta Business Help Center search |
| Agency macros | 2 | `ads_diagnose_underperformance`, `ads_portfolio_summary` (cross-account) |
| Bulk ad creation | 1 | `ads_bulk_create_video_ads` — video URLs → upload, processing wait, auto-thumbnail, creative and ad in one call |
| Instagram | 2 | IG account and media lookup |
| Ad Library (Apify) | 8 | Competitor ad research: `ads_library_scrape` the public Meta Ad Library by keyword or Facebook page, poll run status, page through results, abort runs, plus per-user Apify token register/status/delete |
| Tokens | 4 | List / set-active / register / delete |
| Rate Status | 1 | Live view of quota usage, open circuits and write-pacer state |
| WhatsApp — WABAs & phones | 8 | `whatsapp_get_business_accounts`, phone number list/register/deregister/verify, business profile get/update |
| WhatsApp — Templates & analytics | 6 | Message template CRUD (`whatsapp_create_template`, edit, delete), WABA analytics (messaging/conversation/pricing), per-template analytics |
| WhatsApp — Flows | 6 | Flow list/create/update (incl. Flow JSON upload), publish, deprecate, delete |
| WhatsApp — QR & webhooks | 7 | QR deep-link CRUD (`message_qrdls`), webhook subscription get/subscribe/unsubscribe |

The `ads_library_*` tools read the **public** Meta Ad Library through the
[curious_coder/facebook-ads-library-scraper](https://apify.com/curious_coder/facebook-ads-library-scraper)
Apify actor, so they need no Meta permissions — but they do need an Apify token
and they cost money (about **$0.75 per 1,000 ads**). Each user registers their
own token with `ads_library_register_apify_token`; it is validated against the
Apify API and then stored encrypted with AES-256-GCM in Firestore, scoped to
that user, exactly like Meta tokens. Every scrape sends Apify a hard
`maxTotalChargeUsd` cap derived from the requested `count`, so a single run
cannot bill past it (the cap is per run, not a per-tenant budget).

Registering the token does **not** require going through an assistant: the
server serves an authenticated **`/auth/connections`** page that lists your
stored Meta tokens and your Apify connection, and lets you register, replace or
disconnect the Apify token at any time. The consent screen shown during OAuth
approval carries the same Apify section for first-time setup, plus a link to
that page. The `ads_library_register_apify_token` tool still works for agents
and headless setups.

Credential resolution **fails closed**: in multi-tenant mode a caller with no
OAuth identity is refused rather than falling back to a shared credential. The
`APIFY_TOKEN` environment variable is honoured only in single-tenant mode
(stdio transport, or no Meta OAuth app configured), so one advertiser's scrapes
can never be billed to the operator's Apify account.

Two operational caveats worth knowing: runs execute against the actor's
`latest` build, so an upstream change to its input schema or pricing can alter
behaviour without a change in this repo; and a scrape start that times out is
*indeterminate* rather than failed — Apify may have accepted it — so check
`ads_library_list_runs` before starting another.

WhatsApp tools require the `whatsapp_business_management` permission. Tokens issued before this scope was added must be re-authorized (sign in again through the OAuth flow) before the `whatsapp_*` tools will work, and the Meta App must have the **WhatsApp product** added in the developer dashboard.

Tool definitions live under [src/tools/](src/tools/), wired together in [src/tools/index.ts](src/tools/index.ts).

## Quick start

### Prerequisites

- **Node.js 20.10+** (the project uses Import Attributes for JSON imports). Node 22 is used in the Docker image.
- A **Meta access token** with `ads_management` and `ads_read` permissions, *or* a Meta App configured for Facebook Login (see below).

### Install & run

**Option A — from source (contributors, self-hosters):**

```bash
git clone https://github.com/byadsco/meta-ads-mcp.git
cd meta-ads-mcp
npm install
npm run build
npm start
```

**Option B — from GitHub Packages (npm):** scoped to `@byadsco`, hosted on `npm.pkg.github.com`. Requires a GitHub Personal Access Token with `read:packages` scope.

```bash
# tell npm where the @byadsco scope lives
echo "@byadsco:registry=https://npm.pkg.github.com" >> .npmrc
echo "//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}" >> .npmrc

npm install @byadsco/meta-ads-mcp
npx meta-ads-mcp                 # HTTP transport, port 3000
npx meta-ads-mcp --transport stdio
```

**Option C — from GitHub Container Registry (Docker):**

```bash
docker pull ghcr.io/byadsco/meta-ads-mcp:latest
docker run --rm -p 3000:3000 --env-file .env ghcr.io/byadsco/meta-ads-mcp:latest
```

The server starts on `http://localhost:3000` with the `/mcp` endpoint and a health check at `/health`. New versions are published on every GitHub Release ([releases](https://github.com/byadsco/meta-ads-mcp/releases)).

### Environment variables

See [.env.example](.env.example) for the full list. The minimum to run an HTTP deployment with Meta OAuth login:

```bash
SERVER_URL=https://your-host.com   # required for OAuth redirect URIs
META_APP_ID=...                    # your Meta app
META_APP_SECRET=...
AUTH_ALLOWED_EMAILS=you@x.com      # at least one allowlist source required
TOKEN_ENCRYPTION_KEY=$(openssl rand -hex 32)
SESSION_COOKIE_SECRET=$(openssl rand -base64 32)
OAUTH_SECRET=$(openssl rand -hex 32)
FIRESTORE_PROJECT_ID=my-gcp-project
```

For local development with `stdio` (no OAuth, no Firestore needed):

```bash
META_ACCESS_TOKEN=EAA...           # the only required value in stdio mode
```

## Authentication — three modes

| Mode | Activated by | Used for |
|---|---|---|
| **Sign in with Meta** (recommended) | `META_APP_ID` + `META_APP_SECRET` + `TOKEN_ENCRYPTION_KEY` + allowlist | Each user signs in with Facebook Log

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [byadsco](https://github.com/byadsco)
- **Source:** [byadsco/meta-ads-mcp](https://github.com/byadsco/meta-ads-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-byadsco-meta-ads-mcp
- Seller: https://agentstack.voostack.com/s/byadsco
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
