Written guide · Google Ads and AI

Build a small read-only Google Ads MCP

Connect one approved account, read its identity and verify the result before adding reporting tools.

This is an educational server with one tool. It does not include campaign editing, a hosted service or the full paid bundle.

1 · Check what you need

Use a local AI host that supports stdio MCP servers, a Python environment and a Google Ads account you are authorised to access. Keep credentials outside the website, chat and source repository. The website bundle has been checked on macOS with Python 3.14; other environments require their own check.

2 · Prepare Google Ads authentication

Obtain a developer token with access appropriate to your account. For this user-OAuth example, follow Google’s Python authentication guide to create the client credentials and refresh token. Store them in your private google-ads.yaml. Include login_customer_id when using the relevant manager-account context; the account you query is a separate customer ID.

Google authentication instructions · Developer token requirements

3 · Create an isolated environment

python3 -m venv .venv
.venv/bin/python -m pip install 'google-ads==31.0.0' 'mcp>=1.2,<2'

These commands use a POSIX shell. Save the following file as server.py. The Google Ads library version is pinned; record the resolved MCP version when you test your environment.

import os
from google.ads.googleads.client import GoogleAdsClient
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("google-ads-readonly")

@mcp.tool()
def account_summary() -> dict:
    """Read metadata for the single account configured by the owner."""
    customer_id = os.environ["GOOGLE_ADS_CUSTOMER_ID"]
    if not customer_id.isdigit():
        raise ValueError("Use the customer ID without hyphens")
    client = GoogleAdsClient.load_from_storage(os.environ["GOOGLE_ADS_CONFIG"])
    service = client.get_service("GoogleAdsService")
    response = service.search(customer_id=customer_id, query="""
        SELECT customer.id, customer.currency_code, customer.time_zone
        FROM customer LIMIT 1
    """)
    row = next(iter(response), None)
    if row is None:
        return {"found": False}
    return {"customer_id": str(row.customer.id),
            "currency": row.customer.currency_code,
            "time_zone": row.customer.time_zone}

if __name__ == "__main__":
    mcp.run(transport="stdio")

4 · Add the local server to your host

In your host’s local MCP configuration, use the absolute path to .venv/bin/python as the command and the absolute path to server.py as its argument. Set GOOGLE_ADS_CONFIG to your private YAML path and GOOGLE_ADS_CUSTOMER_ID to the permitted account ID without hyphens. Use the host’s supported configuration format; a local stdio process cannot be pasted into a remote-server URL field.

MCP Python SDK v1 reference

5 · Verify one read before adding more

Ask your assistant to call account_summary. Compare customer ID, currency and time zone with the native Google Ads account. Stop if the identity is wrong. This example exposes no mutation or arbitrary-query tool, but the underlying credentials still retain their Google permissions.

The code is an educational example. Offline checks do not prove your OAuth setup, token access or host configuration. If authentication fails, check token access, user permission, manager context and your host log without sharing secrets.

6 · Add reporting with a clear contract

Start with a fixed read-only report, a completed date range and explicit fields. Name the currency, account time zone and conversion definition. Reconcile totals with Google Ads before drawing a conclusion. Do not let model-generated text become an unrestricted query or campaign mutation.

Choose your next step

Try the reporting worksheet, inspect the complete bundle, or discuss installation for your environment.