A read-only Model Context Protocol (MCP) server for Google Ads (via GAQL), Search Console, and Google Analytics 4. Designed for AI assistants and LLM agents to safely read campaign performance, search analytics, website traffic, and more.
| Tool | Input | Description |
|---|---|---|
list_accessible_customers |
— | Discover Google Ads account IDs |
get_resource_metadata |
resource_name |
Explore selectable/filterable/sortable fields for a resource |
search |
customer_id, resource, fields, conditions?, orderings?, limit? |
Execute read-only GAQL queries |
| Tool | Input | Description |
|---|---|---|
gsc_get_capabilities |
— | Get categorized tool list with auth status |
gsc_list_properties |
— | List all GSC properties (start here) |
gsc_get_site_details |
site_url |
Verification/ownership for a property |
gsc_get_search_analytics |
site_url, days?, dimensions?, row_limit? |
Top queries with clicks, impressions, CTR, position |
gsc_get_performance_overview |
site_url, days? |
Executive summary with daily trend |
gsc_compare_search_periods |
site_url, period1_start/end, period2_start/end |
Compare two date ranges |
gsc_get_advanced_search_analytics |
site_url, start_date?, end_date?, dimensions?, search_type?, row_limit?, start_row?, sort_by?, sort_direction?, filters? |
Filtered, sorted, paginated analytics |
gsc_inspect_url |
site_url, page_url |
Debug a URL's crawl/index status |
gsc_get_sitemaps |
site_url |
List sitemaps with status and errors |
| Tool | Input | Description |
|---|---|---|
ga4_get_capabilities |
— | Get categorized tool list with auth status |
ga4_list_properties |
— | Discover all accessible GA4 properties |
ga4_get_metadata |
property_id |
Browse available dimensions and metrics |
ga4_run_report |
property_id, dimensions?, metrics?, start_date?, end_date?, filters?, order_bys?, limit? |
Run a standard report with filtering and ordering |
ga4_run_realtime_report |
property_id, dimensions?, metrics?, limit? |
Get real-time data (last 30 minutes) |
If search targets a manager (MCC) account and finds no data directly, it automatically:
- Detects the account is a manager
- Finds child accounts
- Runs the query on each child
- Returns combined results with
_source_customer_idmarking which account each row belongs to
- A Google Ads developer token (apply via Google Ads API Center)
- Google Cloud service account with the following APIs enabled:
git clone https://github.com/ceotind/open-google-mcp.git
cd open-google-mcpA single service account authenticates Google Ads, Search Console, and Google Analytics 4.
- Go to GCP Console → APIs & Services → Credentials → Create Credentials → Service Account
- Download the JSON key file, then copy these fields into
.env:GOOGLE_SERVICE_ACCOUNT_EMAILGOOGLE_SERVICE_ACCOUNT_KEY(theprivate_key— keep the\nescapes)GOOGLE_SERVICE_ACCOUNT_KEY_IDGOOGLE_SERVICE_ACCOUNT_CLIENT_IDGOOGLE_SERVICE_ACCOUNT_PROJECT_ID
- Google Ads: add the service account email in your manager account (Settings → Account access → Service account users)
- Search Console: add the same email to your property (Settings → Users and permissions → Add user, grant Full access)
- Google Analytics 4: add the same email to your GA4 property (Admin → Account Access Management → Add user → Viewer)
cp .env.example .env
# Edit .env with the service account values + developer token| Variable | Description |
|---|---|
GOOGLE_ADS_DEVELOPER_TOKEN |
Your Google Ads API developer token |
GOOGLE_SERVICE_ACCOUNT_EMAIL |
Service account email |
GOOGLE_SERVICE_ACCOUNT_KEY |
Private key (with \n newlines) |
GOOGLE_SERVICE_ACCOUNT_KEY_ID |
Private key ID |
GOOGLE_SERVICE_ACCOUNT_CLIENT_ID |
Client ID |
GOOGLE_SERVICE_ACCOUNT_PROJECT_ID |
GCP project ID |
GOOGLE_ADS_LOGIN_CUSTOMER_ID |
Optional — for MCC account routing |
GA4_CREDENTIALS_PATH |
Optional — dedicated GA4 credential file |
docker compose build
docker compose run --rm open-google-mcpClaude Desktop:
{
"mcpServers": {
"open-google-mcp": {
"command": "docker",
"args": ["compose", "run", "--rm", "open-google-mcp"],
"workdir": "/path/to/open-google-mcp"
}
}
}opencode:
{
"mcp": {
"open-google-mcp": {
"type": "local",
"command": ["docker", "compose", "run", "--rm", "open-google-mcp"],
"workdir": "/path/to/open-google-mcp",
"enabled": true
}
}
}Cursor:
- Name:
open-google-mcp - Type:
command - Command:
docker compose run --rm open-google-mcp - Working directory:
/path/to/open-google-mcp
git clone https://github.com/ceotind/open-google-mcp.git
cd open-google-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e .Same steps as Option A above — a single service account works for Ads, GSC, and GA4.
- Go to GCP Console → APIs & Services → Credentials → Create Credentials → Service Account
- Download the JSON key file, then copy these fields into
.env:GOOGLE_SERVICE_ACCOUNT_EMAILGOOGLE_SERVICE_ACCOUNT_KEYGOOGLE_SERVICE_ACCOUNT_KEY_IDGOOGLE_SERVICE_ACCOUNT_CLIENT_IDGOOGLE_SERVICE_ACCOUNT_PROJECT_ID
- Google Ads: add the service account email in your manager account
- Search Console: add the same email to your property with Full access
- Google Analytics 4: add the same email to your GA4 property with Viewer access
cp .env.example .env| Variable | Description |
|---|---|
GOOGLE_ADS_DEVELOPER_TOKEN |
Your Google Ads API developer token |
GOOGLE_SERVICE_ACCOUNT_EMAIL |
Service account email |
GOOGLE_SERVICE_ACCOUNT_KEY |
Private key (with \n newlines) |
GOOGLE_SERVICE_ACCOUNT_KEY_ID |
Private key ID |
GOOGLE_SERVICE_ACCOUNT_CLIENT_ID |
Client ID |
GOOGLE_SERVICE_ACCOUNT_PROJECT_ID |
GCP project ID |
GOOGLE_ADS_LOGIN_CUSTOMER_ID |
Optional — for MCC account routing |
GA4_CREDENTIALS_PATH |
Optional — dedicated GA4 credential file |
source .venv/bin/activate
source .env
python -m open_google_mcpOr use the wrapper script (loads .env automatically):
./server.shClaude Desktop:
{
"mcpServers": {
"open-google-mcp": {
"command": "/path/to/open-google-mcp/server.sh"
}
}
}opencode:
{
"mcp": {
"open-google-mcp": {
"type": "local",
"command": ["/path/to/open-google-mcp/server.sh"],
"enabled": true
}
}
}Cursor:
- Name:
open-google-mcp - Type:
command - Command:
/path/to/open-google-mcp/server.sh
list_accessible_customers
get_resource_metadata(resource_name="campaign")
search(
customer_id="1234567890",
resource="campaign",
fields=["campaign.id", "campaign.name", "campaign.status",
"campaign.advertising_channel_type", "metrics.clicks",
"metrics.impressions", "metrics.cost_micros"],
conditions=["campaign.status = 'ENABLED'",
"segments.date DURING LAST_30_DAYS"],
orderings=["metrics.clicks DESC"],
limit=10
)
search(
customer_id="1234567890",
resource="customer_client",
fields=["customer_client.id", "customer_client.descriptive_name", "customer_client.manager"]
)
gsc_list_properties
gsc_get_search_analytics(
site_url="https://example.com",
days=28,
dimensions="query",
row_limit=10
)
gsc_get_performance_overview(
site_url="https://example.com",
days=28
)
gsc_compare_search_periods(
site_url="https://example.com",
period1_start="2025-01-01",
period1_end="2025-01-31",
period2_start="2025-02-01",
period2_end="2025-02-28",
dimensions="query",
limit=10
)
gsc_get_advanced_search_analytics(
site_url="https://example.com",
dimensions="query,device",
search_type="WEB",
row_limit=50,
sort_by="impressions",
sort_direction="descending",
filters='[{"dimension":"country","operator":"equals","expression":"usa"}]'
)
gsc_inspect_url(
site_url="https://example.com",
page_url="https://example.com/blog/post"
)
gsc_get_sitemaps(site_url="https://example.com")
ga4_list_properties
Returns your property ID (e.g. 123456789) — use it in all other GA4 tools.
ga4_get_metadata(property_id="123456789")
Returns 300+ dimensions and 100+ metrics available for reporting.
ga4_run_report(
property_id="123456789",
metrics="activeUsers,sessions,newUsers",
start_date="28daysAgo",
end_date="today"
)
ga4_run_report(
property_id="123456789",
dimensions="country",
metrics="activeUsers",
start_date="28daysAgo",
end_date="today",
limit=10,
order_bys=[{"metric": "activeUsers", "desc": true}]
)
ga4_run_report(
property_id="123456789",
dimensions="pagePath",
metrics="screenPageViews,activeUsers",
start_date="28daysAgo",
end_date="today",
limit=10,
order_bys=[{"metric": "screenPageViews", "desc": true}]
)
ga4_run_report(
property_id="123456789",
dimensions="sessionDefaultChannelGrouping",
metrics="activeUsers,sessions",
start_date="28daysAgo",
end_date="today",
limit=10,
order_bys=[{"metric": "activeUsers", "desc": true}]
)
ga4_run_report(
property_id="123456789",
dimensions="city",
metrics="activeUsers",
start_date="28daysAgo",
end_date="today",
filters={"field": "country", "type": "string_filter",
"value": "Ireland", "match_type": "EXACT"},
limit=10
)
ga4_run_report(
property_id="123456789",
dimensions="deviceCategory",
metrics="activeUsers,sessions",
start_date="28daysAgo",
end_date="today"
)
ga4_run_realtime_report(
property_id="123456789",
dimensions="country,deviceCategory",
metrics="activeUsers",
limit=10
)
You can use relative or absolute dates:
- Relative:
today,yesterday,7daysAgo,28daysAgo,30daysAgo - Absolute:
2026-01-01(YYYY-MM-DD format)
- Field names must be fully qualified:
campaign.id, notid - Date format:
YYYY-MM-DDwith dashes - Relative dates:
DURING LAST_7_DAYS,LAST_30_DAYS,THIS_MONTH,THIS_QUARTER - For
change_eventresource, limit must be ≤ 10000 - Conditions are AND-combined
- Use
get_resource_metadatafirst to discover valid fields
MIT