google-ads-mcp-coolify
Self-hosted Google Ads MCP server for Coolify, Docker, and any VPS. Streamable HTTP transport with OAuth 2.0 — connects Claude Code, Cursor, and any MCP client to the Google Ads API.
Google Ads MCP Server — Self-Hosted on Coolify (Docker, HTTP/SSE)
Deploy the Google Ads MCP Server on your own VPS with Coolify in 5 minutes. Connects Claude Code, Claude Desktop, Cursor, or any Model Context Protocol client to the Google Ads API via OAuth 2.0 — over HTTPS, with a public endpoint.
This repo is a production-ready Docker wrapper around gomarble-ai/google-ads-mcp-server that solves the two missing pieces for remote deployment:
- No Dockerfile upstream → this repo adds one.
- Upstream runs in
stdiomode (only works locally with Claude Desktop) → this repo wraps it withstreamable-httptransport so it can be reached over the internet.
Perfect for teams running self-hosted MCP infrastructure on platforms like Coolify, Dokploy, EasyPanel, Railway, Render, Fly.io, or any plain Docker/Kubernetes setup.
Table of contents
- Why self-host a Google Ads MCP server?
- Features
- How it works
- Quick start (Coolify)
- Quick start (plain Docker)
- Generating the OAuth credentials.json
- Connecting from Claude Code / Cursor / Claude Desktop
- Available MCP tools
- Security notes
- Troubleshooting
- Contributing
- License
Why self-host a Google Ads MCP server?
- Privacy: your Google Ads OAuth tokens never leave your infrastructure.
- Multi-client: one deployed instance serves Claude Code, Cursor, Continue, Zed, n8n, and any other MCP-compatible tool.
- No paid SaaS gateway: skip third-party MCP relays — go straight from your AI client to your VPS to the Google Ads API.
- Works behind reverse proxies: HTTPS via Let's Encrypt, custom subdomain, optional auth middleware.
Features
- ✅ Streamable HTTP transport (MCP spec) — works with all modern MCP clients
- ✅ OAuth 2.0 with auto refresh — no manual token rotation
- ✅ Bearer token auth built-in (
MCP_AUTH_TOKEN) — endpoint never publicly accessible by default - ✅ Env-var credentials (
GOOGLE_ADS_CREDENTIALS_JSON) — no File Mount required on Coolify - ✅ Single subdomain deploy —
https://google-ads-mcp.yourdomain.com/mcp - ✅ Multi-account / MCC support via
GOOGLE_ADS_LOGIN_CUSTOMER_ID - ✅ Built on FastMCP — fast, async, production-grade
- ✅ Up-to-date upstream: each build pulls the latest
gomarble-ai/google-ads-mcp-serverfrommain - ✅ Coolify-tested — also runs on Dokploy, EasyPanel, Railway, Fly.io, plain Docker
How it works
┌─────────────────┐ HTTPS ┌────────────────────────┐ OAuth ┌──────────────────┐
│ Claude Code / │ ──── /mcp ─────────▶│ This container │ ──── refresh ────▶ │ Google Ads API │
│ Cursor / etc. │ │ (FastMCP HTTP server) │ │ (v19) │
└─────────────────┘ └────────────────────────┘ └──────────────────┘
│
▼
/app/credentials/credentials.json
(mounted as a file by Coolify)
The container does three things at startup:
- Loads OAuth tokens from
/app/credentials/credentials.json(file mount). - Imports the FastMCP app defined in the upstream
server.py. - Runs it on
0.0.0.0:8000usingstreamable-httptransport.
Quick start (Coolify)
1. Point a subdomain to your VPS
| Type | Name | Value |
|---|---|---|
| A | google-ads-mcp | <your VPS IP> |
2. Create the resource
Coolify → + New Resource → Public Repository
| Field | Value |
|---|---|
| Repository | https://github.com/LuckSigog/google-ads-mcp-coolify |
| Branch | main |
| Build Pack | Dockerfile |
| Dockerfile Location | /Dockerfile |
| Port Exposed | 8000 |
| Domain | https://google-ads-mcp.yourdomain.com |
3. Environment Variables
GOOGLE_ADS_DEVELOPER_TOKEN=<your_developer_token>
GOOGLE_ADS_AUTH_TYPE=oauth
PORT=8000
# Paste the full credentials.json content (single line is fine, JSON parser handles it)
GOOGLE_ADS_CREDENTIALS_JSON={"token":"ya29...","refresh_token":"1//0h...","token_uri":"https://oauth2.googleapis.com/token","client_id":"...","client_secret":"...","scopes":["https://www.googleapis.com/auth/adwords"]}
# Bearer token for endpoint auth (RECOMMENDED — without it, your endpoint is public)
# Generate with: python3 -c 'import secrets; print(secrets.token_urlsafe(32))'
MCP_AUTH_TOKEN=<long_random_string>
# Optional — only if you use a Manager (MCC) account:
# GOOGLE_ADS_LOGIN_CUSTOMER_ID=1234567890
⚠️ Do not set
NODE_ENVor any unrelated env var — Coolify injects all env vars as build ARGs, which can break unrelated builds.
4. (Optional) Mount the OAuth credentials as a file
You can skip this entirely if you set GOOGLE_ADS_CREDENTIALS_JSON above. Use a File Mount only if you prefer keeping the JSON out of env vars:
Coolify → Storages → + Add → File Mount
| Mount Path | Content |
|---|---|
/app/credentials/credentials.json | Paste the entire JSON generated below |
5. Deploy
Click Deploy. When the container is healthy:
curl -i https://google-ads-mcp.yourdomain.com/mcp
# Expected: HTTP 200, 405, or similar — NOT 502
Quick start (plain Docker)
docker build -t google-ads-mcp .
docker run -d \
--name google-ads-mcp \
-p 8000:8000 \
-e GOOGLE_ADS_DEVELOPER_TOKEN=your_token \
-e GOOGLE_ADS_AUTH_TYPE=oauth \
-e GOOGLE_ADS_CREDENTIALS_PATH=/app/credentials/credentials.json \
-v $(pwd)/credentials.json:/app/credentials/credentials.json:ro \
google-ads-mcp
Generating the OAuth credentials.json
You only run this once on your local machine to bootstrap the refresh token. The container will refresh access tokens automatically from then on.
Prerequisites
- Go to Google Cloud Console
- Create an OAuth 2.0 Client ID of type Desktop application
- Download the
client_secret_*.jsonfile - Make sure the Google Ads API is enabled in the project
- Have a Google Ads Developer Token (apply here)
Run the bootstrap script
# gen_credentials.py
from google_auth_oauthlib.flow import InstalledAppFlow
import json, glob, sys
matches = glob.glob('client_secret*.json')
if not matches:
sys.exit("Place a client_secret*.json next to this script first.")
flow = InstalledAppFlow.from_client_secrets_file(
matches[0], scopes=['https://www.googleapis.com/auth/adwords'])
creds = flow.run_local_server(port=0)
with open('credentials.json', 'w') as f:
json.dump({
'token': creds.token,
'refresh_token': creds.refresh_token,
'token_uri': creds.token_uri,
'client_id': creds.client_id,
'client_secret': creds.client_secret,
'scopes': creds.scopes,
}, f, indent=2)
print("OK -> credentials.json generated")
python3 -m venv .venv && source .venv/bin/activate
pip install google-auth-oauthlib
python3 gen_credentials.py
A browser will open. Sign in with the Google account that has access to your Google Ads account and authorize. You'll get a credentials.json in the current directory.
Upload that JSON as a File Mount on Coolify (step 4 above).
Connecting from Claude Code / Cursor / Claude Desktop
Claude Code (CLI)
If you set MCP_AUTH_TOKEN:
claude mcp add --transport http google-ads https://google-ads-mcp.yourdomain.com/mcp \
--header "Authorization: Bearer YOUR_MCP_AUTH_TOKEN" --scope user
claude mcp list
Without auth:
claude mcp add --transport http google-ads https://google-ads-mcp.yourdomain.com/mcp --scope user
Test it:
"List my Google Ads accounts"
Cursor / Continue / Zed
Add to your MCP servers config:
{
"mcpServers": {
"google-ads": {
"type": "http",
"url": "https://google-ads-mcp.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
Claude Desktop (local stdio only)
Claude Desktop doesn't speak HTTP MCP. If you want it there, install the upstream gomarble-ai/google-ads-mcp-server directly on your machine.
Available MCP tools
Inherited from upstream:
| Tool | Description |
|---|---|
list_accounts | Lists all accessible Google Ads accounts, including nested sub-accounts under MCC |
run_gaql | Executes any Google Ads Query Language (GAQL) query — campaigns, ad groups, keywords, conversions, reports |
run_keyword_planner | Generates keyword ideas with search volume, competition, and CPC bid range |
GAQL reference is exposed as an MCP resource: gaql://reference.
Security notes
This wrapper ships with built-in Bearer token auth (MCP_AUTH_TOKEN env var). Set it and the endpoint requires Authorization: Bearer <token> on every request — no token, no access.
Generate a strong token:
python3 -c 'import secrets; print(secrets.token_urlsafe(32))'
# or:
openssl rand -base64 32
For team deployments, additional hardening worth considering:
- Per-user tokens with revocation — back the middleware with a Supabase/Postgres table of token hashes (planned in a future release; PRs welcome)
- Cloudflare Access / Tailscale / WireGuard — zero-trust SSO in front of the endpoint
- IP allowlist at the Coolify/Cloudflare layer if connecting from a fixed set of machines
Even with MCP_AUTH_TOKEN, treat the endpoint as a defense-in-depth boundary, not the only line of defense — rotate the token periodically.
Troubleshooting
sh: tsc: not found or build fails with missing devDependencies
You're hitting the Coolify env-var-as-build-ARG quirk. Don't set NODE_ENV=production as an env var on the Coolify service. That gets injected as a build ARG and breaks unrelated Dockerfiles. (This repo is Python, but the same pattern bites Node-based MCP servers.)
ERROR: failed to read dockerfile
Check Base Directory = / and Dockerfile Location = /Dockerfile in the Coolify Configuration tab.
401 Unauthorized / OAuth credentials expired
Open credentials.json and confirm refresh_token is present. If it's missing, regenerate via gen_credentials.py and re-upload the file mount.
Developer token is not approved
A fresh developer token has limited access (test accounts only). For production accounts, apply for Basic Access in the Google Ads API Center.
LOGIN_CUSTOMER_ID required
You're querying through a Manager (MCC) account. Set GOOGLE_ADS_LOGIN_CUSTOMER_ID=<mcc_id_without_dashes> and redeploy.
502 Bad Gateway after deploy
Container started but isn't listening on port 8000. Check the build logs — most often the git clone of upstream failed. Re-trigger the deploy.
Contributing
PRs welcome. Specifically useful:
- Optional auth middleware (Bearer / Basic / IP allowlist)
- Pinned upstream SHA option (currently builds against
main) - Helm chart / Kubernetes manifests
- Examples for n8n, Make, Zapier MCP integrations
License
MIT — same license as the upstream gomarble project.
Credits
- Upstream MCP server: gomarble-ai/google-ads-mcp-server
- Model Context Protocol: modelcontextprotocol.io
- Coolify: coolify.io
- FastMCP: jlowin/fastmcp
Keywords: google ads mcp server, google ads mcp coolify, self-hosted mcp google ads, mcp server docker, deploy mcp server vps, claude code google ads integration, fastmcp http server, google ads api claude, mcp streamable http, model context protocol google ads, cursor google ads mcp, n8n google ads mcp, self host model context protocol, google ads oauth mcp.
Server Terkait
Content Distribution MCP
MCP server that distributes a single piece of content across 8+ channels (DEV.to, Hashnode, GitHub Discussions, Reddit, Bluesky, LinkedIn, Medium, Twitter) with automatic platform-specific adaptation, idempotent publishing, per-community anti-spam rules, and centralized state management.
DigitalPilot
DigitalPilot is an attribution platform for B2B SMBs running paid campaigns. It identifies which companies visit your site from which ads, so you can see exactly which campaigns drive qualified leads.
SocialDataX 小红书 Xiaohongshu XHS RedNote MCP
SocialDataX(社媒数据助手)is a read-only MCP for 小红书 / Xiaohongshu / XHS / RedNote, supporting 笔记搜索, 笔记详情, 评论, 评论回复, 博主信息, 博主笔记列表, note search, note details, comments, comment replies, creator profiles, and creator notes.
Derrick App - B2B Data enrichment MCP
MCP server for B2B data enrichment via Derrick: find verified emails, phone numbers, and 100+ LinkedIn/company data points natively from agents. Powered by Google Sheets-native Derrick API.
Parse
See how any brand surfaces in AI search
AutomateLab-si-seo
Vendor-agnostic MCP server that audits, scores, and rewrites web pages for AI-citation eligibility. No API keys. No registration. Works in Claude Desktop, Cursor, Cline, Windsurf, VS Code (Copilot / Continue), and any client that speaks the Model Context Protocol.
Google My Business MCP
Connect Google My Business to Claude or ChatGPT via Two Minute Reports MCP. Analyze profile views, customer actions, and top-performing locations to improve visibility and conversions.
X Algorithm MCP
Tweet scoring and optimization using X's actual algorithm weights - 22 engagement signals, 18 safety filters, diversity penalty calculator, and 11 research tools.
Coherence
Talk to your CRM's AI agent from Claude, Cursor, and other MCP clients — read records, send email, create reminders, draft outreach, all gated by approvals.
Derrick
B2B Data Enrichment