ga4-seo-mcp
One-line summary: An MCP server that gives AI agents read access to Google Analytics 4, Search Console and PageSpeed Insights — and, with writes enabled, can set up a site's measurement end to end.
GA4 admin (read): list accounts and properties, get property settings, list data streams (incl. measurement IDs), key events, custom dimensions and Google Ads links.
GA4 reporting: flexible
run_report(any metrics/dimensions/date range), realtime reports, top pages, event counts, traffic sources, conversion summaries, GA4-sourced web vitals, and a multi-property portfolio audit.Search Console: list sites, top queries (with country filter), page performance, per-page query breakdown, and sitemap status.
PageSpeed Insights: full audits (Lighthouse lab + CrUX field data, mobile/desktop, selectable categories) or CrUX field data only.
Site setup planning:
bootstrap_site_measurementdetects what already exists (property, web stream, key events, dimensions, GSC property) and returns a plan; withapply=Trueand--enable-writesit creates only the missing pieces, idempotently.Guarded writes: write tools (create/update/delete, DNS verification, sitemap submission) are not registered at all unless
--enable-writesis set; all tools carry read-only/destructive/idempotent annotations.Optional toolsets: keyword research via DataForSEO or Google Ads Keyword Planner, plus guided prompts (site launch, SEO 360 audit, setup audit, portfolio digest).
Flexible deployment: stdio, streamable HTTP or SSE, with bearer-token auth, CORS/host controls and Docker support.
Provides tools for Google Ads Keyword Planner keyword research, including keyword ideas and bucketed search volume data.
Provides tools for Google Analytics 4, including Admin API management (accounts, properties, streams, key events, custom dimensions, Ads links) and Data API reporting (reports, realtime, top pages, events, traffic sources), plus a bootstrap_site_measurement flow to plan and apply site measurement setup.
Provides tools for PageSpeed Insights audits, including Lighthouse lab data and CrUX field data for performance and Core Web Vitals analysis.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ga4-seo-mcp Plan GA4 and Search Console setup for example.com, read-only for now."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
English · Español
ga4-seo-mcp — site measurement for AI agents, end to end
Get a site's measurement ready end to end: GA4 + Search Console + PageSpeed, with optional, guarded writes. An open source Model Context Protocol server for Google Analytics 4 & Search Console. Most MCP servers for Google read your data; this one can also set it up: property, web stream, key events, custom dimensions, Search Console DNS verification, sitemap and a PageSpeed baseline — read-only until you say otherwise.
Tags: mcp-server · ga4 · google-analytics · search-console · seo · pagespeed · core-web-vitals · keyword-research · claude-code · cursor
💡 Why this one?
Launching a site means the same chores every time: create the GA4 property and its web stream, mark the key events, register custom dimensions, add the domain to Search Console, publish a DNS TXT record, verify it, submit the sitemap, and record a PageSpeed baseline. ga4-seo-mcp turns that into one plan your agent shows you, and one confirmation.
ga4-seo-mcp | ||||
GA4 reports (Data API) | ✅ | ✅ | ✅ | ✅ |
Search Console | ✅ | — | ✅ (+ Bing) | ✅ |
PageSpeed Insights / CrUX | ✅ | — | ✅ | ✅ |
Create GA4 property + web stream | ✅ | — | — | — |
Create key events / custom dimensions | ✅ | — | — | ✅ |
Search Console DNS verification | ✅ | — | — | — |
One-call site plan → apply (idempotent) | ✅ | — | — | — |
Read-only by default | ✅ write tools are not even registered | read-only only | see its docs | ✅ read-only mode |
Toolsets | ✅ | — | — | ✅ |
Language | Python | Python | TypeScript | TypeScript |
Based on each project's README on 2026-10-19; "—" means we did not find it documented. Corrections welcome. Those projects go wider than this one (Bing, AdSense, WordPress, GEO audits…); this one goes deeper on setting up measurement.
Related MCP server: google-seo-mcp
🤝 Need this done for you?
This server is built and maintained by Germani Uicab. If you'd rather not run it yourself, ServerStack Solutions can get your GA4 + Search Console measurement ready: a written plan, property and key events configured, the DNS verification and sitemap in place, and a PageSpeed baseline — with a QA pass before handover.
Extras: optional keyword research with DataForSEO (exact long-tail volumes) and Google Ads Keyword Planner (free, bucketed volumes), with es-MX defaults that you can override.
⚡ Quick start
1. Install uv 0.13.4 or newer — the client launches the server with uvx; nothing else to install.
2. Log in with the minimum scopes. The CLI prints the exact gcloud command for the toolsets you enable:
uvx ga4-seo-mcp auth-command --client-id-file=oauth-client.json
# gcloud auth application-default login --client-id-file=oauth-client.json --scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/webmasters.readonlyRun the printed command. Google blocks Analytics and Search Console scopes on gcloud's built-in OAuth client, so you need your own (a one-time, few-minute setup) or a service account — both are explained in docs/AUTH.md.
3. Check everything before connecting a client (read-only, changes nothing):
uvx ga4-seo-mcp doctor
# [ok] credentials found: Credentials via Application Default Credentials
# [ok] access token refreshed
# [ok] token has the 2 scope(s) these toolsets need
# [ok] admin: <n> account(s) visible on the first page
# [ok] data: responded (<n> metrics in the schema)
# [ok] gsc: <n> site(s) visible
# [ok] psi: no Google login needed; PAGESPEED_API_KEY set
# all checks passed4. Add it to your client (Claude Code shown; others below):
claude mcp add ga4-seo -- uvx ga4-seo-mcpAsk: "List my GA4 properties and show last week's sessions for the first one."
🧰 Toolsets, scopes and tools
Enable only what you need with --toolsets (or GA4SEO_TOOLSETS). Default: admin,data,gsc,psi. Only the tools of active toolsets are registered, and the OAuth scopes follow.
Toolset | What | Scopes (read-only) | Extra scopes with | Tools (read + write) |
| GA4 Admin API: accounts, properties, streams, key events, custom dimensions, Ads links, |
|
| 9 + 10 |
| GA4 Data API: reports, realtime, top pages, events, traffic sources, portfolio |
| — | 8 + 0 |
| Search Console: queries, pages, sitemaps, domain add + DNS verification |
|
| 5 + 3 |
| PageSpeed Insights: Lighthouse lab + CrUX field data | none ( | — | 2 + 0 |
| DataForSEO keyword ideas and exact volumes (paid) | none ( | — | 2 + 0 |
| Google Ads Keyword Planner (needs |
| — | 2 + 0 |
Tool counts from the real registry: 24 with the defaults, 37 with --enable-writes, 8 with --toolsets data, 41 with every toolset and writes. The full list with descriptions is in docs/TOOLS.md (generated from the registry and checked in CI).
Prompts: audit_ga4_setup, seo_360_audit, portfolio_performance_digest and launch_site_measurement (the guided flow: plan → your confirmation → apply → DNS verification → sitemap → PageSpeed baseline).
bootstrap_site_measurement
bootstrap_site_measurement(site_url="https://example.com", account_id="123456789",
property_display_name="Example", time_zone="America/Mexico_City",
currency_code="USD", key_events=["generate_lead"],
custom_dimensions=[{"parameter_name": "plan_type", "display_name": "Plan type"}])apply=False(default): a plan. Read-only and always registered. It finds the existing property and web stream by the site's domain, the key events and custom dimensions already declared, and the Search Console domain property, and lists what would be created.apply=True: executes the plan. Only works when the server runs with--enable-writes; otherwise it fails before touching anything. Idempotent: it skips what exists, so you can re-run it. Returns a step-by-step report with the measurement ID (G-…) and the DNS TXT token.DNS verification (
sc_verify_site_dns) and the sitemap (sc_submit_sitemap) stay explicit follow-up steps: you have to publish the TXT record first.
🔒 Security model
Defaults are safe for a single user on a laptop. Details and threat model: SECURITY.md.
Read-only by default. Without
--enable-writes(orGA4SEO_ENABLE_WRITES=1), tools that create, update, delete, submit or verify are not registered at all — the model cannot call what does not exist.MCP annotations on every tool:
readOnlyHinton reads,destructiveHinton deletes and updates,idempotentHintwhere repeating is harmless,openWorldHinteverywhere. Clients that honor them can auto-approve reads and ask before writes.Minimum scopes: each Google client requests only the scope of the call it makes;
auth-commandasks only for the scopes of your toolsets.HTTP transport (
--transport streamable-http): binds to127.0.0.1, DNS-rebinding protection on, CORS off unlessMCP_CORS_ORIGINS, and an optional bearer tokenMCP_AUTH_TOKEN(401 without it). Listening on0.0.0.0without a token prints a warning, and LAN clients needMCP_ALLOWED_HOSTSor the rebinding protection answers421.Secrets (DataForSEO, Ads developer token, PageSpeed key) come only from environment variables or a
chmod 600file, and are never logged or returned in errors.
⚙️ Configuration
Variable | Default | Description |
| — | Service account key file. Unset = Application Default Credentials from |
|
| Same as |
|
|
|
| — | Recommended: the anonymous PageSpeed quota is shared and often exhausted (429). |
| — |
|
| — |
|
| — | Only when operating through a manager (MCC) account. |
|
|
|
|
| HTTP bind address and port. A specific non-loopback address is added to the allowed |
| — | Require |
| — | Comma-separated exact origins for a browser client. Never |
| — | Comma-separated host/IP values clients use (e.g. |
Copy .env.example as a starting point.
🔌 Connect your client
Every client launches the server over stdio. Add --enable-writes to args only for the session where you actually want to set up a site.
Claude Code
claude mcp add ga4-seo -- uvx ga4-seo-mcp
# with options:
claude mcp add ga4-seo -e PAGESPEED_API_KEY=your-key -- uvx ga4-seo-mcp --toolsets admin,data,gsc,psiClaude Desktop (claude_desktop_config.json) and Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"ga4-seo": {
"command": "uvx",
"args": ["ga4-seo-mcp"],
"env": { "PAGESPEED_API_KEY": "your-key" }
}
}
}VS Code (.vscode/mcp.json)
{
"servers": {
"ga4-seo": {
"type": "stdio",
"command": "uvx",
"args": ["ga4-seo-mcp"]
}
}
}Docker (stdio). Mount your credentials file read-only — the ADC file from gcloud or a service account key — and run as your own user so the container can read a 0600 file:
docker run -i --rm --user "$(id -u):$(id -g)" \
-v ~/.config/gcloud/application_default_credentials.json:/creds/credentials.json:ro \
-e GOOGLE_APPLICATION_CREDENTIALS=/creds/credentials.json \
ghcr.io/germaniu/ga4-seo-mcpHTTP (several clients sharing one server):
MCP_AUTH_TOKEN=$(openssl rand -hex 32) uvx ga4-seo-mcp --transport streamable-http
# endpoint: http://127.0.0.1:8000/mcp (send Authorization: Bearer <token>)🩹 Troubleshooting
Symptom | Cause and fix |
| gcloud's built-in client cannot request Analytics or Search Console scopes. Use your own OAuth client ( |
| Use the command printed by |
| Enable the Google Analytics Admin API, Google Analytics Data API and Search Console API in your quota project, then |
| Add your user (or the service account email) to the GA4 property or Search Console site. |
| You logged in before enabling a toolset or writes. Re-run the |
Write tools do not show up | Start the server with |
| The anonymous quota is shared by everyone. Create an API key and set |
Keyword Planner volumes look rounded (10, 30, 170, 210…) | Google Ads reports bucketed volume for accounts without active spend. Use the |
A deleted GA4 property still appears |
|
HTTP answers | DNS-rebinding protection. Connect with the host you bound ( |
HTTP answers | Send |
📚 Documentation
docs/AUTH.md — own OAuth client vs service account, scopes per toolset, Test Users.
docs/TOOLS.md — every tool and prompt, generated from the registry.
docs/ARCHITECTURE.md — modules, registration and security layers.
🧪 Development
uv sync --all-extras
uv run ruff check . && uv run ruff format --check . && uv run pytest
uv run python scripts/smoke_stdio.py --expect 24 # real stdio initialize + tools/list📄 License
MIT. Not affiliated with or endorsed by Google. Google Analytics, Search Console and PageSpeed Insights are trademarks of Google LLC.
Available Tools
24 toolsaudit_portfolioBRead-only
Summary metrics for several GA4 properties in one call.
Returns sessions, active users, conversions, bounce rate and average session duration per property, plus the properties that failed and why.
Args: property_ids: e.g. ['123456789', '987654321'].
Inputs: property_ids (required), date_end, date_start. Returns: object
bootstrap_site_measurementARead-only
Plan, and optionally apply, the full measurement setup of a website.
With apply=False (default) nothing is changed: it detects what already exists for the site (GA4 property and web stream matched by the site's domain, key events, custom dimensions, Search Console domain property) and returns the steps that would run. Show this plan to the user and get explicit confirmation before calling apply=True.
With apply=True (requires the server to run with --enable-writes) it creates only the missing pieces, skipping what exists, so it is safe to re-run. It returns a step-by-step report with the GA4 measurement ID (G-...) and the DNS TXT token for Search Console. DNS verification and sitemap submission stay manual follow-up steps (sc_verify_site_dns, sc_submit_sitemap) because the TXT record must be published first.
Args: site_url: the site, e.g. 'https://example.com'. account_id: GA4 account that owns (or will own) the property; see list_account_summaries. property_display_name: name for a new property; also used to find an existing one. time_zone: IANA time zone for a new property, e.g. 'America/Mexico_City'. currency_code: ISO 4217 currency for a new property, e.g. 'USD'. key_events: event names to mark as key events, e.g. ['generate_lead']. custom_dimensions: parameters to register as custom dimensions. apply: False = plan only (default); True = execute the plan.
Inputs: site_url (required), time_zone (required), account_id (required), currency_code (required), +4 more. Returns: object
conversions_summaryCRead-only
Conversions and total users per event name: a summary of the active key events.
Inputs: property_id (required), date_end, date_start. Returns: object
events_summaryARead-only
Count of every event that fired, to audit what is actually being measured.
Compare it with list_key_events to find key events that never fire.
Inputs: property_id (required), limit, date_end, date_start. Returns: object
get_data_streamBRead-only
Get one data stream, including the measurement ID of a web stream.
Inputs: stream_id (required), property_id (required). Returns: object
get_propertyBRead-only
Get the full settings of a GA4 property (time zone, currency, industry, type).
Inputs: property_id (required). Returns: object
list_account_summariesARead-only
List every GA4 account you can access, with a summary of its properties.
Start here to find the account_id and property_id the other tools need.
Inputs: no named parameters. Returns: result
list_custom_dimensionsBRead-only
List the custom dimensions declared on a GA4 property, with their scope.
Inputs: property_id (required). Returns: result
list_data_streamsBRead-only
List the data streams (web, iOS, Android) of a GA4 property.
Web streams include their measurement ID (G-XXXXXXX) and default URI.
Inputs: property_id (required). Returns: result
list_google_ads_linksCRead-only
List the links between a GA4 property and Google Ads accounts.
Inputs: property_id (required). Returns: result
list_key_eventsCRead-only
List the key events (formerly conversions) declared on a GA4 property.
Inputs: property_id (required). Returns: result
list_propertiesARead-only
List the GA4 properties under an account.
Args: account_id: numeric account ID or 'accounts/123456789'. include_deleted: also return properties in the trash (soft-deleted, kept 35 days).
Inputs: account_id (required), include_deleted. Returns: result
psi_auditARead-only
Run a PageSpeed Insights audit (Lighthouse lab test + CrUX field data) on a public URL.
Takes 30-90 seconds. Without PAGESPEED_API_KEY the anonymous quota is small and Google may answer 429; set the key for regular use.
Args: url: absolute public URL, e.g. 'https://example.com/'. strategy: 'mobile' (default) or 'desktop'. categories: subset of ['performance', 'accessibility', 'best-practices', 'seo']. Default: all four.
Returns 0-100 category scores, lab Core Web Vitals (LCP, FCP, CLS, TBT, SI, TTFB) and, when Chrome has enough real-user traffic, CrUX p75 field data for the URL and its origin.
Inputs: url (required), strategy, categories. Returns: object
psi_field_data_onlyARead-only
Only the CrUX field data (real Chrome users, p75 over 28 days) for a URL and its origin.
PageSpeed Insights still runs a performance-only Lighthouse pass, so expect 15-40 seconds.
overall_category is FAST, AVERAGE or SLOW; it is null when the page has too little traffic.
Inputs: url (required), strategy. Returns: object
run_realtime_reportARead-only
Realtime report for the last 30 minutes.
Useful to confirm that a new event fires in production right after a deploy.
Args: metrics: default ['activeUsers']; 'eventCount' also works. dimensions: default ['eventName']; also 'unifiedScreenName', 'country', 'deviceCategory'.
Inputs: property_id (required), limit, metrics, dimensions. Returns: object
run_reportARead-only
Run a flexible GA4 report.
Args: property_id: numeric ID or 'properties/123456789'. metrics: e.g. ['sessions', 'activeUsers', 'keyEvents']. Catalog: https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics dimensions: optional, e.g. ['date', 'sessionSource', 'pagePath']. Catalog: https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#dimensions date_start: 'YYYY-MM-DD', 'today', 'yesterday' or 'NdaysAgo' (e.g. '28daysAgo'). date_end: same formats as date_start. limit: maximum rows (default 25). order_by_metric: sort by this metric, e.g. 'sessions'. order_desc: sort descending (default True).
Returns the dimension and metric names, the date range, row_count and the rows.
Inputs: metrics (required), property_id (required), limit, date_end, +4 more. Returns: object
sc_list_sitemapsARead-only
List the sitemaps submitted for a Search Console site, with errors and warnings.
Inputs: site_url (required). Returns: result
sc_list_sitesARead-only
List the Search Console sites you can access.
Each entry has siteUrl ('sc-domain:example.com' for domain properties or a URL prefix
like 'https://example.com/') and permissionLevel ('siteOwner', 'siteFullUser',
'siteRestrictedUser' or 'siteUnverifiedUser').
Inputs: no named parameters. Returns: result
sc_page_performanceCRead-only
Top pages in Google Search by clicks, with impressions, CTR (%) and average position.
Inputs: date_end (required), site_url (required), date_start (required), limit. Returns: object
sc_query_breakdown_by_pageBRead-only
Which search queries bring traffic to one specific page.
Useful to decide which keywords to strengthen in that page's content.
Inputs: date_end (required), page_url (required), site_url (required), date_start (required), +1 more. Returns: object
sc_top_queriesARead-only
Top search queries with clicks, impressions, CTR (%) and average position.
Args: site_url: 'sc-domain:example.com' or 'https://example.com/', exactly as in sc_list_sites. date_start: 'YYYY-MM-DD'. date_end: 'YYYY-MM-DD'. Search Console data lags 2-3 days. limit: rows to return (max 25000). country: optional ISO 3166-1 alpha-3 code to filter by, e.g. 'mex' or 'usa'.
Inputs: date_end (required), site_url (required), date_start (required), limit, +1 more. Returns: object
top_pagesCRead-only
Top pages by sessions, with active users, bounce rate and average session duration.
Inputs: property_id (required), limit, date_end, date_start. Returns: object
traffic_sourcesCRead-only
Top traffic sources (source / medium) with sessions, active users and conversions.
Inputs: property_id (required), limit, date_end, date_start. Returns: object
web_vitals_summaryARead-only
Core Web Vitals reported by your own site as GA4 events.
Requires the site to send web-vitals events with the parameters web_vital_metric and
web_vital_rating, both registered as event-scoped custom dimensions.
For Google's field data use psi_field_data_only instead.
Inputs: property_id (required), date_end, date_start. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 24 tools
Most tools have distinct resource+action targets, and the descriptions clearly separate similar pairs (psi_audit vs psi_field_data_only, web_vitals_summary vs psi_field_data_only). However, top_pages, events_summary, traffic_sources and conversions_summary are all essentially preset versions of run_report, creating mild overlap an agent must reason about.
Names use consistent snake_case verb_noun within each domain (list_properties, get_property, run_report; sc_list_sites, sc_top_queries; psi_audit). The sc_/psi_ prefixes are meaningful namespacing, though GA4 tools carry no prefix, leaving a minor stylistic inconsistency across domains.
24 tools is on the heavy side for the stated scope and exceeds the comfortable 3-15 range. Several reporting tools (top_pages, events_summary, traffic_sources, conversions_summary) are convenience wrappers around run_report, so the surface is somewhat inflated.
Reporting, GA4 admin reads, Search Console analytics and PageSpeed are well covered, and bootstrap_site_measurement handles provisioning. Gaps exist: no GA4 config write/update tools and no sc_verify_site_dns/sc_submit_sitemap tools despite bootstrap referencing them as follow-up steps.
Maintenance
Related MCP Connectors
Read-only Google Search Console and Google Analytics for AI agents.
SEO & marketing toolkit for AI agents: GA4, Search Console, AdSense, GTM, PageSpeed, Trends.
Marketing data and actions for AI agents: GA4, Search Console, ads, social, SEO and WordPress.
- AdCopilotDeprecatedcloud.adcopilot
Google Ads, GA4, Search Console and Tag Manager for AI assistants. Every change is proposed first.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage Google Tag Manager, Google Search Console, and Google Analytics (GA4) through unified access to tags, search performance data, URL inspection, sitemaps, and analytics reporting.7 npmISC
- AlicenseBqualityCmaintenanceProvides AI agents with hands-on control of Google SEO and analytics tools including Search Console, GA4, Tag Manager, Indexing API, and PageSpeed Insights, with self-configuring OAuth2.3314 npmMIT
- AlicenseAqualityBmaintenanceEnables AI agents to read and write Google Analytics 4, Search Console, and Tag Manager data through MCP tools, with write operations gated behind an explicit flag for safety.207 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables AI apps to plan, build, audit, and report on Google Ads, GA4, Search Console, and Tag Manager accounts through natural language. Accounts are read-only by default, and every change is validated in a preview, applied only after confirmation, logged, and reversible.4MIT