Google Ads MCP Server
README.md
# Google Ads MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) server that gives an
LLM (Claude, Copilot, …) **read-only** access to Google Ads account data —
campaigns, ad groups, keywords, search terms, segmented performance reports,
bidding, budgets, conversions, Performance Max assets, labels, change history,
impression share, plus an ad-hoc GAQL escape hatch.
It is a thin wrapper over Google Ads' GAQL `search_stream` API. Every tool takes
a `customer_id` per request, so one running server can query any account the
authenticated credentials can reach.
## Two ways to run
| | Local (stdio) | Remote (HTTP + OAuth) |
|---|---|---|
| **Who it's for** | An individual on their own machine | A team sharing one hosted instance |
| **Auth to Google Ads** | Your own refresh-token credentials | Each user signs in with **their own** Google account; their token is forwarded to the Ads API, so they only see accounts they personally can access |
| **The server holds** | Your full credentials | Only the developer token + the OAuth client |
| **Clients** | Claude Desktop, VS Code/Copilot, any stdio MCP client | Claude.ai web connector, Claude Desktop/Code |
| **Setup** | This README, below | [docs/REMOTE_DEPLOY.md](docs/REMOTE_DEPLOY.md) |
Most people want **Local**. Start there.
## What it does
**41 read-only tools**, grouped:
- **Accounts (5)** — account discovery, metadata, conversion actions, labels
- **Reporting (24)** — campaigns, ad groups, keywords, search terms, geo / device / demographic segments, Performance Max assets
- **Diagnostics (9)** — Quality Score, ad extensions, bid strategies, budget pacing, change history, negative keywords, impression share
- **Query (2)** — raw GAQL `SELECT` + a structured GAQL builder
- **Metadata (1)** — selectable / filterable / sortable fields per GAQL resource
Full catalog with per-tool descriptions: **[docs/TOOLS.md](docs/TOOLS.md)**.
---
## Prerequisites
- [**uv**](https://docs.astral.sh/uv/getting-started/installation/) — Python package/runtime manager.
- A **Google Cloud project** with the [Google Ads API enabled](https://console.cloud.google.com/apis/library/googleads.googleapis.com).
- A **Google Ads developer token** ([how to get one](https://developers.google.com/google-ads/api/docs/get-started/dev-token)).
- An **OAuth 2.0 client** in that project (Desktop or Web type) — used to mint your refresh token.
> This project ships **no credentials and no hosted service**. You bring your own
> Google Cloud project, OAuth client, and developer token.
---
## Local setup (stdio)
### 1. Clone and install
```bash
git clone https://github.com/VidenGrowth/public-google-ads-mcp google-ads-mcp
cd google-ads-mcp
uv sync
```
### 2. Configure credentials
```bash
cp .env.example .env
# edit .env
```
Fill in (see [.env.example](.env.example) for the full list):
- `GOOGLE_ADS_DEVELOPER_TOKEN`
- `GOOGLE_ADS_CLIENT_ID`, `GOOGLE_ADS_CLIENT_SECRET`
- `GOOGLE_ADS_REFRESH_TOKEN` *(generate it in the next step)*
- `GOOGLE_ADS_LOGIN_CUSTOMER_ID` *(optional — only when operating through a manager/MCC account; digits, no dashes)*
The target `customer_id` is **not** in `.env`; the agent passes it per request.
### 3. Generate a refresh token
```bash
uv run auth/generate_refresh_token.py -c client_secret.json
```
Sign in with a Google account that can access the Ads accounts you want, then
paste the printed token into `.env` as `GOOGLE_ADS_REFRESH_TOKEN`. Full walkthrough
(incl. a Windows helper): [auth/README.md](auth/README.md).
### 4. Test locally
```bash
uv run python scripts/smoke_test.py
```
Expected: `✓ server wired up — 41 tools registered`, followed by `get_accessible_accounts`
returning your accounts. If credentials are missing you'll get a clear
`<error>{"error":"Google Ads client not configured. …"}</error>` instead — fix `.env`
and re-run.
Run the test suite anytime with:
```bash
uv run --with pytest pytest tests/ -q
```
### 5. Connect a client
**Claude Desktop** (`claude_desktop_config.json` — macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`):
```json
{
"mcpServers": {
"google-ads": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/google-ads-mcp", "run", "google-ads-mcp"]
}
}
}
```
Restart Claude Desktop fully (quit from the tray/menu, not just close the window).
Then enable `Chat > MCP` in settings, run **`MCP: Start Server`** from the Command
---
## Example prompts
Once connected, try (replace the ID with one of your accounts):
- *"Show me all campaigns for customer 1234567890"*
- *"Find wasted spend in search terms for customer 1234567890"*
- *"Which keywords have quality scores below 5 for customer 1234567890?"*
- *"Compare device and geographic performance for customer 1234567890 over the last 30 days"*
- *"Show the age + gender breakdown for customer 1234567890"*
- *"Is customer 1234567890 on pace to spend its budget this month?"*
Parameter conventions (date ranges, ID/name filters, status filters, sorting) are
documented in [docs/TOOLS_DESIGN.md](docs/TOOLS_DESIGN.md).
---
## Remote deploy (teams)
To host one shared instance where each teammate signs in with their own Google account — no per-user install, and everyone only sees the Ads accounts they can access — deploy the HTTP transport with Google OAuth.
The server authenticates users via an OAuth proxy (one-click connect from Claude.ai, no pasted secrets) and forwards each user's token to the Ads API.
Full guide: **[docs/REMOTE_DEPLOY.md](docs/REMOTE_DEPLOY.md)**.
---
## How authentication works
- **Local (stdio):** the server uses *your* refresh-token credentials. There is
no MCP-layer auth — the server runs on your machine under your control.
- **Remote (HTTP):** the server uses FastMCP's Google OAuth proxy. Each request
carries a per-user Google token (with the `adwords` scope) that is forwarded to
the Google Ads API, so authorization is whatever that user's Google account can
do. The server stores **no** user credentials — only the operator's developer
token and the OAuth client_id/secret.
---
## Architecture
See [docs/PROJECT_MAP.md](docs/PROJECT_MAP.md) for a directory tour and request
flow, and [docs/TOOLS_DESIGN.md](docs/TOOLS_DESIGN.md) for the design conventions
every tool follows.
## License
[MIT](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing