|
14 | 14 |
|
15 | 15 | """Tools for gathering Google Analytics account and property information.""" |
16 | 16 |
|
17 | | -from typing import Any, Dict, List |
| 17 | +from typing import Any, Dict, List, Optional |
18 | 18 |
|
19 | 19 | from analytics_mcp.tools.utils import ( |
20 | 20 | construct_property_rn, |
|
24 | 24 | ) |
25 | 25 | from google.analytics import admin_v1beta, admin_v1alpha |
26 | 26 |
|
| 27 | +# Fields stripped from account summaries to reduce token count. |
| 28 | +_ACCOUNT_STRIP_FIELDS = {"name"} |
| 29 | +_PROPERTY_STRIP_FIELDS = {"name", "parent", "property_type"} |
27 | 30 |
|
28 | | -async def get_account_summaries() -> List[Dict[str, Any]]: |
29 | | - """Retrieves information about the user's Google Analytics accounts and properties.""" |
| 31 | + |
| 32 | +def _strip_account_summary(account: Dict[str, Any]) -> Dict[str, Any]: |
| 33 | + """Remove redundant fields from an account summary and its properties.""" |
| 34 | + cleaned = {k: v for k, v in account.items() if k not in _ACCOUNT_STRIP_FIELDS} |
| 35 | + if "property_summaries" in cleaned: |
| 36 | + cleaned["property_summaries"] = [ |
| 37 | + {k: v for k, v in prop.items() if k not in _PROPERTY_STRIP_FIELDS} |
| 38 | + for prop in cleaned["property_summaries"] |
| 39 | + ] |
| 40 | + return cleaned |
| 41 | + |
| 42 | + |
| 43 | +async def get_account_summaries( |
| 44 | + query: Optional[str] = None, |
| 45 | +) -> List[Dict[str, Any]]: |
| 46 | + """Retrieves the user's Google Analytics accounts and properties. |
| 47 | +
|
| 48 | + Returns a compact representation with redundant fields (name, parent, |
| 49 | + property_type) stripped to reduce token usage. Each account keeps its |
| 50 | + ``account`` resource-name and ``display_name``; each property keeps its |
| 51 | + ``property`` resource-name and ``display_name``. |
| 52 | +
|
| 53 | + Args: |
| 54 | + query: Optional case-insensitive search string. When provided, only |
| 55 | + accounts or properties whose display name contains the query are |
| 56 | + returned. An account is included if its own display name matches |
| 57 | + **or** any of its properties match; non-matching properties on an |
| 58 | + otherwise-matching account are still filtered out. |
| 59 | + """ |
30 | 60 |
|
31 | 61 | # Uses an async list comprehension so the pager returned by |
32 | 62 | # list_account_summaries retrieves all pages. |
33 | 63 | summary_pager = await create_admin_api_client().list_account_summaries() |
34 | 64 | all_pages = [ |
35 | 65 | proto_to_dict(summary_page) async for summary_page in summary_pager |
36 | 66 | ] |
| 67 | + |
| 68 | + # Strip redundant fields. |
| 69 | + all_pages = [_strip_account_summary(s) for s in all_pages] |
| 70 | + |
| 71 | + # Apply optional display-name filter. |
| 72 | + if query: |
| 73 | + q = query.lower() |
| 74 | + filtered = [] |
| 75 | + for account in all_pages: |
| 76 | + acct_match = q in account.get("display_name", "").lower() |
| 77 | + matching_props = [ |
| 78 | + p |
| 79 | + for p in account.get("property_summaries", []) |
| 80 | + if q in p.get("display_name", "").lower() |
| 81 | + ] |
| 82 | + if acct_match or matching_props: |
| 83 | + account = dict(account) |
| 84 | + if not acct_match: |
| 85 | + # Only include properties that matched. |
| 86 | + account["property_summaries"] = matching_props |
| 87 | + filtered.append(account) |
| 88 | + all_pages = filtered |
| 89 | + |
37 | 90 | return all_pages |
38 | 91 |
|
39 | 92 |
|
|
0 commit comments