GA4 MCP Server has solid foundations with clear naming conventions, reasonable descriptions, and properly defined input schemas using Zod. All 4 tools follow verb_noun patterns (ga4_listAccounts, ga4_listProperties, ga4_getMetadata, ga4_runReport). Schemas are visible and well-structured with type definitions and descriptions. However, there are notable gaps: output schemas are not documented (responses are structured but not formally declared), parameter descriptions lack guidance on constraints and error recovery, and tool descriptions miss context about when to use tools relative to each other. Error handling returns formatted errors but lacks recovery guidance. Tool composition is good, tools form a logical chain (list accounts → list properties → get metadata/run reports), but response chaining is incomplete.
Retrieve dimensions and metrics metadata for a GA4 property. If propertyId is omitted, falls back to config DEFAULT_GA4_PROPERTY_ID.
Return the GA4 accounts visible to the configured service account
List properties that belong to a given GA4 account
Execute a GA4 report query for the provided property, metrics, and optional dimensions.
Output schemas not documented. Tool descriptions state what data is returned (e.g., 'Return the GA4 accounts') but do not specify the field structure, required vs optional fields, or data types. Clients cannot reliably parse responses or plan downstream tool calls without explicit schema documentation.
Parameter descriptions lack constraint guidance. E.g., ga4_runReport 'metrics' parameter says 'At least one metric must be provided' in validation but not in the parameter description. Parameter descriptions should state format expectations, valid ranges, and examples of valid values (without literal example values LLMs might reuse).
Error responses lack recovery guidance. The code calls formatToolError() but the actual implementation of error messaging is not visible in the provided source. Current pattern (e.g., 'Unable to list GA4 accounts') does not guide the LLM on what to do next. Should return: error category (retryable/user-fixable/fatal), the condition that failed, and suggested next steps.
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 65 | 2025-06-18+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Tool descriptions do not clearly distinguish when to use ga4_getMetadata vs ga4_runReport. Both operate on properties; a user might call either expecting similar results. Descriptions should state: 'Use ga4_getMetadata to discover available dimensions and metrics; use ga4_runReport to execute a query with those dimensions/metrics.'
Parameter 'accountId' in ga4_listProperties description says 'with or without the accounts/ prefix' but does not explain what happens if the wrong format is passed. Should state: 'Automatically normalized; pass either raw ID (e.g. 123456789) or prefixed format (e.g. accounts/123456789).'
ga4_getMetadata accepts optional propertyId and falls back to DEFAULT_GA4_PROPERTY_ID. The description mentions this fallback, but does not state what the fallback value is or how the user can discover it. Should document: 'If omitted, uses the property configured as DEFAULT_GA4_PROPERTY_ID in your environment (currently: [value]).'
dateRanges parameter in ga4_runReport is optional and also has conflicting startDate/endDate params at the top level. The description does not clarify the relationship: are they mutually exclusive? Does one override the other? This undocumented dependency will cause misuse.
Response structure includes 'structuredContent' in addition to 'content'. The code creates responses with both text and structuredContent, but it's unclear to LLM consumers which field they should use or what the structured format is. Should document the structured schema explicitly (e.g., 'structuredContent.accounts is an array of {name, id, displayName}').