google-measurement-mcp
Allows interaction with Google Analytics 4 (GA4), providing read tools for analytics data and reporting, with opt-in write tools available when explicitly enabled.
Allows interaction with Google Search Console, providing tools to access search performance data and related properties, with write operations available only when explicitly enabled.
Click on "Install 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., "@google-measurement-mcpwhat were my top pages from Search Console last week?"
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.
google-measurement-mcp
The Google measurement stack for AI agents — GA4, Search Console, and Tag Manager in one MCP server.
Read tools are always on. Write tools are off unless you explicitly enable them. Destructive operations are not implemented at all.
Status: Early — v0.1.0. 15 read tools and 9 opt-in write tools are available across GA4, Search Console, and Tag Manager. See Roadmap.
Why this exists
Pointing an AI agent at your analytics is low-risk. Pointing one at your live Tag Manager container is not — a bad publish breaks tracking on every page of your site.
Most GTM MCP servers can publish containers. This one makes that hard on purpose:
Write tools are absent unless you pass
--enable-write. Not present-and-erroring — genuinely not in the tool list, so an agent cannot see or attempt them.Destructive operations do not exist in the codebase. No delete, no archive, no removal of tags, triggers, variables, sitemaps, or key events. This is a deliberate design choice, not a gap.
Publishing requires human confirmation.
gtm_publish_versionwithoutconfirm: truereturns a diff of what would go live and refuses to publish.
Related MCP server: Google Analytics MCP Server
Should you use this or Google's official server?
If you only need GA4, and only reads — use Google's. It's maintained by Google, it has a far larger community, and it has GA4 features this server does not.
google-measurement-mcp | ||
APIs | GA4 + Search Console + Tag Manager | GA4 only |
Writes | Yes, behind an explicit flag | No — read-only |
Funnel reports | ❌ not implemented | ✅ |
Google Ads links | ❌ not implemented | ✅ |
Property details | Partial (via account summaries) | ✅ |
Runtime | Node ≥ 20, npm | Python 3.10+, PyPI |
Auth | OAuth, service account, or ADC | ADC |
Maintainer | Community (one person) | |
Status | Early — v0.1.0 | Experimental |
License | Apache-2.0 | Apache-2.0 |
Where Google's is genuinely better: GA4-only workflows, funnel analysis, Google Ads attribution, and the simple fact that it's maintained by the team that owns the API. If your question is "what happened in my GA4 property," reach for theirs first.
Where this one earns its place: you need Search Console and Tag Manager alongside GA4 without running three servers, or you need write access and want the dangerous operations to be hard to reach by accident. Running both side by side is entirely reasonable — they don't conflict.
Quickstart (about 5 minutes)
1. Create a Google Cloud project and enable the APIs
In the Google Cloud console, create a project, then enable:
Google Analytics Data API
Google Analytics Admin API
Google Search Console API
Tag Manager API
2. Configure the consent screen
APIs & Services → OAuth consent screen. Google has migrated this to Google Auth Platform, where the settings are split across left-nav pages — Branding, Audience, Clients, Data Access. Set user type External and your email as both contacts.
Do not name the app
google-measurement-mcp. Google rejects any OAuth app name containing "Google" with a message that doesn't explain why: "The request failed because the app name does not comply with Google's requirements."Name it
Measurement MCPinstead. It's only the label on your own consent screen and has nothing to do with the package name.
3. ⚠️ Publish the app — do not skip this
Google Auth Platform → Audience → Publish app. (Older UI: OAuth consent screen → Publishing status.)
If you leave the status as Testing, Google expires your login after 7 days and you will have to sign in again every week.
Publishing is not Google verification. You are the only user of your own OAuth client, so there is no review, no security audit, and no waiting. You will see a one-time "Google hasn't verified this app" screen — that is expected. Click Advanced → Go to (unsafe). It is your own app.
4. Create an OAuth client
Google Auth Platform → Clients → Create OAuth client → Application type: Desktop app. (Older UI: APIs & Services → Credentials → Create credentials → OAuth client ID.)
Note the client ID and secret. Desktop app matters — a "Web application" client fails with redirect_uri_mismatch.
5. Configure your MCP client
claude mcp add google-measurement \
--scope user \
-e GMCP_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com \
-e GMCP_OAUTH_CLIENT_SECRET=your-client-secret \
-- npx -y google-measurement-mcpAdd --enable-write after the package name to expose write tools.
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": {
"GMCP_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
"GMCP_OAUTH_CLIENT_SECRET": "your-client-secret"
}
}
}
}Reload MCP servers after editing, or the old tool list stays cached.
Same shape as Cursor. macOS: ~/Library/Application Support/Claude/claude_desktop_config.json. Windows: %APPDATA%\Claude\claude_desktop_config.json.
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": {
"GMCP_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
"GMCP_OAUTH_CLIENT_SECRET": "your-client-secret"
}
}
}
}Not currently supported. claude.ai connectors require a remote MCP server over HTTP; this is a local stdio server by design, which keeps your Google credentials on your own machine rather than on someone else's.
6. Sign in once
Run the server once in a terminal. It prints a URL — open it, approve, done. The refresh token is cached at ~/.config/google-measurement-mcp/ with owner-only permissions, and your MCP client picks it up from then on.
GMCP_OAUTH_CLIENT_ID=... GMCP_OAUTH_CLIENT_SECRET=... npx -y google-measurement-mcpNo permission grants needed in GA4, Search Console, or Tag Manager. OAuth uses the access your Google account already has.
Enabling write tools
Write tools are hidden by default. To expose them:
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp", "--enable-write"],
"env": { "GMCP_ENABLE_WRITE": "1" }
}
}
}Either the flag or the env var is sufficient. On startup the server writes a line to stderr naming every write tool it exposed.
Write mode requests additional OAuth scopes, so you must sign in again after enabling it.
Alternative setup: service account (agencies and CI)
Use this when you need headless operation, scheduled jobs, or one identity across many client properties. It is more work — it requires granting access in three separate product UIs.
Create a service account in your Google Cloud project.
Create and download a JSON key.
GA4 → Admin → Property Access Management → add the service account email as Viewer (read) or Editor (write).
Search Console → Settings → Users and permissions → add the email as Full or Owner.
Tag Manager → Admin → User Management → add the email with Publish permission on the container.
Set
GOOGLE_APPLICATION_CREDENTIALSto the JSON key path.
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": { "GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/key.json" }
}
}
}Note: many organizations block service account key creation via the constraints/iam.disableServiceAccountKeyCreation org policy. If key creation fails, use OAuth instead.
If you already have the gcloud CLI:
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/analytics.readonly,\
https://www.googleapis.com/auth/webmasters.readonly,\
https://www.googleapis.com/auth/tagmanager.readonlyNo further configuration is needed — the server picks up ADC automatically.
Untested for write scopes. Google restricts which scopes gcloud's built-in client may request. If write mode fails under ADC, use OAuth or a service account.
Credential resolution order
GOOGLE_APPLICATION_CREDENTIALS— service account, if setCached user OAuth token
Application Default Credentials
The startup line on stderr tells you which one resolved.
Configuration
Variable | Default | Purpose |
| — | OAuth desktop client ID |
| — | OAuth desktop client secret |
| — | Path to a downloaded OAuth client JSON, instead of the two above |
| — | Service-account JSON key path |
| unset |
|
|
| Default row cap on every report tool |
|
| Named profile, for holding several Google identities on one machine |
Tools
Read — always available (15)
Tool | Does |
| Accounts and properties. Start here to find a propertyId |
| GA4 report, returned as flat rows |
| Last ~30 minutes |
| Custom dimensions with scope |
| Key events with counting method |
| Search Console properties. Start here for a siteUrl |
| Clicks, impressions, CTR, position |
| Submitted sitemaps with warnings and errors |
| Index status for one URL (quota: 2,000/day per property) |
| GTM accounts. Start here for an accountId |
| Containers — note |
| Workspaces in a container |
| Tags with type, triggers and parameters |
| Triggers with firing conditions |
| User-defined variables |
Responses are capped at 25 rows by default. When output is clipped you get truncated: true plus guidance — prefer narrowing the query over raising limit.
Write — only with --enable-write (9)
Tool | Does | Reversible |
| Creates a custom dimension | No — archive-only, and slots are limited |
| Marks an event as a key event | Yes, from the GA4 UI |
| Changes counting method | Yes |
| Submits a sitemap URL | Yes, from the Search Console UI |
| Creates a tag in a workspace | Yes — not live until published |
| Updates a tag, merging over its current config | Yes — not live until published |
| Creates a trigger in a workspace | Yes — not live until published |
| Snapshots a workspace into a version | Safe — creating ≠ publishing |
| Publishes to the live site | Yes, via GTM version history |
gtm_update_tag merges — omission preserves, explicit empty clears.
The raw GTM API replaces: omitting firingTriggerId silently empties it, leaving a tag that looks completely normal in the GTM UI and never fires. We verified that against the live API, then made this server read-then-merge so it cannot happen by accident.
// changes the name, keeps everything else
{ "tagPath": "...", "name": "New name", "type": "html" }
// deliberately unwires the tag from all triggers
{ "tagPath": "...", "name": "New name", "type": "html", "firingTriggerId": [] }parameter merges by key, so you can change one parameter without resending the rest. The response lists preservedFields so you can see what was carried over.
Safety
Not implemented, by design:
delete_key_event · archive_custom_dimension · delete_sitemap · tag / trigger / variable deletion · GSC site add & remove · GA4 property and data-stream mutation
These are omitted deliberately. An agent cannot call what does not exist.
Also:
GTM writes operate on a workspace, never directly on the live container.
GTM keeps version history, so a publish can be rolled back from the GTM UI.
The publish confirm gate
gtm_publish_version is the only operation here that changes a live website. It requires confirm: true.
Called without it, the tool performs a dry run: it fetches the version that would go live, diffs it against the currently live version, and returns a summary — naming tags, triggers and variables added or removed. It publishes nothing.
// confirm omitted -> nothing published
{
"published": false,
"dryRun": true,
"wouldPublish": { "containerVersionId": "7", "tagCount": 3 },
"currentlyLive": { "containerVersionId": "6", "tagCount": 3 },
"delta": { "tags": { "added": ["Tag NEW"], "removed": ["Tag GONE"], "unchangedCount": 2 } },
"instruction": "NOTHING WAS PUBLISHED. Show this summary to a human..."
}This is verified by a spy test asserting the publish API is never invoked without confirm: true — including when confirm is a truthy non-boolean like "true" or 1, which validation rejects:
node scripts/verify-confirm-gate.mjsTroubleshooting
"The app name does not comply with Google's requirements"
Your OAuth app name contains "Google", which Google's branding policy prohibits. Rename it to Measurement MCP. This is a consent-screen display label only and is unrelated to the package name.
"Your saved Google login is no longer valid" Most likely your consent screen is still in Testing (7-day token expiry) — see step 3. Other causes: more than 25 saved logins for one OAuth client, a clock out of sync, or access revoked from your Google account page.
redirect_uri_mismatch
Your OAuth client is a "Web application" type. Create a Desktop app client instead.
"Permission denied" The signed-in identity lacks access to that property, site, or container — or the relevant API is not enabled in your Cloud project. On the service-account path, confirm all three grants were made.
One API works but another returns nothing (e.g. GA4 fine, Tag Manager empty)
Your GA4, Search Console and Tag Manager assets are probably split across different Google accounts. gtm_list_accounts returning 0 rather than an error is the tell — the call succeeded, there was simply nothing that identity could see.
Do not re-authenticate as the other account. That usually just moves the problem, forfeiting access to whichever APIs currently work. Instead grant your existing identity access to the missing asset:
Tag Manager → Admin → User Management → add your email
GA4 → Admin → Property access management → add your email
Search Console → Settings → Users and permissions → add your email
No re-authentication needed; the scopes are already granted. Permission changes take a minute or two to propagate.
"Google quota exhausted" Search Console URL Inspection is capped at 2,000/day and 600/minute per property. The Tag Manager API has strict per-user limits — space GTM calls out by minutes, not seconds.
Write tools are missing
Expected unless you passed --enable-write or set GMCP_ENABLE_WRITE=1. Re-authenticate after enabling, since write mode needs extra scopes.
Roadmap
Phase 1 — auth, server,
ga4_run_reportPhase 2 — full read suite across GA4, Search Console, Tag Manager
Phase 3 — write tools behind the flag, publish confirm gate
Phase 4 — contract tests, traceability matrix, CI
Phase 5 — npm release
Development
npm install
npm run build
npm test # 73 contract tests, no network, no credentials
node scripts/verify-confirm-gate.mjs # 17 assertions on the publish gateContract tests stub the Google clients and assert on call behaviour, so they run anywhere including CI. The safety-critical ones live in test/contract/safety.test.ts — a failure there is a release blocker.
Three documents cover the engineering detail:
docs/DESIGN.md— why the safety architecture is shaped the way it isdocs/API-NOTES.md— Google API behaviours that are undocumented, easy to miss, or actively misleadingdocs/TESTING.md— traceability matrix mapping every tool to its API method, scope, reversibility, quota and covering tests, plus the known gaps
Requirements
Node.js >= 20.
License
Apache-2.0
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Read and edit GA4, Search Console and Google Tag Manager from any MCP client. 29 tools.
SEO & marketing toolkit for AI agents: GA4, Search Console, AdSense, GTM, PageSpeed, Trends.
Identity, authorization, audit trails, and revocable permissions for AI agents accessing MCP tools.
Governed app access for AI agents: 1,000+ apps & 12,000+ tools via Code Mode MCP.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables 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.22ISC
- AlicenseAqualityCmaintenanceEnables AI assistants to query Google Analytics accounts, properties, and run reports using natural language through the Admin and Data APIs.61Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables querying Google Analytics 4 data through MCP tools for running reports, listing properties, getting real-time metrics, and exploring metadata.13MIT
- FlicenseNot gradedqualityCmaintenanceEnables agents to access Google Calendar events, search Gmail, and semantically search local notes through MCP tools, with safety guardrails and human-in-the-loop approval.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/jabeer4148-ops/google-measurement-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server