Offline-first AI running coach: a local LLM agent that reasons over Garmin and Strava data through MCP. Provides two separate MCP servers (Garmin and Strava) for training data analysis and workout planning.
PaceForge defines 13 tools with consistent naming (verb_noun pattern: garmin_list_activities, strava_sync) and reasonable descriptions (avg ~100 chars). All tools have input schemas with types and descriptions. However, output schemas are not documented in the visible code, only input schemas are declared. Parameter descriptions are present but often terse (e.g., 'How many days back to look' lacks guidance on valid range or default rationale). Error handling is minimal; no recovery guidance or actionable error messages visible. Tool composition is sound (each does one thing), but descriptions could be more LLM-optimized per the 50 - 200 char baseline. No tool annotations (readOnlyHint, destructiveHint) despite clear risk classifications (READ_ONLY vs WRITE).
Current VDOT with prescribed pace zones and heart-rate zones.
Generate a periodised training plan targeting a race.
Report what Garmin data is available offline and when it last synced.
List recent Garmin activities with distance, pace, and heart rate.
Push planned workouts to the Garmin Connect calendar.
Refresh the local cache from Garmin Connect. Needs credentials + network.
Output schemas not documented. LLMs cannot plan downstream calls or extract required fields without knowing what each tool returns. Visible code shows only input schemas; return types are inferred from implementation.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite explicit risk classification. garmin_sync and garmin_schedule_workouts are WRITE operations; strava_sync is WRITE. LLMs cannot distinguish safe from destructive calls without annotations.
Parameter descriptions lack actionable constraints. 'How many days back to look' (days param) does not specify valid range (1 - 365?), rationale for default (30), or consequences of large values.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | <=2025-11-25 | v2 |
Training load, ACWR, injury-risk band, and intensity distribution.
Full coaching analysis: fitness, load, risk findings, race predictions.
Report what Strava data is available offline and when it last synced.
List recent Strava activities.
Predict a race time from recent training.
Refresh the local cache from Strava. Needs credentials + network.
Kilometres per week, oldest first, for trend analysis.
No error handling or recovery guidance visible in tool definitions. If garmin_sync fails due to invalid credentials or network timeout, LLMs have no guidance on what to do next (retry, ask user, check config).
Dry-run pattern incomplete. garmin_schedule_workouts has a dry_run parameter defaulting to true, which is good, but no description explains what 'dry_run=false' requires (e.g., 'explicit athlete approval'). The description hints at this but does not formalize the gate.