Control your entire Google Ads account through Claude — in plain English. Pause campaigns, pull reports, add keywords, create ads. With built-in permission controls so nothing runs without your approval. Self-hosted on your own server. No third-party relay. No data leaves your infrastructure.
Google Ads MCP is a self-hosted Model Context Protocol server that gives Claude direct, secure access to the Google Ads API v23.2. Built by Opti Webopz.
Once connected, Claude understands natural language — no IDs required:
"Pause all campaigns spending over $50/day in My Client Account"
"Show me the performance of campaign Summer Sale for last 30 days"
"Add these 10 keywords to ad group Branded - Exact in campaign Brand UK"
"Create a new Search campaign called Winter Promo with a $30 daily budget"
"Show me search terms that triggered ads in campaign Google Shopping this month"
"What is the CTR on our top 5 campaigns this month?"
"Create a Responsive Search Ad in ad group Homepage with these headlines and descriptions"
The built-in Prompt Helper dashboard lets you browse accounts, campaigns, and ad groups by name — click any prompt to copy it straight into Claude. No IDs, no copy-pasting.
Before Claude executes any write operation, the server checks your permission settings. You control exactly what Claude is allowed to do — from the dashboard, with a single toggle per tool.
How it works:
- Read tools are always on — list, get, and all report tools cannot be disabled
- Write tools are individually toggleable — 17 write/mutate tools, each with its own on/off switch
- Danger tools highlighted — remove_campaign, remove_ad_group, remove_keyword shown in red
- When a tool is disabled — Claude receives a clear message: "Tool 'remove_campaign' is currently disabled. Enable it in the dashboard under Permission Controls before asking Claude to use it."
- Claude will not attempt workarounds — it will explain the tool is off and ask you to enable it
| Always on (read-only) | Toggleable (write) |
|---|---|
| list_accounts, get_account, run_gaql | create_campaign, update_campaign |
| get_account_summary, get_campaign_report | pause_campaign, enable_campaign |
| get_ad_group_report, get_keyword_report | set_campaign_budget, remove_campaign |
| get_ad_report, get_search_terms | create_ad_group, update_ad_group |
| list_campaigns, get_campaign | pause_ad_group, enable_ad_group |
| list_ad_groups, list_ads | remove_ad_group |
| update_ad_status, add_keywords | |
| update_keyword, remove_keyword |
|
| add_negative_keywords |
⚠️ Danger tools (remove operations) are highlighted in the dashboard and can be disabled independently.
| Version | Deploy on | Runtime | Best for |
|---|---|---|---|
| gads-mcp-php/ | Hostinger / SiteGround | PHP 8.0+ | Shared hosting — no SSH needed |
| gads-mcp/ | DigitalOcean / VPS | Node.js 18+ | Persistent server, live dashboard |
Both versions have identical tools and identical permission controls — 30 tools, 17 of which are individually toggleable.
| Tool | What it does |
|---|---|
list_accounts |
List all client accounts under your MCC with currency, timezone, status |
get_account |
Get full details for a specific account |
run_gaql |
Execute any raw GAQL (Google Ads Query Language) query |
| Tool | What it does |
|---|---|
get_account_summary |
Account-level totals — impressions, clicks, cost, CTR, conversions, ROAS |
get_campaign_report |
Campaign performance sorted by cost |
get_ad_group_report |
Ad group performance metrics |
get_keyword_report |
Keyword metrics with quality scores |
get_ad_report |
Ad performance with headline preview |
get_search_terms |
Actual search queries that triggered your ads |
| Tool | Toggleable | What it does |
|---|---|---|
list_campaigns |
No | All campaigns with status, budget, bidding |
get_campaign |
No | Full campaign details |
create_campaign |
✅ Yes | Create a Search campaign — defaults to PAUSED |
update_campaign |
✅ Yes | Update campaign name or status |
pause_campaign |
✅ Yes | Pause a live campaign immediately |
enable_campaign |
✅ Yes | Enable a paused campaign |
set_campaign_budget |
✅ Yes | Update daily budget |
remove_campaign |
✅ Yes |
Permanently remove a campaign |
| Tool | Toggleable | What it does |
|---|---|---|
list_ad_groups |
No | All ad groups with CPC bids |
create_ad_group |
✅ Yes | Create a new ad group |
update_ad_group |
✅ Yes | Update name, status, or CPC bid |
pause_ad_group |
✅ Yes | Pause an ad group |
enable_ad_group |
✅ Yes | Enable an ad group |
remove_ad_group |
✅ Yes |
Remove an ad group |
| Tool | Toggleable | What it does |
|---|---|---|
list_ads |
No | All ads with headlines, descriptions, status |
create_rsa |
✅ Yes | Create Responsive Search Ad — defaults to PAUSED |
update_ad_status |
✅ Yes | Set ad to ENABLED, PAUSED, or REMOVED |
| Tool | Toggleable | What it does |
|---|---|---|
add_keywords |
✅ Yes | Add BROAD / PHRASE / EXACT keywords |
update_keyword |
✅ Yes | Update keyword status or CPC bid |
remove_keyword |
✅ Yes |
Remove a keyword |
add_negative_keywords |
✅ Yes | Add negatives at campaign or ad group level |
⚠️ All campaign, ad group, and ad creation defaults to PAUSED. Nothing spends money until you explicitly enable it.
Both versions include a PIN-protected web dashboard:
| Panel | What it does |
|---|---|
| OAuth connection | Token status, expiry ring, last refresh time |
| API version status | Running version vs latest, sunset date warning |
| Permission controls | Per-tool on/off toggles — 17 write tools, danger tools highlighted |
| Prompt Helper | Browse accounts → campaigns → ad groups by name, copy Claude prompts |
| Campaign table | 30-day metrics per campaign — impressions, clicks, cost, CTR, conversions |
| MCP token rotation | Generate and save new token |
| Tool call stats | 24h totals, error count, most-used tool |
| Recent log | Last 50 tool calls with timestamp and status |
You need 5 credentials before deploying. Get them in this order:
- Go to console.cloud.google.com
- Create a new project — name it "Google Ads MCP" or similar
- Go to APIs & Services → Library → search Google Ads API → click Enable
- Go to APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID
- If prompted for consent screen: User Type = External → fill App name → Save and Continue
- Application type: Web application
- Add Authorised redirect URI:
- PHP version:
https://yourdomain.com/gads-mcp/auth/oauth_setup.php - Node.js version:
http://localhost:8080/callback
- PHP version:
- Click Create → copy Client ID and Client Secret
- Log into Google Ads Manager (MCC) account
- Click the wrench icon (Tools) → API Centre
- Copy your Developer Token
- Apply for Standard Access if it shows Basic Access — Basic only works on test accounts
- Shown top-right of Google Ads Manager (format:
123-456-7890) - Remove the dashes →
1234567890— this is yourGOOGLE_ADS_MCC_ID
Obtained by running the OAuth setup script — covered in each deployment section below.
public_html/gads-mcp/
├── mcp.php ← MCP endpoint (GET public, POST requires auth)
├── config.php ← Fill in your credentials here
├── .htaccess ← Security + routing rules
├── auth/
│ └── oauth_setup.php ← Run ONCE to get refresh token, then DELETE
├── lib/
│ ├── auth.php ← Token auth — LiteSpeed/Hostinger compatible
│ ├── permissions.php ← Per-tool permission manager
│ ├── oauth.php ← File-cached OAuth token manager
│ ├── gads.php ← Google Ads REST API v23.2 client
│ ├── response.php ← JSON helpers + tool manifest
│ └── logger.php ← File logger
├── tools/ ← 6 tool files (all 30 tools)
├── dashboard/
│ └── index.php ← Full dashboard with permission controls
└── logs/ ← YOU MUST CREATE THIS + logs/rate/ (chmod 755)
├── .permissions.json ← Auto-created on first permission save
└── gads-mcp.log ← Auto-created on first tool call
1. Upload files
In Hostinger hPanel → File Manager, create folder public_html/gads-mcp/. Upload all contents of gads-mcp-php/ into it.
2. Create log folders
Inside public_html/gads-mcp/, create:
logs/— set permissions to 755logs/rate/— set permissions to 755
3. Get your refresh token
In Google Cloud Console, add this Authorised Redirect URI:
https://yourdomain.com/gads-mcp/auth/oauth_setup.php
Visit in browser:
https://yourdomain.com/gads-mcp/auth/oauth_setup.php
Click Authorise with Google → sign in with your MCC account → copy the GOOGLE_REFRESH_TOKEN shown on screen.
🔴 Delete
auth/oauth_setup.phpimmediately after copying the token. In File Manager: select it → Delete.
4. Fill in config.php
In File Manager, right-click config.php → Edit:
define('MCP_SECRET_TOKEN', 'YOUR_64_CHAR_TOKEN'); // openssl rand -hex 32
define('DASHBOARD_PIN', 'YOUR_STRONG_PASSPHRASE');
define('GOOGLE_CLIENT_ID', 'xxxxx.apps.googleusercontent.com');
define('GOOGLE_CLIENT_SECRET', 'GOCSPX-xxxxx');
define('GOOGLE_REFRESH_TOKEN', '1//xxxxxxxx'); // from step 3
define('GOOGLE_ADS_DEV_TOKEN', 'xxxxx');
define('GOOGLE_ADS_MCC_ID', '1234567890'); // digits only, no dashes
define('GOOGLE_ADS_API_VERSION', 'v23.2');5. Test the endpoint
Visit in browser — should return tool manifest JSON with 30 tools listed:
https://yourdomain.com/gads-mcp/mcp.php
6. Open dashboard and configure permissions
https://yourdomain.com/gads-mcp/dashboard/
Enter your DASHBOARD_PIN. Go to Permission Controls → toggle off any tools you don't want Claude to use. Changes save instantly.
- Ubuntu 22.04 Droplet — minimum 512MB RAM ($6/mo Basic is fine)
- Domain or subdomain pointing to your Droplet IP
- SSH access
1. Upload files to server
scp -r gads-mcp/ root@YOUR_DROPLET_IP:/root/gads-mcp2. SSH in and run setup script
ssh root@YOUR_DROPLET_IP
cd /root/gads-mcp
chmod +x setup-digitalocean.sh
./setup-digitalocean.shThis installs Node.js 20, PM2, creates the logs/ directory, and starts the server.
3. Get your refresh token
npm run authOpen the URL it prints → sign in with your MCC Google account → paste the auth code back → copy the GOOGLE_REFRESH_TOKEN printed in terminal.
4. Create and fill in .env
cp .env.example .env
nano .envMCP_SECRET_TOKEN=YOUR_64_CHAR_TOKEN
DASHBOARD_PIN=YOUR_STRONG_PASSPHRASE
GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxx
GOOGLE_REFRESH_TOKEN=1//xxxxxxxx
GOOGLE_ADS_DEV_TOKEN=xxxxx
GOOGLE_ADS_MCC_ID=1234567890
GOOGLE_ADS_API_VERSION=v23.2
PORT=3848
MCP_RATE_LIMIT=605. Start with PM2
pm2 start ecosystem.config.js
pm2 save
pm2 startup
# Run the command it prints to enable auto-start on reboot6. Set up nginx + SSL
cp nginx/gads-mcp.conf /etc/nginx/sites-available/
nano /etc/nginx/sites-available/gads-mcp.conf # replace YOUR_DOMAIN with your domain
ln -s /etc/nginx/sites-available/gads-mcp.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
apt install certbot python3-certbot-nginx -y
certbot --nginx -d gads-mcp.yourdomain.com7. Test the endpoint
curl https://gads-mcp.yourdomain.com/mcp
# Should return tool manifest JSON8. Open dashboard and configure permissions
https://gads-mcp.yourdomain.com/dashboard
Enter your DASHBOARD_PIN. Go to Permission Controls → toggle write tools on or off per your needs.
Open config file:
- Mac:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"gads-mcp": {
"transport": {
"type": "http",
"url": "https://yourdomain.com/gads-mcp/mcp.php",
"headers": {
"X-MCP-Token": "YOUR_MCP_SECRET_TOKEN"
}
}
}
}
}For DigitalOcean, change URL to https://gads-mcp.yourdomain.com/mcp.
Save → quit Claude Desktop completely → reopen.
claude mcp add --transport http gads-mcp \
https://yourdomain.com/gads-mcp/mcp.php \
--header "Authorization: Bearer YOUR_MCP_SECRET_TOKEN"Claude Code on Windows has a known header issue with HTTP transport. Use the bridge script:
- Use the bridge from the OptiMCP bridge script — update
TOKENandHOSTNAME - Add to
.claude.json:
{
"mcpServers": {
"gads-mcp": {
"command": "node",
"args": ["C:\\Users\\YourName\\gads-bridge.js"]
}
}
}| Control | Implementation |
|---|---|
| MCP auth | X-MCP-Token and Authorization: Bearer both accepted |
| LiteSpeed fix | getallheaders() bypasses Hostinger/LiteSpeed header stripping |
| GET public | Tool manifest requires no token (Claude Code health check compatible) |
| POST protected | All 30 tool calls require valid token |
| Permission controls | Per-tool enable/disable — 17 write tools individually controllable |
| Blocked tool response | Returns 403 with clear message to Claude, never silently fails |
| Rate limiting | 60 req/60s per IP (both versions) |
| Error handling | error_reporting(0) prevents PHP warnings corrupting JSON |
| Dashboard | Separate PIN, timing-safe comparison |
| Credentials | Never returned in tool responses — OAuth tokens stay server-side |
| PAUSED defaults | All create operations default to PAUSED — nothing spends accidentally |
| Danger tools | remove_campaign, remove_ad_group, remove_keyword highlighted in dashboard |
Credentials
- All 5 Google credentials filled in — no placeholder values remain
- MCC ID digits only — no dashes (
123-456-7890→1234567890) - Developer token is Standard Access (Basic = test accounts only — will fail on real accounts)
-
GOOGLE_ADS_API_VERSION=v23.2 -
MCP_SECRET_TOKENis 64 chars (openssl rand -hex 32) -
DASHBOARD_PINset — dashboard shows PIN login screen
Server
- Dashboard OAuth panel shows Connected with token expiry countdown
-
oauth_setup.phpdeleted from server immediately after use - GET endpoint returns tool manifest with all 30 tools listed
-
logs/andlogs/rate/folders exist and are writable (PHP version) - PM2 shows
gads-mcpas online (Node.js version)
Permissions
- Dashboard Permission Controls panel loaded — all 17 write tools visible
- Danger tools (remove operations) reviewed — disable if not needed
- Test: ask Claude to "remove a campaign" with it disabled — should get blocked message
Claude connection
-
claude mcp listshows ✓ Connected - "List all accounts" returns your MCC client accounts in Claude
- Prompt Helper in dashboard shows your campaigns by name
optimcp/
├── gads-mcp-php/ # Google Ads MCP — PHP (Hostinger / SiteGround)
│ ├── mcp.php # Main endpoint
│ ├── config.php # Credentials template
│ ├── lib/
│ │ ├── permissions.php # Per-tool permission system
│ │ ├── auth.php # LiteSpeed-compatible token auth
│ │ ├── oauth.php # File-cached token manager
│ │ └── gads.php # Google Ads REST API client
│ ├── tools/ # 30 tools across 6 files
│ └── dashboard/index.php # Full dashboard with permission controls
└── gads-mcp/ # Google Ads MCP — Node.js (DigitalOcean)
├── server.js # Main server (port 3848)
├── lib/
│ ├── permissions.js # Per-tool permission system
│ └── ...
├── dashboard/
│ ├── index.html # Dashboard UI
│ └── routes.js # Dashboard API (permissions, prompt helper)
└── tools/ # 30 tools across 6 files
Opti Webopz — Full-service digital agency specializing in WordPress, WooCommerce, and AI-powered automation.
Contributors: Muhammad Zumair Qureshi · M. Shaheer Mustafa
MIT — free to use, modify, and distribute. See LICENSE.
Part of the OptiMCP suite — self-hosted MCP servers for Claude. Google Ads MCP v2.1.0 · Node.js v1.2.0