Suunto MCP
Suunto MCP
Frag Claude alles über dein Training. Suunto MCP verbindet die Daten deiner Suunto-Uhr mit Claude, sodass du einfach mit deinen Daten sprechen kannst, statt durch Dashboards zu klicken.
Gebaut von einem Suunto-Nutzer, der fragen wollte: „Wie war mein letzter langer Lauf?“ – und eine echte Antwort mit Zahlen bekommen wollte – und der Live-Trainingsdaten an einen persönlichen KI-Coach füttern wollte.
🏃 Für normale Suunto-Nutzer: In der API-Dokumentation von Suunto steht, der Zugriff sei nur für kommerzielle Partner gedacht – das ist nicht das ganze Bild. Auch private Nutzer bekommen Zugriff. Es dauert nur 3–4 Wochen nach der Bewerbung. Einreichen, warten, genießen. Lass dich von diesem Hinweis nicht abhalten. ✅
Was du machen kannst
Wenn alles eingerichtet ist, frag einfach los:
„Wie viele Kilometer bin ich diesen Monat gelaufen?“
„Vergleiche meine letzten drei langen Läufe – hat sich meine Herzfrequenz-Drift verbessert?“
„Hole die GPX-Datei vom gestrigen Trail-Lauf und schreibe einen kurzen Tagebucheintrag.“
„Wie ist der Trend meiner durchschnittlichen Ruheherzfrequenz in den letzten beiden Wochen?“
„Fasse meine Trainingswoche im Stil eines Coach-Berichts zusammen.“
„Ich war nicht ganz fit – wie sehen meine Erholungswerte im Vergleich zum letzten Monat aus?“
„Finde jedes Training, bei dem ich im Schnitt über 160 bpm verkraftete.“
„Welcher meiner Läufe dieses Jahr unternehme ich am meisten Höhenmetern?“
Claude findet dabei heraus, welche Daten es abrufen muss. Du musst nur fragen.
Es ist auch nicht nur lesend – Claude kann auch Dinge auf deine Uhr schreiben:
„Plane heute Abend die Gym-Session und schicke sie mir auf die Uhr.“
„Lade den gestrigen Garmin-Export als Suunto-Workout.“
„Exportiere meine letzte Route als GPX, damit ich sie teilen kann.“
Mehr dazu unter „Was du auf deine Uhr ausspielen kannst“.
Related MCP server: Garmin MCP Server
🤖 Kein Bock auf Selbermachen? Claude Code installiert alles für dich
Falls du bereits Claude Code hast, musst du keinen einzigen Terminal-Befehl ausführen. Einfach öffnen und sagen:
„Bitte install und richte suunto-mcp von https://github.com/googlarz/suunto-mcp ein“
Claude Code klont das Repo, führt alle Installations-Befehle aus und trägt alles in die Claude-Desktop-Konfiguration ein – ganz von allein. Genau so hat es auch der Autor dieses Projekts eingerichtet: kein Handarbeit im Terminal.
Drei Dinge bleiben – aus guter Design-Entscheidung und nicht etwa fehlender Tools – immer deine Sache:
Das Konto bei apizone abhol.
Das Apizone-Webformular (Appname vergeben, Subscription-Key anzeigen) – das sitzt in deiner accountbezogenen Sitzung. Claude sagt dir genau, wo du klicken musst, kann aber nicht für dich dort klicken.
Auf „Autorisieren“ / „Authorize“ klicken beim Log-in – das ist OAuth ganz normal. Eine App, die ihren Zugriff selbst genehmigen könnte, wäre nicht sicher.
Claude sagt dir genau bei jedes dieser interaktiven Schritte, was du tun sollst.
Wer kann das trotzdem von Hand machen, der lest hier weiter.
Was du brauchst
Bevor du loslegest, stellt sicher:
Eine Suunto-Uhr, die mit der Suunto-App synchronisiert ist (jedes moderne Modell – Race, Vertical, 9 Peak, 5 Peak, Ocean, usw.)
Claude Desktop (oder eine andere MCP-kompatible KI-App)
Node.js – kostenlos, hier herunterladen, bitte die „LTS“-Version wählen
Git – kostenlos, hier herunterladen
~5 Min. zum Einreichen + 3–4 Wochen Wartezeit auf Suunto + ~15 Min. Installation
Und wenn du es einmal durchgezogen hast, musst du es nie wieder.
Einrichtung
Lieber eine geführte Schritt-für-Schritt-Anleitung mit früher Wegwahl (einfacher Weg vs. ausführlich erklärt) und einer echten Erklärung, wie das Synchronisieren funktioniert? Dann schau dir GETTING_STARTED.md an. Hier folgen dieselben Schritte in Nachschlageform.
Die Einrichtung besteht aus drei Teilen:
Registrierung im Suunto- Developer-Portal – teils Suunto mit, dass deine App deine Daten lesen darf.
Installation & Konfiguration – bring die Software auf deinen Rechner.
Verbinden mit Claude – dann kann die KI es finden und verwenden.
Teil 1: Registrierung im Suunto-Entwickler-Portal (~5 Min. zum Einreichen, dann att 3–4 Wochen)
Suunto verfügt über ein kostenloses Entwicklerportal namens apizone, in dem du Apps registrierst, die auf deine Daten zugreifen dürfen. Du erstellst ein Konto, abonnierst den Datentarif und registrierst eine kleine „App“ – keine Sorge, du musst nichts bauen, es ist rennt nur ein Name und ein Passwort, das du dir ausdenken kannst.
Step 1: Dein Kosten für apizonte anlegen
Gehe auf apizone.suunto.com und registriere dich oder logge dich ein.
Verwende dieselbe E-Mail-Adresse wie in der Suunto-App. Wenn du einen Sports-Tracker-Account hast, funktioniert das auch – dasselbe Anmeldesystem.
Schritt 2: Die Developer-API abonnieren
Nach der Anmeldung folge den Guide How to start – er durchläuft dich Schritt durch Schritt, wie die Developer-API abonne wird. Das ist kostenlos und gibt dir Zugriff auf deine Trainingshistorie.
Achtung: Auf der Suunto-Website steht, der API-Zugriff sei nur für Business-Partner gedacht – ignoriere das. Auch Privatler haben Zugriff, dauert nur 3–4 Wochen für die Freischaltung. Vielmehr abbrechen, warten, und es kommt. Die damit zu zufriedenheit haben. ✅
You may also see other products like „Sleep API“, „Recovery API“, „Daily Activity API“. Du kannst sie erst mal ignorieren – die Developer API reicht für den Einstieg. Wenn du Schlaf- und Erholungsdaten bei Claude fordern als Es, kann zugige du die anderen später hinzufügen.
⏳ Stop – ab hier warten. Nach dem Abo durchläuft deine Anfrage die Genehmigung durch Suunto. Die dauert 3–4 Wochen. Du bekommst dann eine E-Mail. Komm für Schritt 3–4 erst wieder, wenn dein Abo in deinem apizone-Profil „Active“ steht.
Schritt 3: Beispiel: Deine App registrieren (mach das erst danach)
Du sagst sozusagen zu Suunto: „Ich habe ein kleines Programm, so he is es heißt und das ist sein geheimes Passwort – gib lieber es meine Daten lesen.“
Öffne deine apizone-Profilseite
Scrolle runter zum Look OAuth application settings – „Weitere authentifizierungseinstellungen“
Achtung: Ich habe bei dir anziehen.
Fülle das Formular aus:
Feld | Was du eintragen musst |
App name |
|
Client secret | Den dir ruhig ein einmaliges Passwort aus, das du nur eine kennst, z.B. |
Redirect URI |
|
Klicke auf Save.
Nach dem Speichern zeigt das Formular eine Client ID – einen langen Code, den Suunto für dich generiert zeigt. Kopiere dir.
Was sind die drei Dinge? – Client ID: der Benutzername deiner App, von aus Suunto generiert – Client Secret: das App-Passwort, das du selbst wählst – Redirect URI: das ist die zurück, wohin Suunto dich nach der Freigabe schickt. Muss exakt dem deinem Eingabefeld entsprechen – jeder Zeichenfehler kann ESC. die Redirect-URL
Das Client Secret wird nach dem Speichern nicht nochmal angezeigt. Du es vergessen, kannst du in dem Formular einfach ein neues setzen.
Schritt 4: Hole dir deinen Suunto-Aboschlüssel (nach Genehmigung)
Der subscription key ist ein zweites Password, das du jeder Datenanfrage mit am Zug. So findest du ihn:
Also noch auf deiner apizone-Profilseite
Scrolle zum Bereich Subscriptions.
Dort findest du dein Developer-API-Abo. Daneben gibt es einen Primary-Key – klicke dort auf das Ey🧿, um ihn sichtbar zu machen, und kopiere den Key.
Speichere dir alle drei Werte bevor er bis Temel Teil 2 braucht:
Client ID
Client Secret
Subscription Key
Teil 2: Installieren & Konfigurieren (~10 Min., nachdem Suunto dich freischaltet)
Hast du dir für oben „Claude Code installiert“ entschieden? Claude hat dann schon alle nachstehenden Bei Parameter-Befehl bereits ausgeführt. Überspringe gleich zu Teil 3. Diese Schritte hier sind für alle, die es nicht von selber oder lieber manuell löschen.
Schritt 5: Code herunterladen
Öffne Terminal auf dem Mac (drücke ⌘Leertaste und gib „Terminal“ ein) oder unter Windows die in der BSD-Eingabeaufforderung (cmd). Dann gib diese Befehle nacheinander ein:
git clone https://github.com/googlarz/suunto-mcp
cd suunto-mcp
npm install
npm run buildDas lädt das Projekt herunter, installiert alles Notwendigen und baut es. Dauer 1–2 Minuten. Wenn Fehlermeldungen kommen, it is im Troubleshooting (Fehlerbehebung) nach.
Schritt 6: Deine Zugangs schlüssel eintragen
Du legst eine .env-Datei in dem suunto-mcp-Ordner an und schreibst dort deiner Werte hinein. Auch wenn dich Claude bei allen übrigen Diensten hilft: Tipp die drei Werte einfach selbst in der Datei – nicht in den Chat – damit deine Konversation sie nicht sieht.
Auf dem Mac:
cp .env.example .env
open -e .envDas kopiert die Vorlage und lässt in TextEdit öffnet. Setze deine Werte an die Stellen, speichere ab kann).
Auf Windows:
copy .env.example .env
notepad .envDie Datei sieht so aus – ersetze alles hinter den =-Zeichen:
SUUNTO_CLIENT_ID=your-client-id-here
SUUNTO_CLIENT_SECRET=your-client-secret-here
SUUNTO_SUBSCRIPTION_KEY=your-subscription-key-hereSpeicher die Datei und schließe.
Nur wenn du geführte / Workouts auf die Uhr schicken willst (“Was du auf die Uhr schicken kannst” unten ), fügt danach trotzdem noch eine Zeile hinzu:
SUUNTO_APP_NAME=dein-app-name-hier– Und die muss bring à und darf genau dem App-Namen entsprechen, den du in Schritt 3 auf der apizez angegeben hast, sonst lehnt die Uhr den Upload ab.
Schritt 7: Suunto-Konto koppeln
npm run authDu lief das genau so:
① ① Terminal – du siehst eine lange URL, dazu die Meldung „Öffne Suunto-Autorisierung im Browser…“
② Browser öffnet – Die Anmeldeseite von Suunto erscheint. Sie sieht aus wie die Ausmeldeseite in der Suunto-App: ganz oben die Felder für E-Mail und Passwort, darunter „Mit Apple Sign-in“ sowie „Konto mit Facebook“. Logge dich mit einem wheree same.
③ ③ Einverständnis-Seite – Nach dem Login kommt eine Seite, auf der not yads sie den Zugriff von app auf dein Konto genehmigen – sie listet us sen dass die App angezeigten Daten (deine Workouts). Click auf Authorize.
④ Browser-Bestätigung – Die Webseite zeigt: „Suunto MCP verbunden. Du kannst diese deng-Tab schließen.“
⑤ Terminal-Bestätigung – Es steht: „ Kopplung erfolgreich. Tokes gespeichert.“
Fertig – du musst das nie dass machen. Die Verbindung bleibt aktiv find verlängert sich von allein.
Browser öffnet nicht automatisch? Kopier die lange URL aus dem Terminal und öffne sie manuell im Browser.
Schritt 8: All – überprüfen, ob es läuft
npm run doctorDas führt einen Health-Check durch. Dascheck ruft das Programm eigene Funktions-Test auf – und wie er die Ausgabe aussieht wie z.B. so:
Suunto MCP — health check
✓ Node version 20.18.0 (require ≥ 20)
✓ Credentials client_id, client_secret, subscription_key set
✓ Network reachability reachable
✓ Pairing paired (user: your-username), token expires in 47 min
✓ API probe (workouts) received 1 workoutWenn hier eine Zeile ✗ (rot) hatwird die Meldung angezeigt, was genau du beheben muss. Behebe die Dinge, bevor du weitermachst.
Teil 3: Verbinden mit Claude Desktop (~5 Min.)
Geht’s mit „Claude Code installiert“? Auch dieser Teil ist erledigt – Claude hat ihre Konfigurationsdatei direkt ergänzt. Starte Claude Desktop neu und gehe damit Du dann los zum Schritt 11.
Jetzt bringt du Claude Desktop bei, wo Suunto MCP sich kan findn kann.
Schritt 9: Claude-Konfigdorationsdatei öffnen
Leg folgende Datei mit unserem Texteditor an: (wenn sie nicht existiert)
Mac:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Schnellweg Mac — Diese Befehl starten, im Datei öffnet:
mkdir -p ~/Library/Application\ Support/Claude && open -e ~/Library/Application\ Support/Claude/claude_desktop_config.jsonSchnellvariante für Windows – in Cmd+Kommandozeile eingeben:
notepad "%APPDATA%\Claude\claude_desktop_config.json"(Falls gefragt wird: „Datei nicht erkennung – erstellen?“ Ja wählen.)
Schritt 10: Suunto MCP ein configuration
Holen Sie sich first den Pfad deines suunto-mcp-Ordners. Im Dialog „Terminal“ – wechseln Sie dafür in den Ordner – führe danach:
pwdDort wird etwas wie `/Users/yourname/suunto-mcp/. stehen – kopiere den Pfad.
Nun fügst du als nächstes das Folgende in deiner Konfigurationsdatei ein. ersetze den Pfad /Users/yourname/suunto-mcp mit dem Pfad von pwd,und ersetze die Platzhalter für Zugangsdaten mit deinen richtigen Werten.
Wenn die Datei bereits andere Server konfiguriert hat, ersetze nicht die ganze Datei — füge einfach den Abschnitt
"suunto"daneben hinzu. Die Struktur muss gültiges JSON sein, also müssen alle geschweiften Klammern ausbalanciert bleiben. Wenn du dir unsicher bist, vergleiche deine Datei mit dem Beispiel unten.Wenn die Datei leer ist, füge den gesamten Block unverändert ein.
{
"mcpServers": {
"suunto": {
"command": "node",
"args": ["/Users/yourname/suunto-mcp/dist/index.js"],
"env": {
"SUUNTO_CLIENT_ID": "your-client-id",
"SUUNTO_CLIENT_SECRET": "your-client-secret",
"SUUNTO_SUBSCRIPTION_KEY": "your-subscription-key",
"SUUNTO_APP_NAME": "your-app-name"
}
}
}
}SUUNTO_APP_NAME wird nur gebraucht und Sie werden es nicht, wenn Sie geführte Workouts auf deine Uhr übertragen möchtest — lass ihn weg (oder lösche diese Zeile), wenn du Claude nur nach deinen Daten fragst.
Speichere die Datei.
Schritt 11: Testen
Drei Dinge, in dieser Reihenfolge — das ist der einzige Teil der Einrichtung, den nichts für dich übernehmen kann:
Beende Claude Desktop vollständig. Nicht nur das Fenster schließen — ⌘Q auf dem Mac, oder im Taskleiste-auf dem Windows, rechtsklicken auf das Symbol → Beenden. Konfigurationsänderungen werden erst bei einem neuen Start geladen.
Öffne Claude Desktop erneut.
Frage folgendes:
„Wie war mein letztes Workout?“
Wenn Claude mit deiner tatsächlichen Sportart, dem Datum und der Distanz antwortet — bist du fertig. Wenn nicht, rate nicht herum — gehe zu Fehlerbehebung.
Beispieldialog
You: Compare my last three long runs. Has my heart-rate drift improved?
Claude: Looking up your workouts…
Found 3 runs over 90 minutes in the last 6 weeks:
• Apr 12 — 22.4 km, 2h09, avg HR 148, last-30min drift +6 bpm
• Apr 19 — 24.0 km, 2h21, avg HR 144, last-30min drift +4 bpm
• Apr 26 — 25.1 km, 2h28, avg HR 142, last-30min drift +2 bpm
Drift is trending down despite slightly longer runs — your aerobic
base is improving. Pace at the same HR is also ~3 s/km faster.Welche Daten verfügbar sind
Kategorie | Was du abfragen kannst | Voraussetzung |
Workouts | Jede aufgezeichnete Aktivität — Läufe, Wanderungen, Radfahren, Schwimmen, Skitouren. Distanz, Zeit, Herzfrequenz, Tempo, Höhenmeter, GPS-Route, Leistung. | Developer API (bereits abonniert) |
Schlaf | Schlafdauer, Schlafphasen (leicht/tief/REM), Schlaf-Score. | Sleep-API-Abonnement auf apizone |
Erholung | HRV, Erholungsstatus, Stressbalance. | Recovery-API-Abonnement auf apizone |
Tägliche Aktivität | Schritte, Kalorien, 24/7-Herzfrequenz. | Daily-Activity-API-Abonnement auf apizone |
Um Schlaf, Erholung oder Tagesaktivität hinzuzufügen: gehe zurück zu apizone.suunto.com, suche jedes Produkt und abonniere es. Führe dann npm run doctor aus, um zu bestätigen, dass die Abonnements aktiv sind.
Was du auf deine Uhr übertragen kannst
Suunto MCP ist nicht schreibgeschützt. Claude Desktop kann auch Dinge an dein Konto senden:
Was du möchtest | Frage an Claude Desktop | Voraussetzung |
Einen Trainingsplanin den Handgelenk bekommen | „Plane das heutige Training und schicke es auf meine Uhr“ |
|
Ein Workout von einer anderen Uhr hochladen | „Lade diese FIT-Datei als Suunto-Workout hoch“ | — |
Eine gespeicherte Route als GPX abholen | „Exportiere meine Samstagsroute als GPX“ | — |
Geführte Workouts erscheinen werden als SuuntoPlus-Workout: Übungsname und Gewicht/Wiederholungen am Bildschirm, die Runden-Taste schaltet zum nächsten weiter, eine Stoppuhr (kein Countdown) zwischen den Übungen, mit einem Vorausblick auf den nächsten Schritt, eine Vibration in den neuen Start und ein „Sitzung abgeschlossen“-Vorschau Nach Vibration am Ende. Es gibt keine direkte Ü? the sensible in itself — it is ready after the normal Suunto app sync, exactly like all other data from the watch.
Dies kannt passt gut zu Coaching-Workflows: beschreibe Claude Desktop Ziele und Material, und er kann damit eine progressiven Programm schreiben und jede Sitzung direkt schalten — siehe Pairs well with health-skill oben für erholungsfreundliches Training.
Tägliches Sohr Inbetriebnahme
Bitte Claude Desktop „Erstelle meinen täglichen Zusammenfasssung von gestern“, und Claude erstellt ein Farbcodiert Markdown-Dokument — Schritte, Schlaf, Erholungsbalance, HRV, Trainingsbelastungsmodell (Fitness/Fatigue/Form) — erzwungen wird in SUUNTO_HISTORY.md.
Denk dran: Fitness (CTL), Fatigue (ATL) und Form (TSB) sind keine Suunto-Felder — es gibt keinen eigenen API-Endpunkt dafür. Sie werden hier aus jedem Trainingspaket echter tss.trainingStressScore standardmäßig 40 Tage parieren orthodoteschung, wie auch andere Lauf-App wie Anpassen verwenden. Werte werden im Schreibtisch Endednsatz und ~/.suunto-mcp/averages.json gespeichert (setzen mit SUUNTO_DIGEST_AVERAGES_PATH), weil sonst dort kein Platz dafür.
Ein paar Punkte, bevor du dich darauf Eine Liste:
February/Atem +7 und SD/Beiß.... ETO Energietransport Das Frieden wir 4–6 Wochen vorhanden. Es ist wunderbar.
TSB-Farben entsprechen der eigenen Legende der Uhr (🔵 Optimistisch >+10, 🟢 Ausgewogen 0 bis +10, 🟡 Kompromittiert −10 bis 0, 🔴 Überlastet <−10) — keine erfundene Skala.
Ramp Rate (CTL dieser Woche im Vergleich zu vor 7 Tagen): 🔴 Über +3/Woche bedeutet Risiko, nicht nur „guter Fortschritt“. 🟢 +3 bis +8 ist solider Aufbau, 🟡 −2 bis +2 ist stabil, 🟠 unter −2 bedeutet konditionelle Falls- permanentes FIT und Fitness.
Recovery Balance / Fitness wird als Morgenwert (Maximum in der Nacht) zusammen mit dem Tagesspitzenwert (Maximum am Tag) angezeigt — Sie nutzen unterschiedliche Farbigkeit.
HRV wenn HRV mehr als 2 Tage unter dem normalen Bereich liegt, oder Morgenrecovery mehr als 2 Tage unter 65% liegt, wird eine Warnung zur Messung des Blutdrucks hinzugefügt — halt eine eigentlich (aber langfristig) niedrige HRV / Recovery ist wichtiges Signal.
Rollend Basislinien für jedes Prinzip existieren eigene Basiszinien. Partynacht (>20,000 Schritte) wird getrennt gezählt, dass ein Ausreißer nicht den Durchschnitt für normale Tage verfit.
Daten chronologisch verarbeiten. Die Basisstände basis on „Stand der tatsächlichen Ausführung“, nicht „Stand des Kalenderdatums“. Ein Nacharbeiten nach einem späteren Kalendertag macht den Vergleich an jenem Tag etwas ungenau — für die normalen tagessynchronien Einsatz ist das egal, aber für Nachholtage beachten.
Sleep- und Recovery-API-Abos sind für diese Abschnitte erforder — ohne diese Abschnitte entsteht zwar keiner, aber die Teile sagen nur „keine Datenü,“ statt Fehler.
CLI: suunto-mcp daily-diggest 2026-04-20 [--seed-ctl 42 --seed-atl 38]. MCP-Werkzeug: generate_daily_digest.
Fehlerbehebung
Führe zuerst immer npm run doctor aus — es beseitigt oder An orphan best:
Das passiertSiehst du, ... | Ursache | Lösung |
Claude Mail keine Antwort oder CodeError | Etwas ist noch nicht korrekt verbunden |
|
Leere Workout-Liste | Ihr Uhr ist abgel... gh | Öffne die Suunto-App und warte, dass die |
Nicht autorisiert“ | Das Pairing wurde nicht vollständig abgeschlossen | Starte die „npm run auth“ |
Eingeloggt, aber nichts passiert | Cache ein Problem zur Bestätigung |
|
„Token request failed“ oder 400er-Fehler | Client Secret und Redirect URI passen nicht zu apizon | Einstellungen / API-Referenz auf otionung |
Jede Anfrage gibt 401 | Abonnenten-ID fehlt | Erfolgreich Korrigieren Primary Key |
403 Forbidden bei workouts | Developer API ist nicht angekommen | In apizone „Active“ |
Schlaf / Recovery / Aktivität „not found“ | Dieses Feld braucht Gratis-Sponsoring | API-Abo in ins Abo... |
SSL-Fehler the Apple-Login | Bekanntes Suunto-Sonder-, beidou Test | Fehler-Magseite schließen und die „Auth-URL und. |
„State mismatch“ | Zugleich zweites Authentifizierungsfenster | Alles in Auth und neu |
| Node 20+ installiert? | Prüfen mit |
Port | Port 8421 in Verwendung | Neustart oder |
„owner“ bei Guide-Auftrag |
| Registis no, zum Morgen us/base anfertige von der apizon-App-Code |
Push dabei die Uhr, aber sieht keinen Guide | Konflikt zwischen Uhr und Client | Analyse (en) |
FAQ
Ist das sicher? Riswi? Wird Suunto mein Konto verbieten?
Dies führt “Suunto” bre art ausdrücklich an, damit damit zeigen — es ist also ausdrücklich andrevalteBar für eigene Anwendung. Es verwendest es so, wie es vorgesehen ist.
Verlassen meine Daten meinen Computer?
Deine bisherigen … Sie gehen direkt von deinem Rechner zu Suunto secure. Suunto MCP ist durch eine Bridge. Wenn du Claude fragst, passiert: Claude MCP → Suunto → Claude. Niemand Drittes sieht die Ansicht
Welche Suunto-Uhren funktionieren?
Jede Uhr, die mit Suunto sync: Race u.Weitere. Modell, via app ist egal.
Muss ich etwas tun, wenn ich ein neues Workout bin?
Nein. Frag einfach Claude — er zieht dir Daten z use.
Wie Wenn ich es entfernen?
Siehe Abklemmen unten.
Geht auch außer Claude?
Ja — all, alle MCP-Server: Claude Code, Cursor, Wedge und andere.
Mein Anmeldenname in Suunto ist nicht gleich meiner E-Mail — was oben?
Bitte log in email address, Use deine E-Mail, the exactun MCP zusammensetzen suit in by the Note. Der Benutzername wird in der E-Mail-Management sichtbar.
Privat
Alle Daten fließen direkt zwischen deinem Computer und den Servern von Suunto. Keine Drittanbieter-Server, keine Analyse.
Deine Anmeldedaten werden lokal unter
~/.suunto-mcp/tokens.jsongespeichert — nicht irgendwohin hochgeladen.Suunto zeigt deine verbundene App in apizone → Profil → Autorisierte Anwendungen als „suunto-mcp“ an. Dort kannst du sie jederzeit widerrufen.
Die KI sieht nur Daten, die sie explizit für deine Frage anfordert – nicht deine gesamte Historie auf einmal.
Verbindung trennen
Um den Zugriff vollständig zu entfernen:
Melde dich bei apizone.suunto.com an → Profil → Autorisierte Anwendungen → entferne suunto-mcp. Suunto erkennt die Verbindung ab dann nicht mehr an.
Lösche die lokalen Anmeldedaten:
rm -f ~/.suunto-mcp/tokens.jsonEntferne den Block
"suunto"aus deiner Claude-Konfiguration und starte Claude neu.
Passt gut zu health-skill
Wenn du googlarz/health-skill verwendest – eine Claude-Skill für Symptom-Triage und Gesundheits-Q&A – versorgt Suunto MCP sie mit einem Live-Feed deiner Trainings-, Schlaf- und Erholungsdaten. Gemeinsam können sie Fragen wie „Soll ich bei den Erholungswerten dieser Woche die morgige Intervalleinheit durchziehen?“ mit echten Zahlen beantworten.
Dieselbe Kombination funktioniert auch für die Planung, nicht nur für Q&A: Claude kann deine aktuelle HRV und deinen Schlaf prüfen, bevor er eine Einheit schreibt, sie an einem schlechten Erholungstag zurückschrauben statt ein generisches Programm zu verwenden, und das Ergebnis mit push_workout_guide direkt auf deine Uhr bringen. Frag einfach direkt – „Prüfe meine Erholung und plane das heutige Training“ – ohne zusätzliche Einrichtung, außer dass beide verbunden sind.
Für die vollständige Version – echte progressive-Überlastungs-Programmierung, die Woche für Woche bestehen bleibt, statt einer einmaligen Anfrage – installiere googlarz/gym-skill: einmal /gym setup, danach fortlaufend /gym plan /gym today /gym log /gym review.
Erweitert
Editiere ~/.claude/mcp_config.json und füge denselben "suunto"-Block aus Schritt 10 hinzu. Führe dann claude mcp list aus, um zu prüfen, dass er geladen ist.
Nach dem Build kannst du Suunto-Daten direkt ohne Claude abfragen:
suunto-mcp list-workouts --limit 10
suunto-mcp get-workout <workoutKey>
suunto-mcp export-workout-gpx <workoutKey> > route.gpx
suunto-mcp get-sleep 2026-04-20
suunto-mcp list-recovery --from 2026-04-01 --to 2026-04-30Die Ausgabe ist immer JSON – bei jq eingeben, um zu filtern.
npm run webhookStartet einen HTTP-Empfänger auf Port 8422, der Workout-Ereignisse protokolliert, sobald sie eintreffen. Mache ihn im Internet erreichbar (cloudflared, ngrok, eigener Server) und registriere die URL in apizone → webhooks.
Die meisten Nutzer können das überspringen – Claude einfach auf Anfrage zu fragen, ist unkomplizierter.
Um deine Suunto-Anmelde-Tokens statt in einer Datei in der System-Keychain (macOS Keychain, Windows Credential Manager) zu speichern:
SUUNTO_TOKEN_STORAGE=keychain npm install @napi-rs/keyring
SUUNTO_TOKEN_STORAGE=keychain npm run authClaude wählt das richtige Tool automatisch – du musst sie nicht kennen. Für alle Neugierigen:
Workouts
Tool | Funktion |
| Letzte Workout-Training ohne Bericht, filter nach Datum oder Sport |
| Vollständige Zusammenfassung eines Trainings |
| Zeitreihe: Herzfrequenz, Pace, Höhenmeter, Leistung, GPS pro Sekunde |
| Roh-FIT-Datei in strukturierte Daten dekodiert |
| GPX-Routenexport für Karten, Strava, Routenplanung |
24/7 Gesundheit (erfordert separate Produkt-Abos bei apizone)
Tool | Funktion |
| Schritte, Kalorien, tägliche Herzfrequenz |
| Schlaf, Schlafdauer, Schlafwert |
| Erholungswert, HRV, Stressbalance |
| Gemischte Tagesstatistik über einen Datumszeitraum |
Routen
Tool | Funktion |
| Auf deinem Konto gespeicherte Routen |
| Eine Route als GPX exportieren |
Uploads & geführte Trainings (schreiben – Daten an dein Konto übertragen)
Tool | Funktion |
| Lade eine FIT/GPX-Datei als neues Training hoch |
| Prüfen, ob ein Upload verarbeitet wurde |
| Überträgt ein strukturelles Training (Übungen, Gewichte, Pausen, Benachrichtigungen) als SuuntoPlus Guide – erfordert die |
Danksagungen
Suunto APIzone – dafür, dass sie ihre API für alle geöffnet
Model Context Protocol – der Standard, auf dem das basiert
fit-file-parser– die FIT-Binärdecodierung
Lizenz
MIT – nutzen, forken, verbessern.
Available Tools
25 toolsdelete_guideDelete SuuntoPlus guideADestructiveIdempotent
Permanently deletes one SuuntoPlus Guide from the user's account by id. Use list_guides to find the id. This removes it from the Suunto app / apizone catalogue; it does not reach into the watch to un-pin a copy already synced there. Write operation (irreversible).
| Name | Required | Description | Default |
|---|---|---|---|
| guideId | Yes | Guide id, from list_guides or from a previous push_*_guide response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so safety is partly covered. The description adds valuable behavioral context beyond that: permanence, irreversibility, and the important limitation that it does not un-pin a copy on the watch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences with zero filler; the core action and its id lookup guidance are front-loaded, and the watch-copy caveat is a single clarifying clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter destructive tool with no output schema, the description covers the action, the id source, the irreversibility, and the key side-effect boundary, which is everything an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single guideId parameter is already documented with its provenance. The description only reiterates 'by id' and points to list_guides, adding little beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (deletes), resource (one SuuntoPlus Guide), and scope (by id, from the user's account) in the first sentence, immediately distinguishing it from sibling push_*_guide and list_guides.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to use list_guides to find the id, and clearly scopes what the operation does and does not affect (account/catalogue removal vs. a synced watch copy). Nothing about when to invoke it is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_routeExport route as GPXARead-only
Exports a saved Suunto route as a GPX 1.1 XML string. Suitable for import into navigation apps (Komoot, Strava, Garmin Connect, etc.). Use list_routes to discover valid route IDs. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| routeId | Yes | Route ID returned by list_routes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so 'Read-only' is largely a restatement. The description earns credit beyond that by disclosing the concrete return type (GPX 1.1 XML string) and the interoperability intent, which the annotations do not cover. No auth or rate-limit notes, but none are needed for this read-only export.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the operation and output format, followed by relevance and prerequisite. Every sentence carries distinct information with no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly fills the gap by stating the return value is a GPX 1.1 XML string. Combined with the prerequisite pointer and read-only status, an agent has everything needed to call this one-parameter tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single routeId parameter is already documented in the schema as 'Route ID returned by list_routes.' The description's 'Use list_routes to discover valid route IDs' essentially repeats that provenance rather than adding format or constraint detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource ('Exports a saved Suunto route') and even names the output format (GPX 1.1 XML string), which is unusually specific. It does not, however, explicitly differentiate itself from the sibling export_workout_gpx, leaving the agent to infer the route-vs-workout distinction from the resource name alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when the output is useful ('import into navigation apps such as Komoot, Strava, Garmin Connect') and names the prerequisite discovery tool (list_routes). It stops short of an explicit when-not or an alternative export tool comparison, but the usage context is well conveyed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_workout_gpxExport workout as GPXARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/exportGpx) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Would return the workout's GPS route as a GPX 1.1 XML string. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses the exact failure mode (401 OperationNotFound from /v2/workout/exportGpx), that the error surfaced will be 'endpoint unavailable', and that this is not an auth issue — precisely the context an agent needs to avoid misdiagnosing. It also states the would-be return format (GPX 1.1 XML string) and confirms read-only, adding value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The unavailability notice is front-loaded, which is the right priority, and the remaining clauses are informative rather than filler. Slightly wordy, but every sentence carries signal about state or behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-param, read-only tool with full schema coverage, the description covers what an agent needs: current unavailability, why it fails, and what it would return. Nothing material is missing even without an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single workoutKey parameter is fully documented in the schema (opaque, discovered via list_workouts, SuuntoNotFoundError on invalid key). The description adds nothing about the parameter, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource and output format: exports a workout's GPS route as a GPX 1.1 XML string. An agent immediately knows what it would do. It does not, however, distinguish itself from the sibling export_route or explain how the two differ, which is the one clarity gap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong current-state guidance: the endpoint returns 'endpoint unavailable' and this is not an authentication problem, so an agent should not retry or chase credentials. It stops short of naming an alternative (e.g. get_workout_fit) for obtaining GPS data while the endpoint is broken.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_daily_digestGenerate daily health digestADestructiveIdempotent
Builds a color-coded daily health digest (steps, sleep, recovery balance, HRV, and a training-load model) for one date and appends it as markdown to a history file. Suunto's API has no fitness/fatigue endpoints, so this computes CTL (42-day fitness), ATL (7-day fatigue), and TSB (form) from each workout's tss.trainingStressScore using standard exponential time constants, persisting the running values in a local sidecar file (SUUNTO_DIGEST_AVERAGES_PATH env var, default ~/.suunto-mcp/averages.json) since there's nowhere else to store them. Running-average baselines (all days so far) per metric are also tracked there, with a separate baseline bucket for 'party nights' (>20,000 steps) so those don't skew the normal-day average. Requires Sleep and Recovery API subscriptions on apizone for the sleep/recovery sections to populate — falls back to 'no data' text for sections without a subscription rather than erroring. Write operation (updates the sidecar file and appends to the history file).
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced. | |
| seedAtl | No | Same as seedCtl but for Fatigue (ATL). Only used on the very first digest ever run. | |
| seedCtl | No | Only used on the very first digest ever run (no prior sidecar file). Anchors the starting Fitness (CTL) value to the number shown on the user's watch instead of cold-starting at 0. Ask the user for their watch's displayed Fitness value if this is their first digest. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations (which only say non-read-only, destructive, idempotent, open-world). It discloses the CTL/ATL/TSB computation from tss.trainingStressScore, the sidecar file and env var used for persistence, the baseline bucketing for 'party nights', the subscription-dependent fallback, and explicitly labels itself a write operation that appends to a history file.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but dense, and every sentence carries required information given the tool's complexity. It is front-loaded with the purpose, then proceeds to computation, persistence, prerequisites, and side effects in a logical order with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers behavior, side effects, prerequisites, and fallbacks for a complex tool with no output schema. Remaining gaps are minor: the history file location/format and what the call returns to the caller are not described, though the sidecar path is.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds domain context for the date (via the workload) but says nothing about seedCtl/seedAtl beyond what the schema already documents, so it does not meaningfully extend parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: builds a color-coded daily health digest covering steps, sleep, recovery, HRV and a training-load model for one date. No sibling tool does anything comparable, so differentiation is inherent, and the side effects (sidecar update, markdown append) are stated up front.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: one date per call, requires Sleep and Recovery API subscriptions for those sections, and falls back to 'no data' instead of erroring. It does not name an alternative tool or an explicit when-not-to-use condition, but there is no overlapping sibling to route against.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_activityGet daily activityARead-only
Returns the 24/7 activity samples for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample) from the /247samples API, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } } — 144 rows for a full day, one per 10 minutes (138 or 150 on the days the clocks change). A day without synced data returns []. Use list_daily_activity for a date range. Requires 24/7 Activity API subscription on apizone. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial behavior beyond that — 144 rows at one per 10 minutes, 138/150 rows on DST change days, empty array for unsynced days, and the local-time stamping of each sample. This is exactly the extra context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but well-structured: day scope, source API, return shape, row count, DST exception, empty case, alternative, prerequisite, and read-only marker all in one sentence. The return-shape detail is front-loaded enough to be usable, though the em-dash clause is heavy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return value: array of objects with timestamp (ISO 8601 + offset) and entryData fields with units, plus row count and the empty-day case. An agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the date parameter already documents format, pattern, examples, and the partial-today behavior, so the schema carries the load. The description's restatement of local-day semantics adds little beyond what the parameter description already states, matching the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (returns 24/7 activity samples for one local calendar day) with a precisely scoped resource, underlying API endpoint, and day definition. It explicitly names the sibling list_daily_activity as the range alternative, letting an agent distinguish it without reading any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear routing rule ('Use list_daily_activity for a date range') and a precondition (requires 24/7 Activity API subscription on apizone). It does not restate the today/future partial-data caveat here, though the schema parameter description covers it, so usage context is clear but not fully self-contained.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_activity_statisticsGet daily activity statisticsARead-only
Returns aggregated daily step count and energy consumption (joules) from the /247 API for the given datetime range. Response is an array of AggregatedActivityData objects, each with a Name ('stepcount' or 'energyconsumption'), Aggregation ('sum'), and Sources array containing per-device Samples with TimeISO8601 and Value. The window must be less than 28 days (exactly 28 is rejected). Samples with null Value indicate no data synced for that day. Each daily Sample is stamped local noon (TimeISO8601 like 2026-09-27T12:00:00+02:00); a one-day window (startdate = enddate = D) was observed returning the samples for D and the day after, so select samples by the date in TimeISO8601 rather than summing the response. Prefer this tool over list_daily_activity when you need totals rather than intraday time-series. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| enddate | Yes | End datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate. | |
| startdate | Yes | Start datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint/openWorldHint; the description goes far beyond them with the hard 28-day window limit, null-Value semantics (no data synced that day), local-noon timestamp stamping, and the observed one-day-window off-by-one quirk with an explicit workaround (select samples by TimeISO8601 date rather than summing). It also restates read-only, which is consistent with, not contradicting, the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and data source, then return shape, constraints, edge cases, and sibling routing in that order. Sentences are dense but each carries distinct operational information; nothing is restated filler despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of describing the return value and does so precisely: an array of AggregatedActivityData with Name, Aggregation, and Sources/Samples shape. Combined with the range constraint and timestamp caveat, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds real parameter-relevant meaning: the strict 'less than 28 days, exactly 28 rejected' boundary nuance beyond the schema's looser 'must be less than 28 days after startdate', plus the guidance to select samples by the TimeISO8601 date because of how start/end boundaries behave.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource (aggregated daily step count and energy consumption) and states the backing endpoint (/247 API) plus the required datetime range. It also distinguishes itself from the sibling list_daily_activity by contrasting totals vs. intraday time-series, so an agent can choose without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Prefer this tool over list_daily_activity when you need totals rather than intraday time-series.' The constraint 'window must be less than 28 days (exactly 28 is rejected)' tells the agent when a call will fail, which is actionable selection guidance rather than inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_snapshotGet daily snapshotARead-only
One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller. Output: { date, sleepNightOf, sleep, recovery, activity, workouts, errors }. sleep describes the NIGHT THAT LED INTO the date (sleepNightOf = the previous date, i.e. sleeps that began between noon on the previous day and noon on the date): { main (the longest non-nap sleep: sleepId, bedtimeStart, bedtimeEnd, durationS, deepS, lightS, remS, score, avgHrv, hrAvg, hrMin, spo2Max, latencyS, wasoS, wakeBeforeOffBedS — all durations in seconds: time to fall asleep, awake after falling asleep, awake in bed before getting up), otherNights (further non-nap sleeps, when the watch split a night), nightSleepS (total of main + otherNights, null when there is none), naps }. Suunto marks any sleep shorter than about 3 hours as a nap, so a short night appears under naps with main null. recovery covers the local calendar day: { samples, low: { balance, at }, high, first, last, morning: { balance, at } (the sample nearest the main sleep's bedtimeEnd — the waking value), atBedtime: { balance, at } (nearest its bedtimeStart, which falls on the previous local day), both null when there is no main sleep or no sample within an hour, stressStateSamples (samples per StressState) } or null without data. low is the day's lowest balance — not necessarily overnight (after an evening workout it can fall in the evening). activity: { steps, energyKcal } for the local day — energyKcal is the daily-statistics energy converted from joules; real days come out around 700-1,500 kcal, well below a resting rate, so it looks like ACTIVE energy rather than a total (not verified against the watch). A value is null, never 0, when Suunto has no sample for the date. workouts: the day's workouts (by their own local date) with { workoutKey, activityId, startLocal, totalTimeS, kcal, hrAvg, hrMax, tss (HR method), guide, hasLaps } — pass a workoutKey with hasLaps to get_workout_laps. Each section is fetched independently: one that fails is null and explained in errors, the others are still valid. With to, returns { from, to, days: [...], errors } instead (errors is shared by the whole range; a failed section is null in every day). Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Optional last day of a range (inclusive, at most 14 days from `date`). The result is then { from, to, days: [one entry per day, in the shape above without errors], errors } — one request per section for the whole range, so prefer it to calling this once per day. | |
| date | Yes | The local calendar day YYYY-MM-DD (the first day when `to` is given). Use yesterday or earlier for a complete day; today's data is partial until the watch has synced, and the night that led into today may still be in progress. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/openWorld, so the description carries the real burden and delivers: per-section independent fetch with partial failure semantics ('one that fails is null and explained in errors, the others are still valid'), the null-never-0 convention, the ~3-hour nap threshold, and the unverified energyKcal caveat. This is well beyond what the annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with a clear purpose sentence, and given the absent output schema most details earn their place. But it is delivered as one dense block of nested parentheticals that is hard to scan, and the shape could have been split into labeled sections.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must describe return values and does so exhaustively: the top-level shape, per-section field lists, range-mode shape, and error behavior. Nothing an agent needs to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3 and the schema already documents both params. The description adds value by documenting the return-shape switch when `to` is present and the local-calendar-day semantics of `date` including the midnight-to-noon sleep attribution window, going slightly past what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening states a specific verb+resource and positions it explicitly as an aggregation: 'One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller.' It then names the exact siblings it replaces (get_sleep, get_recovery, get_daily_activity_statistics, list_workouts), so an agent can distinguish it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use with alternatives named: 'Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand.' It also gives a when-not condition for the date param ('today's data is partial until the watch has synced') and the range alternative ('prefer it to calling this once per day').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recoveryGet recoveryARead-only
Returns recovery-balance samples from the /247samples API for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample), as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } } — 48 half-hourly rows for a full day (46 or 50 on the days the clocks change). A day without recovery data returns []. Use list_recovery for a date range. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, it discloses concrete behaviors: 404 without a Recovery API subscription, [] for a day with no data, 48 half-hourly rows (46/50 on clock-change days), and the local-time stamping. That is rich operational context an agent cannot get from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded, leading with the return shape and following with the routing hint and edge cases; every clause adds operational value. It is a single long sentence rather than cleanly separated, which slightly hurts readability but not content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although there is no output schema, the description fully specifies the return shape, field types, and value ranges (Balance 0.0–1.0, StressState enum mapping) plus the empty-array and subscription-failure cases. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the date format and the today-is-partial caveat, so baseline would be 3. The description adds edge-case meaning: the exact 00:00–23:59 local-day boundary and the clock-change row count that defines a 'full day'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns recovery-balance samples from the /247samples API') and pins the scope to one local calendar day. It explicitly names the sibling it is not (list_recovery), so an agent can distinguish it without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes range queries to list_recovery, and warns that today/future dates return empty or partial payloads, advising yesterday or earlier for complete results. This is clear when-to-use, when-not, and named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleepGet sleepARead-only
Returns the sleeps of one night from the /247samples API. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Plain array with one row per sleep — Suunto re-sends a sleep every time it revises it, and only the longest revision is kept — of { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. IsNap is true for any sleep shorter than about 3 hours, at any time of day, and can flip while a sleep is still being recorded — so it also marks a short fragment of a split night; do not drop rows by IsNap alone. A night can hold several rows (a split night, or a nap beside it): rows are not merged, so decide from BedtimeStart and Duration which belong together. Returns [] when no sleep began in that window, e.g. today's date before tonight. Use list_sleep for a range. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Date YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and open-world access, but the description adds critical behavior: Sleep API subscription requirement, 404 response, revision-deduplication behavior, unmerged split rows, and IsNap flipping. These go well beyond annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense with necessary domain nuance; it front-loads the return type and date semantics. However, it repeats the schema's date explanation and packs multiple caveats into a single paragraph, which slightly hurts scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return array shape, nested fields, and edge cases (empty array, revisions, split nights, IsNap caveats). It also covers auth requirements and sibling routing, leaving no critical gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the date-window semantics, so the baseline is 3. The description adds some distinct value by explicitly mentioning that afternoon naps are filed with the following night and giving multiple bedtime examples, but much of its date explanation repeats the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the sleeps of one night from the /247samples API') and names the sibling alternative ('Use list_sleep for a range'), so an agent can distinguish it immediately from range-based sleep queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes range queries to list_sleep, explains the noon-to-noon date window, notes that last night is filed under yesterday, and states that a subscription is required with 404 otherwise. When and when-not are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_upload_statusGet workout upload statusARead-only
Polls the processing status of a workout upload initiated by upload_workout. Returns status (e.g. 'Queued', 'Processing', 'Processed', 'Error') and the workoutKey once processing completes. Use the returned workoutKey with get_workout for full detail.
| Name | Required | Description | Default |
|---|---|---|---|
| uploadId | Yes | Upload ID returned by upload_workout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it readOnly and openWorld. The description adds concrete return behavior: the set of status values and the fact that workoutKey appears once processing completes, which helps the agent interpret results. It does not cover rate limits or auth, but with annotations present it adds useful context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core purpose, then return values, then next action. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter status tool with no output schema, the description adequately explains what is returned (status values and workoutKey) and how to proceed. Annotations cover safety, and the schema covers the input, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the single uploadId parameter is fully documented as the ID returned by upload_workout. The description reinforces the dependency but adds no syntax or format detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Polls') and resource ('processing status of a workout upload'), identifies the initiating sibling (upload_workout), and distinguishes its output from get_workout. An agent can tell this is a status-checking tool rather than a data-retrieval or upload tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly ties invocation to a prior upload_workout call and directs the agent to use the returned workoutKey with get_workout for full detail. It does not explicitly state when not to call it (e.g., avoid polling repeatedly), but the context and alternative are clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workoutGet workoutARead-only
Returns the base summary for one workout (about 1.6 KB): the same scalar fields as a list_workouts item (times, distance, energy, hrdata, tss/tssList, recoveryTime) plus extensionTypes, the list of data streams Suunto holds for it. It does NOT include laps, HR zones or other extension data — use get_workout_laps for laps and zone times, get_workout_fit for record-level data. Throws SuuntoNotFoundError if the workoutKey is malformed (not 24 hex characters) or does not exist. Use list_workouts to discover valid workoutKey values. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/open-world, and the description adds substantial behavior beyond them: approximate response size (~1.6 KB), the exact field set and extensionTypes, explicit exclusions, and the SuuntoNotFoundError failure mode for malformed or missing keys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the return shape, then exclusions/alternatives, then error behavior, then key discovery. Dense but every clause carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully compensates by describing the returned fields, the non-returned data, response size, and failure modes. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the opaque key and its discovery path. The description adds the malformed-key format detail ('not 24 hex characters') and reinforces the discover-via-list_workouts rule, marginally exceeding the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the base summary for one workout') and enumerates the exact scalar fields returned. It explicitly distinguishes itself from siblings get_workout_laps and get_workout_fit by naming what it does NOT include.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use get_workout_laps for laps/zone times, get_workout_fit for record-level data, and list_workouts to discover valid keys. The condition selecting each alternative is stated, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_fitGet workout FIT dataARead-only
Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON. Default (full=false): compact summary { sport, total_distance_km, avg_heart_rate, training_effect, laps (a COUNT only, not the laps), records_sample: { first, middle, last (one record each), count } }. Set full=true to receive every parsed FIT record and lap — pretty-printed, about 550 KB for a 35-lap strength session, so the result usually spills to a file. For per-lap data use get_workout_laps instead (about 2.5 KB); use full=true only when record-level data is required. An unknown workoutKey fails with a 403 Forbidden error here (not-found on the other workout tools). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | false (default): return compact summary. true: return all parsed FIT records. | |
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, it discloses non-obvious behavior: an unknown workoutKey returns 403 Forbidden HERE but not-found on other workout tools, and large results spill to a file. These are exactly the operational traits annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the default behavior, then the escape hatch, then the error quirk. Dense but every clause carries actionable information (size estimates, error code divergence, sibling pointer) with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so thoroughly, describing both the compact summary fields and the full payload nature. Combined with the error behavior and sibling routing, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further by spelling out the exact shape the full=false summary returns (sport, total_distance_km, records_sample structure) and the size consequence of full=true. This adds meaning beyond the terse schema text, though much of it is return-shape rather than parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON'), and immediately distinguishes itself from siblings by naming get_workout_laps as the per-lap alternative. An agent can tell what this does and how it differs from nearby tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes usage: default compact summary vs full=true for record-level data, with a concrete size signal ('about 550 KB for a 35-lap strength session, so the result usually spills to a file') and a named alternative ('For per-lap data use get_workout_laps instead (about 2.5 KB)'). It even states the exclusivity condition ('use full=true only when record-level data is required').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_lapsGet workout lapsARead-only
Returns the manual laps of one workout as a compact table, plus its training-load fields — the way to read back a guided gym session set by set (push_strength_guide records one lap per set and per rest; push_workout_guide one lap per exercise and one per rest between exercises). A session from push_interval_guide auto-advances and is expected to record no manual laps (unverified), so it should return an empty table. About 2.5 KB for a 35-lap strength session, versus ~550 KB for get_workout_fit full=true. Output: { workoutKey, activityId, startTime (epoch ms), totalTimeS, guide: { id, name } | null (the guide that ran, as recorded by Suunto — not looked up in list_guides, because guides are often deleted afterwards), tss: [{ method (seen so far: 'HR', 'MET'), value }], pte, peakEpoc, recoveryTime (from the workout's summary extension; units not verified, and it can differ from the recoveryTime that list_workouts and get_workout carry), hrZoneTimeS: [zone1..zone5 seconds], feeling (the answer to the watch's 'How was it?' question, passed through as Suunto sends it; null when skipped), lapCount, checks: [{ code, detail }], laps: { cols, rows } }. checks lists reasons not to trust positional reading of the table (empty when clean): 'duplicate-rest' (the same rest label twice in a row — a set lap is missing or a rest was split), 'no-session-complete' (a guided table without its final lap — session ended early, buttons locked or watch restarted), 'unlabelled-laps' (some laps have no guide label), 'no-heart-rate' (no lap has heart rate, e.g. battery mode Tour). laps.cols = [i (1-based), startOffsetS (from workout start), durationS, hrAvg, hrMax, hrMin (bpm), kcal, kind, label]; each row is an array in that order. label is the text of the guide step that was active during the lap (lines joined with ' | '), or null when no guide ran. kind is 'rest' when the label contains 'Next:' at its start or after a '·' (a per-set rest lap reads 'Next: set k/S', or 's target · Next: set k/S' with restMode 'stopwatch'), 'done' for the final 'Session complete' lap, 'step' for any other labelled lap, null when there is no label. A per-set strength guide yields, per exercise, a prep lap, then set 1, rest, set 2, rest, … — 2 × sets laps — and one trailing 'Session complete' lap for the whole session; a prep lap and a set lap look alike in the label, so tell them apart by position. Real sessions can deviate (skipped or repeated rest laps), so check the labels rather than only counting. A workout without manual laps (unguided gym, cycling) returns lapCount 0 and laps.rows [] — not an error. Call list_workouts first for the workoutKey.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | The 24-character workoutKey returned by list_workouts. Anything else fails with a not-found error without calling Suunto. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial context the annotations cannot supply: payload size, the checks codes that flag untrustworthy positional reads, the fact that real sessions deviate (skipped/repeated rests), the caveat that recoveryTime can differ from list_workouts/get_workout, and that guide is recorded by Suunto rather than looked up because guides are often deleted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and the sibling comparison before diving into output detail, so the most decision-relevant content comes first. It is dense and delivered as one long block, but with no output schema the detail is load-bearing rather than padding; slightly better visual structure would help.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining the return shape and does so exhaustively: field-by-field output, laps.cols ordering, label/kind derivation rules, and the checks codes. It also warns about positional-reading pitfalls, leaving nothing an agent needs to interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is already documented there, including the 24-character constraint and not-found failure mode. The description's 'Call list_workouts first for the workoutKey' mostly restates the schema's provenance note, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the manual laps of one workout as a compact table, plus its training-load fields') and immediately scopes the use case to guided gym sessions read back set by set. It also distinguishes itself from get_workout_fit by quantifying the size difference (~2.5 KB vs ~550 KB), so an agent can separate the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing context: use it for push_strength_guide and push_workout_guide sessions, expect no laps from push_interval_guide, and fall back to get_workout_fit for the full payload. It also states the prerequisite ('Call list_workouts first for the workoutKey') and clarifies that an empty table is not an error, removing the most likely false-negative inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_samplesGet workout samplesARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/samples) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Use get_workout_fit with full=true for record-level data (heart rate etc.), or get_workout_laps for laps. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint/openWorldHint; the description adds the critical behavioral fact that the endpoint currently returns 401 OperationNotFound and fails, that this is not an auth failure, and that the tool is retained for future restoration. That is exactly the kind of operational context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with 'UNAVAILABLE', then the failure mode, then the alternatives, then the retention rationale. Every clause earns its place; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description supplies everything needed: it is broken right now, why, and what to call instead. Nothing an agent needs to avoid misusing this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single workoutKey parameter is already richly documented (opaque, discover via list_workouts, throws SuuntoNotFoundError). The description adds nothing about parameters, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description makes clear this tool retrieves workout sample (record-level) data for a given workout, and it distinguishes itself from siblings by naming get_workout_fit and get_workout_laps as the working alternatives. It is slightly indirect — the functional purpose is inferred from the routing sentence rather than stated as a standalone verb+resource — but an agent can still tell what it is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit, unambiguous routing: the endpoint is rejected, the call fails with 'endpoint unavailable', this is not an authentication problem, and the agent should use get_workout_fit with full=true for record-level data or get_workout_laps for laps. Both the when-not and the alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_daily_activityList daily activityARead-only
Returns 24/7 activity samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } }. Days without synced data are simply absent. Use get_daily_activity for a single day or get_daily_activity_statistics for aggregated daily step/energy totals. Requires 24/7 Activity API subscription on apizone. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals). | |
| from | Yes | Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, it discloses the output shape (array of timestamp + entryData with HR, StepCount, EnergyConsumption), the absence-instead-of-error behavior for unsynced days, chronology, and the subscription requirement. This is unusually rich behavioral context for a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One long sentence but front-loaded and dense: resource and request first, output shape second, alternatives and constraints last. Every clause carries information, though the parenthetical nested object definition makes it heavier to parse than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description fully specifies the return structure, ordering, missing-day behavior, and the API subscription gate. Combined with the 100%-covered input schema, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents format, inclusivity, and size guidance, so the baseline is 3. The description adds genuine param-level semantics: intervals are interpreted in the local time the watch stamped on each sample, and results are ordered chronologically, which the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource (returns 24/7 activity samples from /247samples) with explicit scope (local calendar days [from, to] inclusive). It directly distinguishes itself from the sibling tools get_daily_activity (single day) and get_daily_activity_statistics (aggregated totals), so an agent can route without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use this tool versus the two alternatives, names those alternatives, and adds a hard prerequisite (24/7 Activity API subscription on apizone) plus a range-size preference. Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_guidesList SuuntoPlus guidesARead-only
Returns all SuuntoPlus Guides (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, newest first. Each item includes id, name, description, owner, localDate, and usage. Use the id with delete_guide, or with push_*_guide's guideId param to update an existing guide instead of creating a new one. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, and the description redundantly confirms 'Read-only'. It adds genuine context beyond annotations: the ordering (newest first) and the fact that it returns ALL guides with no pagination/limit caveat mentioned. No auth or rate-limit detail, but nothing contradicts annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the verb+resource+ordering, followed by the returned fields and the actionable id usage. No filler; every sentence carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fills the gap by enumerating returned fields and ordering, and it explains the follow-up call pattern with delete_guide and push_*_guide. Combined with annotations covering the safety profile, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline of 4 applies. The description correctly implies no filtering (returns all guides on the account) and details the fields present on each returned item (id, name, description, owner, localDate, usage), which compensates for the absent output schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Returns all SuuntoPlus Guides') and scopes the sources (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, plus ordering (newest first). An agent can distinguish this from sibling list_* tools without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent downstream: use the id with delete_guide, or with push_*_guide's guideId to update an existing guide rather than create a new one. There is no competing 'list guides' sibling, so no when-not-to-use exclusion exists, but the context for use is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recoveryList recoveryARead-only
Returns recovery-balance samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } }. Days without recovery data are simply absent. Use get_recovery for a single day. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output. | |
| from | Yes | Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, and the description redundantly restates read-only but adds real value beyond them: the Recovery API subscription requirement and the 404 behavior without it, the chronological ordering guarantee, and the silent omission of empty days. It stops short of pagination or rate-limit detail, so 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behavior and return shape in one dense sentence, then adds short supporting sentences for the alternative and the subscription constraint. The parenthetical balance/StressState enumeration is long but earns its place because there is no output schema to carry it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return structure, ordering, missing-day behavior, and the auth/error profile, so nothing an agent needs to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds semantics the schema does not: that days are interpreted in the local time the watch stamped on each sample, and that the output is a plain array. This meaningfully clarifies the temporal boundary beyond the raw date pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Returns) and resource (recovery-balance samples) with precise scope: local calendar days [from, to] inclusive, chronological ordering, and the exact return shape. It explicitly contrasts with get_recovery for a single day, so an agent can distinguish it from siblings without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative explicitly ('Use get_recovery for a single day') and gives the selecting condition (single day vs. range). It also warns days without data are simply absent, so the agent will not misread an empty stretch as an error.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_routesList routesARead-only
Returns all routes saved in the user's Suunto account. Each route: id, description, visibility, distance (m), start/end coordinates, waypoint count. Use export_route to get the GPX track for navigation. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so 'Read-only' largely repeats structured data. However, the description adds genuinely useful context beyond annotations by describing the per-route payload (id, description, visibility, distance in m, start/end coordinates, waypoint count), compensating for the absence of an output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, none wasted: purpose, return shape, and routing to the sibling tool, with the primary purpose front-loaded. Optimal size for a simple list operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, describing the returned route fields is exactly the right compensation and is done here. The only minor gap is absence of pagination/volume hints for an 'all routes' call, but overall the definition is complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is nothing to disambiguate; baseline for a zero-parameter tool is 4. No parameter-related confusion is possible here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Returns all routes'), the resource, and the scope ('saved in the user's Suunto account'), then enumerates the returned fields. It is immediately distinguishable from siblings like export_route without needing the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to the right alternative: 'Use export_route to get the GPX track for navigation,' making the boundary between listing and exporting clear. No explicit when-not guidance is given, but the alternative is named with its triggering condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sleepList sleepARead-only
Returns the sleeps of the nights [from, to] inclusive from the /247samples API, ordered chronologically by bedtime. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Same rows as get_sleep, one per sleep (revisions collapsed): { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. Nights without recorded sleep are simply absent. Use get_sleep for a single night. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Last bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness. | |
| from | Yes | First bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld; the description adds substantial behavioral context beyond them: the noon-to-noon 'night' filing rule, chronological ordering, revision collapsing ('one per sleep'), 404 auth behavior, and that absent nights are simply not present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing, then schema/return detail. The inline entryData field enumeration is dense but justified since no output schema exists. Length is high but most sentences carry distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies the full return shape (timestamp, entryData fields) plus the semantic caveats needed to interpret dates correctly. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds interpretive depth (a date means the NIGHT beginning at noon, 23:00/00:30/03:00 bedtimes all map to one date, naps file with the following night). That said, it largely restates the schema's own 'date went to bed, not woke up' note.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the sleeps of the nights') with explicit scope (from/to, /247samples API, ordered chronologically by bedtime). It distinguishes itself from the sibling get_sleep by naming it and its different use case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Use get_sleep for a single night.' It also states a prerequisite ('Requires Sleep API subscription on apizone; returns 404 without it') and notes that missing nights are silently omitted rather than errors.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_subscriptionsList webhook subscriptionsARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/subscriptions) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error rather than returning a list. Would return the active webhook subscriptions as an array of { id, eventType, callbackUrl, createdAt }. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds the critical behavioral fact that the gateway rejects the endpoint with a 401 OperationNotFound and that the call surfaces an 'endpoint unavailable' error. It also specifies the intended return shape { id, eventType, callbackUrl, createdAt }, which is far beyond annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences that each carry distinct information: the failure, the intended return shape, and the rationale for keeping the tool. The structure is front-loaded with the unavailability. Slight redundancy between the first sentence's error description and the parenthetical, but no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description covers everything an agent needs: current failure mode, expected error behavior, and the intended return payload. Nothing actionable is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero properties, so the baseline is 4; there is nothing for the description to disambiguate. It does not add parameter detail, but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the exact resource (active webhook subscriptions at /v2/subscriptions) and what it would return, and no sibling tool covers subscriptions, so it is trivially distinguishable. It also front-loads that the endpoint is currently unavailable, which is the single most important fact about this tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent the call will fail with an 'endpoint unavailable' error rather than returning data, which is effectively a strong 'do not use' signal, and explains the tool is retained for future restoration. It stops short of naming an alternative for listing subscriptions, but no sibling offers that capability.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workoutsList workoutsARead-only
Returns the user's recent Suunto workouts ordered newest-first (Workout API v3). Each item: workoutKey (string id), activityId (numeric activity code — there is no separate plain-language 'sport' field; use get_workout_fit for the parsed FIT file's session.sport if a sport name is needed), startTime (epoch ms), totalTime (s), totalDistance (m), totalAscent (m), totalDescent (m), energyConsumption (kilocalories, not 'totalCalories'), hrdata: { avg, max } (workout heart rate — hrdata.max is the account's overall max HR, use hrdata.workoutMaxHR for this specific workout's peak). Auto-paginates with offset-based pagination until limit is reached or no more workouts exist. Each item also embeds SummaryExtension (including apps[]: the SuuntoPlus guide that ran, if any) and IntensityExtension (HR-zone times). Use get_workout_laps for the lap table of a single workout. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout. | |
| since | No | ISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size. | |
| until | No | ISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/open-world, and the description adds genuine behavioral detail beyond them: auto-pagination semantics ('until limit is reached or no more workouts exist'), plus field-level traps (hrdata.max is the account's overall max HR, not the workout peak; energyConsumption is not totalCalories; no plain-language sport field exists). These gotchas materially change how an agent interprets results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense paragraph, front-loaded with the core action before field details. It is long, but with no output schema the field-level exposition earns its place; the sole weakness is that field descriptions and usage hints are interleaved rather than separated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema in structured form, the description compensates by enumerating the returned shape (workoutKey, activityId, startTime, totalTime, distance, ascent/descent, energy, hrdata, SummaryExtension, IntensityExtension). An agent has enough to call it and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents limit, since, and until thoroughly. The description adds only the pagination caveat ('auto-paginates... until limit is reached'), which the schema also states, so it does not meaningfully exceed the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Returns/list), resource (user's recent Suunto workouts), and ordering (newest-first), with versioning (Workout API v3). An agent can immediately distinguish it from get_workout (single) and get_workout_laps (lap table).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to alternatives for adjacent needs ('use get_workout_fit for the parsed FIT file's session.sport', 'Use get_workout_laps for the lap table of a single workout'). It gives clear context for related lookups but never states the inverse boundary (e.g. list vs. fetch a specific workout) or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_interval_guidePush interval guide to watchADestructive
Pushes an interval/cardio guide (warmup, timed or distance-based work intervals, recoveries, optional repeats) to the user's Suunto account via the SuuntoPlus Guide Cloud API. Unlike push_workout_guide (manual lap-per-exercise), interval segments auto-advance by elapsed time or distance — hands-off during a run or ride. Each segment can show a target heart-rate range alongside live HR. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. Same delivery caveat as push_workout_guide: appears after the phone's next normal Suunto app sync, no live push. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. '4x4 VO2max'. | |
| blocks | Yes | Ordered list of blocks. A block with times>1 repeats its segments as a unit (e.g. 4x[interval,recovery]) — put only the segments that repeat inside it; warmup/cooldown go in their own times=1 blocks before/after. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write/destructive/openWorld/non-idempotent, so the safety profile is covered. The description adds genuinely new context beyond them: the exact-match SUUNTO_APP_NAME env var requirement and the delivery caveat (no live push; appears after the next normal sync). It stops short of explaining the destructive aspect — that supplying guideId overwrites an existing guide — which the destructiveHint=true flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence, followed by comparison, environment prerequisite, and delivery caveat. It is dense but every sentence carries distinct information; the 'Write operation.' tail is mildly redundant with annotations but otherwise there is little waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive write tool with no output schema and full schema coverage, the definition covers purpose, alternative routing, environment requirement, and delivery latency. The main remaining gap is not spelling out the overwrite behavior when guideId is supplied, but overall an agent has what it needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (date, title, blocks/segments, guideId) is already richly documented. The description describes the segment/block model conceptually (warmup, intervals, recoveries, repeats, target HR) but adds no syntax or format details beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Pushes an interval/cardio guide ... to the user's Suunto account') plus the underlying mechanism (SuuntoPlus Guide Cloud API). It explicitly contrasts itself with the sibling push_workout_guide, so an agent can distinguish it without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative (push_workout_guide) and gives the exact condition that selects this tool: interval segments auto-advance by elapsed time or distance for a hands-off run/ride, versus manual lap-per-exercise. It also supplies the required SUUNTO_APP_NAME precondition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_strength_guidePush strength guide to watchADestructive
Pushes a resistance-training guide to the user's Suunto account via the SuuntoPlus Guide Cloud API — the tool to use for gym sessions. Per exercise: a prep step (self-paced stopwatch showing the plate breakdown if given, otherwise the weight/sets detail, plus the exercise name and live HR; a lap press starts the exercise), then with lapGranularity 'perSet' (default) each set is its own step ended by a lap press, and each rest between sets is its own step showing 'Next: set k/S'. restMode 'countdown' (default) counts down restSec and auto-advances into the next set with a vibration; 'stopwatch' counts up and waits for a lap press. lapGranularity 'perExercise' gives one step per exercise after its prep, with no between-set rests and no per-set laps. Every prep, set and rest is its own lap and the guide ends with one extra 'Session complete' step, so a perSet session records 2 × (total sets) + 1 laps. Read them back after the workout with get_workout_laps — its labels are the step texts. Requires SUUNTO_APP_NAME to exactly match the app name registered on apizone.suunto.com. Without guideId a new guide is created on every call (see list_guides / delete_guide to tidy up); with guideId that guide is overwritten. There is no live push to the watch: it appears after the phone's next normal Suunto app sync. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. 'Push A'. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. | |
| restMode | No | Rest between sets. 'countdown' (default): counts down from restSec and auto-advances into the next set. 'stopwatch': counts up and waits for a lap press — the user paces it. Has no effect with lapGranularity 'perExercise' (no between-set rests). Before/between exercises is always a self-paced stopwatch. | countdown |
| exercises | Yes | ||
| lapGranularity | No | 'perSet' (default, recommended): one step per set plus one per rest, so laps bound every set/rest individually — needed to read per-set HR and duration from the synced workout. 'perExercise': one step per whole exercise instead, like push_workout_guide — shorter Guide list, coarser data. | perSet |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false) by disclosing non-obvious behavior: no live push to the watch (appears on next phone sync), the SUUNTO_APP_NAME exact-match requirement, create-on-every-call without guideId vs overwrite with it, and the lap-recording formula 2×(total sets)+1. This is exactly the kind of context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and nearly every clause carries functional information (lap math, sync behavior, mode interactions). It is nonetheless a dense single block of ~200 words with no formatting, which makes it slower to parse than a structured layout would for a tool this complex.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex write tool with no output schema, the description covers the write semantics, idempotency caveat, environment prerequisite, sync timing, and readback path, leaving little an agent would need to call it correctly. Return values are appropriately delegated to get_workout_laps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 83% (>80%), so the schema already documents most parameters and the baseline is 3. The description adds genuine cross-parameter meaning beyond the schema: restMode's interaction with lapGranularity, the prep-step/lap flow, and the plate-vs-detail display logic, which helps the agent reason about effects the per-field schema does not connect.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Pushes a resistance-training guide to the user's Suunto account') and explicitly positions itself against siblings ('the tool to use for gym sessions', references to push_workout_guide, list_guides, delete_guide, get_workout_laps). An agent can distinguish this from push_workout_guide and push_interval_guide without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear when-to-use routing ('the tool to use for gym sessions') and conditional guidance for the guideId create-vs-overwrite behavior, with pointers to list_guides/delete_guide for cleanup and get_workout_laps for readback. It does not explicitly state when to prefer push_workout_guide over this tool beyond the terse 'like push_workout_guide' aside, so it stops short of full alternative selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_workout_guidePush workout guide to watchADestructive
Pushes a text-step workout guide to the user's Suunto account via the SuuntoPlus Guide Cloud API. Each exercise becomes one step, advanced by a lap-button press on the watch. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. There is no live push to the watch itself — delivery depends on the phone's normal Suunto app sync. In testing it showed up on the watch after the next ordinary sync with no manual pinning needed; if it doesn't appear, check the Suunto app under SuuntoPlus Guides and pin it there. For gym sessions prefer push_strength_guide: it records one lap per set and per rest, which get_workout_laps can read back. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. 'Push A'. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. | |
| exercises | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-idempotent write (readOnlyHint=false, destructiveHint=true, openWorldHint=true), and the description adds substantial context beyond that: no live push to the watch, delivery depends on the phone's next normal sync, and a fallback pinning procedure. It also discloses the guideId update-vs-create behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in sentence one, followed by mechanics, constraints, troubleshooting, and sibling routing in a logical order. It is on the longer side and the troubleshooting sentence could be trimmed, but each sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with no output schema, the description covers everything needed: the required env var, that the operation is a create-or-update depending on guideId, the lack of a live push, the sync dependency, and the correct sibling for gym sessions. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so date/title/exercises/guideId are mostly documented structurally. The description adds meaning beyond the schema by explaining that each exercise becomes one watch step advanced by a lap-button press, which clarifies how the exercises array is consumed. It doesn't add syntax detail for date or guideId.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Pushes a text-step workout guide') and names the exact mechanism (SuuntoPlus Guide Cloud API). It also distinguishes itself from the two sibling pushers by explaining that exercises map to lap-button steps, which push_strength_guide and push_interval_guide do differently.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'For gym sessions prefer push_strength_guide' with the reason (one lap per set/rest, readable by get_workout_laps). It also states the precondition (SUUNTO_APP_NAME must match the registered name) and what to do on failure (pin under SuuntoPlus Guides).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_workoutUpload workout fileA
Uploads a workout file to the user's Suunto account. Provide the absolute path to the file on disk. The file is pushed to Suunto and appears in the app after processing (usually a few seconds). Returns an uploadId you can poll with get_upload_status. Suunto's own upload API docs state only .fit (binary) is currently supported for this endpoint — a .gpx path is still accepted here (sent as application/gpx+xml) in case that changes, but treat it as unverified; use .fit for a workout that must reliably show up. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| comment | No | Longer notes for the workout. Optional. | |
| privacy | No | Visibility. DEFAULT uses the account's default setting. | DEFAULT |
| filePath | Yes | Absolute path to the .fit or .gpx file on disk. | |
| description | No | Short workout title shown in the Suunto app. Optional. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the closing 'Write operation.' is largely redundant. The description earns credit for behavior beyond the annotations: server-side processing delay before the workout appears, and the return of an uploadId that must be polled via get_upload_status.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action, path requirement, and polling workflow are front-loaded in the first sentences; the trailing .fit/.gpx caveat is long but carries real decision-relevant information. Slightly verbose, nothing clearly wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by explaining the uploadId return and the polling path. Missing secondary details (size limits, auth/permission requirements, failure behavior), which matters for an open-world, non-idempotent write.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuinely new semantics: the endpoint officially supports only .fit binary, the .gpx path is accepted but unverified behavior. It restates the absolute-path requirement, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Uploads a workout file to the user's Suunto account') and clearly separates this from siblings like push_workout_guide and export_workout_gpx, which move structured guides or export data rather than uploading a file from disk.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear conditions for choosing a format ('use .fit for a workout that must reliably show up', .gpx is unverified) and names the follow-up tool (get_upload_status). It stops short of comparing this tool against other upload/push siblings, so no explicit when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.18.0- Added
get_daily_snapshot
9 tool updates
v0.15.1- Changed
generate_daily_digest1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — Suunto syncs once daily, so today's data is usually incomplete."New value: +"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced."
- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_daily_activity_statistics3 fields changed- changed
Input schema / properties / enddate / descriptionPrevious value: -"End datetime in ISO-8601 format (e.g. 2026-04-30T23:59:59). Must be within 28 days of startdate."New value: +"End datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate." - changed
Input schema / properties / enddate / examplesPrevious value: -[ - "2026-04-30T23:59:59" -]New value: +[ + "2026-04-27T23:59:59" +] - changed
Input schema / properties / startdate / descriptionPrevious value: -"Start datetime in ISO-8601 format (e.g. 2026-04-01T00:00:00). Data is stored in UTC."New value: +"Start datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins."
- Added
get_workout_laps - Changed
list_daily_activity1 field changed- changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals)."
- Changed
list_recovery1 field changed- changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output."
- Changed
push_strength_guide2 fields changed- changed
Input schema / properties / exercises / items / properties / detail / descriptionPrevious value: -"Display string shown on the exercise's set steps and on the prep screen before it — include weight and sets, e.g. '60kg 3x10'."New value: +"Display string shown on the exercise's set steps, and on the prep screen before it unless 'plates' is given — include weight and sets, e.g. '60kg 3x10'." - added
Input schema / properties / exercises / items / properties / platesAdded value: +{ + "description": "Per-side plate breakdown for barbell exercises, e.g. '2x20+1x5/side' — shown on the prep screen instead of detail, since that's when the bar actually gets loaded. Omit for non-barbell exercises (dumbbell, machine, bodyweight, cable); compute the math yourself before calling this tool, it isn't done here.", + "type": "string" +}
3 tool updates
v0.15.0- Added
delete_guide - Added
list_guides - Added
push_strength_guide
2 tool updates
v0.14.4- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
2 tool updates
v0.14.1- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."
- Changed
list_sleep2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404."New value: +"First bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"Last bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
7 tool updates
v0.14.0- Added
export_route - Added
generate_daily_digest - Added
get_upload_status - Added
list_routes - Added
push_interval_guide - Added
push_workout_guide - Added
upload_workout
1 tool update
v0.10.0- Added
get_daily_activity_statistics
11 tool updates
v0.9.2- Changed
export_workout_gpx1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Wake-up date YYYY-MM-DD. Example: 2026-04-20."New value: +"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."
- Changed
get_workout1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
get_workout_fit1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first."
- Changed
get_workout_samples1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
list_daily_activity2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_recovery2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_sleep2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_workouts3 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum number of workouts to return (1–1000). Defaults to 25."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout." - changed
Input schema / properties / since / descriptionPrevious value: -"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z."New value: +"ISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size." - changed
Input schema / properties / until / descriptionPrevious value: -"ISO 8601 upper bound on startTime (inclusive)."New value: +"ISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window."
7 tool updates
v0.9.1- Changed
get_daily_activity3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
get_recovery3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
get_sleep3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
list_daily_activity6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_recovery6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_sleep6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_workouts2 fields changed- added
Input schema / properties / since / examplesAdded value: +[ + "2026-04-01T00:00:00Z" +] - added
Input schema / properties / until / examplesAdded value: +[ + "2026-04-30T23:59:59Z" +]
11 tool updates
v0.9.0- Changed
export_workout_gpx2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_daily_activity3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_recovery3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_sleep3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Wake-up date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_workout2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_workout_fit3 fields changed- changed
Input schema / properties / full / descriptionPrevious value: -"If true, returns ALL parsed records (large). Default false returns a summary + sampled records."New value: +"false (default): return compact summary. true: return all parsed FIT records." - added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_workout_samples2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
list_daily_activity6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD (inclusive)"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD (inclusive)"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_recovery6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_sleep6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD"New value: +"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_workouts8 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Max workouts to return."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25." - added
Input schema / properties / limit / maximumAdded value: +1000 - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / limit / typePrevious value: -"number"New value: +"integer" - changed
Input schema / properties / since / descriptionPrevious value: -"ISO 8601 datetime — only workouts on/after this time."New value: +"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z." - added
Input schema / properties / since / formatAdded value: +"date-time" - changed
Input schema / properties / until / descriptionPrevious value: -"ISO 8601 datetime — only workouts on/before this time."New value: +"ISO 8601 upper bound on startTime (inclusive)." - added
Input schema / properties / until / formatAdded value: +"date-time"
12 tool updates
v0.1.0- First observed
export_workout_gpx - First observed
get_daily_activity - First observed
get_recovery - First observed
get_sleep - First observed
get_workout - First observed
get_workout_fit - First observed
get_workout_samples - First observed
list_daily_activity - First observed
list_recovery - First observed
list_sleep - First observed
list_subscriptions - First observed
list_workouts
TDQS
Scored across 25 tools
Most tools have clearly distinct purposes and the descriptions explicitly route between overlapping ones (get_daily_activity vs list_daily_activity vs get_daily_activity_statistics, get_sleep vs list_sleep, get_recovery vs list_recovery, and the get_workout/get_workout_fit/get_workout_laps trio). The single-day/get vs range/list pairs are genuinely near-duplicates and could be misselected, but the descriptions actively steer the agent and the three clearly-labelled UNAVAILABLE tools reduce confusion rather than add it.
All 25 tools follow a consistent snake_case verb_noun pattern (list_*, get_*, push_*, export_*, upload_*, delete_*, generate_*). Verbs map predictably to read vs write operations, and there are no mixed conventions or camelCase deviations.
25 tools is on the heavy side for a single-account fitness/health API. The breadth of the Suunto domain (sleep, recovery, activity, workouts, routes, guides, upload, digest) justifies much of it, but three unavailable endpoints are dead weight and the get/list single-vs-range pairs are redundant surface that bloats the set.
The surface covers the full read lifecycle for sleep, recovery, activity, workouts, routes, and guides, plus write operations for uploads and guide management and an aggregation tool. Minor gaps exist (e.g. no route creation, no user/profile or subscription management beyond a broken read, no guide editing beyond overwrite), and three endpoints are non-functional, but core workflows are complete.
Maintenance
Related MCP Connectors
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server for Polar Signals Cloud continuous profiling platform, enabling AI assistants to analyze CPU performance, memory usage, and identify optimization opportunities in production systems.9-
- FlicenseNot gradedqualityDmaintenanceEnables ChatGPT to access and analyze personal Garmin health data including daily steps, heart rate, calories, sleep duration, and body battery levels. Collects data via webhook from Garmin devices and provides health insights through natural language queries.2-
- AlicenseAqualityNot gradedmaintenanceEnables interaction with Siemens Polarion requirements management system through natural language. Supports authentication, project management, work item queries, document access, and requirements analysis.9MIT
- AlicenseNot gradedqualityDmaintenanceConnects WHOOP fitness data to Claude Desktop, enabling natural language queries about workouts, recovery, sleep patterns, and physiological cycles with secure OAuth authentication and local data storage.61 npm27MIT