Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ any contributor run the auto-formatter [`black`](https://github.com/psf/black).
To get started, first install `nox` and `black`:

```
pip install -e .[dev]
uv pip install -e ".[dev]"
```

Then run the formatter on all Python files:
Expand Down Expand Up @@ -73,30 +73,19 @@ Gemini outputs debug information as it processes prompts.

### Test from GitHub

After you push changes to GitHub, use `pipx` to run the server for a specific
branch, and use the `--no-cache` option so `pipx` gets the
latest changes.
After you push changes to GitHub, use `uvx` to run the server for a specific
branch, and use the `--no-cache` option so `uvx` gets the
latest code from your branch.

Here's an example of an `mcpServers` entry that runs the latest code from a
branch named `awesome-feature-42` in this repo:
In the `mcpServers` configuration in `~/.gemini/settings.json`, set the `command`
to `uvx` and `args` as follows (replacing `YOUR_GITHUB_USERNAME` and
`YOUR_BRANCH_NAME`):

```json
{
"mcpServers": {
"analytics-mcp": {
"command": "pipx",
"args": [
"run",
"--no-cache",
"--spec",
"git+https://github.com/googleanalytics/google-analytics-mcp.git@awesome-feature-42",
"analytics-mcp"
],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "PATH_TO_CREDENTIALS_JSON",
"GOOGLE_PROJECT_ID": "YOUR_PROJECT_ID"
}
}
}
}
"analytics-mcp": {
"command": "uvx",
"args": [
"--no-cache",
"git+https://github.com/YOUR_GITHUB_USERNAME/google-analytics-mcp.git@YOUR_BRANCH_NAME"
],
```
19 changes: 19 additions & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Google Analytics MCP Extension

This extension provides tools to interact with Google Analytics 4 (GA4) properties.
It uses the Google Analytics Admin API and Data API.

## Available Tools

- `get_account_summaries`: List accounts and properties.
- `get_property_details`: Get details for a specific property.
- `list_google_ads_links`: List linked Google Ads accounts.
- `run_report`: Execute core reporting queries.
- `get_custom_dimensions_and_metrics`: List custom definitions for a property.
- `run_realtime_report`: Execute realtime reporting queries.

## Usage Guidelines

- Always try to find the `property_id` first using `get_account_summaries` if the user doesn't provide it.
- When running reports, refer to the official GA4 schema for dimensions and metrics names.
- For complex filters, follow the hints provided in the tool descriptions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Setup involves the following steps:

### Configure Python 🐍

[Install pipx](https://pipx.pypa.io/stable/#install-pipx).
[Install uv](https://docs.astral.sh/uv/getting-started/installation/).

### Enable APIs in your project ✅

Expand Down Expand Up @@ -136,9 +136,8 @@ Credentials saved to file: [PATH_TO_CREDENTIALS_JSON]
{
"mcpServers": {
"analytics-mcp": {
"command": "pipx",
"command": "uvx",
"args": [
"run",
"analytics-mcp"
],
"env": {
Expand Down
5 changes: 4 additions & 1 deletion analytics_mcp/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@
from mcp.server.fastmcp import FastMCP

# Creates the singleton.
mcp = FastMCP("Google Analytics Server")
mcp = FastMCP(
"Google Analytics Server",
description="MCP server for Google Analytics 4 (GA4) Admin and Reporting APIs",
)
111 changes: 54 additions & 57 deletions analytics_mcp/tools/reporting/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,58 @@
from google.analytics import data_v1beta


_RUN_REPORT_DOC = """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.
"""


def _run_report_description() -> str:
"""Returns the description for the `run_report` tool."""
return f"""
{run_report.__doc__}
{_RUN_REPORT_DOC}

## Hints for arguments

Expand Down Expand Up @@ -79,6 +127,10 @@ def _run_report_description() -> str:
"""


@mcp.tool(
title="Run a Google Analytics Data API report using the Data API",
description=_run_report_description(),
)
async def run_report(
property_id: int | str,
date_ranges: List[Dict[str, str]],
Expand All @@ -92,52 +144,7 @@ async def run_report(
currency_code: str = None,
return_property_quota: bool = False,
) -> Dict[str, Any]:
"""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.
"""
run_report.__doc__ = _RUN_REPORT_DOC
request = data_v1beta.RunReportRequest(
property=construct_property_rn(property_id),
dimensions=[
Expand Down Expand Up @@ -172,13 +179,3 @@ async def run_report(

return proto_to_dict(response)


# The `run_report` tool requires a more complex description that's generated at
# runtime. Uses the `add_tool` method instead of an annnotation since `add_tool`
# provides the flexibility needed to generate the description while also
# including the `run_report` method's docstring.
mcp.add_tool(
run_report,
title="Run a Google Analytics Data API report using the Data API",
description=_run_report_description(),
)
105 changes: 51 additions & 54 deletions analytics_mcp/tools/reporting/realtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,55 @@
from google.analytics import data_v1beta


_RUN_REALTIME_REPORT_DOC = """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.
"""


def _run_realtime_report_description() -> str:
"""Returns the description for the `run_realtime_report` tool."""
return f"""
{run_realtime_report.__doc__}
{_RUN_REALTIME_REPORT_DOC}

## Hints for arguments

Expand Down Expand Up @@ -77,6 +122,10 @@ def _run_realtime_report_description() -> str:
"""


@mcp.tool(
title="Run a Google Analytics realtime report using the Data API",
description=_run_realtime_report_description(),
)
async def run_realtime_report(
property_id: int | str,
dimensions: List[str],
Expand All @@ -88,49 +137,7 @@ async def run_realtime_report(
offset: int = None,
return_property_quota: bool = False,
) -> Dict[str, Any]:
"""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.
"""
run_realtime_report.__doc__ = _RUN_REALTIME_REPORT_DOC
request = data_v1beta.RunRealtimeReportRequest(
property=construct_property_rn(property_id),
dimensions=[
Expand Down Expand Up @@ -161,13 +168,3 @@ async def run_realtime_report(
response = await create_data_api_client().run_realtime_report(request)
return proto_to_dict(response)


# The `run_realtime_report` tool requires a more complex description that's generated at
# runtime. Uses the `add_tool` method instead of an annnotation since `add_tool`
# provides the flexibility needed to generate the description while also
# including the `run_realtime_report` method's docstring.
mcp.add_tool(
run_realtime_report,
title="Run a Google Analytics realtime report using the Data API",
description=_run_realtime_report_description(),
)
17 changes: 17 additions & 0 deletions gemini-extension.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "google-analytics",
"version": "0.1.0",
"description": "Google Analytics MCP Server extension for Gemini CLI",
"author": "Josh Radcliff, Matt Landers",
"mcpServers": {
"analytics-mcp": {
"command": "uvx",
"args": [
"analytics-mcp"
]
}
},
"gemini": {
"contextFile": "GEMINI.md"
}
}
Loading