MCP server for Fathom Analytics that provides tools to access analytics data, account information, sites, events, and visitor metrics
The server implements 5 tools with READ_ONLY risk profile against Fathom Analytics API. All tools have descriptions and input schemas are present using Zod for validation. However, there are significant gaps: parameter descriptions lack actionable detail (format constraints, ranges, examples), output schemas are not documented, error messages are generic API pass-throughs without recovery guidance, and no tool annotations (readOnlyHint/destructiveHint) are present despite all being read-only operations. The aggregation tool has the most complex schema with nested filter objects, but lacks documentation on filter operator semantics. Tool naming follows verb_noun convention (get-*, list-*) which is good, but parameter naming is inconsistent (site_id vs entity_id) and some descriptions are vague (e.g., 'aggregates' parameter just lists comma-separated values without explaining what each aggregate means or when to use which). Error handling returns raw API errors without guidance on retryability or next steps.
Get Fathom Analytics account information
Get aggregated analytics data from Fathom
Get current visitors for a Fathom Analytics site
List all events for a Fathom Analytics site (automatically handles pagination)
List all Fathom Analytics sites on the account
Output schemas not documented. Tools return content arrays with type='text', but LLMs cannot plan downstream calls without knowing response structure. list-sites returns site objects but no schema is visible for what fields each site contains (site_id, name, tracking_domain, etc.). get-aggregation returns aggregation data array but format of array items is undocumented.
Parameter descriptions lack actionable constraints and format guidance. 'aggregates' parameter in get-aggregation lists valid values ('visits,uniques,pageviews,...') in description but should validate via enum or regex pattern. 'date_from' and 'date_to' accept multiple formats ('2025-01-01 00:00:00 or 2025-01-01') but this is described loosely, should specify exact ISO 8601 format or list alternatives with regex patterns. 'filters' array structure is defined in Zod but description doesn't explain operator semantics (what does 'is like' mean? substring or regex?).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-21 | D | 56 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 57 | - | v1 |
Error handling returns raw API error strings without recovery guidance. In account.ts, errors are formatted as 'Failed to retrieve account information: {status}: {error}', an LLM sees this and has no idea what to do next (retry? ask user for auth? try a different tool?). Pattern:recovery-guide requires error responses to tell the LLM what to do next, e.g., 'API error 401: Invalid API key. Check FATHOM_API_KEY environment variable.'
Tool annotations missing. No readOnlyHint despite all 5 tools being READ_ONLY operations. Tool annotations help agents reason about side effects and retry safety, all read-only tools should declare readOnlyHint=true (or in MCP 2026-07-28 format, via schema metadata).
Parameter naming inconsistency. get-account uses no parameters. list-sites uses 'limit'. list-events and get-current-visitors use 'site_id'. get-aggregation uses 'entity_id', 'entity', 'date_from', 'date_to', 'timezone', etc. This heterogeneity (site_id vs entity_id for similar lookups) forces LLMs to reason about which parameter to use for which tool and increases confusion. Consider standardizing to 'resource_id' or tool-specific but consistent naming.
No pagination support or result limits enforced. list-sites accepts 'limit' parameter but no offset/cursor, if user has 500 sites, how are results paginated? list-events has 'limit' parameter but no indication of default or max. get-aggregation has 'limit' parameter but no cursor or offset for multi-page results. Without pagination, large datasets blow context windows.
Incomplete parameter descriptions. 'date_grouping' in get-aggregation is described as 'Optional date grouping' but does not explain what happens when omitted or what each value (hour, day, month, year) returns. 'field_grouping' is described as 'Comma-separated fields to group by (e.g., hostname,pathname)' but doesn't explain if these are the ONLY valid values, whether custom fields are supported, or what the response structure looks like when grouped.
list-events description is generic ('List all events for a Fathom Analytics site (automatically handles pagination)') but does not explain what 'automatically handles pagination' means to the LLM. Does the tool return all events in one call? Or does pagination happen server-side transparently? Does the limit parameter override auto-pagination? LLMs need explicit guidance.