diff --git a/analytics_mcp/coordinator.py b/analytics_mcp/coordinator.py index 7d5274b..4b8f711 100644 --- a/analytics_mcp/coordinator.py +++ b/analytics_mcp/coordinator.py @@ -42,6 +42,9 @@ run_realtime_report, _run_realtime_report_description, ) +from analytics_mcp.tools.reporting.compatibility import ( + check_compatibility, +) from analytics_mcp.tools.reporting.metadata import ( get_custom_dimensions_and_metrics, ) @@ -62,6 +65,7 @@ FunctionTool(get_custom_dimensions_and_metrics), run_report_with_description, run_realtime_report_with_description, + FunctionTool(check_compatibility), ] tool_map = {t.name: t for t in tools} diff --git a/analytics_mcp/tools/reporting/compatibility.py b/analytics_mcp/tools/reporting/compatibility.py new file mode 100644 index 0000000..852d1c9 --- /dev/null +++ b/analytics_mcp/tools/reporting/compatibility.py @@ -0,0 +1,89 @@ +# Copyright 2025 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tool for checking dimension and metric compatibility.""" + +from typing import Any, Dict, List + +from analytics_mcp.tools.utils import ( + construct_property_rn, + create_data_api_client, + proto_to_dict, +) +from google.analytics import data_v1beta + + +async def check_compatibility( + property_id: int | str, + dimensions: List[str] = None, + metrics: List[str] = None, + dimension_filter: Dict[str, Any] = None, + metric_filter: Dict[str, Any] = None, +) -> Dict[str, Any]: + """Checks compatibility of dimensions and metrics for a report. + + This method checks which dimensions and metrics can be added to a + report request given the dimensions and metrics already present in + the request. The compatibility check is useful for discovering + which dimensions and metrics can be used together in a report + before running the report. + + Note that the reference docs at + https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/checkCompatibility + 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. + + 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 dimension names to check compatibility + for. If omitted, checks compatibility for all dimensions. + metrics: A list of metric names to check compatibility for. If + omitted, checks compatibility for all metrics. + dimension_filter: A Data API FilterExpression + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + to apply to the dimensions. + metric_filter: A Data API FilterExpression + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + to apply to the metrics. + """ + request = data_v1beta.CheckCompatibilityRequest( + property=construct_property_rn(property_id), + ) + + if dimensions: + request.dimensions = [ + data_v1beta.Dimension(name=dimension) + for dimension in dimensions + ] + + if metrics: + request.metrics = [ + data_v1beta.Metric(name=metric) for metric in metrics + ] + + if dimension_filter: + request.dimension_filter = data_v1beta.FilterExpression( + dimension_filter + ) + + if metric_filter: + request.metric_filter = data_v1beta.FilterExpression(metric_filter) + + response = await create_data_api_client().check_compatibility(request) + + return proto_to_dict(response) diff --git a/tests/compatibility_test.py b/tests/compatibility_test.py new file mode 100644 index 0000000..b761161 --- /dev/null +++ b/tests/compatibility_test.py @@ -0,0 +1,39 @@ +# Copyright 2025 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test cases for the compatibility module.""" + +import unittest + +from analytics_mcp.tools.reporting import compatibility + + +class TestCheckCompatibility(unittest.TestCase): + """Test cases for the check_compatibility tool.""" + + def test_check_compatibility_is_importable(self): + """Tests that check_compatibility can be imported.""" + self.assertTrue( + callable(compatibility.check_compatibility), + "check_compatibility should be a callable function", + ) + + def test_check_compatibility_is_async(self): + """Tests that check_compatibility is an async function.""" + import asyncio + + self.assertTrue( + asyncio.iscoroutinefunction(compatibility.check_compatibility), + "check_compatibility should be an async function", + )