This repo contains the source code for running a local MCP server that interacts with APIs for Google Analytics.
This is a fork. Upstream (googleanalytics/google-analytics-mcp) is read-only by design. This fork adds opt-in write tools for the Google Analytics Admin API, behind a
GA_MCP_MODEenvironment variable. With no configuration it behaves exactly like upstream: read-only tools only, and credentials that request only theanalytics.readonlyscope. See Write tools below, and ROADMAP.md for what is deliberately not built yet.
Join the discussion and ask questions in the π€-analytics-mcp channel on Discord.
The server uses the Google Analytics Admin API and Google Analytics Data API to provide several Tools for use with LLMs.
get_account_summaries: Retrieves information about the user's Google Analytics accounts and properties.get_property_details: Returns details about a property.list_google_ads_links: Returns a list of links to Google Ads accounts for a property.
run_report: Runs a Google Analytics report using the Data API.run_funnel_report: Runs a Google Analytics funnel report using the Data API.get_custom_dimensions_and_metrics: Retrieves the custom dimensions and metrics for a specific property.
run_realtime_report: Runs a Google Analytics realtime report using the Data API.
Write tools are off by default. Set GA_MCP_MODE to turn them on:
GA_MCP_MODE |
Tools registered | OAuth scopes requested |
|---|---|---|
unset or readonly |
Read tools only (identical to upstream) | analytics.readonly |
edit |
Read tools + configuration write tools | analytics.readonly, analytics.edit |
admin |
Same as edit today |
analytics.readonly, analytics.edit, analytics.manage.users |
admin exists so credentials can be minted once for future user and
access-binding tools; no user-management tools ship yet.
An invalid value is a hard error rather than a silent fallback, in either direction.
Admin API lookups, needed to get the resource names the write tools take:
list_custom_dimensions,list_custom_metrics,list_key_events,list_data_streams,get_data_retention_settings
Create and update:
create_custom_dimension,update_custom_dimensioncreate_custom_metric,update_custom_metriccreate_key_event,update_key_eventcreate_data_stream,update_data_streamupdate_property
Destructive β see below:
archive_custom_dimension,archive_custom_metricdelete_key_event,delete_data_streamupdate_data_retention_settings
Two mechanisms, because "clean up the old GA config" should not be enough for a model to delete a production data stream.
- MCP annotations. Every tool is published with
readOnlyHintanddestructiveHint, so a client can prompt before running the destructive ones. - Echo-back confirmation. Each destructive tool takes a required
confirmargument. The server reads the resource first and requiresconfirmto match its human-readable name exactly β the display name of a dimension, metric, or stream; the event name of a key event; the property display name for retention changes. A wrong or missing value aborts before the API call.
Echoing back the ID the caller already passed would prove nothing, so the confirmation is deliberately a value the caller has to look up. That also catches the more common failure: acting on the wrong resource ID.
Sending event data (the Measurement Protocol) is out of scope here; these tools change configuration only.
Application Default Credentials must be minted with the edit scope, otherwise write calls fail with a permission error at the API:
gcloud auth application-default login \
--scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/analytics.edit,https://www.googleapis.com/auth/cloud-platform
Add https://www.googleapis.com/auth/analytics.manage.users as well for
admin mode. Your Google Analytics user also needs Editor (or Administrator)
role on the property; the scope alone is not enough.
Then set the mode in your MCP client config, for example:
{
"mcpServers": {
"analytics-admin-mcp": {
"command": "uvx",
"args": ["uvx", "--from", "git+https://github.com/dcfabian/google-analytics-mcp.git", "analytics-admin-mcp"],
"env": { "GA_MCP_MODE": "edit" }
}
}
}This tracks main, so a push changes what everyone runs. For anything you
depend on, pin a commit instead by appending @<sha> to the git URL.
Three choices worth stating, since the alternatives all look simpler:
A mode, not a scope swap. The obvious approach is to replace
analytics.readonly with analytics.edit and be done. That makes every session
a write session, including the ones that only ever ask "why did traffic drop".
The mode keeps least privilege as the default and makes enabling writes a
deliberate, visible act.
Two independent gates, not one. The mode decides which tools are
registered; require_write_enabled re-checks at call time. That is
redundant on purpose β a client that somehow calls an unregistered tool, or a
future refactor that registers tools eagerly, still hits the second gate.
New code in new files. Nearly all of the fork lives in
tools/write_policy.py and tools/admin/write.py. Only five upstream files are
touched, each in one or two places, which is what keeps rebasing on upstream
cheap. See below.
Upstream is active. To pull its changes in:
git fetch upstream
git rebase upstream/main
The fork's conflict surface is deliberately small β these are the only upstream files it modifies:
| File | Change |
|---|---|
analytics_mcp/tools/client.py |
Credentials request scopes_for_mode() instead of a hardcoded read-only scope. |
analytics_mcp/coordinator.py |
Imports the write tools, registers them only in a write mode, and sets tool annotations. |
analytics_mcp/tools/utils.py |
Appends construct_child_rn. |
tests/utils_test.py |
Appends a TestConstructChildRn class. |
README.md |
This section and the two above it. |
Everything else is additive: analytics_mcp/tools/write_policy.py,
analytics_mcp/tools/admin/write.py, tests/write_policy_test.py,
tests/admin_write_test.py, and ROADMAP.md.
If upstream ever adds its own write tools, coordinator.py is where the two
approaches will collide, and the fork's registration block should give way.
β¨ Watch the Google Analytics MCP Setup Tutorial on YouTube for a step-by-step walkthrough of these instructions.
Setup involves the following steps:
- Configure Python.
- Configure credentials for Google Analytics.
- Configure Gemini.
Follow the instructions to enable the following APIs in your Google Cloud project:
Configure your Application Default Credentials (ADC). Make sure the credentials are for a user with access to your Google Analytics accounts or properties.
Credentials must include the Google Analytics read-only scope:
https://www.googleapis.com/auth/analytics.readonly
Check out Manage OAuth Clients for how to create an OAuth client.
Here are some sample gcloud commands you might find useful:
-
Set up ADC using user credentials and an OAuth desktop or web client after downloading the client JSON to
YOUR_CLIENT_JSON_FILE.gcloud auth application-default login \ --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform \ --client-id-file=YOUR_CLIENT_JSON_FILE
-
Set up ADC using service account impersonation.
gcloud auth application-default login \ --impersonate-service-account=SERVICE_ACCOUNT_EMAIL \ --scopes=https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform
When the gcloud auth application-default command completes, copy the
PATH_TO_CREDENTIALS_JSON file location printed to the console in the
following message. You'll need this for the next step!
Credentials saved to file: [PATH_TO_CREDENTIALS_JSON]
-
Install Gemini CLI or Gemini Code Assist.
-
Create or edit the file at
~/.gemini/settings.json, adding your server to themcpServerslist.Replace
PATH_TO_CREDENTIALS_JSONwith the path you copied in the previous step.We also recommend that you add a
GOOGLE_CLOUD_PROJECTattribute to theenvobject. ReplaceYOUR_PROJECT_IDin the following example with the project ID of your Google Cloud project.{ "mcpServers": { "analytics-admin-mcp": { "command": "uvx", "args": ["uvx", "--from", "git+https://github.com/dcfabian/google-analytics-mcp.git", "analytics-admin-mcp"], "env": { "GOOGLE_APPLICATION_CREDENTIALS": "PATH_TO_CREDENTIALS_JSON", "GOOGLE_PROJECT_ID": "YOUR_PROJECT_ID" } } } }
-
Add the MCP server with the following command:
Replace
PATH_TO_CREDENTIALS_JSONwith the path you copied in the previous step, and replaceYOUR_PROJECT_IDwith the project ID of your Google Cloud project.claude mcp add analytics-admin-mcp \ --scope user \ -e "GOOGLE_APPLICATION_CREDENTIALS=PATH_TO_CREDENTIALS_JSON" \ -e "GOOGLE_PROJECT_ID=YOUR_PROJECT_ID" \ -- uvx --from git+https://github.com/dcfabian/google-analytics-mcp.git analytics-admin-mcp
Launch Gemini Code Assist or Gemini CLI and type /mcp. You should see
analytics-admin-mcp listed in the results.
Here are some sample prompts to get you started:
-
Ask what the server can do:
what can the analytics-admin-mcp server do? -
Ask about a Google Analytics property
Give me details about my Google Analytics property with 'xyz' in the name -
Prompt for analysis:
what are the most popular events in my Google Analytics property in the last 180 days? -
Ask about signed-in users:
were most of my users in the last 6 months logged in? -
Ask about property configuration:
what are the custom dimensions and custom metrics in my property?
Contributions welcome! See the Contributing Guide.
