# scaleforge-mcp-meta-ads

**Category:** 🌐 Social Media  
**Repository:** https://github.com/Mike25app/scaleforge-mcp-meta-ads  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/scaleforge-mcp-meta-ads

## Description
Control Facebook & Instagram Ads via Meta Graph API v24.0. 32 tools, no backend required.

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "scaleforge-mcp-meta-ads": {
    "command": "npx",
    "args": ["-y","scaleforge-mcp-meta-ads"]
  }
}
```

## Documentation & README

# Meta Ads MCP by ScaleForge

> **Control Facebook & Instagram Ads from Claude, ChatGPT, Cursor, or any MCP-compatible agent.**
>
> Direct Meta Graph API v24.0 wrapper. 32 tools. No backend required — just bring your own Meta access token.

[![npm](https://img.shields.io/npm/v/@getscaleforge/mcp-meta-ads.svg)](https://www.npmjs.com/package/@getscaleforge/mcp-meta-ads)
[![license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Node](https://img.shields.io/badge/node-%E2%89%A520-blue.svg)](#prerequisites)

---

## The problem

Meta's Marketing API is powerful but punishing. Anyone who's tried to automate Meta Ads has run into these five walls:

1. **Rate-limit whack-a-mole (error code #17).** Your script hits `User request limit reached` halfway through a launch and leaves campaigns in a half-configured state. Meta's per-account budget of calls resets over 5 minutes, but nothing in the API tells you that without context.
2. **Token expiry chaos.** User access tokens from the Graph API Explorer die every ~2 hours. You fix a bug, come back from lunch, and every request is suddenly `(#190) Error validating access token`.
3. **v22 → v24 deprecations (Sept 2025).** `instagram_actor_id` → `instagram_user_id`, `degrees_of_freedom_spec` is gone entirely, `asset_feed_id` has been deprecated since v3.1. Copy-pasted sample code from Stack Overflow breaks silently.
4. **Image hashes are per-ad-account.** An image uploaded on Account A cannot be used on Account B — you get `Image Not Found` on the second account. Video IDs are global, but image hashes are not. This trips up 100% of first-time multi-account automations.
5. **The 250-ads-per-Page cap.** Meta limits ads-running-or-in-review per Page (not per account) — and this limit is shared across every account using that Page. Overshoot and the 251st ad silently fails review.

## The solution

This MCP is a thin, typed wrapper over Meta's Graph API with those five pains baked out:

- **Auto-batch for bulk ops** (`pause_campaigns_batch`, `activate_campaigns_batch`, `update_bids_batch`) — up to 50 ops per HTTP request, chunked automatically. Sidesteps rate-limit code #17 for bulk work.
- **Pre-flight ads_volume check** before every bulk activation — warns you when a Page is near the 250-ad cap, per ad account, before Meta silently fails the reviews.
- **Enhanced error messages** with actionable links — when your token expires or a rate limit fires, the MCP tells your agent exactly what to do (create a System User token, wait 5 min, etc.).
- **v24.0 everywhere** — current field names, no deprecated spec shapes.
- **PBIA auto-provisioning** (`get_pbia`) — when a Page has no linked Instagram account, the MCP creates a Page-Backed Instagram Account on demand so IG placements work.

No ScaleForge backend is in the chain. Your agent → this MCP → `https://graph.facebook.com/v24.0/*`. That's it.

---

## Hosted endpoint (no install)

Use the ScaleForge-hosted Streamable HTTP endpoint — zero install, nothing to run locally:

- **Smithery listing:** `https://smithery.ai/server/kirichyk-misha/meta-ads` (one-click install for Claude Desktop, Cursor, Windsurf, Continue, ChatGPT Desktop — Smithery prompts for your Meta token, writes the config).
- **Direct URL** for custom clients: `https://getscaleforge.com/mcp` (MCP Streamable HTTP). Supply your token via Smithery session config or `Authorization: Bearer <token>` header.

Prefer a local npm install? Use the stdio package below.

---

## Quick start — pick one

### Smithery (easiest, auto-configures the client)

```bash
npx -y @smithery/cli install @getscaleforge/mcp-meta-ads --client claude
# also: --client cursor | --client windsurf | --client continue
```

Smithery will prompt you for the Meta access token and write the config file.

### Claude Code CLI

```bash
claude mcp add scaleforge \
  --env META_ACCESS_TOKEN=YOUR_TOKEN \
  -- npx -y @getscaleforge/mcp-meta-ads
```

Verify with `claude mcp list`.

### Claude Desktop (manual JSON config)

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS (or the Windows / Linux equivalent — Claude Desktop creates it if missing):

```json
{
  "mcpServers": {
    "meta-ads": {
      "command": "npx",
      "args": ["-y", "@getscaleforge/mcp-meta-ads"],
      "env": {
        "META_ACCESS_TOKEN": "YOUR_TOKEN_HERE"
      }
    }
  }
}
```

Restart Claude Desktop. The 32 tools appear under the hammer icon.

### Cursor

Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):

```json
{
  "mcpServers": {
    "meta-ads": {
      "command": "npx",
      "args": ["-y", "@getscaleforge/mcp-meta-ads"],
      "env": { "META_ACCESS_TOKEN": "YOUR_TOKEN_HERE" }
    }
  }
}
```

### Local test (no client setup)

```bash
META_ACCESS_TOKEN=YOUR_TOKEN npx -y @getscaleforge/mcp-meta-ads
```

The server starts on stdio. Poke it interactively with `@modelcontextprotocol/inspector`:

```bash
npx -y @modelcontextprotocol/inspector \
  env META_ACCESS_TOKEN=YOUR_TOKEN npx -y @getscaleforge/mcp-meta-ads
```

---

## Architecture

```
┌──────────────┐       MCP stdio        ┌───────────────────┐    HTTPS + OAuth token    ┌──────────────────────┐
│ Claude / GPT │ ◄────────────────────► │  mcp-meta-ads     │ ◄───────────────────────► │  Meta Graph API v24  │
│   Cursor     │   JSON-RPC over stdio  │  (this package)   │   graph.facebook.com      │  Marketing API       │
│ ChatGPT Desk │                        │                   │                           │                      │
└──────────────┘                        └───────────────────┘                           └──────────────────────┘
```

The MCP is a thin, typed translation layer. It does not cache, does not proxy, does not phone home. Every call goes from your machine straight to Meta's servers with your token.

---

## Get a Meta Access Token

You need an access token with `ads_management`, `ads_read`, `business_management`, and (for Page-scoped work like PBIA provisioning) `pages_read_engagement` + `pages_manage_ads`.

There are two kinds of tokens. Pick based on your use case.

### Option 1 — Quick token (2 minutes, expires in ~2 hours)

Good for: trying the MCP, quick experiments, one-off scripts.

1. Open the [Graph API Explorer](https://developers.facebook.com/tools/explorer/).
2. In the **User or Page** dropdown, select **User Token**.
3. Click **Add a Permission** and select: `ads_management`, `ads_read`, `business_management`, `pages_read_engagement`, `pages_manage_ads`.
4. Click **Generate Access Token** and approve the dialog.
5. Copy the token at the top. That's your `META_ACCESS_TOKEN`.

The token expires in ~2 hours. When it dies, the MCP will return an enhanced error pointing you here.

### Option 2 — Stable token (never expires) <a id="stable-tokens"></a>

Good for: production, scheduled jobs, anything you don't want to re-auth every 2 hours.

You generate a **System User** token inside **Meta Business Manager**. System User tokens have no expiry and can be scoped to specific assets (ad accounts + Pages). This is the same token type ScaleForge and every production Meta integration uses.

1. **Create a Facebook App** (if you don't have one) at [developers.facebook.com/apps](https://developers.facebook.com/apps/). Any app works — Business type is fine.
2. **Create a Business Manager** at [business.facebook.com](https://business.facebook.com/). You need this as the container for your System User.
3. **Add your ad accounts and Pages to the Business** under Business Settings → Accounts → Ad Accounts / Pages. (If they're owned by another Business, request access.)
4. **Create a System User:** Business Settings → Users → **System Users** → **Add** → name it (e.g. `mcp-meta-ads`) → role **Admin**.
    *[screenshot: Business Settings → Users → System Users tab with "Add" button]*
5. **Assign ad accounts to the System User:** click the System User → **Add Assets** → pick Ad Accounts → select yours → turn on **Manage** permission. Repeat for Pages.
    *[screenshot: Add Assets dialog with "Manage" toggle highlighted]*
6. **Generate the token:** click **Generate New Token** → select your Facebook App → pick scopes:
   - `ads_management`
   - `ads_read`
   - `business_management`
   - `pages_read_engagement`
   - `pages_manage_ads`
   - `read_insights` (optional — needed for some insight breakdowns)
   *[screenshot: Generate Token dialog with scopes checklist]*
7. **Click Generate** and copy the token. It never expires. Store it in a secret manager / env var / password manager.

Now use it:

```bash
META_ACCESS_TOKEN=EAAB...your-token... npx -y @getscaleforge/mcp-meta-ads
```

If you revoke or regenerate later, the old token stops working immediately.

---

## Baked-in pain point fixes

| Meta pain point | How this MCP handles it |
| --- | --- |
| Rate limit code #17 in bulk ops | `pause_campaigns_batch`, `activate_campaigns_batch`, `update_bids_batch` use Meta Batch API (up to 50 ops/request) with auto-chunking and a 2s gap between chunks. |
| 250-ads-per-Page silent cap | `get_ads_volume` + automatic pre-flight check inside `activate_campaigns_batch` — warnings come back in the response before Meta starts any review. |
| Token-expired errors | `enhanceMetaError` detects codes 190 / 102 / 104 / 463 / 467 and returns a message pointing to the [stable-token setup](#stable-tokens). |
| Instagram placements without IG login | `get_pbia` auto-creates a Page-Backed Instagram Account and returns the `instagram_user_id` for your `object_story_spec`. |
| v22 deprecations | Uses `instagram_user_id`, no `degrees_of_freedom_spec`, no `asset_feed_id`. |
| Image hash scoping | Documented on `upload_image` + `create_ad_creative` — hashes are per-account, you must re-upload to each target account. (Cached per-account caching logic lives in ScaleForge's backend and will be added here in a later release.) |

---

## Tools reference

**32 tools** across 10 categories.

### Accounts (3)
| Name | Purpose |
| --- | --- |
| `list_ad_accounts` | List Ad Accounts accessible to the token |
| `get_ad_account` | Detailed info for one account (status, spend cap, balance) |
| `get_ads_volume` | Per-Page running-ads count + limit + remaining slots (pre-flight check) |

### Campaigns (5)
| Name | Purpose |
| --- | --- |
| `list_campaigns` | Paginated campaign list |
| `get_campaign` | Single campaign by ID |
| `create_campaign` | **WRITE** — create new campaign (defaults to PAUSED) |
| `update_campaign` | **WRITE** — update any mutable field |
| `delete_campaign` | **WRITE** — hard delete |

### Ad Sets (5)
| Name | Purpose |
| --- | --- |
| `list_adsets` | List by ad_account_id OR campaign_id |
| `get_adset` | Single ad set by ID |
| `create_adset` | **WRITE** — create ad set under a campaign |
| `update_adset` | **WRITE** — update targeting, bid, budget, status |
| `delete_adset` | **WRITE** — hard delete |

### Ads (4)
| Name | Purpose |
| --- | --- |
| `list_ads` | List by ad_account_id, adset_id, or campaign_id |
| `get_ad` | Single ad by ID (incl. creative + issues + preview link) |
| `update_ad` | **WRITE** — update name, status, swap creative |
| `delete_ad` | **WRITE** — hard delete |

### Creatives (4)
| Name | Purpose |
| --- | --- |
| `list_creatives` | List all creatives in an ad account |
| `get_creative` | Single creative by ID |
| `create_ad_creative` | **WRITE** — single-text creative via `object_story_spec` |
| `create_ad_creative_with_asset_feed` | **WRITE** — dynamic/multi-text creative via `asset_feed_spec` |

### Media (2)
| Name | Purpose |
| --- | --- |
| `upload_video` | **WRITE** — upload video via remote URL (returns video_id) |
| `upload_image` | **WRITE** — upload image via remote URL (returns image_hash, scoped to account) |

### Insights (3)
| Name | Purpose |
| --- | --- |
| `get_campaign_insights` | Metrics at campaign level with breakdowns |
| `get_adset_insights` | Metrics at ad set level |
| `get_ad_insights` | Metrics at ad level (compare creatives) |

### Bulk (3)
| Name | Purpose |
| --- | --- |
| `pause_campaigns_batch` | **WRITE (BULK)** — pause many campaigns via Batch API |
| `activate_campaigns_batch` | **WRITE (BULK)** — activate many + pre-flight ads_volume check |
| `update_bids_batch` | **WRITE (BULK)** — update `bid_amount` on many ad sets |

### Pages (2)
| Name | Purpose |
| --- | --- |
| `list_pages` | Facebook Pages the token can manage |
| `get_pbia` | Get or auto-create a Page-Backed Instagram Account |

### Ads Library (1)
| Name | Purpose |
| --- | --- |
| `search_ads_library` | Public Meta Ad Library search for competitive research |

---

## Example prompts

Once the server is connected, try these in your agent.

### Read-only

- *"List my Meta ad accounts and show me which ones are active, currency, and spend cap."*
- *"For campaign `1234567890`, pull last_14d insights with breakdown by placement — which placement has the lowest CPL?"*
- *"Show me the ads_volume for account `act_555` — any Page over 85% of its limit?"*
- *"Search the Meta Ad Library for ads from Competitor X running in the US in the last month."*
- *"List all ad sets in campaign `ABCD` and show which ones have is_dynamic_creative=true."*

### Write (confirm first)

> Write operations change live Meta Ads state — spend starts or stops immediately. A well-behaved agent (Claude, GPT-4) will show you the target list and ask "proceed?" before calling these.

- *"Pause campaigns `111`, `222`, `333` — show me their names and current spend first, then pause."*
- *"Activate campaigns `444` and `555`. Run the ads_volume pre-flight first; if any Page is over 85%, abort and tell me which."*
- *"Bump the bid on ad sets `6001` and `6002` to $4.50. Convert to cents for me."*
- *"Create a new campaign in `act_777` called 'Spring Promo Test', OUTCOME_LEADS objective, daily_budget 5000 cents, PAUSED."*

---

## FAQ

### How do I get a Meta access token?

See [Get a Meta Access Token](#get-a-meta-access-token) above. Two options: quick 2-hour token (Graph API Explorer) or stable System User token (Business Manager, never expires).

### Why does my token keep expiring?

You're using a **User access token** from the Graph API Explorer. Those expire in ~2 hours by design. For anything beyond experimentation, generate a **System User token** via Business Manager — those never expire. [Full steps here.](#stable-tokens)

### What's ads_volume?

Meta limits how many ads can be "running or in review" per Facebook Page — default 250 — and this limit is shared across every ad account using that Page. The `get_ads_volume` tool shows you how much headroom each Page has. `activate_campaigns_batch` calls it automatically as a pre-flight check.

### Is this free?

Yes. MIT license, npm package is free. You pay Meta for ads as usual. There is no ScaleForge account or subscription needed to use this MCP.

### How does this compare to Pipeboard / other MCPs?

- **Pipeboard / hosted MCPs** — run on their server, you send your token to them, they rate-limit you. Fine for very light usage, but the token lives on someone else's machine.
- **This MCP** — runs locally, your token never leaves your box, direct path to Meta. 32 tools (more coverage than any other Meta MCP we've seen).
- **ScaleForge managed platform** (see below) — a separate product for teams that want managed Meta access, RedTrack integration, scheduled auto-rules, UI dashboards. This MCP is a standalone tool that does not depend on it.

### Can I use this without ScaleForge?

Yes. This MCP is a standalone npm package — it talks straight to `graph.facebook.com`. No account anywhere.

### Can I contribute more tools?

Please do. PRs welcome at [github.com/Mike25app/scaleforge-mcp-meta-ads](https://github.com/Mike25app/scaleforge-mcp-meta-ads). Each tool is a small file in `src/tools/` — copy one of the existing files as a template.

---

## Powered by ScaleForge

Built and maintained by the [ScaleForge](https://getscaleforge.com) team. If you need managed Meta access (System User provisioning, RedTrack integration, scheduled auto-rules, dashboards), check out the full platform — this MCP stays free and standalone regardless.

---

## Security

- **Generate least-privilege tokens.** Scope your System User to only the ad accounts + Pages it needs. Revoking a token takes effect immediately.
- **Never commit tokens** to source control. The MCP reads from `META_ACCESS_TOKEN` env var — keep it in your agent host's secret store (Claude Desktop's env block, shell profile with 600 perms, 1Password, etc.).
- **Rotate periodically.** Even non-expiring System User tokens should be rotated on a team policy. Regenerating in Business Manager invalidates the old one.
- **No telemetry.** This MCP does not phone home. The only outbound requests it makes are to `https://graph.facebook.com/v24.0/*`.
- **Rate limits apply per token / per ad account** (Meta-side). Bulk tools automatically use Meta Batch API to stay under.

---

## Links

- **npm:** [@getscaleforge/mcp-meta-ads](https://www.npmjs.com/package/@getscaleforge/mcp-meta-ads)
- **GitHub:** [Mike25app/scaleforge-mcp-meta-ads](https://github.com/Mike25app/scaleforge-mcp-meta-ads)
- **Issues:** [github.com/Mike25app/scaleforge-mcp-meta-ads/issues](https://github.com/Mike25app/scaleforge-mcp-meta-ads/issues)
- **ScaleForge (managed platform):** [getscaleforge.com](https://getscaleforge.com)
- **Meta Marketing API docs:** [developers.facebook.com/docs/marketing-apis](https://developers.facebook.com/docs/marketing-apis)

---

## License

MIT — see [LICENSE](LICENSE).

