Skip to main content
Glama
noviq-ai

Google Analytics MCP Server

by noviq-ai

Google Analytics MCP Server (Experimental)

PyPI version Python 3.10+ GitHub branch check runs PyPI - Downloads GitHub stars GitHub forks YouTube Video Views

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: Google Analytics MCP Server

Setup instructions 🔧

✨ Watch the Google Analytics MCP Setup Tutorial on YouTube for a step-by-step walkthrough of these instructions.

Watch the video

Setup involves the following steps:

  1. Configure Python.

  2. Configure credentials for Google Analytics.

  3. Configure Gemini.

Configure Python 🐍

Install pipx.

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.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]

Configure Gemini

  1. Install Gemini CLI or Gemini Code Assist.

  2. Create or edit the file at ~/.gemini/settings.json, adding your server to the mcpServers list.

    Replace PATH_TO_CREDENTIALS_JSON with the path you copied in the previous step.

    We also recommend that you add a GOOGLE_CLOUD_PROJECT attribute to the env object. Replace YOUR_PROJECT_ID in 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 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?

Contributing ✨

Contributions welcome! See the Contributing Guide.

Available Tools

7 tools
get_account_summariesA

Retrieves information about the user's Google Analytics accounts and properties.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, description implies read-only retrieval. However, it lacks details on potential size of returned data or any side effects. Basic behavioral context is present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence is concise and front-loaded. Every word adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless tool with no output schema, description provides sufficient context. Could mention it returns a list or summary, but current wording is adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so baseline score of 4 applies. Description adds no parameter-level info, which is acceptable given zero parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it retrieves information about accounts and properties. Verb is 'retrieves' and resource is specific, distinguishing it from sibling tools like get_property_details which likely target a single property.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

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 siblings. For example, it doesn't indicate that this is for account-level summaries versus property-level details.

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_metricsB

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

ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYes

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description should disclose behavioral traits like read-only nature, rate limits, or authentication. It only mentions return of custom dimensions and metrics with no details on response format or side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and structured with a purpose statement and an Args section. It is front-loaded and succinct, though it could be slightly more informative without adding verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

While the parameter explanation is sufficient, the description lacks details about the output structure (e.g., field names, array vs object). Given no output schema, the agent might need more context to handle the response correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning to the property_id parameter by specifying accepted formats (number or 'properties/' prefix), which is beyond the schema's bare anyOf type. However, only one parameter exists, so no gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns custom dimensions and metrics for a property, using a specific verb and resource. It distinctively separates from sibling tools like get_account_summaries 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.

Usage Guidelines2/5

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 like get_property_details or list_google_ads_links. It lacks any context about typical use cases or when not to use 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

ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYes

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, and the description does not disclose behavioral traits such as read-only nature, required permissions, or potential errors. The description only states it returns details, without further behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (two sentences) and front-loaded with the main purpose. However, it could be slightly more structured for clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of output schema, the description does not explain what 'details' are returned. For a simple tool with one parameter, it is adequate but incomplete regarding return value and behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds value beyond the input schema by specifying accepted formats for property_id (number or 'properties/' string). The schema only lists types, so this clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns details about a property, which distinguishes it from sibling tools like run_report or list_google_ads_links. However, it could be more specific about what details are included.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

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. The description lacks context on prerequisites or scenarios where this tool is preferable.

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

ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It only says 'Returns annotations' without stating read-only nature, side effects, or authentication needs. The lack of output schema further reduces transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a purpose sentence, paragraph explanation, and Args section. It is slightly verbose but avoids rambling; each part adds context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

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, the description covers purpose and parameter format but lacks return structure or pagination details. Given no output schema, some completeness is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the tool description explains property_id accepted formats (number or 'properties/'+number) in detail, significantly adding value beyond the schema's type-only definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it 'Returns annotations for a property' and explains what annotations are, but does not explicitly differentiate from sibling tools, which are distinct enough.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when annotations are used (e.g., service releases, marketing campaigns), giving implicit guidance, but lacks explicit 'when to use' vs. 'alternatives' statements.

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.
ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYes
dimensionsYes
metricsYes
dimension_filterNo
metric_filterNo
order_bysNo
limitNo
offsetNo
return_property_quotaNo

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness3/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.
ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYes
date_rangesYes
dimensionsYes
metricsYes
dimension_filterNo
metric_filterNo
order_bysNo
limitNo
offsetNo
currency_codeNo
return_property_quotaNo

TDQS

B3.4/5.0
Behavior3/5

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.

Conciseness3/5

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.

Completeness3/5

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.

Parameters5/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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. Dates show when Glama detected each change.

  1. 6 tool updatesv0.2.2
    • Changedget_custom_dimensions_and_metrics1 field changed
      • addedInput schema / required
        Added value: +[
        +  "property_id"
        +]
    • Changedget_property_details1 field changed
      • addedInput schema / required
        Added value: +[
        +  "property_id"
        +]
    • Changedlist_google_ads_links1 field changed
      • addedInput schema / required
        Added value: +[
        +  "property_id"
        +]
    • Changedlist_property_annotations1 field changed
      • addedInput schema / required
        Added value: +[
        +  "property_id"
        +]
    • Changedrun_realtime_report7 fields changed
      • addedInput schema / properties / dimension_filter / nullable
        Added value: +true
      • addedInput schema / properties / limit / nullable
        Added value: +true
      • addedInput schema / properties / metric_filter / nullable
        Added value: +true
      • addedInput schema / properties / offset / nullable
        Added value: +true
      • addedInput schema / properties / order_bys / nullable
        Added value: +true
      • addedInput schema / properties / return_property_quota / default
        Added value: +false
      • addedInput schema / required
        Added value: +[
        +  "property_id",
        +  "dimensions",
        +  "metrics"
        +]
    • Changedrun_report8 fields changed
      • addedInput schema / properties / currency_code / nullable
        Added value: +true
      • addedInput schema / properties / dimension_filter / nullable
        Added value: +true
      • addedInput schema / properties / limit / nullable
        Added value: +true
      • addedInput schema / properties / metric_filter / nullable
        Added value: +true
      • addedInput schema / properties / offset / nullable
        Added value: +true
      • addedInput schema / properties / order_bys / nullable
        Added value: +true
      • addedInput schema / properties / return_property_quota / default
        Added value: +false
      • addedInput schema / required
        Added value: +[
        +  "property_id",
        +  "date_ranges",
        +  "dimensions",
        +  "metrics"
        +]
  2. 7 tool updatesv0.2.0
    • First observedget_account_summaries
    • First observedget_custom_dimensions_and_metrics
    • First observedget_property_details
    • First observedlist_google_ads_links
    • First observedlist_property_annotations
    • First observedrun_realtime_report
    • First observedrun_report

TDQS

A3.7/5.0
Disambiguation5/5

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.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern in snake_case (get_*, list_*, run_*). No mixed conventions or ambiguous names.

Tool Count4/5

7 tools is appropriate for a Google Analytics MCP server, covering essential metadata retrieval and reporting. Slightly on the lower side but still reasonable.

Completeness4/5

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

ActivityInactive
ResponsivenessNo issues

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

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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

Latest Blog Posts

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/noviq-ai/google-analytics-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server