Skip to main content
Glama

Suunto MCP

CI License: MIT suunto-mcp MCP server

Спрашивайте 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. Именно так это сделал автор проекта: без ручной работы в терминале.

Но есть три вещи, которые останутся за вами независимо ни от чего, — по замыслу, а не из-за отсутствия инструментов:

  1. Создание аккаунта на apizone.suunto.com — Claude не может создавать аккаунты от вашего имени.

  2. Веб-форма apizone (имя вашего приложения, отображение ключа подписки) — это ваша сессия; Claude точно говорит, куда нажать, но нажать за вас не может.

  3. Нажатие кнопки «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. Здесь приведены те же шаги в справочной форме.

Настройка состоит из трёх частей:

  1. Регистрация на портале разработчиков — сообщает Suunto, что вашему приложению разрешено читать ваши данные

  2. Установка и настройка — запускает программное обеспечение на вашем компьютере

  3. Подключение к 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: «У меня есть небольшая программа — вот её имя и секресный пароль — пожалуйста, разрешите ей читать мои данные».

  1. Перейдите на страницу профиля apizone

  2. Войдите в OAuth application settings

  3. Заполните форму:

    Поле

    Что в виде

    App name

    suunto-mcp (или что угодно)

    Client secret

    Придумайте уникальный пароль — например что-то, что знаете только вы: `alice-suunto-2026, включённое ваше имя. Запишите. Не используйте именно этот пример.

    Redirect URI

    http://localhost:8421/callback — скопируйте точное

  4. Нажмите Save

После сохранения в форме отобразится Client ID — длинный код, который сгенерировала Suunto. Скопируйте его.

Что это за три вещи? — Client ID — имя вашего приложения, создан Suunto — Client Secret — пароль вашего приложения, вы его выбрали сами — Redirect URI — адрес, по которому Suunto возвращает вас после одобрения доступа; он должен точно распознаться, опечатки нарушают работу

Client Secret после сохранения больше нигде не отображается. Если оно забыли, просто установите новое в той же форме.

Шаг 4: Получите ключ подписки (делайте после одобрения)

Ключ подписки — это второй пароль, который отправляется с каждым запросом данных. Вот как его найти:

  1. Останки на странице профиля apizone

  2. Перейдите в раздел Subscriptions

  3. Там указана ваша подписка 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.json

  • Windows: %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: Проверка

Три действия по порядку — это единственная часть настройки, которую за вас никто не сделает:

  1. Полностью закройте Claude Desktop. Начать не просто закройте окно: ⌘Q на Mac или правый клик по значку на панели задач → Выйти (Quit) в Windows. Изменения конфигурации подхватываются только при новом запуске.

  2. Откройте Claude Desktop заново.

  3. Спросите:

    «Какой была моя последняя тренировка?»

Если 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

Требуется

Получить план тренировок прямо на часах

«Составь сегодняшнюю тренировку и отправь её на мои часы»

Установлен SUUNTO_APP_NAME (см. Шаг 6)

Загрузить тренировку с другого устройства

«Загрузи этот 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 отвечает ошибкой или вообще не отвечает

Что-то ещё не подключено

Запустите npm run doctor и исправьте строки с ✗

Пустые список тренировок

Часы давно не синхронизировалось

Откройте приложение Suunto на телефоне и дождитесь завершения синхронизации

«Not authenticated»

Шаг подключения не был заверён

Выполните npm run auth снова

Вы вошли, но ничего не произошло

Вкладка браузера закрылась или истекла время до подтверждения Suunto

Закройте все вкладки Suunto и заново запустите npm run auth — нажмите Authorize promptly

«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»

Второй процесс авторизации начался, пока первый ещё не вышел

Закройте всё возможные странички авторизации и перезапустите npm run auth начисто

npm run build падает с ошибкой

Версия Node.js слишком старая или её нет

Выполните node --version — версия должна быть 20 или выше; переставьте Node с nodejs.org

Терминал говорит «EADDRINUSE» или использует порт

Порт 8421 занят другой программой

Перезаністнет компьтер или lsof -i :8421, чтобы узнать, кто занимает этот порт

Ошибка «owner» при отправке gaid

SUUNTO_APP_NAME не точно совпадает с именем вашего зарегистрированного приложения

Посмотрите 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 → профиль → авторизованные приложения. Вы можете отозвать доступ там в любой момент.

  • ИИ видит только те данные, которые он явно запрашивает для вашего вопроса, — а не всю вашу историю сразу.


Отключение доступа

Чтобы полностью удалить доступ:

  1. Войдите в apizone.suunto.com → профиль → Авторизованные приложения → удалите suunto-mcp. Suunto немедленно перестанет считать подключение действующим.

  2. Удалите локальные учётные данные:

    rm -f ~/.suunto-mcp/tokens.json
  3. Удалите блок "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 auth

Claude автоматически выбирает нужный инструмент — вам не обязательно знать их. Для тех, кому интересно:

Тренировки

Инструмент

Что делает

list_workouts

Последние тренировки с фильтром по дате или виду спорта

get_workout

Полная сводка по одной тренировке

get_workout_samples

Временные ряды: ЧСС, темп, высота, мощность, GPS посекундно

get_workout_fit

Сырой FIT-файл, декодированный в структурированные данные

export_workout_gpx

Экспорт GPX-маршрута для карт, Strava и планирования маршрутов

Здоровье 24/7 (требуются отдельные подписки на продукты в apizone)

Инструмент

Описание

get_daily_activity / list_daily_activity

Шаги, калории, повседневная частота сердечных сокращений

get_sleep / list_sleep

Стадии сна, длительность, оценка

get_recovery / list_recovery

Оценка восстановления, HRV, баланс стресса

get_daily_activity_statistics

Сводная дневная статистика за диапазон дат

Маршруты

Инструмент

Описание

list_routes

Сохранённые маршруты на вашем аккаунте

export_route

Экспорт маршрута в формат GPX

Загрузка и управляемые тренировки (запись — отправка данных обратно в аккаунт)

Инструмент

Описание

upload_workout

Загрузить FIT/GPX-файл как новую тренировку

get_upload_status

Проверить, завершилась ли обработка загрузки

push_workout_guide

Отправить структурированную тренировку (упражнения, веса, отдых, уведомления) как SuuntoPlus Guide — требует переменную SUUNTO_APP_NAME


Благодарности

Лицензия

MIT — используйте, создавайте форки, улучшайте.

Available Tools

25 tools
delete_guideDelete SuuntoPlus guideA
DestructiveIdempotent

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
guideIdYesGuide id, from list_guides or from a previous push_*_guide response.

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 GPXA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
routeIdYesRoute ID returned by list_routes.

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 GPXA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workoutKeyYesOpaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError.

TDQS

A4.1/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 digestA
DestructiveIdempotent

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced.
seedAtlNoSame as seedCtl but for Fatigue (ATL). Only used on the very first digest ever run.
seedCtlNoOnly 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

A4.4/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 activityA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar 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

A4.4/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 statisticsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
enddateYesEnd datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate.
startdateYesStart 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

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 snapshotA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoOptional 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.
dateYesThe 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

A4.7/5.0
Behavior5/5

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.

Conciseness3/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 recoveryA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar 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

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 sleepA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesDate 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

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 statusA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uploadIdYesUpload ID returned by upload_workout.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 workoutA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workoutKeyYesOpaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 dataA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
fullNofalse (default): return compact summary. true: return all parsed FIT records.
workoutKeyYesOpaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 lapsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workoutKeyYesThe 24-character workoutKey returned by list_workouts. Anything else fails with a not-found error without calling Suunto.

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 samplesA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workoutKeyYesOpaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError.

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines5/5

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 activityA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd 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).
fromYesStart date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404.

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 guidesA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 recoveryA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd 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.
fromYesStart date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404.

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 routesA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 sleepA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesLast 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.
fromYesFirst 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

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 subscriptionsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 workoutsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum 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.
sinceNoISO 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.
untilNoISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window.

TDQS

A4.4/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 watchA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesSession date YYYY-MM-DD.
titleYesShort session name shown in the Suunto app, e.g. '4x4 VO2max'.
blocksYesOrdered 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.
guideIdNoIf provided, updates this existing guide instead of creating a new one.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 watchA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesSession date YYYY-MM-DD.
titleYesShort session name shown in the Suunto app, e.g. 'Push A'.
guideIdNoIf provided, updates this existing guide instead of creating a new one.
restModeNoRest 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
exercisesYes
lapGranularityNo'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

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 watchA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesSession date YYYY-MM-DD.
titleYesShort session name shown in the Suunto app, e.g. 'Push A'.
guideIdNoIf provided, updates this existing guide instead of creating a new one.
exercisesYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
commentNoLonger notes for the workout. Optional.
privacyNoVisibility. DEFAULT uses the account's default setting.DEFAULT
filePathYesAbsolute path to the .fit or .gpx file on disk.
descriptionNoShort workout title shown in the Suunto app. Optional.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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. 1 tool updatev0.18.0
    • Addedget_daily_snapshot
  2. 9 tool updatesv0.15.1
    • Changedgenerate_daily_digest1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_daily_activity_statistics3 fields changed
      • changedInput schema / properties / enddate / description
        Previous 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."
      • changedInput schema / properties / enddate / examples
        Previous value: -[
        -  "2026-04-30T23:59:59"
        -]New value: +[
        +  "2026-04-27T23:59:59"
        +]
      • changedInput schema / properties / startdate / description
        Previous 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."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Addedget_workout_laps
    • Changedlist_daily_activity1 field changed
      • changedInput schema / properties / to / description
        Previous 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)."
    • Changedlist_recovery1 field changed
      • changedInput schema / properties / to / description
        Previous 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."
    • Changedpush_strength_guide2 fields changed
      • changedInput schema / properties / exercises / items / properties / detail / description
        Previous 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'."
      • addedInput schema / properties / exercises / items / properties / plates
        Added 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. 3 tool updatesv0.15.0
    • Addeddelete_guide
    • Addedlist_guides
    • Addedpush_strength_guide
  4. 2 tool updatesv0.14.4
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
  5. 2 tool updatesv0.14.1
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedlist_sleep2 fields changed
      • changedInput schema / properties / from / description
        Previous 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."
      • changedInput schema / properties / to / description
        Previous 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."
  6. 7 tool updatesv0.14.0
    • Addedexport_route
    • Addedgenerate_daily_digest
    • Addedget_upload_status
    • Addedlist_routes
    • Addedpush_interval_guide
    • Addedpush_workout_guide
    • Addedupload_workout
  7. 1 tool updatev0.10.0
    • Addedget_daily_activity_statistics
  8. 11 tool updatesv0.9.2
    • Changedexport_workout_gpx1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous 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."
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous 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."
    • Changedget_workout1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous 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."
    • Changedget_workout_fit1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous 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."
    • Changedget_workout_samples1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous 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."
    • Changedlist_daily_activity2 fields changed
      • changedInput schema / properties / from / description
        Previous 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."
      • changedInput schema / properties / to / description
        Previous 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."
    • Changedlist_recovery2 fields changed
      • changedInput schema / properties / from / description
        Previous 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."
      • changedInput schema / properties / to / description
        Previous 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."
    • Changedlist_sleep2 fields changed
      • changedInput schema / properties / from / description
        Previous 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."
      • changedInput schema / properties / to / description
        Previous 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."
    • Changedlist_workouts3 fields changed
      • changedInput schema / properties / limit / description
        Previous 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."
      • changedInput schema / properties / since / description
        Previous 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."
      • changedInput schema / properties / until / description
        Previous 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."
  9. 7 tool updatesv0.9.1
    • Changedget_daily_activity3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedget_recovery3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedget_sleep3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedlist_daily_activity6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_recovery6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_sleep6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_workouts2 fields changed
      • addedInput schema / properties / since / examples
        Added value: +[
        +  "2026-04-01T00:00:00Z"
        +]
      • addedInput schema / properties / until / examples
        Added value: +[
        +  "2026-04-30T23:59:59Z"
        +]
  10. 11 tool updatesv0.9.0
    • Changedexport_workout_gpx2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_daily_activity3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_recovery3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_sleep3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Wake-up date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_workout2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_workout_fit3 fields changed
      • changedInput schema / properties / full / description
        Previous 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."
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_workout_samples2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedlist_daily_activity6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD (inclusive)"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD (inclusive)"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_recovery6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_sleep6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD"New value: +"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD"New value: +"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_workouts8 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Max workouts to return."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25."
      • addedInput schema / properties / limit / maximum
        Added value: +1000
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / limit / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / since / description
        Previous 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."
      • addedInput schema / properties / since / format
        Added value: +"date-time"
      • changedInput schema / properties / until / description
        Previous value: -"ISO 8601 datetime — only workouts on/before this time."New value: +"ISO 8601 upper bound on startTime (inclusive)."
      • addedInput schema / properties / until / format
        Added value: +"date-time"
  11. 12 tool updatesv0.1.0
    • First observedexport_workout_gpx
    • First observedget_daily_activity
    • First observedget_recovery
    • First observedget_sleep
    • First observedget_workout
    • First observedget_workout_fit
    • First observedget_workout_samples
    • First observedlist_daily_activity
    • First observedlist_recovery
    • First observedlist_sleep
    • First observedlist_subscriptions
    • First observedlist_workouts

TDQS

A4.3/5.0

Scored across 25 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count3/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP 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
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
    -