feat(skills): add garmin-workout skill with sportType validation and schema reference

This commit is contained in:
Moritz Graf
2026-09-20 08:04:55 +02:00
parent be96b1234f
commit 42f37a89f8
+120
View File
@@ -0,0 +1,120 @@
---
name: garmin-workout
description: Design, validate, upload, repair, delete, and schedule Garmin Connect workouts. Enforces strict sportType IDs, DTO schemas, and avoids Garmin Connect mobile app list corruption. Use when creating, modifying, uploading, scheduling, or deleting workouts in Garmin Connect.
---
# 🏋️ Garmin Connect Workout Manager & Schema Validator
This skill defines the technical standards, DTO schemas, sport type identifiers, and safety protocols for creating, uploading, scheduling, and managing Garmin Connect workouts without corrupting the Garmin Connect mobile app or web client.
---
## 🚨 Critical Safety Rule: Sport Type Integrity
Whenever creating or uploading workouts via `garmin__upload_workout` or `schedule_workout`, **BOTH `sportTypeId` (integer) AND `sportTypeKey` (string)** MUST be provided in:
1. The top-level workout object: `workout_data["sportType"]`
2. Every segment object: `workout_data["workoutSegments"][i]["sportType"]`
### ⚠️ The "0 Workouts" Bug
If you send only `{"sportTypeKey": "yoga"}` without `sportTypeId`, Garmin's backend accepts the HTTP POST but defaults `sportTypeId` to `0` and sets `sportTypeKey: null` in its database.
When the Garmin Connect mobile app (iOS / Android) or modern web UI attempts to deserialize the workout list, it crashes on `null` and displays **"0 Workouts"**, making it appear as if all user workouts were deleted!
### 📋 Canonical Garmin Sport Type Mapping
| Sport | `sportTypeId` | `sportTypeKey` | `displayOrder` | Notes |
|---|---|---|---|---|
| **Yoga** | `7` | `"yoga"` | `8` | Essential for yoga flows |
| **Running** | `1` | `"running"` | `1` | Standard running |
| **Cycling** | `2` | `"cycling"` | `2` | Road, gravel, Tacx indoor |
| **Strength** | `5` | `"strength_training"` | `5` | Home gym, supersets |
| **Cardio** | `6` | `"cardio_training"` | `6` | General cardio |
| **Pilates** | `8` | `"pilates"` | `9` | Core & flexibility |
| **HIIT** | `9` | `"hiit"` | `7` | Tabata, SIT, sprint intervals |
| **Swimming** | `4` | `"lap_swimming"` | `4` | Pool swimming |
| **Walking** | `12` | `"walking"` | `10` | Recovery walks |
| **Mobility** | `11` | `"mobility"` | `11` | Joint mobility |
---
## 🏗️ Workout JSON Structure Reference
```json
{
"workoutName": "GeminiYoga#1 Fixed",
"description": "Optimierte Yoga-Sequenz ohne Redundanz.",
"estimatedDurationInSecs": 1800,
"sportType": {
"sportTypeId": 7,
"sportTypeKey": "yoga",
"displayOrder": 8
},
"workoutSegments": [
{
"segmentOrder": 1,
"sportType": {
"sportTypeId": 7,
"sportTypeKey": "yoga",
"displayOrder": 8
},
"workoutSteps": [
{
"type": "ExecutableStepDTO",
"stepOrder": 1,
"stepType": {
"stepTypeId": 1,
"stepTypeKey": "warmup"
},
"endCondition": {
"conditionTypeId": 2,
"conditionTypeKey": "time"
},
"endConditionValue": 60.0,
"targetType": {
"workoutTargetTypeId": 1,
"workoutTargetTypeKey": "no.target"
},
"description": "Mountain Pose - Atmung etablieren"
}
]
}
]
}
```
---
## 🛠️ Operational Recipes
### 1. Removing a Corrupted Workout
If a workout was uploaded with `sportTypeId: 0` or corrupt data:
```json
// Tool: mcp:garmin:garmin__delete_workout
{
"workout_id": 1703067815
}
```
*Effect:* Instantly restores Garmin Connect app visibility for all remaining workouts.
### 2. Uploading a Fixed Workout
```json
// Tool: mcp:garmin:garmin__upload_workout
{
"workout_data": {
"workoutName": "...",
"sportType": {
"sportTypeId": 7,
"sportTypeKey": "yoga",
"displayOrder": 8
},
"workoutSegments": [ ... ]
}
}
```
### 3. Scheduling to Watch Calendar
```json
// Tool: mcp:garmin:garmin__schedule_workout
{
"workout_id": 1703067815,
"calendar_date": "2026-09-20"
}
```