Skip to main content
Glama
Google Ads MCP Server

Google Ads MCP Server

by MaxGhenis

Google Ads MCP Server

A Model Context Protocol (MCP) server for Google Ads with read AND write capabilities. Unlike Google's official read-only MCP server, this one lets you actually manage your campaigns.

Features

Read operations

  • list_accounts - List all accessible Google Ads accounts

  • execute_query - Run GAQL queries for campaigns, ad groups, keywords, metrics, etc.

Write operations

  • create_campaign - Create new campaigns (paused by default for safety)

  • create_ad_group - Create ad groups in a campaign

  • add_keywords - Add keywords to an ad group

  • add_negative_keywords - Add negative keywords (campaign or ad group level)

  • create_responsive_search_ad - Create RSAs with headlines/descriptions

  • pause_campaign / enable_campaign - Toggle campaign status

  • pause_ad_group / enable_ad_group - Toggle ad group status

  • update_ad_group_bid - Update CPC bids

Safety features

  • Dry run mode - All write operations support dry_run=True to validate without executing

  • Safe defaults - New campaigns are created PAUSED

  • Clear feedback - All operations return success status and error messages

Related MCP server: Google Ads MCP Server

Installation

# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install the package
uv pip install google-ads-mcp

# Or install from source
git clone https://github.com/maxghenis/google-ads-mcp-rw
cd google-ads-mcp
uv pip install -e .

Using pip

pip install google-ads-mcp

Configuration

1. Create Google Ads API credentials

  1. Go to the Google Ads API Center

  2. Create a developer token (or use an existing one)

  3. Set up OAuth2 credentials in Google Cloud Console

  4. Generate a refresh token

2. Create google-ads.yaml

Create a google-ads.yaml file with your credentials:

developer_token: YOUR_DEVELOPER_TOKEN
client_id: YOUR_CLIENT_ID.apps.googleusercontent.com
client_secret: YOUR_CLIENT_SECRET
refresh_token: YOUR_REFRESH_TOKEN
# MCC account ID if using multiple accounts (digits only, no dashes)
login_customer_id: "1234567890"
use_proto_plus: true

See google-ads.yaml.example for a template.

3. Set the config path (optional)

By default, the server looks for google-ads.yaml in the current directory. You can specify a custom location:

export GOOGLE_ADS_CONFIG_PATH=/path/to/your/google-ads.yaml

Usage with Claude Desktop

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "google-ads": {
      "command": "uv",
      "args": ["run", "--with", "google-ads-mcp", "google-ads-mcp"],
      "env": {
        "GOOGLE_ADS_CONFIG_PATH": "/path/to/your/google-ads.yaml"
      }
    }
  }
}

Or if installed globally:

{
  "mcpServers": {
    "google-ads": {
      "command": "google-ads-mcp",
      "env": {
        "GOOGLE_ADS_CONFIG_PATH": "/path/to/your/google-ads.yaml"
      }
    }
  }
}

Example workflows

List your accounts

Use list_accounts to show me all my Google Ads accounts

Query campaign performance

Run this GAQL query for customer ID 1234567890:
SELECT campaign.name, metrics.clicks, metrics.impressions, metrics.cost_micros
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
ORDER BY metrics.clicks DESC

Create a new campaign with ad group, keywords, and ad

Create a new search campaign called "Q1 Promo" with a $20/day budget,
then add an ad group "Product Keywords" with keywords like "buy widgets",
"widget sale", "best widgets", and create a responsive search ad with
these headlines: "Buy Widgets Now", "50% Off Widgets", "Free Shipping"
and descriptions: "Shop our huge selection of widgets. Free shipping on orders over $50.",
"Premium quality widgets at the best prices. Order today!"
Final URL: https://example.com/widgets

Add negative keywords

Add these negative keywords to campaign 19638300165:
- "free"
- "cheap"
- "diy"
- "tutorial"

Pause underperforming ad groups

First, show me all ad groups in campaign 19638300165 with their metrics.
Then pause any ad groups with CTR below 1%.

API reference

Budget and bid values

All monetary values use micros (1/1,000,000 of the currency unit):

  • 1,000,000 micros = $1.00

  • 2,500,000 micros = $2.50

  • 10,000,000 micros = $10.00

Match types

Keywords support three match types:

  • BROAD - Shows for related searches (default)

  • PHRASE - Shows when query contains the phrase

  • EXACT - Shows only for exact query match

Customer IDs

Customer IDs should be digits only, no dashes:

  • Correct: 1234567890

  • Incorrect: 123-456-7890

Development

# Clone the repo
git clone https://github.com/maxghenis/google-ads-mcp-rw
cd google-ads-mcp

# Install dev dependencies
uv pip install -e ".[dev]"

# Run tests
pytest

# Format code
black src tests
ruff check --fix src tests

License

MIT License - see LICENSE for details.

Contributing

Contributions welcome! Please open an issue or PR.

Available Tools

12 tools
add_keywordsA

Add keywords to an ad group.

Args: ad_group_id: Ad group ID to add keywords to keywords: List of keyword texts to add customer_id: Target customer ID (optional if set in config) match_type: Keyword match type - BROAD, PHRASE, or EXACT. BROAD matches related searches, PHRASE matches the phrase with words before/after, EXACT matches the exact query only. dry_run: If True, validate but don't execute

Returns: Result with success status and count of keywords added

Inputs: ad_group_id (required), keywords (required), customer_id, match_type, +1 more. Returns: object

add_negative_keywordsA

Add negative keywords to block irrelevant searches.

Negative keywords prevent your ads from showing for certain searches. Add them at campaign level to affect all ad groups, or at ad group level for more targeted exclusions.

Args: keywords: List of negative keyword texts customer_id: Target customer ID (optional if set in config) campaign_id: Campaign ID for campaign-level negatives ad_group_id: Ad group ID for ad group-level negatives match_type: Match type - BROAD, PHRASE, or EXACT dry_run: If True, validate but don't execute

Note: Provide EITHER campaign_id OR ad_group_id, not both.

Returns: Result with success status and count of negatives added

Inputs: keywords (required), customer_id, campaign_id, ad_group_id, +2 more. Returns: object

create_ad_groupA

Create an ad group in a campaign.

Args: campaign_id: Campaign ID to add the ad group to name: Ad group name customer_id: Target customer ID (optional if set in config) cpc_bid_micros: Default CPC bid in micros (1,000,000 = $1.00). Default is $2.00. dry_run: If True, validate but don't execute

Returns: Result with success status, resource_name, and ad_group_id

Inputs: campaign_id (required), name (required), customer_id, cpc_bid_micros, +1 more. Returns: object

create_campaignA

Create a new Google Ads campaign.

Creates a new campaign with the specified settings. For safety, campaigns are created in PAUSED status by default - use enable_campaign to start them.

Args: name: Campaign name customer_id: Target customer ID (optional if set in config) budget_amount_micros: Daily budget in micros (1,000,000 = $1.00). Default is $10/day. advertising_channel_type: Channel type - SEARCH, DISPLAY, SHOPPING, etc. dry_run: If True, validate but don't execute the operation

Returns: Result with success status, resource_name, and campaign_id

Inputs: name (required), customer_id, budget_amount_micros, advertising_channel_type, +1 more. Returns: object

create_responsive_search_adA

Create a responsive search ad (RSA).

RSAs dynamically combine headlines and descriptions to show the best performing combinations. Google recommends providing many variations for optimal performance.

Args: ad_group_id: Ad group ID to add the ad to headlines: List of headline variations (3-15 required). Each headline max 30 characters. descriptions: List of description variations (2-4 required). Each description max 90 characters. final_url: Landing page URL where users go after clicking customer_id: Target customer ID (optional if set in config) path1: Display URL path 1 (max 15 chars, e.g., "products") path2: Display URL path 2 (max 15 chars, e.g., "shoes") dry_run: If True, validate but don't execute

Returns: Result with success status, resource_name, and ad_id

Inputs: ad_group_id (required), headlines (required), descriptions (required), final_url (required), +4 more. Returns: object

enable_ad_groupB

Enable an ad group.

Args: ad_group_id: Ad group ID to enable customer_id: Target customer ID (optional if set in config) dry_run: If True, validate but don't execute

Returns: Result with success status

Inputs: ad_group_id (required), customer_id, dry_run. Returns: object

enable_campaignA

Enable a campaign.

Enabling starts ad serving. Make sure budget, targeting, and ads are properly configured before enabling.

Args: campaign_id: Campaign ID to enable customer_id: Target customer ID (optional if set in config) dry_run: If True, validate but don't execute

Returns: Result with success status

Inputs: campaign_id (required), customer_id, dry_run. Returns: object

execute_queryA

Execute a Google Ads Query Language (GAQL) query.

Use this for any read operation - campaigns, ad groups, keywords, ads, metrics, etc.

Common queries:

  • Campaigns: SELECT campaign.id, campaign.name FROM campaign

  • Ad groups: SELECT ad_group.id, ad_group.name FROM ad_group

  • Keywords: SELECT ad_group_criterion.keyword.text FROM ad_group_criterion

  • Metrics: SELECT campaign.name, metrics.clicks FROM campaign

Args: query: The GAQL query to execute customer_id: Target customer ID (optional if set in config). Use digits only, no dashes.

Returns: List of result rows as dictionaries

Inputs: query (required), customer_id. Returns: result

list_accountsA

List all Google Ads accounts accessible by this credential.

Returns a list of accounts with their customer IDs that you can use for subsequent operations.

Returns: List of account dictionaries with customer_id and resource_name

Inputs: no named parameters. Returns: result

pause_ad_groupB

Pause an ad group.

Args: ad_group_id: Ad group ID to pause customer_id: Target customer ID (optional if set in config) dry_run: If True, validate but don't execute

Returns: Result with success status

Inputs: ad_group_id (required), customer_id, dry_run. Returns: object

pause_campaignA

Pause a campaign.

Pausing stops ad serving but preserves all settings and history.

Args: campaign_id: Campaign ID to pause customer_id: Target customer ID (optional if set in config) dry_run: If True, validate but don't execute

Returns: Result with success status

Inputs: campaign_id (required), customer_id, dry_run. Returns: object

update_ad_group_bidA

Update the CPC bid for an ad group.

Args: ad_group_id: Ad group ID to update cpc_bid_micros: New CPC bid in micros (1,000,000 = $1.00) customer_id: Target customer ID (optional if set in config) dry_run: If True, validate but don't execute

Returns: Result with success status

Inputs: ad_group_id (required), cpc_bid_micros (required), customer_id, dry_run. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 12 tools

    Disambiguation5/5

    Each tool has a distinct purpose (adding keywords vs adding negatives, creating vs enabling vs pausing, etc.) with no overlapping functionality, so an agent can easily differentiate them.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern using snake_case (e.g., add_keywords, create_ad_group, pause_campaign), making the set predictable.

    Tool Count5/5

    12 tools is a well-scoped number for managing Google Ads campaigns, covering creation, state changes, and querying without being excessive or too sparse.

    Completeness2/5

    Missing crucial operations like updating campaign settings, deleting keywords or ads, and managing budgets beyond creation. The surface leaves agents with dead ends (e.g., no way to remove a mistakenly added keyword).

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      A
      maintenance
      MCP server that provides tools and resources for interacting with Google Ads API, enabling search, metadata retrieval, and account management through natural language.
      7
      5,144 PyPI
      1,165
      Apache 2.0
    • F
      license
      Not graded
      quality
      D
      maintenance
      A read-only MCP server for the Google Ads API, exposing reporting tools for account summaries, campaigns, performance, search terms, and conversion actions. Enables natural-language queries to Google Ads data without write access.
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for managing Google Ads campaigns through the official Google Ads API, covering accounts, campaigns, budgets, keywords, search terms, and keyword ideas. It provides tools for both reading and mutating live ads data, such as pausing campaigns, updating budgets, and adding keywords.
      MIT