# Google Ads MCP Server — Full Build Plan

## Why Build This

The existing Google Ads MCPs are garbage:
- **Google's official** → 2 tools total (just GAQL queries lol)
- **samihalawa's** → 8 campaign-only tools, no annotations, no apps
- **None** have tool labeling, lazy loading, safety annotations, or MCP Apps

Google Ads API v21 has **90+ services**. There's a massive opportunity to build the definitive Google Ads MCP with proper architecture.

---

## Architecture

### Tech Stack
- **Runtime:** Node.js + TypeScript (matches our 30 existing servers)
- **MCP SDK:** `@modelcontextprotocol/sdk` (latest)
- **Google Ads API:** v21 via REST (or `google-ads-api` npm package)
- **Auth:** OAuth2 refresh token flow + optional ADC support
- **Build:** tsup → dist, publish to npm as `@busybee/google-ads-mcp`

### Key Differentiators
1. **Tool Annotations** — every tool labeled with `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`
2. **Lazy Loading / Progressive Discovery** — tools grouped by category, loaded on demand
3. **MCP Apps** — rich UI components (structuredContent) for dashboards, campaign views, etc.
4. **Safety Guardrails** — confirmation flows for destructive operations (pause campaigns, change budgets)
5. **GAQL Query Builder** — natural language → GAQL translation helper

---

## Tool Categories & Tools (~45 tools)

### Category 1: Account Management (5 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_accessible_customers` | List all customer accounts you can access | readOnly |
| `get_account_info` | Get account details (name, currency, timezone) | readOnly |
| `get_account_hierarchy` | Get manager → client account tree | readOnly |
| `get_billing_info` | Get billing setup and payment accounts | readOnly |
| `get_account_budget` | Get account-level budget proposals | readOnly |

### Category 2: Campaign Management (8 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_campaigns` | List campaigns with status, type, budget, metrics | readOnly |
| `get_campaign` | Get detailed campaign info by ID | readOnly |
| `create_campaign` | Create a new campaign (Search, Display, PMax, etc.) | destructive, NOT idempotent |
| `update_campaign` | Update campaign settings (name, status, targeting) | destructive |
| `pause_campaign` | Pause a running campaign | destructive |
| `enable_campaign` | Enable a paused campaign | destructive |
| `remove_campaign` | Remove/delete a campaign | destructive, NOT idempotent |
| `update_campaign_budget` | Change daily/total budget for a campaign | destructive |

### Category 3: Ad Group Management (6 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_ad_groups` | List ad groups for a campaign | readOnly |
| `get_ad_group` | Get ad group details | readOnly |
| `create_ad_group` | Create a new ad group | destructive |
| `update_ad_group` | Update ad group settings (bids, status, targeting) | destructive |
| `pause_ad_group` | Pause an ad group | destructive |
| `enable_ad_group` | Enable a paused ad group | destructive |

### Category 4: Ad Management (5 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_ads` | List ads in an ad group with approval status | readOnly |
| `get_ad` | Get detailed ad info (headlines, descriptions, URLs) | readOnly |
| `create_responsive_search_ad` | Create an RSA with headlines + descriptions | destructive |
| `update_ad` | Update ad copy or URLs | destructive |
| `pause_ad` | Pause a specific ad | destructive |

### Category 5: Keywords & Targeting (6 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_keywords` | List keywords for an ad group with match types + QS | readOnly |
| `add_keywords` | Add keywords to an ad group | destructive |
| `remove_keywords` | Remove keywords from an ad group | destructive |
| `get_keyword_ideas` | Generate keyword ideas (Keyword Planner) | readOnly, openWorld |
| `get_keyword_metrics` | Get search volume, competition, CPC estimates | readOnly, openWorld |
| `list_negative_keywords` | List negative keywords (campaign + ad group level) | readOnly |

### Category 6: Performance & Reporting (7 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `get_performance_summary` | Account-level performance (clicks, impressions, cost, conversions) | readOnly |
| `get_campaign_performance` | Campaign-level metrics with date range | readOnly |
| `get_ad_group_performance` | Ad group-level metrics | readOnly |
| `get_keyword_performance` | Keyword-level metrics with quality scores | readOnly |
| `get_search_terms_report` | Actual search terms triggering ads | readOnly |
| `get_geo_performance` | Performance by geographic location | readOnly |
| `get_device_performance` | Performance by device type | readOnly |

### Category 7: Bidding & Budget (4 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_bidding_strategies` | List portfolio bidding strategies | readOnly |
| `get_bid_recommendations` | Get Google's bid recommendations | readOnly |
| `update_keyword_bids` | Change CPC bids for keywords | destructive |
| `list_recommendations` | Get Google's optimization recommendations | readOnly |

### Category 8: Conversion Tracking (4 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `list_conversion_actions` | List configured conversion actions | readOnly |
| `get_conversion_metrics` | Get conversion data by campaign/ad group | readOnly |
| `create_conversion_action` | Create a new conversion action | destructive |
| `upload_offline_conversions` | Upload offline conversion data | destructive |

### Category 9: Advanced / Utilities (4 tools)
| Tool | Description | Annotations |
|------|-------------|-------------|
| `run_gaql_query` | Execute raw GAQL query (power users) | readOnly, openWorld |
| `export_report` | Export any report to CSV/JSON | readOnly |
| `get_change_history` | Get recent changes to the account | readOnly |
| `get_labels` | List and manage labels | readOnly |

---

## Lazy Loading Architecture

```
Initial load → Core tools only (8 tools):
  - list_accessible_customers
  - list_campaigns  
  - get_performance_summary
  - get_campaign_performance
  - run_gaql_query
  - export_report
  - get_keyword_ideas
  - list_recommendations

On-demand categories (loaded when referenced):
  - "campaign_management" → 8 campaign CRUD tools
  - "ad_groups" → 6 ad group tools  
  - "ads" → 5 ad tools
  - "keywords" → 6 keyword tools
  - "bidding" → 4 bidding tools
  - "conversions" → 4 conversion tools
  - "advanced" → 4 utility tools
```

Implementation: Use MCP `tools/list` with pagination hints, or a `load_category` meta-tool that dynamically registers tools.

---

## MCP Apps (structuredContent UI Components)

### App 1: Campaign Dashboard
- Grid view of all campaigns with status pills, spend, CTR, conversions
- Sparkline charts for 7-day trends
- Quick actions: pause/enable buttons

### App 2: Performance Overview
- Account-level KPI cards (total spend, clicks, impressions, avg CPC, conversions)
- Date range selector
- Comparison to previous period (green/red deltas)

### App 3: Campaign Detail Card
- Full campaign settings display
- Budget utilization bar
- Metric breakdown table
- Ad group list within campaign

### App 4: Keyword Analyzer
- Keyword list with quality score visualization (color-coded bars)
- Match type indicators
- Search term cloud from actual queries
- Bid vs. position scatter

### App 5: Search Terms Report
- Table of triggering search terms
- Relevance scoring
- Quick "add as keyword" or "add as negative" actions

### App 6: Recommendations Panel
- Google's recommendations with estimated impact
- Accept/dismiss actions
- Category filters (bids, keywords, ads, etc.)

### App 7: Budget Optimizer
- Budget allocation visualization across campaigns
- Projected spend vs. actual
- Reallocation suggestions based on performance

---

## Tool Annotations Schema

Every tool gets proper MCP annotations:

```typescript
{
  name: "pause_campaign",
  description: "Pause a running campaign. This will stop all ads from serving.",
  annotations: {
    readOnlyHint: false,
    destructiveHint: true,
    idempotentHint: true,  // pausing twice = same result
    openWorldHint: false,
    title: "Pause Campaign",
    category: "campaign_management"
  },
  inputSchema: { ... }
}
```

```typescript
{
  name: "get_keyword_ideas", 
  description: "Generate keyword ideas based on seed keywords or URL.",
  annotations: {
    readOnlyHint: true,
    destructiveHint: false,
    idempotentHint: true,
    openWorldHint: true,  // queries external data
    title: "Keyword Ideas",
    category: "keywords"
  },
  inputSchema: { ... }
}
```

---

## Safety Guardrails

For any tool with `destructiveHint: true`:

1. **Budget changes** → require explicit confirmation, show before/after
2. **Campaign pause/remove** → show what's at stake (current daily spend, impressions, active ads)
3. **Keyword removal** → show keyword performance before removing
4. **Bulk operations** → require `confirm: true` parameter + show count of affected items
5. **Budget floor** → warn if setting budget below Google's recommended minimum

---

## Auth Flow

```
Option 1: OAuth2 Refresh Token (recommended for MCP)
  - User provides: client_id, client_secret, refresh_token, developer_token
  - Server handles token refresh automatically
  - Stored in env vars or config file

Option 2: Application Default Credentials (GCP)
  - For users already in GCP ecosystem
  - gcloud auth application-default login with Google Ads scope

Option 3: Service Account (enterprise)
  - For automated/server setups
  - Domain-wide delegation
```

---

## File Structure

```
google-ads-mcp/
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── README.md
├── src/
│   ├── index.ts              # Main server entry
│   ├── client.ts             # Google Ads API client wrapper
│   ├── auth.ts               # OAuth2/ADC auth handling
│   ├── tools/
│   │   ├── index.ts          # Tool registry + lazy loading
│   │   ├── accounts.ts       # Account management tools
│   │   ├── campaigns.ts      # Campaign CRUD tools
│   │   ├── ad-groups.ts      # Ad group tools
│   │   ├── ads.ts            # Ad management tools
│   │   ├── keywords.ts       # Keyword & targeting tools
│   │   ├── reporting.ts      # Performance & reporting tools
│   │   ├── bidding.ts        # Bidding & budget tools
│   │   ├── conversions.ts    # Conversion tracking tools
│   │   └── advanced.ts       # GAQL, export, utilities
│   ├── apps/
│   │   ├── campaign-dashboard.ts
│   │   ├── performance-overview.ts
│   │   ├── campaign-detail.ts
│   │   ├── keyword-analyzer.ts
│   │   ├── search-terms.ts
│   │   ├── recommendations.ts
│   │   └── budget-optimizer.ts
│   └── utils/
│       ├── gaql.ts           # GAQL query builder
│       ├── formatters.ts     # Data formatting helpers
│       └── validators.ts     # Input validation
├── dist/                     # Compiled output
└── tests/
    ├── tools.test.ts
    └── apps.test.ts
```

---

## Build Phases

### Phase 1: Core (MVP) — ~2 days
- Auth flow (OAuth2 refresh token)
- API client with proper error handling
- Account + Campaign tools (13 tools)
- Performance reporting tools (7 tools)
- Tool annotations on all tools
- Basic lazy loading architecture

### Phase 2: Full Tool Suite — ~1 day
- Ad group, ad, keyword tools (17 more tools)
- Bidding + conversion tools (8 more tools)
- GAQL query builder
- Export functionality

### Phase 3: MCP Apps — ~2 days
- Campaign Dashboard app
- Performance Overview app
- Campaign Detail Card
- Keyword Analyzer
- Recommendations Panel

### Phase 4: Polish — ~1 day
- Search Terms Report app
- Budget Optimizer app
- Full test coverage
- README + docs
- npm publish

**Total estimate: ~6 days with paired agents, ~3 days if we parallelize hard**

---

## Competitive Edge vs. Existing

| Feature | Google Official | samihalawa | **Ours** |
|---------|----------------|------------|----------|
| Tools | 2 | 8 | **~45** |
| Tool Annotations | ❌ | ❌ | **✅** |
| Lazy Loading | ❌ | ❌ | **✅** |
| MCP Apps (UI) | ❌ | ❌ | **7 apps** |
| Safety Guardrails | ❌ | ❌ | **✅** |
| Keyword Planner | ❌ | ❌ | **✅** |
| GAQL Builder | ❌ | ❌ | **✅** |
| Conversion Tracking | ❌ | ❌ | **✅** |
| Ad Management | ❌ | ❌ | **✅** |
| Language | Python | Node.js | **TypeScript** |

---

## Revenue Potential

Based on our MCP pricing research:
- **Free tier:** Read-only tools (reporting, performance, recommendations)
- **Pro ($19-29/mo):** Full CRUD, keyword planner, all apps
- **Enterprise ($99-199/mo):** Multi-account, bulk ops, custom GAQL, offline conversions

Google Ads has **~10M+ active advertisers**. Even capturing 0.01% = 1,000 users at $29/mo = $29K MRR.

---

*Ready to build on your call, Jack.*
