Google Analytics MCP Server
Provides functionality to list links between Google Analytics properties and their associated Google Ads accounts.
Interacts with Google Analytics Admin and Data APIs to retrieve account summaries, property details, and custom dimensions, as well as running core and real-time reports.
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., "@Google Analytics MCP Servershow me the top 10 pages by views for the last 7 days"
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 Analytics MCP Server (Experimental)
This repo contains the source code for running a local MCP server that interacts with APIs for Google Analytics.
Join the discussion and ask questions in the 🤖-analytics-mcp channel on Discord.
Tools 🛠️
The server uses the Google Analytics Admin API and Google Analytics Data API to provide several Tools for use with LLMs.
Retrieve account and property information 🟠
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 core reports 📙
run_report: Runs a Google Analytics report using the Data API.get_custom_dimensions_and_metrics: Retrieves the custom dimensions and metrics for a specific property.
Run realtime reports ⏳
run_realtime_report: Runs a Google Analytics realtime report using the Data API.
Related MCP server: MCP Server for Google Analytics 4
Setup instructions 🔧
✨ 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.
Configure Python 🐍
Enable APIs in your project ✅
Follow the instructions to enable the following APIs in your Google Cloud project:
Configure credentials 🔑
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.readonlyCheck 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_FILESet 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]Configure Gemini
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-mcp": { "command": "pipx", "args": [ "run", "analytics-mcp" ], "env": { "GOOGLE_APPLICATION_CREDENTIALS": "PATH_TO_CREDENTIALS_JSON", "GOOGLE_PROJECT_ID": "YOUR_PROJECT_ID" } } } }
Try it out 🥼
Launch Gemini Code Assist or Gemini CLI and type /mcp. You should see
analytics-mcp listed in the results.
Here are some sample prompts to get you started:
Ask what the server can do:
what can the analytics-mcp server do?Ask about a Google Analytics property
Give me details about my Google Analytics property with 'xyz' in the namePrompt 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?
Contributing ✨
Contributions welcome! See the Contributing Guide.
Available Tools
7 toolsget_account_summariesB
Retrieves information about the user's Google Analytics accounts and properties.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description only states that information is retrieved, which implies a read operation. However, with no annotations, it fails to disclose potential behavioral traits like authentication requirements, rate limits, or error cases (e.g., empty account list).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that is front-loaded with the action and resource. It contains no unnecessary words or redundancy, making it highly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no parameters, the description is adequate but minimal. It lacks details about the output structure, potential limitations, or what constitutes 'summaries.' Given the absence of an output schema and annotations, more context would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so the description does not need to elaborate on parameter semantics. It correctly implies that the tool requires no input, which is consistent with a summary retrieval operation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the verb 'Retrieves' and specifies the resource as 'information about the user's Google Analytics accounts and properties.' This clearly communicates the core function and distinguishes it from sibling tools like get_property_details or run_report.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as get_property_details or list_google_ads_links. There are no exclusions or context cues to help the agent decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_custom_dimensions_and_metricsA
Returns the property's custom dimensions and metrics.
Args: property_id: The Google Analytics property ID. Accepted formats are: - A number - A string consisting of 'properties/' followed by a number
| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description carries full burden but only states it returns data, with no mention of side effects, authorization needs, rate limits, or read-only nature. The name implies read-only, but this is not explicitly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: one for purpose, one for parameter format. Both are front-loaded and contain no unnecessary words. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description lacks details on return value structure, which would be helpful since no output schema is provided. However, for a simple retrieval tool with one parameter, it is minimally adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds significant value beyond the input schema by specifying accepted formats for property_id (number or 'properties/' + number), which is crucial for correct invocation. Schema description coverage is 0%, so this compensation raises the score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it returns the property's custom dimensions and metrics, using a specific verb and resource, and distinguishes it from sibling tools like run_report or get_property_details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, nor any prerequisites or exclusions. The description only states what the tool does, not when to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_property_detailsB
Returns details about a property. Args: property_id: The Google Analytics property ID. Accepted formats are: - A number - A string consisting of 'properties/' followed by a number
| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, and the description does not disclose behavioral traits such as authentication requirements, rate limits, or the scope of 'details' returned. For a tool lacking annotations, more context is needed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, with only two sentences and zero waste. The key information is front-loaded, and every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description covers the parameter format but omits what 'details' includes or any behavioral context. It is minimally complete but lacks depth.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds significant value beyond the schema by explaining the accepted formats for property_id (number or string with prefix). Since schema description coverage is 0%, this compensation is crucial and well done.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns details about a property, using a specific verb and resource. However, it does not explicitly distinguish from sibling tools like get_account_summaries or list_property_annotations, which also retrieve property-related information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus its siblings or alternatives. The description only explains what the tool does, not the context or prerequisites for its use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_google_ads_linksA
Returns a list of links to Google Ads accounts for a property.
Args: property_id: The Google Analytics property ID. Accepted formats are: - A number - A string consisting of 'properties/' followed by a number
| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It does not disclose behaviors like error handling, empty results, authentication requirements, or that it is a read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no wasted words. The first sentence states the purpose, the second explains the argument. Ideal length for a simple tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with no output schema, the description should hint at the return structure (e.g., account names, IDs). It only says 'links,' which is vague. Adequate but incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description adds significant value by explaining accepted formats for property_id (number or string with 'properties/' prefix), clarifying the ambiguous schema type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it returns a list of links to Google Ads accounts for a property. This is specific and distinct from sibling tools like run_report or get_property_details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives (e.g., get_account_summaries). The description only states what it does, not when it's appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_property_annotationsB
Returns annotations for a property.
Annotations are a feature that allows you to leave notes on GA4 for specific dates or periods. They are typically used to record service releases, marketing campaign launches or changes, and rapid traffic increases or decreases due to external factors.
Args: property_id: The Google Analytics property ID. Accepted formats are: - A number - A string consisting of 'properties/' followed by a number
| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must carry full burden. It only states it returns annotations, but does not disclose pagination, authentication needs, rate limits, output format, or side effects. Minimal behavioral info.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is somewhat verbose with an explanatory paragraph about annotation usage that is not essential for calling the tool. Could be more concise by focusing on usage details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one parameter and no output schema, the description is adequate but lacks details about return format, pagination, or error handling. No annotations further reduce completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description adds useful format guidance for property_id (number or 'properties/' string). This compensates well for the schema's lack of description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it returns annotations for a property and explains what annotations are used for. It is specific enough to distinguish from sibling tools like get_property_details or run_report, though it does not explicitly differentiate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage from the description but no explicit guidance on when to use this tool versus alternatives. No exclusions or context provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_realtime_reportA
Runs a Google Analytics Data API realtime report.See https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-basics for more information.
Args:
property_id: The Google Analytics property ID. Accepted formats are:
- A number
- A string consisting of 'properties/' followed by a number
dimensions: A list of dimensions to include in the report. Dimensions must be realtime dimensions.
metrics: A list of metrics to include in the report. Metrics must be realtime metrics.
dimension_filter: A Data API FilterExpression
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression)
to apply to the dimensions. Don't use this for filtering metrics. Use
metric_filter instead. The field_name in a dimension_filter must
be a dimension, as defined in the get_standard_dimensions and
get_dimensions tools.
For more information about the expected format of this argument, see
the run_report_dimension_filter_hints tool.
metric_filter: A Data API FilterExpression
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression)
to apply to the metrics. Don't use this for filtering dimensions. Use
dimension_filter instead. The field_name in a metric_filter must
be a metric, as defined in the get_standard_metrics and
get_metrics tools.
For more information about the expected format of this argument, see
the run_report_metric_filter_hints tool.
order_bys: A list of Data API OrderBy
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/OrderBy)
objects to apply to the dimensions and metrics.
For more information about the expected format of this argument, see
the run_report_order_bys_hints tool.
limit: The maximum number of rows to return in each response. Value must
be a positive integer <= 250,000. Used to paginate through large
reports, following the guide at
https://developers.google.com/analytics/devguides/reporting/data/v1/basics#pagination.
offset: The row count of the start row. The first row is counted as row
0. Used to paginate through large
reports, following the guide at
https://developers.google.com/analytics/devguides/reporting/data/v1/basics#pagination.
return_property_quota: Whether to return realtime property quota in the response.
## Hints for arguments
Here are some hints that outline the expected format and requirements
for arguments.
### Hints for `dimensions`
The `dimensions` list must consist solely of either of the following:
1. Realtime standard dimensions defined in the HTML table at
https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#dimensions.
These dimensions are available to *every* property.
2. User-scoped custom dimensions for the `property_id`. Use the
`get_custom_dimensions_and_metrics` tool to retrieve the list of
custom dimensions for a property, and look for the custom
dimensions with an `apiName` that begins with "customUser:".
### Hints for `metrics`
The `metrics` list must consist solely of the Realtime standard
metrics defined in the HTML table at
https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#metrics.
These metrics are available to *every* property.
Realtime reports can't use custom metrics.
### Hints for `date_ranges`:
Example date_range arguments:
1. A single date range:
[ {"start_date": "2025-01-01", "end_date": "2025-01-31", "name": "Jan2025"} ]
2. A relative date range using 'yesterday' and 'today':
[ {"start_date": "yesterday", "end_date": "today", "name": "YesterdayAndToday"} ]
3. A relative date range using 'NdaysAgo' and 'today':
[ {"start_date": "30daysAgo", "end_date": "yesterday", "name": "Previous30Days"}]
4. Multiple date ranges:
[ {"start_date": "2025-01-01", "end_date": "2025-01-31", "name": "Jan2025"}, {"start_date": "2025-02-01", "end_date": "2025-02-28", "name": "Feb2025"} ]
### Hints for `dimension_filter`:
Example dimension_filter arguments:
1. A simple filter:
{"filter": {"field_name": "eventName", "string_filter": {"match_type": 2, "value": "add", "case_sensitive": false}}}
2. A NOT filter:
{"not_expression": {"filter": {"field_name": "eventName", "string_filter": {"match_type": 2, "value": "add", "case_sensitive": false}}}}
3. An empty value filter:
{"filter": {"field_name": "source", "empty_filter": {}}}
4. An AND group filter:
{"and_group": {"expressions": [{"filter": {"field_name": "sourceMedium", "string_filter": {"match_type": 1, "value": "google / cpc", "case_sensitive": false}}}, {"filter": {"field_name": "eventName", "in_list_filter": {"values": ["first_visit", "purchase", "add_to_cart"], "case_sensitive": true}}}]}}
5. An OR group filter:
{"or_group": {"expressions": [{"filter": {"field_name": "sourceMedium", "string_filter": {"match_type": 1, "value": "google / cpc", "case_sensitive": false}}}, {"filter": {"field_name": "eventName", "in_list_filter": {"values": ["first_visit", "purchase", "add_to_cart"], "case_sensitive": true}}}]}} Notes:
The API applies the dimension_filter and metric_filter
independently. As a result, some complex combinations of dimension and
metric filters are not possible in a single report request.
For example, you can't create a `dimension_filter` and `metric_filter`
combination for the following condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
This isn't possible because there's no way to apply the condition
"eventCount > 100" only to the data with eventName of "page_view", and
the condition "eventCount < 50" only to the data with eventName of
"join_group".
More generally, you can't define a `dimension_filter` and `metric_filter`
for:
(
((dimension condition D1) AND (metric condition M1))
OR
((dimension condition D2) AND (metric condition M2))
)
If you have complex conditions like this, either:
a) Run a single report that applies a subset of the conditions that
the API supports as well as the data needed to perform filtering of the
API response on the client side. For example, for the condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
You could run a report that filters only on:
eventName one of "page_view" or "join_group"
and include the eventCount metric, then filter the API response on the
client side to apply the different metric filters for the different
events.
or
b) Run a separate report for each combination of dimension condition and
metric condition. For the example above, you'd run one report for the
combination of (D1 AND M1), and another report for the combination of
(D2 AND M2).
Try to run fewer reports (option a) if possible. However, if running
fewer reports results in excessive quota usage for the API, use option
b. More information on quota usage is at
https://developers.google.com/analytics/blog/2023/data-api-quota-management.
### Hints for `metric_filter`:
Example metric_filter arguments:
1. A simple filter:
{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}
2. A NOT filter:
{"not_expression": {"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}}
3. An empty value filter:
{"filter": {"field_name": "purchaseRevenue", "empty_filter": {}}}
4. An AND group filter:
{"and_group": {"expressions": [{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}, {"filter": {"field_name": "purchaseRevenue", "between_filter": {"from_value": {"double_value": 10.0}, "to_value": {"double_value": 25.0}}}}]}}
5. An OR group filter:
{"or_group": {"expressions": [{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}, {"filter": {"field_name": "purchaseRevenue", "between_filter": {"from_value": {"double_value": 10.0}, "to_value": {"double_value": 25.0}}}}]}} Notes:
The API applies the dimension_filter and metric_filter
independently. As a result, some complex combinations of dimension and
metric filters are not possible in a single report request.
For example, you can't create a `dimension_filter` and `metric_filter`
combination for the following condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
This isn't possible because there's no way to apply the condition
"eventCount > 100" only to the data with eventName of "page_view", and
the condition "eventCount < 50" only to the data with eventName of
"join_group".
More generally, you can't define a `dimension_filter` and `metric_filter`
for:
(
((dimension condition D1) AND (metric condition M1))
OR
((dimension condition D2) AND (metric condition M2))
)
If you have complex conditions like this, either:
a) Run a single report that applies a subset of the conditions that
the API supports as well as the data needed to perform filtering of the
API response on the client side. For example, for the condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
You could run a report that filters only on:
eventName one of "page_view" or "join_group"
and include the eventCount metric, then filter the API response on the
client side to apply the different metric filters for the different
events.
or
b) Run a separate report for each combination of dimension condition and
metric condition. For the example above, you'd run one report for the
combination of (D1 AND M1), and another report for the combination of
(D2 AND M2).
Try to run fewer reports (option a) if possible. However, if running
fewer reports results in excessive quota usage for the API, use option
b. More information on quota usage is at
https://developers.google.com/analytics/blog/2023/data-api-quota-management.
### Hints for `order_bys`:
Example order_bys arguments:
1. Order by ascending 'eventName':
[ {"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false} ]
2. Order by descending 'eventName', ignoring case:
[ {"dimension": {"dimension_name": "campaignName", "order_type": 2}, "desc": true} ]
3. Order by ascending 'audienceId':
[ {"dimension": {"dimension_name": "audienceId", "order_type": 3}, "desc": false} ]
4. Order by descending 'eventCount':
[ {"metric": {"metric_name": "eventValue"}, "desc": true} ]
5. Order by ascending 'eventCount':
[ {"metric": {"metric_name": "eventCount"}, "desc": false} ]
6. Combination of dimension and metric order bys:
[
{"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false},
{"metric": {"metric_name": "eventValue"}, "desc": true},
]
7. Order by multiple dimensions and metrics:
[
{"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false},
{"dimension": {"dimension_name": "audienceId", "order_type": 3}, "desc": false},
{"metric": {"metric_name": "eventValue"}, "desc": true},
]
The dimensions and metrics in order_bys must also be present in the report
request's "dimensions" and "metrics" arguments, respectively.| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes | ||
| dimensions | Yes | ||
| metrics | Yes | ||
| dimension_filter | No | ||
| metric_filter | No | ||
| order_bys | No | ||
| limit | No | ||
| offset | No | ||
| return_property_quota | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses behaviors such as pagination (limit/offset), independent application of dimension and metric filters with complex limitations, and notes that realtime reports cannot use custom metrics. It also provides quota management guidance. While it doesn't explicitly state read-only behavior, the nature of a report implies it. Overall, it is transparent about key behavioral aspects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long, but it is well-structured with sections, hints, and examples. However, the 'Notes' on filter combinations are repeated verbatim for both dimension_filter and metric_filter, which is redundant. Some trimming could improve conciseness while maintaining clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (9 parameters, nested objects, no output schema), the description is comprehensive. It covers parameter constraints, usage examples, and complex limitations. Missing are explicit error handling details and output format, but these are partially addressed by links to the API documentation. Overall, it is thorough and helps the agent use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description fully compensates. It explains each parameter in detail, including accepted formats for property_id, allowed types for dimensions/metrics (with links to schemas), structure of filter expressions and order_bys with examples, and constraints for limit/offset. This goes far beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool runs a Google Analytics Data API realtime report. It specifies the resource (realtime report) and the action (runs), and the title reinforces 'realtime' to distinguish from the sibling 'run_report' which implies standard reports. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides rich context for using the tool, including parameter constraints and examples. However, it does not explicitly state when to use this tool versus the sibling 'run_report' or when not to use it. The usage is implied by the 'realtime' designation, but no direct comparison or exclusion criteria are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_reportB
Runs a Google Analytics Data API report.Note that the reference docs at https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta all use camelCase field names, but field names passed to this method should be in snake_case since the tool is using the protocol buffers (protobuf) format. The protocol buffers for the Data API are available at https://github.com/googleapis/googleapis/tree/master/google/analytics/data/v1beta.
Args:
property_id: The Google Analytics property ID. Accepted formats are:
- A number
- A string consisting of 'properties/' followed by a number
date_ranges: A list of date ranges
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/DateRange)
to include in the report.
dimensions: A list of dimensions to include in the report.
metrics: A list of metrics to include in the report.
dimension_filter: A Data API FilterExpression
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression)
to apply to the dimensions. Don't use this for filtering metrics. Use
metric_filter instead. The field_name in a dimension_filter must
be a dimension, as defined in the get_standard_dimensions and
get_dimensions tools.
metric_filter: A Data API FilterExpression
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression)
to apply to the metrics. Don't use this for filtering dimensions. Use
dimension_filter instead. The field_name in a metric_filter must
be a metric, as defined in the get_standard_metrics and
get_metrics tools.
order_bys: A list of Data API OrderBy
(https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/OrderBy)
objects to apply to the dimensions and metrics.
limit: The maximum number of rows to return in each response. Value must
be a positive integer <= 250,000. Used to paginate through large
reports, following the guide at
https://developers.google.com/analytics/devguides/reporting/data/v1/basics#pagination.
offset: The row count of the start row. The first row is counted as row
0. Used to paginate through large
reports, following the guide at
https://developers.google.com/analytics/devguides/reporting/data/v1/basics#pagination.
currency_code: The currency code to use for currency values. Must be in
ISO4217 format, such as "AED", "USD", "JPY". If the field is empty, the
report uses the property's default currency.
return_property_quota: Whether to return property quota in the response.
## Hints for arguments
Here are some hints that outline the expected format and requirements
for arguments.
### Hints for `dimensions`
The `dimensions` list must consist solely of either of the following:
1. Standard dimensions defined in the HTML table at
https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#dimensions.
These dimensions are available to *every* property.
2. Custom dimensions for the `property_id`. Use the
`get_custom_dimensions_and_metrics` tool to retrieve the list of
custom dimensions for a property.
### Hints for `metrics`
The `metrics` list must consist solely of either of the following:
1. Standard metrics defined in the HTML table at
https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics.
These metrics are available to *every* property.
2. Custom metrics for the `property_id`. Use the
`get_custom_dimensions_and_metrics` tool to retrieve the list of
custom metrics for a property.
### Hints for `date_ranges`:
Example date_range arguments:
1. A single date range:
[ {"start_date": "2025-01-01", "end_date": "2025-01-31", "name": "Jan2025"} ]
2. A relative date range using 'yesterday' and 'today':
[ {"start_date": "yesterday", "end_date": "today", "name": "YesterdayAndToday"} ]
3. A relative date range using 'NdaysAgo' and 'today':
[ {"start_date": "30daysAgo", "end_date": "yesterday", "name": "Previous30Days"}]
4. Multiple date ranges:
[ {"start_date": "2025-01-01", "end_date": "2025-01-31", "name": "Jan2025"}, {"start_date": "2025-02-01", "end_date": "2025-02-28", "name": "Feb2025"} ]
### Hints for `dimension_filter`:
Example dimension_filter arguments:
1. A simple filter:
{"filter": {"field_name": "eventName", "string_filter": {"match_type": 2, "value": "add", "case_sensitive": false}}}
2. A NOT filter:
{"not_expression": {"filter": {"field_name": "eventName", "string_filter": {"match_type": 2, "value": "add", "case_sensitive": false}}}}
3. An empty value filter:
{"filter": {"field_name": "source", "empty_filter": {}}}
4. An AND group filter:
{"and_group": {"expressions": [{"filter": {"field_name": "sourceMedium", "string_filter": {"match_type": 1, "value": "google / cpc", "case_sensitive": false}}}, {"filter": {"field_name": "eventName", "in_list_filter": {"values": ["first_visit", "purchase", "add_to_cart"], "case_sensitive": true}}}]}}
5. An OR group filter:
{"or_group": {"expressions": [{"filter": {"field_name": "sourceMedium", "string_filter": {"match_type": 1, "value": "google / cpc", "case_sensitive": false}}}, {"filter": {"field_name": "eventName", "in_list_filter": {"values": ["first_visit", "purchase", "add_to_cart"], "case_sensitive": true}}}]}} Notes:
The API applies the dimension_filter and metric_filter
independently. As a result, some complex combinations of dimension and
metric filters are not possible in a single report request.
For example, you can't create a `dimension_filter` and `metric_filter`
combination for the following condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
This isn't possible because there's no way to apply the condition
"eventCount > 100" only to the data with eventName of "page_view", and
the condition "eventCount < 50" only to the data with eventName of
"join_group".
More generally, you can't define a `dimension_filter` and `metric_filter`
for:
(
((dimension condition D1) AND (metric condition M1))
OR
((dimension condition D2) AND (metric condition M2))
)
If you have complex conditions like this, either:
a) Run a single report that applies a subset of the conditions that
the API supports as well as the data needed to perform filtering of the
API response on the client side. For example, for the condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
You could run a report that filters only on:
eventName one of "page_view" or "join_group"
and include the eventCount metric, then filter the API response on the
client side to apply the different metric filters for the different
events.
or
b) Run a separate report for each combination of dimension condition and
metric condition. For the example above, you'd run one report for the
combination of (D1 AND M1), and another report for the combination of
(D2 AND M2).
Try to run fewer reports (option a) if possible. However, if running
fewer reports results in excessive quota usage for the API, use option
b. More information on quota usage is at
https://developers.google.com/analytics/blog/2023/data-api-quota-management.
### Hints for `metric_filter`:
Example metric_filter arguments:
1. A simple filter:
{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}
2. A NOT filter:
{"not_expression": {"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}}
3. An empty value filter:
{"filter": {"field_name": "purchaseRevenue", "empty_filter": {}}}
4. An AND group filter:
{"and_group": {"expressions": [{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}, {"filter": {"field_name": "purchaseRevenue", "between_filter": {"from_value": {"double_value": 10.0}, "to_value": {"double_value": 25.0}}}}]}}
5. An OR group filter:
{"or_group": {"expressions": [{"filter": {"field_name": "eventCount", "numeric_filter": {"operation": 4, "value": {"int64_value": "10"}}}}, {"filter": {"field_name": "purchaseRevenue", "between_filter": {"from_value": {"double_value": 10.0}, "to_value": {"double_value": 25.0}}}}]}} Notes:
The API applies the dimension_filter and metric_filter
independently. As a result, some complex combinations of dimension and
metric filters are not possible in a single report request.
For example, you can't create a `dimension_filter` and `metric_filter`
combination for the following condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
This isn't possible because there's no way to apply the condition
"eventCount > 100" only to the data with eventName of "page_view", and
the condition "eventCount < 50" only to the data with eventName of
"join_group".
More generally, you can't define a `dimension_filter` and `metric_filter`
for:
(
((dimension condition D1) AND (metric condition M1))
OR
((dimension condition D2) AND (metric condition M2))
)
If you have complex conditions like this, either:
a) Run a single report that applies a subset of the conditions that
the API supports as well as the data needed to perform filtering of the
API response on the client side. For example, for the condition:
(
(eventName = "page_view" AND eventCount > 100)
OR
(eventName = "join_group" AND eventCount < 50)
)
You could run a report that filters only on:
eventName one of "page_view" or "join_group"
and include the eventCount metric, then filter the API response on the
client side to apply the different metric filters for the different
events.
or
b) Run a separate report for each combination of dimension condition and
metric condition. For the example above, you'd run one report for the
combination of (D1 AND M1), and another report for the combination of
(D2 AND M2).
Try to run fewer reports (option a) if possible. However, if running
fewer reports results in excessive quota usage for the API, use option
b. More information on quota usage is at
https://developers.google.com/analytics/blog/2023/data-api-quota-management.
### Hints for `order_bys`:
Example order_bys arguments:
1. Order by ascending 'eventName':
[ {"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false} ]
2. Order by descending 'eventName', ignoring case:
[ {"dimension": {"dimension_name": "campaignName", "order_type": 2}, "desc": true} ]
3. Order by ascending 'audienceId':
[ {"dimension": {"dimension_name": "audienceId", "order_type": 3}, "desc": false} ]
4. Order by descending 'eventCount':
[ {"metric": {"metric_name": "eventValue"}, "desc": true} ]
5. Order by ascending 'eventCount':
[ {"metric": {"metric_name": "eventCount"}, "desc": false} ]
6. Combination of dimension and metric order bys:
[
{"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false},
{"metric": {"metric_name": "eventValue"}, "desc": true},
]
7. Order by multiple dimensions and metrics:
[
{"dimension": {"dimension_name": "eventName", "order_type": 1}, "desc": false},
{"dimension": {"dimension_name": "audienceId", "order_type": 3}, "desc": false},
{"metric": {"metric_name": "eventValue"}, "desc": true},
]
The dimensions and metrics in order_bys must also be present in the report
request's "dimensions" and "metrics" arguments, respectively.| Name | Required | Description | Default |
|---|---|---|---|
| property_id | Yes | ||
| date_ranges | Yes | ||
| dimensions | Yes | ||
| metrics | Yes | ||
| dimension_filter | No | ||
| metric_filter | No | ||
| order_bys | No | ||
| limit | No | ||
| offset | No | ||
| currency_code | No | ||
| return_property_quota | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description extensively covers parameter behavior, especially filter independence and limitations, and includes notes on pagination and snake_case naming. However, it lacks information on response structure, error handling, and authentication, leaving gaps for a tool with no annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headings and examples, but it is overly long and repetitive (e.g., filter notes repeated twice). Conciseness is compromised despite good organization.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description thoroughly covers parameter usage and filter limitations, but does not describe the response format or provide usage context relative to sibling tools. Missing output schema information further reduces completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description compensates exceptionally well by providing detailed hints, examples, and links for each parameter including date_ranges, filters, order_bys, and more. This adds significant meaning beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it runs a Google Analytics Data API report, specifying the primary function. However, it does not explicitly distinguish from the sibling tool 'run_realtime_report', relying on the name difference alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus the sibling 'run_realtime_report' or other alternatives. The description focuses on parameter details rather than use case differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.2.2- Changed
get_custom_dimensions_and_metrics1 field changed- added
Input schema / requiredAdded value: +[ + "property_id" +]
- Changed
get_property_details1 field changed- added
Input schema / requiredAdded value: +[ + "property_id" +]
- Changed
list_google_ads_links1 field changed- added
Input schema / requiredAdded value: +[ + "property_id" +]
- Changed
list_property_annotations1 field changed- added
Input schema / requiredAdded value: +[ + "property_id" +]
- Changed
run_realtime_report7 fields changed- added
Input schema / properties / dimension_filter / nullableAdded value: +true - added
Input schema / properties / limit / nullableAdded value: +true - added
Input schema / properties / metric_filter / nullableAdded value: +true - added
Input schema / properties / offset / nullableAdded value: +true - added
Input schema / properties / order_bys / nullableAdded value: +true - added
Input schema / properties / return_property_quota / defaultAdded value: +false - added
Input schema / requiredAdded value: +[ + "property_id", + "dimensions", + "metrics" +]
- Changed
run_report8 fields changed- added
Input schema / properties / currency_code / nullableAdded value: +true - added
Input schema / properties / dimension_filter / nullableAdded value: +true - added
Input schema / properties / limit / nullableAdded value: +true - added
Input schema / properties / metric_filter / nullableAdded value: +true - added
Input schema / properties / offset / nullableAdded value: +true - added
Input schema / properties / order_bys / nullableAdded value: +true - added
Input schema / properties / return_property_quota / defaultAdded value: +false - added
Input schema / requiredAdded value: +[ + "property_id", + "date_ranges", + "dimensions", + "metrics" +]
7 tool updates
v0.2.0- First observed
get_account_summaries - First observed
get_custom_dimensions_and_metrics - First observed
get_property_details - First observed
list_google_ads_links - First observed
list_property_annotations - First observed
run_realtime_report - First observed
run_report
TDQS
Scored across 7 tools
Each tool targets a distinct aspect of Google Analytics: account summaries, custom dimensions/metrics, property details, ads links, annotations, realtime reporting, and historical reporting. No overlap in purpose.
All tools follow a consistent verb_noun pattern in snake_case (get_*, list_*, run_*). No mixed conventions or ambiguous names.
7 tools is appropriate for a Google Analytics MCP server, covering essential metadata retrieval and reporting. Slightly on the lower side but still reasonable.
The tool set covers account/property info, custom fields, ads links, annotations, and both realtime and historical reporting. Missing administrative features like data streams or user management, but core analytics is well-covered.
Maintenance
Related MCP Connectors
SEO & marketing toolkit for AI agents: GA4, Search Console, AdSense, GTM, PageSpeed, Trends.
Connect Google Analytics to ChatGPT. Query GA4 data in plain English and get instant insights.
Read and edit GA4, Search Console and Google Tag Manager from any MCP client. 29 tools.
Query your Betterlytics web analytics from AI agents: traffic, funnels, journeys, errors, uptime.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with Google Analytics 4 data, providing tools for historical reporting, real-time activity monitoring, and property management. It supports secure service account authentication to access metrics like traffic summaries, user acquisition, and custom dimensions.MIT
- AlicenseNot gradedqualityFmaintenanceEnables LLMs to interact with Google Analytics 4 data through the Google Analytics Data API, supporting standard reports, real-time data, and metadata retrieval.19MIT
- AlicenseAqualityDmaintenanceEnables LLMs to interact with Google Analytics via Admin and Data APIs, allowing users to retrieve account summaries, run reports, and analyze realtime data.6Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to query Google Analytics 4 data, including listing accounts and properties, running historical and real-time reports with customizable metrics and dimensions.-