ads-mcp-server
Provides tools for retrieving Google Ads performance data, campaign settings, and change history, enabling live daily-dashboard workflows.
Provides tools for retrieving Meta (Facebook) Ads performance data and campaign settings, enabling live daily-dashboard workflows.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ads-mcp-servershow Google Ads report for last week"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
| Performance + diagnostics + 56-day series + WoW + 8-week DoW comparisons + campaign settings + change history |
| Same shape as Google. Conversions filtered to |
| Settings + change history for |
Architecture: pull ad×day raw once per platform per hour, cache to parquet, derive every aggregation in pandas. No API call per breakdown.
Related MCP server: Google Ads MCP Server
Prerequisites
macOS / Linux
Python 3.13 (via pyenv recommended)
uvpackage manager:brew install uvGoogle Ads API access — see Google Ads API getting started
Meta Marketing API access — see Marketing API getting started
Credential setup links
Credential | Where to get it |
| Google Ads UI → Tools → API Center |
| https://console.cloud.google.com → OAuth 2.0 client (Desktop app) |
| Run |
| Comma-separated, no dashes. Find in Google Ads UI top-right |
| MCC manager account ID, no dashes |
| https://developers.facebook.com → My Apps → Settings → Basic |
| https://business.facebook.com → Business Settings → System Users → Generate New Token (long-lived, with |
| Meta Ads Manager → top-left account picker. Format: |
Install
cd ~/marketing-ds/ads-mcp-server
uv sync --extra devuv 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/.envOption B — local .env:
cp .env.example .env
# fill in the blanksRequired keys are listed in .env.example with comments explaining each.
Run
Locally for testing:
uv run ads-mcp-serverThe 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).logWhat it does each morning at 6am:
Pulls Google Ads perf 56d, settings, change_event 29d → cache
(Meta currently disabled — see "Meta status" below)
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.plistMeta 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=campaignfor the 56-day series,level=adfor 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.pyIf Meta keeps rate-limiting, fallback options (not yet implemented):
Async report runs (
async=True) for the perf pullTighter
effective_statusfilter (ACTIVEonly, 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.csvIf 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 -vAll tests are mock-based — no network calls. Covers:
classify_campaignBrand/Non-Brand/Otherdiagnose5-state classifier8-week same-DoW selector picks the right 8 dates
WoW delta + zero-division
actions[]filter for MetaSnapshot 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-adsinstall fails: ensure Python 3.13 (uv python pin 3.13) andpip install grpcioworks 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*.logfor spawn errors. Confirmuvis inPATHfor the GUI process (you may need a full path:which uv).Cache stale: delete
cache/*.parquetto 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 constantsMaintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmacaggi-gfm/ads-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server