Skip to main content
Glama
estapel-ai

mcp-facebook-ads

by estapel-ai
README.md
# Custom Facebook Ads MCP Server

Eigen MCP server (Python) voor Meta/Facebook Business Manager, met:

- data inladen via Marketing API (insights/reporting),
- campagnes opbouwen (campaigns, ad sets, ads, creatives),
- optimalisatie en budgetadvies op basis van best practices.

## Architectuur en endpoints

- **MCP-transport**: stdio. Cursor (of een andere MCP-client) start het proces; er is **geen** apart HTTP-endpoint voor de MCP zelf.
- **Meta API**: alle calls gaan via de Graph API / Marketing API zoals de SDK (`facebook-business`) die gebruikt. Basis-URL:

  `https://graph.facebook.com/{META_API_VERSION}/...`

  De standaard API-versie in deze codebase is **`v25.0`** (zet `META_API_VERSION` in `.env` gelijk aan wat je app ondersteunt).

## 1) Vereisten

- Python 3.11+
- [`uv`](https://docs.astral.sh/uv/)
- Een Meta Developer-app met **Marketing API** en een geldig **access token** met rechten op het gewenste ad account

**Benodigde permissies (scopes) op het token:**

- `ads_management`
- `ads_read`
- `business_management`
- `pages_read_engagement`

Zonder deze scopes kunnen tools deels of volledig falen.

## 2) Meta Developer-app aanmaken

1. Ga naar [Meta for Developers](https://developers.facebook.com/).
2. Maak een **app** (kies het type dat past bij Marketing API / zakelijke ads).
3. Voeg het product **Marketing API** toe en voltooi de stappen die Meta vraagt.
4. Noteer onder **App settings → Basic**:
   - **App ID** → `META_APP_ID`
   - **App Secret** → `META_APP_SECRET`

## 3) Ad account en token (aanbevolen: System User)

**Aanbevolen** voor een stabiele, team- of server-achtige setup: een **System user** in [Meta Business Settings](https://business.facebook.com/settings) (Gebruikers → System users), met toegewezen assets (het juiste **ad account** en indien nodig **Pages**). Genereer daar een token met de scopes hierboven.

- **Ad account-ID** in `.env` als `act_<numeriek_id>`. De server voegt `act_` automatisch toe als je alleen het nummer invult.

**Alternatieven (minder ideaal voor productie):**

- Korte tokens uit de Graph API Explorer (vooral geschikt om even te testen).
- OAuth-flow (zie hieronder) om user tokens of long-lived tokens te verkrijgen.

## 4) OAuth- en token-endpoints (Meta)

Vervang `{VERSION}` door dezelfde waarde als `META_API_VERSION` (bijv. `v25.0`). Vervang placeholders door je echte app- en redirect-gegevens.

| Stap | URL |
|------|-----|
| Gebruiker inloggen en scopes goedkeuren | `https://www.facebook.com/{VERSION}/dialog/oauth?client_id={APP_ID}&redirect_uri={REDIRECT_URI}&scope=ads_management,ads_read,business_management,pages_read_engagement&response_type=code` |
| **Authorization code** omzetten naar **short-lived** access token | `GET https://graph.facebook.com/{VERSION}/oauth/access_token?client_id={APP_ID}&client_secret={APP_SECRET}&redirect_uri={REDIRECT_URI}&code={CODE}` |
| **Short-lived** token omzetten naar **long-lived** token (ca. 60 dagen) | `GET https://graph.facebook.com/{VERSION}/oauth/access_token?grant_type=fb_exchange_token&client_id={APP_ID}&client_secret={APP_SECRET}&fb_exchange_token={SHORT_LIVED_TOKEN}` |

**Redirect URI**: in de Meta-app (bijv. onder Facebook Login / OAuth-instellingen) moet de **OAuth redirect URI** exact overeenkomen met `{REDIRECT_URI}` in bovenstaande requests.

## 5) Installatie en `.env`

```bash
git clone <jouw-repo-url> mcp-facebook-ads
cd mcp-facebook-ads
uv sync
cp .env.example .env   # of maak .env handmatig
```

Vul `.env` (zie `.env.example` voor veldnamen):

```env
META_APP_ID=...
META_APP_SECRET=...
META_ACCESS_TOKEN=...
META_AD_ACCOUNT_ID=act_...
META_API_VERSION=v25.0
```

De server laadt `.env` via `python-dotenv` vanaf de **working directory** van het proces. Zorg dat de MCP in Cursor `cwd` op de projectroot heeft staan als je geen inline `env` in de MCP-config gebruikt.

**Commit `.env` nooit**; die staat in `.gitignore`.

## 6) Cursor-configuratie

Je kunt de MCP op twee manieren configureren:

1. **Project** (aanbevolen voor dit repo): `.cursor/mcp.json` in de projectroot (staat mogelijk niet in git; maak hem lokaal aan).
2. **Globaal**: Cursor Settings → MCP, afhankelijk van je Cursor-versie.

Voorbeeld `.cursor/mcp.json` (geldige JSON — geen `//`-comments). Vervang het pad door je eigen projectmap; secrets horen in `.env` in die map, niet in git.

**Optie A** — `cwd` op de projectroot (aanbevolen; `.env` wordt dan automatisch geladen):

```json
{
  "mcpServers": {
    "facebook-ads": {
      "command": "uv",
      "args": ["run", "python", "-m", "mcp_facebook_ads.server"],
      "cwd": "/ABSOLUUT/PAD/NAAR/mcp-facebook-ads"
    }
  }
}
```

**Optie B** — zonder `cwd`, met expliciet pad in `uv run`:

```json
{
  "mcpServers": {
    "facebook-ads": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/ABSOLUUT/PAD/NAAR/mcp-facebook-ads",
        "python",
        "-m",
        "mcp_facebook_ads.server"
      ]
    }
  }
}
```

Secrets kun je óf in `.env` in die `cwd` laten staan, óf (minder ideaal) als `env`-object in `mcp.json` zetten — let op dat je die file dan niet deelt.

## 7) Delen met collega’s

**Wel delen:** repository, deze README, `App ID`, bekende ad account-identifiers waar ze toch al toegang toe moeten hebben, en het Cursor-commando + `cwd`.

**Niet delen** (alleen via een secrets manager of 1:1 veilig kanaal): `META_APP_SECRET`, `META_ACCESS_TOKEN`. Liever per persoon of per omgeving een eigen System user-token met minimale benodigde rechten dan één gedeelde token zonder rotatie.

## 8) Sneltest tegen de Graph API

Controleer of je token werkt (zelfde `{VERSION}` als in `.env`):

```http
GET https://graph.facebook.com/{VERSION}/me?access_token={META_ACCESS_TOKEN}
```

Als dit faalt, los eerst app- en tokenconfiguratie op voordat je de MCP gebruikt.

## 9) Starten als MCP-server (handmatig)

```bash
uv run python -m mcp_facebook_ads.server
```

Draait op stdio; normaal start Cursor dit proces zelf.

## 10) Beschikbare toolgroepen

### Account Management

- `get_ad_accounts`
- `get_account_info`
- `get_account_pages`

### Campaigns

- `get_campaigns`
- `get_campaign_details`
- `create_campaign`
- `update_campaign`
- `delete_campaign`

### Ad Sets

- `get_adsets`
- `get_adset_details`
- `create_adset`
- `update_adset`
- `delete_adset`

### Ads

- `get_ads`
- `get_ad_details`
- `create_ad`
- `update_ad`
- `delete_ad`

### Creatives & Media

- `get_ad_creatives`
- `upload_ad_image`
- `create_ad_creative`
- `create_asset_feed_ad_creative`
- `update_ad_creative`
- `get_ad_previews`

### Insights & Reporting

- `get_insights`
- `get_account_insights`
- `compare_performance`

### Audience & Targeting

- `search_interests`
- `search_behaviors`
- `search_demographics`
- `search_geo_locations`
- `estimate_audience_size`

### Best Practices & Optimization

- `get_campaign_templates`
- `create_campaign_from_template`
- `analyze_campaign`
- `suggest_budget_allocation`

## 11) Best-practice defaults

- Nieuwe entities worden standaard met status `PAUSED` aangemaakt.
- Templates zijn beschikbaar voor `awareness`, `traffic`, `leads`, `sales`.
- Adviezen sturen op CTR/CPC, en op funnel-gescheiden structuur.

## 12) Veiligheid en governance

- Gebruik bij voorkeur een **system user**-token, niet je persoonlijke user-token.
- Geef productie-activatie (`ACTIVE`) pas na review.
- Log API-fouten en `fbtrace_id`-waarden voor snelle debugging bij Meta.

## 13) Testen

```bash
uv run pytest
```

TDQS

C2.5/5.0

Scored across 39 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions (campaign vs adset vs ad vs creative). Some overlap remains between get_insights, get_account_insights, and compare_performance, and between get_ad_accounts and get_account_info, but descriptions help differentiate.

Naming Consistency4/5

The set is predominantly snake_case with a verb_noun pattern. Minor deviations exist, such as get_account_info versus get_campaign_details/get_adset_details/get_ad_details, and multiple similar prefixes for creative tools.

Tool Count2/5

39 tools is heavy for this domain and exceeds the 25+ threshold for 'too many'. Several tools could be consolidated, including the multiple creative-creation tools, insight variants, and separate targeting search tools.

Completeness4/5

Core CRUD/lifecycle coverage exists for campaigns, adsets, ads, and creatives, plus targeting searches, uploads, previews, and insights. Minor gaps include no delete_ad_creative and no clear adset/ad-level insights tool.

Maintenance

ActivityInactive
ResponsivenessNo issues