Skip to main content
Glama
adeshsarwan

google-ads-function-gateway

by adeshsarwan

Google Ads Function Gateway

Standalone, deterministic Google Ads function gateway for Google Ads Function Catalogue v1 Phase A and Phase B functions 01-06.

The gateway includes a stdio MCP server adapter, but it is intentionally not an MCP conversational client. MCP clients should call approved function names with validated parameters; they must not supply raw GAQL or construct Google Ads API logic at runtime.

Architecture Rules

  • No arbitrary GAQL endpoint.

  • No GAQL supplied by users, CLI callers, or MCP clients.

  • No runtime AI-generated Google Ads API code.

  • Google Ads queries remain predefined and version-controlled.

  • All reporting customer IDs require explicit authorization.

  • No mutation/write operations.

  • The CLI and MCP server use the same catalogue and function classes as future HTTP, cron, dashboard, and automation consumers.

Related MCP server: Google Ads MCP

Local Setup

A. Clone Repository

git clone https://github.com/adeshsarwan/google-ads-mcp-client.git
cd google-ads-mcp-client

B. Create Virtual Environment

python3 -m venv .venv
source .venv/bin/activate

C. Install Dependencies

python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

This installs the official google-ads Python client, python-dotenv, and dev tooling including ruff.

D. Create Local Environment File

cp .env.example .env

Never commit .env. It is ignored by Git.

E. Configure Google Ads Credentials

Edit .env and set:

GOOGLE_ADS_DEVELOPER_TOKEN=replace-me
GOOGLE_ADS_CLIENT_ID=replace-me
GOOGLE_ADS_CLIENT_SECRET=replace-me
GOOGLE_ADS_REFRESH_TOKEN=replace-me

If you do not already have a refresh token, generate one locally:

python -m google_ads_function_gateway oauth-generate-refresh-token

The command reads GOOGLE_ADS_CLIENT_ID and GOOGLE_ADS_CLIENT_SECRET from .env, opens a local Google OAuth consent flow, and prints GOOGLE_ADS_REFRESH_TOKEN=... once. It does not write the token to disk.

This helper intentionally requests only the Google Ads scope and disables incremental authorization. That prevents unrelated scopes previously granted to the same Google Cloud project, such as Ad Manager, from being merged into this local Google Ads setup.

For Web Application OAuth clients, add the local loopback redirect URI in Google Cloud Console under Authorized redirect URIs. The default command uses:

http://127.0.0.1:8080/

If you run the helper with --port, add the matching http://127.0.0.1:<port>/ URI. At minimum, the redirect must use http://127.0.0.1; localhost is not the host used by this helper.

F. Configure Login MCC

GOOGLE_ADS_LOGIN_CUSTOMER_ID is the manager/MCC account used as the discovery root:

GOOGLE_ADS_LOGIN_CUSTOMER_ID=1234567890

The login customer ID is not the same as a reporting customer ID. It identifies the manager account context for Google Ads API access and account discovery.

G. Run Doctor

python -m google_ads_function_gateway doctor

Doctor prints readiness statuses and package/API version details without printing secrets.

H. Discover Accounts

python -m google_ads_function_gateway list-accounts

Discovery can list child accounts under the configured MCC even before those child accounts are in GOOGLE_ADS_ALLOWED_CUSTOMER_IDS. Discovery does not grant reporting authorization.

I. Authorize Selected Customer IDs

Choose customer IDs from discovery output and add them to the allow-list:

GOOGLE_ADS_ALLOWED_CUSTOMER_IDS=1112223333,4445556666

Reporting functions fail closed until the target customer ID is explicitly listed here.

J. Run Standardized Functions

python -m google_ads_function_gateway get-account-details \
  --customer-id 1112223333

python -m google_ads_function_gateway list-campaigns \
  --customer-id 1112223333

python -m google_ads_function_gateway get-campaign-details \
  --customer-id 1112223333 \
  --campaign-id 987654321

python -m google_ads_function_gateway get-campaign-cost \
  --customer-id 1112223333 \
  --start-date 2026-08-30 \
  --end-date 2026-08-30

python -m google_ads_function_gateway get-campaign-performance \
  --customer-id 1112223333 \
  --start-date 2026-08-30 \
  --end-date 2026-08-30

Each command prints the normalized JSON envelope returned by the catalogue.

MCP Transports

The MCP server exposes only the six existing read-only catalogue functions through both stdio and Streamable HTTP. Both transports use the same MCP server object, tool handlers, and Google Ads Function Catalogue. They do not add conversational routing, caller-supplied GAQL, direct HTTP Google Ads calls, or write operations.

Install the project into the local virtual environment first:

source .venv/bin/activate
python -m pip install -e ".[dev]"

Local Stdio Mode

Configure a local MCP client to launch the stdio server from the project root. The client configuration should contain only the executable, arguments, working directory if supported, and non-secret runtime options:

{
  "mcpServers": {
    "google-ads-function-gateway": {
      "command": "/absolute/path/to/google-ads-mcp-client/.venv/bin/python",
      "args": ["-m", "google_ads_function_gateway.mcp_server"],
      "cwd": "/absolute/path/to/google-ads-mcp-client"
    }
  }
}

Local Streamable HTTP Mode

Start the Streamable HTTP MCP endpoint locally:

GOOGLE_ADS_MCP_HOST=127.0.0.1 GOOGLE_ADS_MCP_PORT=8000 \
  python -m google_ads_function_gateway.mcp_server --transport streamable-http

Default endpoint:

http://127.0.0.1:8000/mcp

The server defaults to 127.0.0.1 for safety. Set GOOGLE_ADS_MCP_AUTH_TOKEN to require Authorization: Bearer ... on HTTP MCP requests before using any HTTPS reverse proxy or tunnel.

GOOGLE_ADS_MCP_AUTH_TOKEN=replace-with-a-long-random-token \
  python -m google_ads_function_gateway.mcp_server --transport streamable-http

Example local MCP protocol smoke test:

curl -i http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl-smoke","version":"0"}}}'

If bearer auth is enabled, add:

-H "Authorization: Bearer $GOOGLE_ADS_MCP_AUTH_TOKEN"

Secret Handling

Do not place GOOGLE_ADS_DEVELOPER_TOKEN, OAuth client secrets, refresh tokens, or any other Google Ads credentials in MCP client JSON or remote connector settings. The MCP server uses the same load_local_env() mechanism as the CLI and loads the ignored .env file from the project root.

Google Ads credentials stay server-side and are never provided to ChatGPT. If you expose the Streamable HTTP endpoint through a secure tunnel or HTTPS reverse proxy, ChatGPT connects only to the MCP protocol endpoint and, when configured, presents the MCP bearer token.

MCP stdio reserves stdout for JSON-RPC protocol messages. The MCP entrypoint does not print banners or debug output, and operational logging is configured for stderr.

Tunnel Compatibility

The Streamable HTTP server is designed to sit behind a standard HTTPS reverse proxy or secure tunnel. Keep the local server bound to 127.0.0.1, require GOOGLE_ADS_MCP_AUTH_TOKEN, expose the /mcp path over HTTPS, and ensure the proxy forwards request bodies and MCP headers unchanged. The application does not depend on a specific tunnel vendor.

Configuration

Supported environment variables:

  • GOOGLE_ADS_DEVELOPER_TOKEN

  • GOOGLE_ADS_CLIENT_ID

  • GOOGLE_ADS_CLIENT_SECRET

  • GOOGLE_ADS_REFRESH_TOKEN

  • GOOGLE_ADS_LOGIN_CUSTOMER_ID

  • GOOGLE_ADS_ALLOWED_CUSTOMER_IDS

  • GOOGLE_ADS_API_VERSION optional; when omitted, the gateway uses the highest API version packaged by google-ads-python

  • GOOGLE_ADS_RETRY_ATTEMPTS optional, default 3

  • GOOGLE_ADS_RUN_LIVE_TESTS optional; set to 1 only when intentionally running live read-only tests

  • GOOGLE_ADS_MCP_HOST optional Streamable HTTP bind host, default 127.0.0.1

  • GOOGLE_ADS_MCP_PORT optional Streamable HTTP bind port, default 8000

  • GOOGLE_ADS_MCP_AUTH_TOKEN optional bearer token for Streamable HTTP MCP requests

Development Checks

python -m compileall src tests
python -m unittest discover -s tests
ruff check .

Live Smoke Tests

Live tests are opt-in and read-only. They never run unless this flag is set:

GOOGLE_ADS_RUN_LIVE_TESTS=1 python -m unittest tests.integration.test_live_google_ads_smoke

The tests require valid credentials, a configured login MCC when using MCC discovery, and at least one explicitly allowed reporting customer ID.

F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides read-only access to Google Ads account data including campaigns, ad groups, keywords, and performance reports. Enables querying via GAQL through an MCP interface.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables reading and modifying Google Ads accounts, including campaign management, ad status changes, budget updates, and more.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables reading and mutating Google Ads campaigns via MCP tools, and includes structured marketer workflows for search term mining, budget optimization, and weekly reviews.
    83
    5
    MIT
  • F
    license
    Not graded
    quality
    C
    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.

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adeshsarwan/google-ads-mcp-client'

If you have feedback or need assistance with the MCP directory API, please join our Discord server