Suunto MCP
Suunto MCP
Спрашивайте Claude что угодно о своих тренировках. Suunto MCP подключает данные ваших часов Suunto к Claude, чтобы вы могли просто разговаривать со своими данными, а не кликать по дашбордам.
Создано пользователем Suunto, который хотел спросить: «Как прошла моя последняя длительная пробежка?» — и получить реальный ответ с цифрами, а также передавать живые данные тренировок личному ИИ-тренеру.
🏃 Для обычных пользователей Suunto: в документации Suunto API сказано, что доступ предназначен только для коммерческих партнёров — это не вся картина. Частные пользователи тоже получают доступ. Просто одобрение после подачи заявки занимает 3–4 недели. Подайте заявку, подождите и пользуйтесь. Не позволяйте этой оговорке вас остановить. ✅
Что вы можете сделать
После настройки просто спрашивайте:
«Сколько километров я пробежал в этом месяце?»
«Сравни мои последние три длительные пробежки — дрейф пульса улучшился?»
«Вытащи GPX вчерашней трейловой пробежки и сделай короткую запись в дневник.»
«Какова динамика моего среднего пульса в покое за последние две недели?»
«Суммируй мою тренировочную неделю в стиле отчёта тренера.»
«Мне что-то нездоровится — как мои показатели восстановления выглядят по сравнению с прошлым месяцем?»
«Найди все тренировки, где мой средний пульс был выше 160 ударов в минуту.»
«Какая из моих пробежек в этом году была с самым большим набором высоты?»
Claude сам разбирается, какие данные нужно запросить. Вы просто спрашиваете.
Но это не только чтение — Claude также может отправлять данные на ваши часы:
«Запланируй сегодняшнюю тренировку в зале и отправь её на мои часы.»
«Загрузи вчерашний экспорт Garmin как тренировку Suunto.»
«Экспортируй мой последний маршрут в GPX, чтобы я мог им поделиться.»
Смотрите раздел Что можно отправлять на часы ниже.
Related MCP server: Garmin MCP Server
🤖 Не хотите делать это сами? Пусть это сделает Claude Code
Если у вас уже есть Claude Code, вам не нужно вводить ни одной команды. Просто откройте его и скажите:
«Пожалуйста, установите и настройте suunto-mcp из https://github.com/googlarz/suunto-mcp»
Claude Code сам склонирует репозиторий, выполнит все команды установки и добавит всё в конфигурацию Claude Desktop. Именно так это сделал автор проекта: без ручной работы в терминале.
Но есть три вещи, которые останутся за вами независимо ни от чего, — по замыслу, а не из-за отсутствия инструментов:
Создание аккаунта на apizone.suunto.com — Claude не может создавать аккаунты от вашего имени.
Веб-форма apizone (имя вашего приложения, отображение ключа подписки) — это ваша сессия; Claude точно говорит, куда нажать, но нажать за вас не может.
Нажатие кнопки «Authorize» во время входа — это OAuth работает так, как надо. Приложение, способное одобрить собственный доступ, не было бы безопасным.
Claude подскажет вам точно, что и когда сделать для каждого из этих пунктов.
Если вы хотите сделать всё вручную, читайте дальше.
Что вам понадобится
Прежде чем начинать, убедитесь, что у вас есть:
Часы Suunto, синхронизированные с приложением Suunto (любая современная модель — Race, Vertical, 9 Peak, 5 Peak, Ocean и т. д.)
Claude Desktop (или другое MCP-совместимое ИИ-приложение)
Node.js — бесплатно, скачать здесь, выберите версию «LTS»
Git — бесплатно, скачать здесь
~5 минут на отправку заявки + 3–4 недели ожидания одобрения Suunto + ~15 минут на установку
После того как вы всё завершите, повторять это не придётся.
Настройка
Предпочитаете пошаговое руководство с выбором темпа заранее (быстрый путь или объяснение по шагам) и полноценное объяснение, как работает синхронизация? Смотрите GETTING_STARTED.md. Здесь приведены те же шаги в справочной форме.
Настройка состоит из трёх частей:
Регистрация на портале разработчиков — сообщает Suunto, что вашему приложению разрешено читать ваши данные
Установка и настройка — запускает программное обеспечение на вашем компьютере
Подключение к Claude — позволяет ИИ находить и использовать сервер
Часть 1: Регистрация на портале разработчиков в Suunto (~5 минут, затем ожидание 3–4 недели)
У Suunto есть бесплатный портал разработчиков под названием apizone, где вы регистрируете приложения, имеющие доступ к ваших данным. Вы создадите аккаунт, подпишетесь на тарифный план данных и зарегистрируете небольшое «приложение» — не переживайте, ничего создавать не нужно. Это просто имя и пароль которые вы придумаете.
Шаг 1: Создайте свой аккаунт apizone
Перейдите на apizone.suunto.com и зарегистрируйтесь или войдите.
Используйте ту же электронную почту, что и для приложения Suunto. Если у вас есть аккаунт Sports Tracker, он тоже подойдёт — это одна и та же система входа.
Шаг 2: Подписка на Developer API
После входа в систему пройдите все действия в руководстве How to start — там поэтапно описано, как подписаться на Developer API. Это бесплатно и даёт доступ к истории ваших тренировок.
Важно: на сайте Suunto указано, что доступ к API предназначен только для коммерческих партнёров — не обращайте внимания. Частные пользователи тоже получают доступ, просто одобрение подписки занимает 3–4 недели. Подайте заявку и подождите.
Также могут появиться другие продукты, например «Sleep API», «Recovery API», «Daily Activity API». Пока пропустите их — про ознакомление Developer API достаточно. Остальные можно добавить позже, если захотите видеть данные о сне и восстановлении в Claude.
⏳ Остановитесь и подождите. После того как вы оставили заявку, Suunto должно одобрить ваш запрос. Это занимает 3–4 недели. Когда всё будет готово, вы получите письмо. Возвращайтесь к шагам 3–4 только после того, как ваша подписка будет показана как Active в профиле apizone.
Шаг 3: Регистрация приложения (делайте после одобрения)
Вы заранее говорите Suunto: «У меня есть небольшая программа — вот её имя и секресный пароль — пожалуйста, разрешите ей читать мои данные».
Перейдите на страницу профиля apizone
Войдите в OAuth application settings
Заполните форму:
Поле
Что в виде
App name
suunto-mcp(или что угодно)Client secret
Придумайте уникальный пароль — например что-то, что знаете только вы: `alice-suunto-2026, включённое ваше имя. Запишите. Не используйте именно этот пример.
Redirect URI
http://localhost:8421/callback— скопируйте точноеНажмите Save
После сохранения в форме отобразится Client ID — длинный код, который сгенерировала Suunto. Скопируйте его.
Что это за три вещи? — Client ID — имя вашего приложения, создан Suunto — Client Secret — пароль вашего приложения, вы его выбрали сами — Redirect URI — адрес, по которому Suunto возвращает вас после одобрения доступа; он должен точно распознаться, опечатки нарушают работу
Client Secret после сохранения больше нигде не отображается. Если оно забыли, просто установите новое в той же форме.
Шаг 4: Получите ключ подписки (делайте после одобрения)
Ключ подписки — это второй пароль, который отправляется с каждым запросом данных. Вот как его найти:
Останки на странице профиля apizone
Перейдите в раздел Subscriptions
Там указана ваша подписка Developer API. Рядом с ней вы увидите Primary Key — нажмите кнопку рядом с ним, чтобы показать его, и скопируйте ключ.
Сохраните все три значения до продолжения — они понадобятся вам во Части 2:
Client ID (из формы OAuth-приложения выше)
Client Secret (придуман постепенно)
Subscription Key (из раздела Subscriptions)
Часть 2: Установка и конфигурация (~10 минут, после одобрения Suunto)
Использовали опцию „Пусть установит Claude Code“ выше? Клод уже выполнил all commands below — переходите к Часть 3. Эти шаги — для тех, кто делает всё вручную.
Шаг 5: Загрузите код
Откройте Terminal на Mac (нажмите ⌘Space и введите «Terminal») или Command Prompt в Windows. Затем выполняйте эти команды по одной:
git clone https://github.com/googlarz/suunto-mcp
cd suunto-mcp
npm install
npm run buildЭто загрузит код, установит необходимые зависимости и соберёт проект. Займёт 1–2 минуты. Если появятся ошибки, загляните в раздел Troubleshooting.
Шаг 6: Добавьте свои учётные данные
Вы создадите файл .env в папке suunto-mcp и поместите в него три значения. Даже если все остальное сделает Claude, введите эти три значения сами, а не вставляйте их в разговор — так они не попадут в историю общения.
На Mac:
cp .env.example .env
open -e .envЭта команда копирует шаблон и открывает его в TextEdit. Замените каждое место нужным значениям, затем сохраните и закройте.
На Windows:
copy .env.example .env
notepad .envФайл выглядит так — замените части после знаков =:
SUUNTO_CLIENT_ID=your-client-id-here
SUUNTO_CLIENT_SECRET=your-client-secret-here
SUUNTO_SUBSCRIPTION_KEY=your-subscription-key-hereСохраните и закройте файл.
Только если вы хотите отправлять готовые тренировки на часы (см. Что можно отправить), добавьте ещё одну строку:
SUUNTO_APP_NAME=your-app-name-here— она должна точно соответствовать имени приложения, которое зарегистрировано на apizone.suunto.com в Шаге 3, иначе часы отклонят загрузку. Для остального это не нужно.
Шаг 7: Свяжите свой аккаунт Suunto
npm run authВот что присходит:
① Terminal — вы видите длинный URL и сообщение „Открываем авторизацию Suunto в вашем браузере…”
② Браунсер открывается — появляется страница входа Suunto. Это выглядит так же, как вход в приложении Suunto: поля email и пароль в верхней части, затем „Войти с помощью Apple“ и „Войти с помощью Facebook“ ниже. Войдите через любой способ, которым пользуетесь.
③ Экран разрешений — после входа появляется экран с запросом доступа для „suunto-mcp“. В нём перечислено, что именно приложение сможет видеть (ваши тренировки). Нажмите Authorize.
④ Подтверждение в браузере — на странице отображается: « Suunto MCP connected. Вы можете закрыть эту вкладку.»
⑤ Подтверждение в терминале — выводится: „Успешно выполнено. Токены сохранены.“
Готово. Вам не придётся делать это снова. Соединение остаётся активным и автоматически продлевается.
Браузер не открылся автоматически? Скопируйте длинный URL из терминала и вставьте его вручную в браузер.
Шаг 8: Проверьте работу
npm run doctorЭта команда выполняет проверку работоспособности. В результате вы увидите:
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 workoutЕсли в строке появится ✗, сообщение подскажет, что именно поправить. Устраните проблемы до перехода дальше.
Часть 3: Подключение к Claude Desktop (~5 минут)
Использовали „Let Claude Code install it“? Эта часть тоже уже выполнена: Claude отредактировал конфигурацию напрямую. Перезапустите Claude Desktop и переходите к Шагу 11.
Теперь вы сообщите Claude Desktop, где найти Suunto MCP.
Шаг 9: Откройте config "файл" доктора configuration
Откройте этот файл в текстовом редакторе (если его нет, создайте его):
Mac:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Быстрый способ для Mac — выполните в терминале:
mkdir -p ~/Library/Application\ Support/Claude && open -e ~/Library/Application\ Support/Claude/claude_desktop_config.jsonБыстрый способ для Windows — выполните в командной строке:
notepad "%APPDATA%\Claude\claude_desktop_config.json"(Если появится вопрос „File not found — create it?“, нажмите „Yes“.)
Шаг 10: Добавьте Suunto MCP
Сначала найдите папку suunto-mcp. В терминале, находясь в этой одной папке, выполните:
pwdВывод будет похож на /Users/yourname/suunto-mcp. Скопируйте это.
Затем вставьте в config file следующее. Замените /Users/yourname/suunto-mcp на путь, полученный из pwd, и замените значения учётных данных своими реальными значениями.
Если в файле уже настроены другие серверы, не заменяйте весь файл — просто добавьте секцию
"suunto"к остальным. Структура должна быть корректным JSON, поэтому следите, чтобы все фигурные скобки оставались сбалансированными. Если сомневаетесь, сверьте свой файл с примером ниже.Если файл пуст, вставьте весь блок как есть.
{
"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 нужен только в том случае, если вы хотите отправлять управляемые тренировки (guided workouts) на свои часы — пропустите его (или удалите эту строку), если вы лишь спрашиваете Claude о своих данных.
Сохраните файл.
Шаг 11: Проверка
Три действия по порядку — это единственная часть настройки, которую за вас никто не сделает:
Полностью закройте Claude Desktop. Начать не просто закройте окно: ⌘Q на Mac или правый клик по значку на панели задач → Выйти (Quit) в Windows. Изменения конфигурации подхватываются только при новом запуске.
Откройте Claude Desktop заново.
Спросите:
«Какой была моя последняя тренировка?»
Если Claude назовёт ваш реальный вид спорта, дату и дистанцию — вы справились. Если нет, не гадайте — перейдите к Устранению неисправностей.
Пример диалога
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.Какие данные доступны
Категория | Что можно спросить | Для чего |
Тренировки | Любая записанная активность: пробежки, походы, велосипед, плавание, лыжные прогулки. Дистанция, время, пульс, темп, высота, GPS-маршрут, мощность. | Developer API (уже подключена) |
Сон | Длительность сна, стадии (лёгкий/глубокий/REM), оценка сна. | Подписка на Sleep API в apizone |
Восстановление | HRV, статус восстановления, баланс стресса. | Подписка на Recovery API в apizone |
Ежедневная активность | Шаги, калории, пульс 24/7. | Подписка на Daily Activity API в apizone |
Чтобы добавить сон, восстановление или повседневную активность: зайдите снова на apizone.suunto.com, найдите нужный продукт и подпишитесь. Затем запустите npm run doctor, чтобы убедиться, что они активны.
Что можно отправлять на часы
Suunto MCP — не только для чтения. Claude также может отправлять данные в ваш аккаунт:
Вы хотите | Скажите Claude | Требуется |
Получить план тренировок прямо на часах | «Составь сегодняшнюю тренировку и отправь её на мои часы» | Установлен |
Загрузить тренировку с другого устройства | «Загрузи этот FIT-файл как тренировку Suunto» | — |
Выгрузить сохранённый маршрут как GPX | «Экспортируй мой воскресный маршрут как GPX» | — |
Guided workouts появляются в виде подарка SuuntoPlus Guide: на экрана приложение выполняющего упражнение, вес/количество повторений, кнопка круга (lap) переделяет нас к следующему шагу, между циклами — секундомер (а не обратный отсчёт) с предпросмотром того, что идёт дальше, вибрация при начале нового упражнения и экран «сессия завершена» в конце. Прями доставaty*, но appearing until next sync normal Suunto into your phone — ровно как и любые другие данные вашихчасов.
Это отлично работает с тренерцемкой работой: описываете Claude свои цели, оборудование и текущие рабочии "веса", и она может построить настоящую прогрессивную программу и отправлять каждую тренировь напрямую. См. Pairs well with health-skill ниже — туда про программирование с учётом восстановления.
Ежедневный дайджест здоровья
Попросите Claude «сгенерируй мой ежедневный дайджест за вчера» — и вы получите цветь маркдавку — шаги, сон, баланс восстановления, HRV и модель тренировочной нагрузки (Fitness/Fatigue/Form) — добавленную в SUUNTO_HISTORY.md.
Fitness (CTL), Fatigue (ATL) и Form (TSB) не являются полями Suunto API — для них нет эндпоинта. Здесь они вычисляются из реального tss.trainingStressScore каждой тренировки по стандартной экспоненте на 42/7 дней — интернет как в инструментах типа TrainingPeaks. Продолжаемые значения живут в ~/.suunto-mcp/averages.json (можете переопределить через SUUNTO_DIGEST_AVERAGES_PATH), потому что хранить перемен здесь больше негде.
Несколько важных вещей, прежде чем на бы ему/обеday:
CTL/ATL начинаются с 0 на первом запуске и для получения правдоподобных цифр им нужно 4–6 недель, — API нет отдельных полей для чисел, которые покачо самы часы. Они hide cold start: при первом дайджесте скажите Claude числа с ваших часов («на моих часах сразу Fitness 42, Fatigue 38, вескай дайджест с них») — или укажите
--seed-ctl 42 --seed-atl 38в CLI. Работает только при первиде первого дайджест; дальше игнорируется.Цвета TSB совпадают семье ваши часы (🔵 Оптима >+10, 🟢 Сбалансирован от 0 до +10, 🟡 Компромисс −10 до 0, 🔴 Перенаправленность <−10) — здесь не выдуманная шкала.
Ramp rate (CTL этой недели против CTL 7 дней назад) live со своей шкалой: 🔴 уровень сума >, поступаетнако +8/за неделю — вы слишком быстро «вражива сердце», это реальный риск травмы, а не просто «прогресс». 🟢 +3…+8 — прогресс и это хорошо, 🟡 −2…+2 — стабильность/удержание, 🟠 ниже на −2 — общая форма снижается.
Recovery Balance сходится как утреннее (низшая точка за ночь) против пикового (максимальное за день) — они используют различающие цветки шкалы, потому что пик естественно выше ночного минимума.
HRV ниже обычного диапазона в течение 2+ дней подряд, либо утреннее восстановление ниже 65% в течение 2+ дней подряд — это повод добавить заметку и проверине артериальное давление; стойкое понижение HRV/восстановление — реальный физиологический признак, к которому стоит приглядеться.
Скользящие базовые показатели считают все метрики раздельно, для «вечеринокок ночей» (>20 000 шагов) заведена отдельная корзинка, чтобы день-выброс не искажал среднее обычных дней.
Даты должны быть в хронологическом порядке. Базовые показатели́ «начало на момент запуска», а не «на календарной датах»: если добавите забытую прошлую дату после более поздней, в этот день базовое сравнение безудета не чуть — полит normale; но имей это в виду, если навёртроды назад.
Для заполнения соответствующих разделов нужна подписка на Sleep и Recovery API в apizone. Без них дайджест всё равно создаётся, в этих разделах будет просто сообщение «нет данных», а неошибок.
CLI: suunto-mcp daily-digest 2026-04-20 [--seed-ctl 42 --seed-atl 38]. MCP–инструмент: generate_daily_digest.
Устранение неисправностей
Всегда сперва запускайте npm run doctor — он автоматически определяет большинство проблем.
Что вы увидите | Что это означает | Как это исправить |
Claude отвечает ошибкой или вообще не отвечает | Что-то ещё не подключено | Запустите |
Пустые список тренировок | Часы давно не синхронизировалось | Откройте приложение Suunto на телефоне и дождитесь завершения синхронизации |
«Not authenticated» | Шаг подключения не был заверён | Выполните |
Вы вошли, но ничего не произошло | Вкладка браузера закрылась или истекла время до подтверждения Suunto | Закройте все вкладки Suunto и заново запустите |
«Token request failed» / «ошибка 400» | Client Secret или Redirect URI не соответствуют apizone | Перейдите в apizone → профиль → настройки OAuth‑приложения и сличите оба значения |
Ошибка «401» при любом запросе | Неправомерный или неполный ключ подписки | apizone → профиль → Subscriptions, откройте и скопируйте заново Primary Key |
«403 Forbidden» для тренировок | Developer API подписка не активна | Авторизуйтесь на apizone и замечайте активность Active |
Sleep/восстановление/активность возвращают «not found» | Для них нужны отдельные подписки | Зайдите на apizone и подключите Sleep, Recovery или Daily Activity API |
Ошибка SSL после входа через Apple | Частный случай Suunto для входа Apple | Закройте вкладку с ошибкой, вернитесь к авторизационному URL-у в терминале и продолжайте |
Ошибка «State mismatch» | Второй процесс авторизации начался, пока первый ещё не вышел | Закройте всё возможные странички авторизации и перезапустите |
| Версия Node.js слишком старая или её нет | Выполните |
Терминал говорит «EADDRINUSE» или использует порт | Порт 8421 занят другой программой | Перезаністнет компьтер или |
Ошибка «owner» при отправке gaid |
| Посмотрите apizone → ваш app → точное имя, исправьте переменную окружения и перезапустите Claude |
Отправили на часы, но тренировка не появилась | Часы ещё не синхронизировались с телефоном | Откройте Суunто приложение и дайте ему синхронизироваться; всё появится без доп. шагов |
FAQ
Это безопасно? Заблокирует ли Suunto мой аккаунт? Suunto создал этот API специально, чтобы люди подключали свои инструменты — это легально и официально разрешено. Вы используете его именно так, как предполагалось.
Мои данные покидают компьютер? Данные передаются между напрямую между вашим компьютером и серверами Suunto. Suunto MCP — просто мост. Когда Claude спрашивает о тренировках, это выглядит так: Claude → Suunto MCP (на вашей машине) → серверы Suunto → обратно. Никакие сторонние сервисы данные не видят.
С какими часами Suunto это работает? Любые часы, которые синхронизируются с приложением Suunto: Race, Vertical, о Peak Pro, о Peak, 5 Peak, Wing, Ocean и старые модели. Если они появляются в приложении Suunto — здесь будут работать.
Нужно ли мне что‑то делать, когда я записываю новую тренировку? Нет. Просто спросите Claude — он всегда берёт свежие данные напрямую Suunto.
Что если я захочу отсоединиться и перестать пользоваться? Смотрите раздел Отключение. Доступ не полностью через менее минуты.
Могу ли я использовать это с ИИ‑программами, кроме Claude? Да — всё, что поддерживает MCP: Claude Code, Cursor, Windsurf и другие.
Имя пользователя в приложении Suunto отличается от моей почты — что использовать? Для входа в apizone используйте адрес электронной почты. После авторизации ваше имя пользователя будет отображаться.
Конфиденциальность
Все данные передаются напрямую между вашим компьютером и серверами Suunto. Никаких сторонних серверов и аналитики.
Ваши учётные данные для входа хранятся локально в
~/.suunto-mcp/tokens.json— никуда не загружаются.Suunto показывает ваше подключённое приложение как «suunto-mcp» в apizone → профиль → авторизованные приложения. Вы можете отозвать доступ там в любой момент.
ИИ видит только те данные, которые он явно запрашивает для вашего вопроса, — а не всю вашу историю сразу.
Отключение доступа
Чтобы полностью удалить доступ:
Войдите в apizone.suunto.com → профиль → Авторизованные приложения → удалите suunto-mcp. Suunto немедленно перестанет считать подключение действующим.
Удалите локальные учётные данные:
rm -f ~/.suunto-mcp/tokens.jsonУдалите блок
"suunto"из конфигурации Claude и перезапустите Claude.
Хорошо сочетается с health-skill
Если вы используете googlarz/health-skill — навык Claude для оценки симптомов и вопросов и ответов о здоровье, — Suunto MCP даёт ему живой поток ваших данных о тренировках, сне и восстановлении. Вместе они могут отвечать на вопросы вроде «с учётом моих показателей восстановления на этой неделе, стоит ли оставить завтрашнюю интервальную тренировку?» на реальных числах.
То же сочетание работает и для планирования, а не только для вопросов и ответов: Claude может проверить ваши актуальные HRV и сон перед составлением тренировки, снизить нагрузку в день плохого восстановления вместо стандартного плана и отправить результат прямо на часы с помощью push_workout_guide. Запросите это напрямую — «проверь моё восстановление и спланируй сегодняшнюю тренировку» — никакой дополнительной настройки, кроме подключения обоих сервисов, не требуется.
Для полной версии — настоящего программирования с прогрессивной перегрузкой, которое продолжается неделю за неделей, а не является разовым запросом, — установите googlarz/gym-skill: один раз выполните /gym setup, затем используйте /gym plan//gym today//gym log//gym review.
Дополнительно
Отредактируйте ~/.claude/mcp_config.json и добавьте тот же блок "suunto" из шага 10. Затем выполните claude mcp list, чтобы убедиться, что он загружен.
После сборки вы можете запрашивать данные Suunto напрямую без Claude:
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-30Все выходные данные — JSON, можно пропустить через jq для фильтрации.
npm run webhookЗапускается HTTP-приёмник на порту 8422, который протоколирует события тренировок по мере их поступления. Откройте к нему доступ из интернета (cloudflared, ngrok, собственный сервер) и укажите URL в apizone → вебхуки.
Большинству пользователей это можно пропустить — проще спросить Claude напрямую.
Чтобы хранить ваши учётные токены Suunto в системной связке ключей (macOS Keychain, Windows Credential Manager) вместо файла:
SUUNTO_TOKEN_STORAGE=keychain npm install @napi-rs/keyring
SUUNTO_TOKEN_STORAGE=keychain npm run authClaude автоматически выбирает нужный инструмент — вам не обязательно знать их. Для тех, кому интересно:
Тренировки
Инструмент | Что делает |
| Последние тренировки с фильтром по дате или виду спорта |
| Полная сводка по одной тренировке |
| Временные ряды: ЧСС, темп, высота, мощность, GPS посекундно |
| Сырой FIT-файл, декодированный в структурированные данные |
| Экспорт GPX-маршрута для карт, Strava и планирования маршрутов |
Здоровье 24/7 (требуются отдельные подписки на продукты в apizone)
Инструмент | Описание |
| Шаги, калории, повседневная частота сердечных сокращений |
| Стадии сна, длительность, оценка |
| Оценка восстановления, HRV, баланс стресса |
| Сводная дневная статистика за диапазон дат |
Маршруты
Инструмент | Описание |
| Сохранённые маршруты на вашем аккаунте |
| Экспорт маршрута в формат GPX |
Загрузка и управляемые тренировки (запись — отправка данных обратно в аккаунт)
Инструмент | Описание |
| Загрузить FIT/GPX-файл как новую тренировку |
| Проверить, завершилась ли обработка загрузки |
| Отправить структурированную тренировку (упражнения, веса, отдых, уведомления) как SuuntoPlus Guide — требует переменную |
Благодарности
Suunto APIzone — за то, что открыли свой API для всех
Model Context Protocol — стандар, на котором это работает
fit-file-parser— декодирование бинарных FIT-файлов
Лицензия
MIT — используйте, создавайте форки, улучшайте.
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