meta-ads-mcp
Provides read-only access to Meta Ads data and optionally creates paused ads, with safety features like OAuth and validation.
README
Meta Ads MCP
This repository contains two deliberately separate local MCP servers:
meta-ads-mcpis the default read-only reporting server. It usesads_readand cannot change Meta.meta-ads-writer-mcpis an optional, guarded creation server. It can upload reviewed images and create only newPAUSEDads from a validated manifest.
Both run over stdio. The writer reuses the same private credential store, but
it must be registered as a separate MCP server so enabling it never expands the
read-only server's tool set.
It also includes the meta-ads-upload-qa Codex skill under
skills/meta-ads-upload-qa. The skill coordinates
the two servers, requires explicit write authorization, renders every requested
placement preview, and keeps ads paused when visual QA does not pass.
What it can do
| Tool | Purpose |
|---|---|
health_check |
Validate authorization and inspect granted permissions |
list_ad_accounts |
List accessible ad accounts |
get_ad_account |
Read account configuration and status |
list_campaigns |
Read campaign budgets, objectives, schedules, and delivery |
list_ad_sets |
Read targeting, optimization, attribution, and budgets |
list_ads |
Read ads and attached creative details |
list_ad_creatives |
Read creative copy, images, calls to action, and asset feeds |
get_ad_previews |
Generate Meta-rendered placement previews for visual QA |
get_insights |
Query paginated performance data and breakdowns |
compare_performance |
Compare matched entities across equal-length periods |
export_insights |
Write paginated CSV or JSON reports locally |
compare_performance calculates spend, delivery, CTR, CPC, CPM, conversions,
cost per conversion, conversion value, and ROAS deltas. export_insights
flattens Meta action arrays by action_type, safely quotes CSV values, and
protects spreadsheet programs from formula injection.
Safety model
- Meta access is read-only. The server never creates, updates, pauses, resumes, or deletes campaigns, ad sets, ads, or creatives.
- OAuth requests only
ads_read. - The app secret and access token live outside the repository under
~/.config/meta-ads-mcp, with owner-only file permissions. - Graph API requests send the token in the
Authorizationheader. - Meta pagination URLs are never returned because they can contain credentials.
get_ad_previewsreturns Meta's ephemeral preview URLs and, by default, renders each successful placement to a labeled PNG image directly in the MCP response. This lets an agent inspect placement overlays without controlling the user's browser. Setrender_imagestofalsewhen only URLs are needed, orinclude_iframe_htmltotruewhen raw embed HTML is useful for debugging. Rendering uses an isolated temporary Chrome/Chromium profile and deletes its local files after the response. It does not edit the ad.- The renderer discovers Chrome/Chromium automatically. Set
META_ADS_PREVIEW_BROWSER_PATHto an executable path to override discovery. export_insightscreates a new local file and never overwrites an existing export. It cannot modify Meta.- The server never logs tokens or app secrets.
Guarded writer
The optional writer exposes five tools:
| Tool | Purpose |
|---|---|
plan_ad_upload |
Validate local 4:5/9:16 files, hash them, and save a plan |
validate_ad_upload |
Read and verify the account, campaign, ad set, Page, and IG ID |
upload_images |
Upload only the files fingerprinted in the validated plan |
upload_assets |
Upload fingerprinted images and MP4 videos in a validated plan |
create_ads_paused |
Create placement or carousel ads hard-coded PAUSED |
It has no edit, publish, pause, resume, archive, or delete tools. Both write
phases require a specific confirmation string after the plan is reviewed.
Progress is saved after every successful Meta response, so the same plan can be
retried without intentionally duplicating completed items. A partial failure is
never rolled back or cleaned up automatically. Before each real creative or ad
creation, the writer sends the exact payload through Meta's validate_only
execution option.
Every creative validation and creation request explicitly sends
contextual_multi_ads with enroll_status set to OPT_OUT, so new ads do not
participate in multi-advertiser ad units by default.
The manifest is JSON and uses absolute media paths. Existing placement-image entries remain backward compatible:
{
"version": 1,
"account_id": "123",
"campaign_id": "456",
"campaign_name": "Main campaign",
"adset_id": "789",
"adset_name": "Testing",
"page_id": "101",
"instagram_user_id": "202",
"link": "https://example.com/landing",
"display_link": "https://apps.apple.com/",
"call_to_action_type": "DOWNLOAD",
"ads": [
{
"name": "Concept 01",
"title": "Headline ✨",
"body": "Primary text 🧡",
"description": "Description 📲",
"feed_image_path": "/absolute/path/concept_F45.png",
"vertical_image_path": "/absolute/path/concept_V916.png"
}
]
}
Placement image and video ads can use two to five primary-text options in one
creative by replacing the singular "body" field with a "bodies" array:
{
"name": "Concept 01",
"title": "Headline ✨",
"bodies": [
"Primary text option A 🧡",
"Primary text option B 🧡"
],
"description": "Description 📲",
"feed_image_path": "/absolute/path/concept_F45.png",
"vertical_image_path": "/absolute/path/concept_V916.png"
}
Placement videos use "format": "video" with feed_video_path (1:1 or 4:5)
and vertical_video_path (9:16). Carousels use "format": "carousel" and
two to ten square PNG/JPEG card objects under cards, each with an
image_path and optional card title, description, or HTTPS link.
Story-only image ads use "format": "story_image" with one
vertical_image_path (9:16):
{
"name": "Story concept",
"format": "story_image",
"title": "One Dinner. Two Plates. 🧡",
"body": "Family recipes with a baby-friendly version 🍽️",
"description": "7-day free trial • Then $29/year 🧡",
"vertical_image_path": "/absolute/path/concept_V916.png"
}
The writer validates the target ad set before upload and rejects
story_image plans unless every explicitly configured placement is a
Facebook, Instagram, or Messenger Story. Automatic placements, feeds, Reels,
Search, Audience Network, and Threads are rejected. This prevents a
single-asset Story creative from silently delivering outside Stories.
The campaign and ad-set names are checked as well as their IDs. Images must be PNG or JPEG and no larger than 30 MB. MP4 videos are limited to 1 GB by the writer. A plan is invalidated if any fingerprinted file changes. Campaigns and ad sets must already exist in the Marketing API; unpublished Ads Manager drafts cannot be targeted.
Requirements
- Node.js 20 or newer
- A Meta developer app with access to the Marketing API
- A Meta user who can access the required ad accounts
Install
git clone https://github.com/lil-j/meta-ads-mcp.git
cd meta-ads-mcp
npm install
npm run build
Authorize Meta
In the Meta app dashboard, enable a Facebook Login web flow and add this exact Valid OAuth Redirect URI:
http://localhost:53682/callback
Start the local setup flow:
META_APP_ID=your_app_id npm run auth -- setup
The helper opens a local browser page. Enter the app secret there, then authorize
Meta. The form posts only to 127.0.0.1; credentials are not sent to the MCP
client or this repository.
Meta user tokens are time-limited. Reauthorize when health_check reports an
expired token:
npm run auth -- login
Connect an MCP client
For Codex CLI, register the built server using its absolute path:
codex mcp add meta-ads -- node /absolute/path/to/meta-ads-mcp/dist/index.js
For clients that use a JSON MCP configuration:
{
"mcpServers": {
"meta-ads": {
"command": "node",
"args": ["/absolute/path/to/meta-ads-mcp/dist/index.js"]
}
}
}
Restart or refresh the MCP client after changing its configuration.
Register the writer separately only when paused-ad creation is needed:
codex mcp add meta-ads-writer -- node /absolute/path/to/meta-ads-mcp/dist/writer-index.js
The configured token must grant ads_management for the writer. The included
authorization helper intentionally requests only ads_read; it does not widen
the default server's access.
Install the Codex skill
Copy the included skill into your personal Codex skills directory:
mkdir -p ~/.codex/skills
cp -R skills/meta-ads-upload-qa ~/.codex/skills/
Restart or refresh Codex after installing or updating the skill.
Development
npm run typecheck
npm run build
npm test
The test suite uses fake credentials and local mock transports. It does not call Meta or require access to an ad account.
Exports
Exports are written to ~/Downloads/Meta Ads by default. Set
META_ADS_EXPORT_DIR to use a different directory. Files are created with
owner-only permissions and receive a numeric suffix if a name already exists.
Environment overrides
META_ADS_CONFIG_DIRMETA_OAUTH_CLIENT_FILEMETA_ACCESS_TOKEN_FILEMETA_ACCESS_TOKENMETA_APP_SECRETMETA_GRAPH_API_VERSION(defaults tov25.0)META_GRAPH_BASE_URLMETA_ADS_EXPORT_DIRMETA_ADS_WRITER_PLAN_DIRMETA_OAUTH_PORT
Security
Never commit Meta credentials or exported ad data. See SECURITY.md for reporting instructions and additional guidance. CI runs Gitleaks on every push and pull request as an additional guard against committed credentials.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。