--- name: coros-mcp-integration description: "Use when: COROS-Sportuhr-Daten in PersoEnt anbinden." version: 1.0.0 author: mehlzoerwer platforms: [linux] models: default: mimo-v2-flash license: MIT related_skills: [content-creator, pocketbase-deployment] --- # COROS-MCP — Sportuhr-Daten in PersoEnt Nutze diesen Skill, wenn PersoEnt (oder ein anderes Projekt) **echte COROS-Sportuhr-Gesundheitsdaten** anbinden soll: Schlaf, HRV, Stress, Ruhe-Herzfrequenz, Training, Erholung, VO2max. ## Status (2026-08-10) - **Installiert** global: `npm install -g coros-mcp` (OFFIZIELLES Paket von `coros_openplatform`, ~0.1.1) - **Eingeloggt** — Token gecacht in `/root/.coros-mcp-skill-gateway-ts//token.json` - **22 MCP-Tools** verfügbar, Endpoint `mcp.coros.com` (Europa: `mcpeu.coros.com`) ## CLI-Syntax (WICHTIG — Flags, nicht Positional) Das Paket nutzt Flags, NICHT Positionsargumente: ```bash coros-mcp list-tools # alle Tools + Schema coros-mcp describe-tool --tool # Schema eines Tools coros-mcp call-tool --tool --arguments-json '{}' # Tool aufrufen ``` - `call-tool --tool X queryDailyHealthData` (ohne `--tool`) → **Fehler "unknown argument"** - `--args '{}'` / `--name X` / `--tool` mit Positional → **alles falsch** (richtig: `--tool NAME --arguments-json JSON`) ## Login-Flow (einmalig, nur Nutzerkonto) ```bash coros-mcp login-start # erzeugt Browser-Login-Link (mcpeu.coros.com/cli/login/...) # Nutzer oeffnet Link + meldet sich mit COROS-Konto an coros-mcp login-finish # bestaetigt Session -> 'login ok' coros-mcp login-status # 'no pending login session' = sauber/fertig ``` Login-Link ist region-/sessiongebunden. Andere COROS-Region → `--issuer`/`--mcp-url` anpassen. ## Wichtigste Tools (Daten fuer PersoEnt-Gesundheitsdetektiv) | Tool | Daten | |------|-------| | `queryDailyHealthData` | 7 Tage: Schritte, Kalorien, Stress, Schlaf (Tief/Leicht/REM), Schlaf-HR | | `querySleepHrv` | taegl. HRV + Baseline + Normbereich | | `queryRestingHeartRate` / `queryAvgHeartRate` | Ruhe-/durchschnittl. HF | | `queryStressLevel` / `queryStressTimeSeries` | Stress (avg/roh) | | `querySportRecords` | Workout-Protokoll (+ labelId, sportType) | | `getActivityDetail` / `queryActivityLapData` | Activity-Details inkl. HR | | `queryRecoveryStatus` | Erholung % + Level | | `queryFitnessAssessmentOverview` | VO2max, Threshold-Pace | | `querySleepData` | Schlafscore, Dauer, Stufen | | `queryDevices` / `queryUserInfo` | Geraete / Profil | ## Integration in PersoEnt (Architektur-Vorgabe) - **Server-seitig auf VPS** (Master): Poller ruft `coros-mcp call-tool` auf → Daten nach **PocketBase** (`health_records`-ahnliche Struktur) → PersoEnt-Dashboard/Detektiv liest von dort. - HRV + Schlaf + Stress + Erholung = ideale **Kausal-Merkmale** fuer den Gesundheitsdetektiv (besser als Google-Health-Fit). - Gleiche Basis-Assets (ein COROS-Konto) fuer mehrere Kanaele/Personas. ## Edge Cases - **Daten brauchen echten Login** — ohne `login-finish` kein Token, `call-tool` schlaegt fehl. - Zeitfenster-Tools (`queryCustomActivityLapData`) brauchen `startTimestamp`/`endTimestamp` in Unix-Sekunden. - Sport-Records-Details brauchen `labelId` + `sportType` aus der Records-Liste. ## Verifizierte Daten-Shapes Siehe `references/coros-mcp-data-shapes.md` — echte Antwort-Formate (queryDailyHealthData = ein String mit `--- JJJJMMTT ---`-Tag-Abschnitten, Sport-Records mit labelId/sportType), Token-Sicherheit (root-only Cache + age-Backup, NIE die Klartext-token.json verschluesseln) und der PersoEnt-Write-Hinweis (kein datum-Feld). ## 🔥 Robustes Parsen der 7-Tage-Helth-Antwort (verifiziert 2026-08-15) `queryDailyHealthData` liefert EINEN String mit 7 `--- 20260815 ---`-Tagbloecken. Naive Extraktion (erstes "Steps" finden) ist FEHLERHAFT — es erwischt das Datum oder einen alten Tag. Robust: - **Letzten Tages-Block nehmen**, nicht den ersten: `re.split(r'--- (\d{8}) ---', text)` → nimm das letzte (date, body)-Paar. - **`Stress: Avg 22`** hat "Avg" zwischen Label und Zahl → Regex `re.escape(label) + r'[^\d]*?([\d.,]+)'` (Ueberspringt Zwischenwoerter). - **Puls zuverlaessig aus `Sleep HR: Avg 51 bpm`** im Health-Block (AVG HR-Call `queryAvgHeartRate` hat anderes/leeres Block-Format — nicht darauf stuetzen). - **Schlaf** = `Total: 7h 46min` → `(\d+)h (\d+)min` → 7.77h. - COROS-Werte kommen mit **Tausender-Komma** (z.B. `9,304`) → `,` entfernen. - Nach jedem Fix: **real gegen die Live-Antwort testen** (echten `call-tool`-String parsen), nie von Schema raten — Daten-Shapes weichen ab.