meta-ads-mcp-patched
# meta-ads-mcp-patched
Patched fork of [`@mikusnuz/meta-ads-mcp`](https://www.npmjs.com/package/@mikusnuz/meta-ads-mcp)
**v1.3.0** (MIT, upstream author mikusnuz — original docs in
[README.upstream.md](README.upstream.md)). The fork exists because the upstream tool schemas lag
behind what the Meta Marketing API v25 actually requires; every gap below was reproduced with a
live API call before patching.
## Patches over upstream 1.3.0
| Tool | Change |
|---|---|
| `create_campaign` | + `bid_strategy` (enum), `bid_amount`, `is_adset_budget_sharing_enabled` (bool, `false` preserved — required by Meta for ABO campaigns) |
| `update_campaign` | + `bid_strategy`, `bid_amount` (lets an agent move a campaign off a bid cap) |
| `create_adset` | + `promoted_object` (JSON string — required for `LEAD_GENERATION` / `OFFSITE_CONVERSIONS`), `bid_amount` |
| `upload_image` | + `file_path` (local file → base64 `bytes` upload; `url` now optional, exactly one required), + `name` |
| `upload_video` | + `file_path` (local file → multipart `source` upload; `file_url` now optional, exactly one required) |
| `list_lead_forms`, `create_lead_form` | Page-scoped calls now resolve the **Page Access Token internally** (derived from the configured token via `/{page_id}?fields=access_token`, cached per page, never surfaced in output) instead of failing with `#190` |
| `get_lead_form`, `get_form_leads` | + optional `page_id` to ride the Page token when Meta rejects the account token |
| `create_adset`, `update_adset` (v1.3.2) | + `dsa_beneficiary`, `dsa_payor` — mandatory for any EU-delivering ad set since the DSA (`#100` subcode 3858081 without them) |
| `create_lead_form` (v1.3.2) | + `context_card` (form headline/intro), `privacy_policy_link_text`, `block_display_for_non_targeted_viewer` (`false` preserved); `follow_up_action_url` now also merges into `thank_you_page.website_url` when absent (Meta requires it for VIEW_WEBSITE and ignores the top-level param) |
| `AdsClient` | `request()` accepts a per-call token override; new `getPageToken` / `getAsPage` / `postAsPage` / `postForm` (multipart) helpers |
Everything else is upstream `dist/` output, byte-identical. Patches are applied directly to the
unminified ESM in `dist/` (upstream ships no source in the npm tarball).
## Usage
Same contract as upstream — stdio MCP server, env-configured:
```
META_ADS_ACCESS_TOKEN (required)
META_AD_ACCOUNT_ID (required, numeric — no act_ prefix)
META_APP_ID / META_APP_SECRET / META_BUSINESS_ID / META_PIXEL_ID (optional)
```
Run: `npx -y github:Green-pep/meta-ads-mcp-patched#v1.3.1`
## Release procedure
1. Apply the change in `dist/`, bump `version` in `package.json` (keep the `1.3.x` base to track
the upstream pin).
2. Update the patch table above.
3. Commit, tag `v1.3.x`, push with tags.
4. Repoint the consumer (MCP catalog `args`) at the new tag.
## Upstream status
Fork base pinned at upstream **1.3.0**. The intent is to offer these patches upstream
(mikusnuz/meta-ads-mcp) and retire this fork if they land.
TDQS
Scored across 134 tools
Most tools have clear, distinct purposes, but there is overlap among lead-related tools (get_campaign_leads, get_adset_leads, get_form_leads, get_lead) and between get_creative vs create_creative vs update_creative. Descriptions help disambiguate, but the sheer number of tools increases the chance of selecting the wrong one.
The naming generally follows a consistent verb_noun pattern (list_, get_, create_, update_, delete_). Minor deviations exist, such as get_campaign_adsets vs list_adsets, and add_to_block_list vs add_users_to_audience, but these are understandable and do not significantly hinder predictability.
With 134 tools, this server is massively over-scoped. The rubric states that 50+ tools is an extreme mismatch, and this server far exceeds that threshold. The tool count alone makes the server difficult to navigate and operate.
The server covers a very broad range of Meta Ads operations, including campaigns, ad sets, ads, creatives, audiences, catalogs, leads, insights, business management, and more. Minor gaps exist (e.g., no delete_catalog, no delete_feed, no get_block_list), but overall the surface is impressively complete for the domain.