Skip to main content
Glama
UnopndJude

gam-mcp

by UnopndJude

gam-mcp

A security-first MCP server for Google Ad Manager — least-privilege by default, gated writes, and a path to per-user OAuth that existing GAM MCP servers don't offer.

(한국어 설명은 아래에 있습니다 / Korean version below.)


English

What this is

gam-mcp is a self-hosted Model Context Protocol server that lets an AI client (Claude Code, Claude Desktop, etc.) read and — with explicit confirmation — write Google Ad Manager data through the Ad Manager API (Beta) REST.

It is built for an enterprise posture where billions in ad spend are at stake: the service-account key and access tokens stay inside the server process and are never exposed to the model, reads and writes are separated by OAuth scope, and every mutation requires a deliberate two-step confirmation.

Why another GAM MCP server? (the gap)

Ad Manager MCP servers already exist, but they share one architectural choice that doesn't fit a security-sensitive, multi-user org:

Project

Auth model

Transport

Gap for enterprise use

MatiousCorp/google-ad-manager-mcp

Single shared service account (GAM_CREDENTIALS_PATH), HTTP bearer token

stdio + HTTP

One "master key" for the whole network; every action attributes to the service account, so per-user accountability is lost

OrbiAds/Orbiads-GAM-MCP

Vendor-hosted managed proxy

Hosted HTTP

Credentials are entrusted to a third-party vendor

googleads/google-ads-mcp (official)

Per-user OAuth, on-behalf-of

stdio + Cloud Run

For Google Ads (advertiser), not Google Ad Manager (publisher) — different product/API

In short: the per-user OAuth on-behalf-of pattern — where each call runs against the caller's own GAM permissions and stays fully auditable — exists for Google Ads but not for Google Ad Manager. Every off-the-shelf GAM MCP server is a shared-service-account ("master key") design.

gam-mcp fills that gap. It starts as a least-privilege single-user server and is deliberately structured (transport- and auth-agnostic) to grow into per-user OAuth on-behalf-of for central deployment — the model the existing GAM servers don't provide.

Security model

Layer

Control

Where

1

Least-privilege token — the read-only OAuth scope (admanager.readonly) is requested when GAM_READ_ONLY=true, so a bug can't mutate GAM at Google's side.

src/gam/client.ts

2

Read-only kill-switch — write tools aren't even registered.

src/index.ts

3

Network allowlist — every tool re-checks the network code against GAM_NETWORK_ALLOWLIST.

src/config.ts

4

Propose → confirm gatepropose_* returns a short-lived, single-use token plus a before/after preview; nothing mutates until confirm_write.

src/security.ts

5

Append-only audit log — every call is recorded with redacted args before the result returns.

src/audit.ts

The service-account key and access tokens live in this process only and are never placed in a tool result. Claude Code's own permission prompt gates each tool call as a separate, outer layer.

Authentication modes

The client is auth-agnostic (AuthStrategy), so the same tools work under any of:

  • service_account — one shared identity. Simplest for a local, single-operator setup. This is the "master key" model every off-the-shelf GAM MCP server uses.

  • user_oauthper-user identity. Each operator runs npm run login once to authorize with their own Google account; the server then calls GAM as that user, so their own GAM role bounds every action and the audit trail attributes to a real person. Works over stdio today. Only a refresh token (never an access token) is cached, at GAM_TOKEN_STORE.

  • OBO (roadmap) — central multi-tenant on-behalf-of, where an incoming authenticated user maps to their stored per-user credential. Requires the HTTP transport; the AuthStrategy interface is the drop-in point.

Set the mode with GAM_AUTH_MODE. For user_oauth:

GAM_AUTH_MODE=user_oauth
GAM_OAUTH_CLIENT_ID=xxxx.apps.googleusercontent.com
GAM_OAUTH_CLIENT_SECRET=xxxx
npm run build && npm run login   # opens a browser, caches the refresh token

Tools

Read (always on): get_network, list_orders, get_order, list_line_items, get_line_item, run_report.

Write (only when GAM_READ_ONLY=false): propose_update_line_itemconfirm_write.

Prerequisites (one-time, in the GAM + GCP consoles)

Shared, both modes:

  1. Enable the API — GAM → Admin → Global settings → Network settings → turn on API access. Note your network code (the number in admanager.google.com/<code>#home).

  2. GCP project — enable the Google Ad Manager API.

Then, depending on GAM_AUTH_MODE:

  • service_account — create a service account, download a JSON key (never commit it), and add the service-account email as a GAM user with a least-privilege role (start read-only).

  • user_oauth — create an OAuth 2.0 Client ID (type: Desktop app) and configure the consent screen. No key file and no extra GAM user needed — each operator just has to already be a GAM user. Run npm run login to authorize.

Install

npm install
cp .env.example .env      # fill in credentials path + network code(s)
npm run build

Configure (.env)

GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.key.json
GAM_NETWORK_ALLOWLIST=1234567
GAM_READ_ONLY=true        # flip to false only after validating reads

Register with Claude Code / Claude Desktop

{
  "mcpServers": {
    "gam": {
      "command": "node",
      "args": ["/absolute/path/to/gam-mcp/dist/index.js"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/service-account.key.json",
        "GAM_NETWORK_ALLOWLIST": "1234567",
        "GAM_READ_ONLY": "true"
      }
    }
  }
}

API surface & gaps

Uses the Ad Manager API (Beta) REST (https://admanager.googleapis.com/v1). Not every mutating operation exists in Beta yet — some remain SOAP-only. Where a write endpoint isn't live, confirm_write surfaces the GAM error verbatim; a SOAP fallback is future work.

Roadmap

  • Per-user OAuth identity for local/stdio (GAM_AUTH_MODE=user_oauth)

  • Central multi-tenant on-behalf-of (needs HTTP transport + IdP)

  • Streamable HTTP transport

  • SOAP fallback for operations not yet in Beta REST

  • Rate limiting and budget/impression caps on writes


Related MCP server: Google MCP Server

한국어

개요

gam-mcp는 AI 클라이언트(Claude Code, Claude Desktop 등)가 Ad Manager API (Beta) REST를 통해 Google Ad Manager 데이터를 읽고, 명시적 확인을 거쳐 쓰도록 해주는 self-hosted MCP 서버입니다.

수십억 규모의 광고 집행을 다루는 보안 민감 환경을 전제로 설계했습니다 — 서비스 계정 키와 액세스 토큰은 서버 프로세스 안에만 존재하며 모델에 노출되지 않고, 읽기/쓰기는 OAuth scope로 분리되며, 모든 변경은 2단계 확인을 거쳐야 합니다.

왜 또 다른 GAM MCP 서버인가? (채우는 공백)

Ad Manager용 MCP 서버는 이미 있지만, 전부 보안 민감·다중 사용자 조직에 맞지 않는 하나의 설계를 공유합니다:

프로젝트

인증 모델

전송

엔터프라이즈 관점의 공백

MatiousCorp/google-ad-manager-mcp

단일 공유 서비스 계정 + HTTP bearer

stdio + HTTP

네트워크 전체가 하나의 "마스터 키" → 모든 액션이 서비스 계정에 귀속되어 사용자별 추적성 상실

OrbiAds/Orbiads-GAM-MCP

벤더 호스팅 관리형 프록시

호스티드 HTTP

자격증명을 외부 벤더에 위탁

googleads/google-ads-mcp (공식)

per-user OAuth, on-behalf-of

stdio + Cloud Run

Google Ads(광고주) 용, Ad Manager(퍼블리셔) 아님 — 다른 제품/API

요약하면, 각 호출이 호출자 본인의 GAM 권한으로 실행되고 완전히 감사 가능한 per-user OAuth on-behalf-of 패턴은 Google Ads에는 있지만 Google Ad Manager에는 없습니다. 기성 GAM MCP 서버는 전부 공유 서비스 계정("마스터 키") 방식입니다.

gam-mcp가 그 공백을 메웁니다. 최소 권한 단일 사용자 서버로 시작하되, 중앙 배포용 per-user OAuth on-behalf-of로 확장할 수 있도록 transport·auth-agnostic하게 설계했습니다 — 기존 GAM 서버가 제공하지 않는 모델입니다.

보안 모델

계층

통제

위치

1

최소 권한 토큰GAM_READ_ONLY=true면 읽기 전용 scope(admanager.readonly)만 발급 → 버그가 있어도 Google 쪽에서 변경 불가

src/gam/client.ts

2

읽기 전용 kill-switch — 쓰기 도구를 아예 등록하지 않음

src/index.ts

3

네트워크 allowlist — 모든 도구가 네트워크 코드를 재검증

src/config.ts

4

propose → confirm 게이트propose_*는 단회성·만료 토큰 + before/after 미리보기만 반환, confirm_write 전엔 변경 없음

src/security.ts

5

append-only 감사 로그 — 모든 호출을 redaction 후 기록

src/audit.ts

키·토큰은 서버 프로세스에만 존재하고 도구 결과에 절대 담기지 않습니다. Claude Code 자체 permission 프롬프트가 별도의 바깥 계층으로 각 호출을 게이트합니다.

인증 모드

클라이언트가 auth-agnostic(AuthStrategy)이라 아래 어느 방식이든 같은 도구가 동작합니다:

  • service_account — 단일 공유 신원. 로컬 단일 운영자에게 가장 단순. 기성 GAM MCP가 모두 쓰는 "마스터 키" 모델.

  • user_oauth사용자별 신원. 각 운영자가 npm run login으로 자기 Google 계정을 1회 인증하면, 서버가 그 사용자로서 GAM을 호출 → 본인의 GAM role이 모든 액션의 한도가 되고 감사 로그가 실제 사람에게 귀속됩니다. 지금 stdio에서 동작하며, refresh token만(액세스 토큰은 절대 저장 안 함) GAM_TOKEN_STORE에 캐시됩니다.

  • OBO (로드맵) — 중앙 멀티테넌트 on-behalf-of. 인증된 사용자를 그의 저장된 자격증명에 매핑. HTTP transport 필요하며, AuthStrategy 인터페이스가 그 확장 지점입니다.

GAM_AUTH_MODE로 선택. user_oauth 예:

GAM_AUTH_MODE=user_oauth
GAM_OAUTH_CLIENT_ID=xxxx.apps.googleusercontent.com
GAM_OAUTH_CLIENT_SECRET=xxxx
npm run build && npm run login   # 브라우저 인증 → refresh token 캐시

도구

읽기(상시): get_network, list_orders, get_order, list_line_items, get_line_item, run_report.

쓰기(GAM_READ_ONLY=false일 때만): propose_update_line_itemconfirm_write.

사전 준비 (GAM + GCP 콘솔, 1회)

공통 (두 모드 모두):

  1. API 활성화 — GAM → Admin → Global settings → Network settings → API access 켜기. 네트워크 코드(admanager.google.com/<코드>#home의 숫자) 확인.

  2. GCP 프로젝트Google Ad Manager API 활성화.

그다음 GAM_AUTH_MODE에 따라:

  • service_account — 서비스 계정 생성 → JSON 키 다운로드(커밋 금지) → 서비스 계정 이메일을 GAM 사용자로 추가하고 최소 권한 role 부여(읽기 전용으로 시작).

  • user_oauthOAuth 2.0 Client ID(유형: 데스크톱 앱) 생성 + consent 화면 설정. 키 파일·추가 GAM 사용자 불필요 — 각 운영자가 이미 GAM 사용자이기만 하면 됨. npm run login으로 인증.

설치 · 설정 · 등록

위 English 섹션의 명령/설정과 동일합니다.

API 범위와 한계

Ad Manager API (Beta) REST(https://admanager.googleapis.com/v1)를 사용합니다. 일부 변경 작업은 아직 Beta에 없고 SOAP 전용입니다. REST 엔드포인트가 없는 경우 confirm_write가 GAM 오류를 그대로 전달하며, SOAP 폴백은 향후 과제입니다.


License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
    91
    264
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A unified MCP server that gives AI assistants direct access to Google Analytics 4, Google Search Console, Google Ads and Google Merchant Center data using OAuth2 user credentials.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables authorized users to securely connect to and manage their Google Ads accounts through MCP clients, with support for campaigns, ad groups, ads, keywords, reporting, and billing. Runs as a remote multi-user server on Cloudflare Workers with per-user authentication and safety controls.
    -
  • A
    license
    A
    quality
    B
    maintenance
    An MCP server that extends the official Google Ads MCP with safe, confirmed campaign administration across manager accounts, featuring immutable mutation plans, multi-step approvals, and post-write verification.
    8
    Apache 2.0