ads-mcp-server

ads-mcp-server

Exposes Google Ads and Meta Marketing performance data, campaign settings, and change history to Claude (Cowork) for live daily-dashboard workflows.

Category
访问服务器

README

ads-mcp-server

Local MCP server exposing Google Ads + Meta Marketing performance data, campaign settings, and change history to Claude (Cowork) for live daily-dashboard workflows.


What it does

Three tools registered with MCP:

Tool Purpose
get_google_ads_report(date_range, breakdown) Performance + diagnostics + 56-day series + WoW + 8-week DoW comparisons + campaign settings + change history
get_meta_ads_report(date_range, breakdown) Same shape as Google. Conversions filtered to META_CONVERSION_EVENT_NAME
get_campaign_settings(platform) Settings + change history for google / meta / both

Architecture: pull ad×day raw once per platform per hour, cache to parquet, derive every aggregation in pandas. No API call per breakdown.


Prerequisites

Credential setup links

Credential Where to get it
GOOGLE_ADS_DEVELOPER_TOKEN Google Ads UI → Tools → API Center
GOOGLE_ADS_CLIENT_ID / CLIENT_SECRET https://console.cloud.google.com → OAuth 2.0 client (Desktop app)
GOOGLE_ADS_REFRESH_TOKEN Run python -m google.ads.googleads.examples.authentication.generate_user_credentials after installing google-ads
GOOGLE_ADS_CUSTOMER_IDS Comma-separated, no dashes. Find in Google Ads UI top-right
GOOGLE_ADS_LOGIN_CUSTOMER_ID MCC manager account ID, no dashes
META_APP_ID / META_APP_SECRET https://developers.facebook.com → My Apps → Settings → Basic
META_ACCESS_TOKEN https://business.facebook.com → Business Settings → System Users → Generate New Token (long-lived, with ads_read)
META_AD_ACCOUNT_ID Meta Ads Manager → top-left account picker. Format: act_XXXXXXXXX

Install

cd ~/marketing-ds/ads-mcp-server
uv sync --extra dev

uv creates .venv/ and installs all deps pinned in pyproject.toml.


Configure credentials

Two options:

Option A — point at existing .env (recommended if you already have keys in ~/marketing-ds/decision_science/.env):

export ADS_MCP_ENV_FILE=/Users/jmacaggi/marketing-ds/decision_science/.env

Option B — local .env:

cp .env.example .env
# fill in the blanks

Required keys are listed in .env.example with comments explaining each.


Run

Locally for testing:

uv run ads-mcp-server

The server speaks MCP over stdio — Cowork (or any MCP client) spawns it on demand.


Connect to Claude (Cowork)

Add this block to ~/.claude/claude_desktop_config.json (create if missing):

{
  "mcpServers": {
    "ads": {
      "command": "uv",
      "args": [
        "--directory",
        "/Users/jmacaggi/marketing-ds/ads-mcp-server",
        "run",
        "ads-mcp-server"
      ],
      "env": {
        "ADS_MCP_ENV_FILE": "/Users/jmacaggi/marketing-ds/decision_science/.env"
      }
    }
  }
}

Restart Claude/Cowork. Tools get_google_ads_report, get_meta_ads_report, get_campaign_settings should appear.

No background daemon required — Cowork starts/stops the process per session.


Daily pre-warm (recommended for live dashboard)

Cache validity rule: a cache is fresh if it contains yesterday's date. Refreshes once per day. The first user query of the day triggers the refresh — and a 56-day pull on a large account can take 1-3 minutes.

To avoid that wait, schedule a pre-warm at 6am via macOS launchd:

# Install
cp /Users/jmacaggi/marketing-ds/ads-mcp-server/launchd/com.jmacaggi.adsmcp.prewarm.plist \
   ~/Library/LaunchAgents/

launchctl load ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist

# Verify it's scheduled
launchctl list | grep adsmcp

# Trigger immediately (test)
launchctl start com.jmacaggi.adsmcp.prewarm

# Logs
tail -f ~/marketing-ds/ads-mcp-server/logs/prewarm.stdout.log
tail -f ~/marketing-ds/ads-mcp-server/logs/$(date +%Y-%m-%d).log

What it does each morning at 6am:

  1. Pulls Google Ads perf 56d, settings, change_event 29d → cache
  2. (Meta currently disabled — see "Meta status" below)
  3. Writes refresh stamp cache/google_lastrefresh.txt = today

By the time you open Cowork, Google data is hot. Tool calls return in <1s.

To uninstall:

launchctl unload ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist
rm ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist

Meta status (as of 2026-05-07)

Meta tools (get_meta_ads_report, get_campaign_settings(platform="meta"|"both")) are structurally complete but not yet verified end-to-end.

What works:

  • Performance pull is chunked into 7-day windows (avoids the Service temporarily unavailable / subcode 1504044 "result too large" error)
  • Ad-level data is split: level=campaign for the 56-day series, level=ad for yesterday-only (avoids 5-minute pagination)
  • AdSet pull is filtered to effective_status IN [ACTIVE, PAUSED] (avoids paginating thousands of archived ad sets)

What blocked us:

  • After the first big perf chunked pull, the AdSet pull hit Meta's hourly rate limit (code 17, subcode 2446079: "User request limit reached"). Cooldown is typically 10-60 minutes.

To re-test tomorrow morning (after quota resets):

# Remove --skip-meta from the launchd plist to enable Meta in pre-warm
sed -i '' '/<string>--skip-meta<\/string>/d' \
   ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist
launchctl unload ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist
launchctl load ~/Library/LaunchAgents/com.jmacaggi.adsmcp.prewarm.plist

# Or run manually
ADS_MCP_ENV_FILE=/Users/jmacaggi/marketing-ds/decision_science/.env \
   uv run python scripts/prewarm.py

If Meta keeps rate-limiting, fallback options (not yet implemented):

  • Async report runs (async=True) for the perf pull
  • Tighter effective_status filter (ACTIVE only, drop paused)

If you prefer a long-running background process (optional, not required for Cowork): use nohup uv run ads-mcp-server > /tmp/ads-mcp.log 2>&1 & or a launchd plist.


Optional: CSV override (skip the API)

Google Ads UI exports CSV reports without API quota limits. Drop a CSV into cache/external/ to override the API pull:

cache/external/google_2026-05-07.csv
cache/external/meta_2026-05-07.csv

If a matching CSV exists AND is newer than the parquet cache, the server loads it instead of calling the API. The response sets metadata.data_source = "csv_override" so Cowork knows.

CSV column schema must match the parquet (see src/ads_mcp_server/google_ads.py and meta_ads.py for column names: date, campaign_id, campaign_name, ad_id, ad_name, spend, impressions, clicks, conversions, ...).


Test

uv run pytest -v

All tests are mock-based — no network calls. Covers:

  • classify_campaign Brand/Non-Brand/Other
  • diagnose 5-state classifier
  • 8-week same-DoW selector picks the right 8 dates
  • WoW delta + zero-division
  • actions[] filter for Meta
  • Snapshot diff including null-old-value and pruning
  • Missing creds returns clean error (no exception)

Logs

Every API call and error is logged to logs/YYYY-MM-DD.log (one file per day).


Troubleshooting

  • google-ads install fails: ensure Python 3.13 (uv python pin 3.13) and pip install grpcio works on your system. On Apple Silicon: arch -arm64 uv sync.
  • Meta token expired: regenerate the system user token in Business Settings; long-lived tokens last 60 days.
  • Tool not appearing in Cowork: check ~/Library/Logs/Claude/mcp*.log for spawn errors. Confirm uv is in PATH for the GUI process (you may need a full path: which uv).
  • Cache stale: delete cache/*.parquet to force fresh pull.

File map

src/ads_mcp_server/
  server.py        # MCP entry + tool handlers
  config.py        # env loading, validates creds
  google_ads.py    # 3 GAQL queries: perf, settings, change_event
  meta_ads.py      # Insights + AdSet pull
  snapshots.py     # Meta snapshot diff (Meta has no reliable change API)
  cache.py         # parquet + CSV override
  aggregate.py     # all pandas math
  classify.py      # Brand/NB/Other
  diagnose.py      # 5-state diagnosis
  date_ranges.py   # window resolution + 8wk DoW
  retry.py         # exponential backoff
  logging_setup.py # daily file logs
  schema.py        # response shape constants

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选