Analyser l'entraînement
strava_analyze_trainingAnalyzes recent training load by calculating weekly volume in kilometers and time, sessions count, longest run, average pace per week, and consistency score over a configurable number of weeks.
Instructions
Analyse la charge d'entraînement récente : volume hebdomadaire (km, temps, sorties), longue sortie, allure moyenne par semaine, score de régularité.
Tool call template
This tool declares no required parameters. Add optional parameters from the input schema as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {},
"name": "strava_analyze_training"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| weeks | No | Nombre de semaines récentes à analyser |
Implementation Reference
- src/analytics/analysisTools.ts:14-56 (registration)Tool 'strava_analyze_training' is registered in registerAnalysisTools() via server.registerTool at line 15. It accepts a 'weeks' parameter (default 12).
export function registerAnalysisTools(server: McpServer): void { server.registerTool( "strava_analyze_training", { title: "Analyser l'entraînement", description: "Analyse la charge d'entraînement récente : volume hebdomadaire (km, temps, sorties), " + "longue sortie, allure moyenne par semaine, score de régularité.", inputSchema: z.object({ weeks: z .number() .int() .min(1) .max(52) .default(12) .describe("Nombre de semaines récentes à analyser"), }), }, async ({ weeks }) => { const afterEpoch = Math.floor(Date.now() / 1000) - weeks * 7 * 86400 - 86400; const activities = await listAllActivities(afterEpoch); const weeklyStats = computeWeeklyStats(activities, weeks); const consistency = consistencyScore(weeklyStats); const avgKm = averageWeeklyKm(weeklyStats); const result = { periode: `${weeks} dernières semaines`, moyenne_hebdo_km: avgKm, regularite_pct: consistency, semaines: weeklyStats, resume: { total_sorties: weeklyStats.reduce((s, w) => s + w.runs, 0), total_km: Math.round(weeklyStats.reduce((s, w) => s + w.totalDistanceKm, 0) * 10) / 10, plus_longue_sortie_km: Math.max(0, ...weeklyStats.map((w) => w.longRunKm)), semaine_max_km: Math.max(0, ...weeklyStats.map((w) => w.totalDistanceKm)), }, }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } ); - src/analytics/analysisTools.ts:32-56 (handler)Handler function for strava_analyze_training. Fetches recent Strava activities via listAllActivities, computes weekly stats, consistency score, and average weekly km, then returns a JSON response with period, average weekly km, consistency percentage, weekly breakdown, and summary.
async ({ weeks }) => { const afterEpoch = Math.floor(Date.now() / 1000) - weeks * 7 * 86400 - 86400; const activities = await listAllActivities(afterEpoch); const weeklyStats = computeWeeklyStats(activities, weeks); const consistency = consistencyScore(weeklyStats); const avgKm = averageWeeklyKm(weeklyStats); const result = { periode: `${weeks} dernières semaines`, moyenne_hebdo_km: avgKm, regularite_pct: consistency, semaines: weeklyStats, resume: { total_sorties: weeklyStats.reduce((s, w) => s + w.runs, 0), total_km: Math.round(weeklyStats.reduce((s, w) => s + w.totalDistanceKm, 0) * 10) / 10, plus_longue_sortie_km: Math.max(0, ...weeklyStats.map((w) => w.longRunKm)), semaine_max_km: Math.max(0, ...weeklyStats.map((w) => w.totalDistanceKm)), }, }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } ); - src/index.ts:14-14 (registration)The tool registration function is called in the main entry point src/index.ts at line 14.
registerAuthTools(server); - src/analytics/metrics.ts:47-89 (helper)Helper function computeWeeklyStats groups run activities by ISO week and returns weekly stats including runs, total distance km, duration, average pace, longest run, and elevation gain.
export function computeWeeklyStats( activities: StravaActivity[], weeks = 12 ): WeeklyStats[] { const runs = activities.filter((a) => a.type === "Run" && !a.trainer); const byWeek = new Map<string, StravaActivity[]>(); for (const run of runs) { const ws = getWeekStart(new Date(run.start_date)); if (!byWeek.has(ws)) byWeek.set(ws, []); byWeek.get(ws)!.push(run); } // Generate last N week starts const now = new Date(); const weekStarts: string[] = []; for (let i = weeks - 1; i >= 0; i--) { const d = new Date(now); d.setDate(d.getDate() - i * 7); weekStarts.push(getWeekStart(d)); } return weekStarts.map((ws) => { const weekRuns = byWeek.get(ws) ?? []; const totalDistanceM = weekRuns.reduce((s, r) => s + r.distance, 0); const totalTime = weekRuns.reduce((s, r) => s + r.moving_time, 0); const longRunM = Math.max(0, ...weekRuns.map((r) => r.distance)); const avgSpeed = weekRuns.length > 0 ? weekRuns.reduce((s, r) => s + r.average_speed, 0) / weekRuns.length : 0; return { weekStart: ws, runs: weekRuns.length, totalDistanceKm: metersToKm(totalDistanceM), totalDurationMin: Math.round(totalTime / 60), avgPaceMinPerKm: avgSpeed > 0 ? formatPace(avgSpeed) : "N/A", longRunKm: metersToKm(longRunM), elevationGainM: Math.round(weekRuns.reduce((s, r) => s + r.total_elevation_gain, 0)), }; }); } - src/analytics/metrics.ts:129-139 (helper)Helper functions consistencyScore and averageWeeklyKm used by the tool handler to compute consistency percentage and average weekly km.
export function consistencyScore(weeklyStats: WeeklyStats[]): number { const activeWeeks = weeklyStats.filter((w) => w.runs > 0).length; return Math.round((activeWeeks / weeklyStats.length) * 100); } export function averageWeeklyKm(weeklyStats: WeeklyStats[]): number { const active = weeklyStats.filter((w) => w.runs > 0); if (active.length === 0) return 0; const total = active.reduce((s, w) => s + w.totalDistanceKm, 0); return Math.round((total / active.length) * 10) / 10; }