Suunto MCP
Suunto MCP
훈련에 관한 어떤 것이든 Claude에게 물어보세요. Suunto MCP는 Suunto 시계 데이터를 Claude와 연결해서, 대시보드를 클릭하며 헤매는 대신 데이터에 그냥 말을 걸 수 있게 해줍니다.
"마지막 장거리 러닝 어땠지?"라고 물어보고 숫자로 된 실제 답변을 받고 싶었고, 개인 AI 코치에게 실시간 훈련 데이터를 보내주고 싶었던 Suunto 사용자가 만들었습니다.
🏃 일반 Suunto 사용자에게: Suunto의 API 문서에는 API 접근이 상업 파트너 전용이라고 나와 있습니다 — 하지만 그게 다가 아닙니다. 개인 사용자도 접근 권한을 받을 수 있어요. 신청 후 승인까지 3–4주가 걸릴 뿐입니다. 신청하고, 기다리고, 즐기세요. 그 안내 문구 때문에 포기하지는 마세요. ✅
할 수 있는 일
설정이 끝나면, 그냥 물어보세요:
"이번 달에 몇 킬로미터를 뛰었어?"
"지난 세 번의 장거리 러닝을 비교해 줘 — 심박수 드리프트 드리프드 개선됐어?"
"어제 트레일 러닝의 GPX를 가져와서 짧은 훈련 일기를 써 줘."
"지난 2주 동안 평균 안정 시 심박수 추이는 어때?"
"이번 훈련 주를 코칭 리포트 방식으로 요약해 줘."
"몸이 좀 안 좋았는데 — 회복 점수는 지난달과 비교해 어때?"
"평균 심박의 160을 넘긴 모든 운동을 찾아 줘."
"올해 내 러닝 중에 고도 상승이 가장 큰 운동은 어느 거야?"
Claude가 어떤 데이터를 가져와야 하는지 알아서 판단합니다. 여러분은 그냥 물어보기만 하면 됩니다.
읽기 전용 이것도 아닙니다. Claude가 시계로 데이터를 보내는 일도 할 수 있습니다:
"오늘 밤 헬스 세션을 계획해 전에 내 시계에 보내 줘."
"어제 가민에서 내보낸 파일을 Suunto 운동 기록으로 업로드해 줘."
"지난번 경로를 GPX로 내보내서 공유할 수 있게 해 줘."
아래의 시계에 보낼 수 있는 기능을 참고하세요.
Related MCP server: Garmin MCP Server
🤖 직접 하기 싶지 않으세요? Claude Code가 설치하게 하세요
이미 Claude Code가 있다면 그것을 terminal 명령을 딱 하나도 실행할 필요가 없습니다. 그냥 열어서 이렇게 말하세요:
"https://github.com/googlarz/suunto-mcp에서 suunto-mcp를 설치하고 설정해 줘."
Claude Code가 스스로 저장소를 클론하고, 설치 명령을 모두 실행하고, 모든 것을 자동으로 Claude Desktop이 실행하도록 설정해 줍니다. 이 프로젝트의 작성자가 실제로 설정한 것과 똑같은 방식입니다. 수동으로 터미널 작업을 전혀 하지 않았습니다.
어떤 방식을 쓰든 세 가지는 반드시 여러분의 몫이며, 도구 부족 때문이 아니라 의도적으로 설계된 부분입니다:
apizone.suunto.com 계정 만들기 — Claude는 여러분 대신 계정을 만들 수 없습니다.
apizone 웹 양식 작성(여러분의 앱 이름 지정 및 구독 키 표시) — 이 부분은 여러분의 계정 세션이기 때문입니다. Claude는 정확히 어디를 클릭해야 하는지 알려주지만, 직접 클릭할 수 는 없습니다.
로그인 중 "Authorize" 클릭하기 — 이는 OAuth가 의도한 대로 작동하는 것입니다. 스스로 자신의 접근을 승인할 수 있는 앱은 안전하다고 볼 수 없겠죠.
Claude가 이 세 가지 각각의 경우에 정확히 무엇을 언제 해야 하는지 알려줍니다.
직접 하고 싶다면 계속 읽어보세요.
필요한 것이것
시작하기 전에 다음이 있는지 확인하세요:
Suunto 앱과 동기화된 Suunto 시계(최신 기어 모델이면 모두 가능 — Race, Vertical, 9 Peak, 5 Peak, Ocean 등)
Claude Desktop(또는 MCP를 지원하는 다른 AI 앱)
Node.js — 무료입니다. 여기서 다운로드, "LTS" 버전을 선택하세요.
Git — 무료입니다. 여기서 다운로드
~5분 신청 시간 + Suunto 승인까지 3–4주 대기 + ~15분 설치 시간
한 번 설정해 두면 다시 하지 않아도 됩니다.
설정
처음부터 안내를 받으며 빠른 경로 vs 단계별 설명 중 선택하고, 동기화가 어떻게 실행되는지 제대로 설명을 원하나요? 그렇다면 [GETTING]: _STARTED.md](GETTING_STARTED.md)를 보세요. 아래 내용은 덜 그 단계들을 참고용 형태로 정리한 것입니다.
설정은 세 부분으로 이루어져 있습니다.
Suunto 개발자 포털에 등록 — Suunto에 여러분의 앱이 데이터를 읽을 수 있도록 허용받았다는 것을 알립니다.
설치 및 구성 — 컴퓨터에서 소프트웨어가 실행되게 합니다.
Claude에 연결 — AI가 이 기능을 찾아 사용할 수 있게 합니다.
파트 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주 걸립니다. 완료되면 이메일을 받게 됩니다. apizone 프로필에 구독이 Active로 표시된 이후에만 3~4단계로 돌아오세요.
3단계: 앱 등록 (승인 후에 하세요)
이제 수액 "작은 프로그램이 하나 있고 선라이프이름과 비밀번호가 주어져 내 데이터를 읽도록 허락해 달라"라고 알리게 되는 것입니다.
apizone 프로필 페이지로 갑니다.
OAuth application settings 까지 아래로 스크롤합니다.
양식을 작성합니다:
필드
입력 내용
앱 이름(App name)
suunto-mcp(원하는 다른 이름이무엇이든 가능)클라이언트 시크릿(Client secret)
당신만 알 수 있는 고유한 비밀번호를 만드세요. 예:
alice-suunto-2026, 이 예는 자신의 이름으로. 적어두세요. 이 정확한 예을 사용하지 마세요.리다이렉트 URI(Redirect URI)
http://localhost:8421/callback— 이 내용을 정확히 복사하세요Save를 클릭하세요.
저장하면 양식에 답한 Client ID — Suunto가 자동 생성한 긴 코드 — 가 표시됩니다. 그것을 복사하세요.
이 세 가지는 무엇인가요? — Client ID: Suunto가 생성한 여러분의 앱 계정 이름 — Client Secret: 사용자가 직접 정한 앱 비밀번호 — Redirect URI: 액세스를 승인한 후 Suunto가 다시 돌려보낼 주소 — 반드시 정확히 일치해야 됩니다. 오식이 따로하면 꺼집니다.
Client Secret은 저장한 뒤에는 다시 표시되지 않습니다. 잊어버려면 동일한 양식에서 다시 설정해 새걸로 설정하면 됩니다.
4단계: 구독 키 가져오기 (승인 후에)
구독 키(Subscription Key)는 모든 데이터 요소에 포함되는 두 번째 패스코드입니다. 찾는 방법은 다음과 같습니다.
apizone 프로필 페이지에서입니다.
Subscriptions 섹션으로 스크롤합니다.
개발자 API 구독기 그곳에 나열됩니다. 그 옆에 없고 Primary Key이 표시됩니다 — 옆 버튼 클릭해서 표시하고, 그 키를 복사하세요.
계속하기 전에 이 세 가지 값을 모두 저장하세요. 파트 2에서 아래 필요합니다:
Client ID(위의 OAuth 앱 양식에서의 값)
Client Secret(직접 만든 비밀번호)
Subscription Key(Subscriptions 섹션에서 확인)
파트 2: 설치 및 구성(Suunto 승인 후 약 10분)
윗의 "Claude Code가 설치해 주기" 옵션을 사용했나요? Claude가 위 모든 명령을 이미 실행했다는 뜻입니다. — 바로 Part 3. 아래 단계는 직접 만드는 분만 해당니다.
5단계: 코드 내려받기
터미널(⌘Space를 누른 후 "Terminal"을 입력) 또는 Windows에서 명령 프롬프트를 엽니다. 그 다음 다음 명령들이 실행합니다.
git clone https://github.com/googlarz/suunto-mcp
cd suunto-mcp
npm install
npm run build이 명령은 코드 다운로드, 코드 다운로드, 의존성 설치, 빌드까지 수행합니다. 1–2분 걸립니다. 오류가 보인다면 Troubleshooting 섹션 확인하세요.
6단계: 자격 증명 추가
suunto-mcp 폴더 안에 .env라는 파일을 만들어 세 값을 넣을 것입니다. 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— 이 값은 3단계에서 apizone.suunto.com에 등록한 이름과 설정정확히 일치해야 합니다. 그렇지 않으면 시계에서 업로드를 거부합니다. 그 밖의 기능에는 필요 없습니다.
7단계: Suunto 계정 연결
npm run auth정확히 다음과 같이 확인됩니다.
① 터미널 — 긴 URL과 함께 "Opening Suunto authorization in your browser…"라는 메시지가 표시됩니다.
② 브라우저가 열립니다 — Suunto 로그인 페이지가 나타납니다. Suunto 앱과 동일하게 상단에 이메일+비밀번호 필드, 그리고 그 하단에는 "Apple로 로그인" 과 그 "Facebook으로 로그인"이 있습니다. 사용하는 방법으로 로그인하세요.,
③ 권한 화면 — 로그인하면 "suunto-mcp"의 접근을 승인할 것인지 묻는 화면이에 나타납니다. 앱이 읽을 수 있는 항목(여러분의 운동)이 있는 목록입니다. Authorize를 누르세요.
④ 브라우저 확인 페이지 — "Suunto MCP connected. You can close this tab." 이 보입니다.
⑤ 터미널 확인 메시지 — "Paired successfully. Tokens saved." 이 출력됩니다.
완료 — 더 이상 이 절차를 하지 않아도 됩니다. 연결이 계속 유지되고 자동으로 갱신됩니다.
브라우저가 자동으로 열리지 않랜나요? 터미널에서 출력된 긴 URL을 복사해 브라우저 주소창에 붙여넣기세요.
8. 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분)
"Claude Code 설치"를 선택한 분 계신가요? 이 절차 또한 끝났습니다 — Claude가 설정 파일을 직접 편집했습니다. Claude Desktop을 다시 시작하고 Step 11으로 건너뛰세요.
이제 Claude Desktop에 Suunto MCP 경로를 지정합니다.
9단계: Claude 설정 파일 열기
텍스트 편집기로 이 파일을 엽니다(없으면 새로 만들어도 됩니다):
Mac:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Mac에서 빨리 여는 방법 — Terminal에서 이 명령을 실행하세요:
mkdir -p ~/Library/Application\ Support/Claude && open -e ~/Library/Application\ Support/Claude/claude_desktop_config.jsonWindows에서 빨리 하는 방법 — 명령 프롬프트에서 이를 실행하세요:
notepad "%APPDATA%\Claude\claude_desktop_config.json"("파일이 없습니다. 새로 만들까요? " 같은 묻는 메시지가 나오면 예를 선택하세요.)
10단계: Suunto MCP 추가
먼저 suunto-mcp 폴더의 실제 위치를 찾으세요. 그 폴더 안에서 Terminal에:
pwd/Users/yourname/suunto-mcp 같은 형태로 출력됩니다. 그 값을 복사하세요.
이제 아래 내용을 config 파일에 붙여넣습니다. /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은 가이드 운동을 워치에 푸시하려는 경우에만 필요합니다. Claude에게 데이터에 대해서만 묻는다면 이 줄을 비워 두거나(또는 삭제하거나) 두시면 됩니다.
파일을 저장하세요.
11단계: 테스트하기
순서대로 세 가지를 확인하세요. 여기는 설정 중 그 무엇도 대신해 줄 수 없는 부분입니다.
Claude Desktop을 완전히 종료하세요. 창을 닫는 것만으로는 부족합니다. Mac에서는 ⌘Q, Windows에서는 작업 표시줄 아이콘을 마우스 오른쪽 클릭 → 종료를 선택하세요. 설정 변경 사항은 새로 시작해야 로드됩니다.
Claude Desktop을 다시 여세요.
이렇게 물어보세요:
"제 최근 운동은 무엇이었나요?"
Claude가 실제 운동 종목, 날짜, 거리를 말해 준다면 완료입니다. 그렇지 않다면 추측하지 말고 문제 해결로 이동하세요.
예시 대화
You: Compare my last three long runs. Has my heart-rate drift improved?
Claude: Looking up your workouts…
Found 3 runs over 90 minutes in the last 6 weeks:
• Apr 12 — 22.4 km, 2h09, avg HR 148, last-30min drift +6 bpm
• Apr 19 — 24.0 km, 2h21, avg HR 144, last-30min drift +4 bpm
• Apr 26 — 25.1 km, 2h28, avg HR 142, last-30min drift +2 bpm
Drift is trending down despite slightly longer runs — your aerobic
base is improving. Pace at the same HR is also ~3 s/km faster.제공되는 데이터는 다음과 같습니다
카테고리 | 무엇을 예측할 수 있는지 | 필요 조건 |
운동 | 기록된 모든 행동. 달리기, 하이킹, 사이드, 수영, 스키 투어. 거리, 시간, 심박수, 페스, 심박수, GPS 경로, 파워. | Developer API (이미 구독) |
수면 | 지속시간, 단계(얇은/깊은/REM), 수면 점수. | Sleep API 구독 on apizone |
지친 회복 | 변화 폭(HRV, 회복 상태, 스트레스 균형), | Recovery API 구독 on apizone |
일일 활동 | 걸음 수, 소비 칼로리, 24/7 심박수. | Daily Activity API 구독 on apizone |
수면, 회복 또는 일일 활동을 추가하려면 apizone.suunto.com로 돌아가 각 제품을 찾아 정기 구독하세요. 그런 다음 npm run doctor를 실행하여 활성화되어 있는지 확인하세요.
워치로 보낼 수 있는 것
보내고 싶은 것 | Claude에게 요청 | 필요한 조건 |
헬스장 운동 프로그램을 못 밖에 | "오늘 운동을 계획하고 내 시계로 보내줘" |
|
다른 기기에서 운동 업로드 | "이 FIT 파일을 Suunto 운동으로 업로드해 줘" | — |
복잡한 경로를 GPX로 가져오기 | "일요일 경로를 GPX로 내보내줘" | — |
Girlded workouts은 가이드 SuuntoPlus 가이드로 표시됩니다: 화면에 운동 이름과 무게/반복 수가 나타내고, 랩(랩) 버튼을 누르면 다음 운동으로 넘어갑니다. 운동 사이에는 카운트다운이 아닌 스톱워치가 표시되며 다음 운동 미리보기, 새 운동 시작 시 매번 진동, 그리고 마지막에 "세션 완료" 화면이 표시됩니다. 워치 자체에는 실시간 전송되지 않고, 다른 워치가 데이터처럼 당신의 폰에서 다음 정기 Suunto 앱 동기화된 시점에 나타나 봅니다.
이것은 코칭 워크플로우와 자연스럽게 연결됩니다. 목표, 장비, 현재 득량을 Claude에게 알려주면 실제 진행성 잡기운동 프로그램을 작성해 각 세션을 바로 전송할 수 있습니다. 체력 관리를 반영한 프로그래밍은 아래의 건강 스보련과 함께 필어올을 참조하세요.
하루 건강 다이제스트
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 사용) 다른 데이터 저장 공간이 없기 때문입니다.
그 전에 알아 두면 좋을 몇 가지가 있습니다:
CTL/ATL은 처음 0에서 시작하며 현실적인 설정을 가까워지는데 4-6주가 걸립니다. 워치에 표시된 벌시된 Fitness/Fatigue를 읽은 API가 없습니다. 이러한 콜드 스타트를 건너뛰려면 첫 번째 다이제스트 호출에서 워치 표시 값을 알려주세요 ("워치에 Fitness 42, Fatigue 38이 표시돼, 이 값으로 다이제스트를 초기화해 줘") — 또는 CLI에서
--seed-ctl 42 --seed-atl 38을 전달합니다. 첫 번째 다이제스트에서만 적용되며 이후에는 무시됩니다.TSB 색상은 워치의 자체 범례와 일치합니다 (🔵 최적 >+10, 🟢 귀부합 0부터 +10, 🟡 평저럼 −10에서 0, 🔴 과도 <−10) — 임시적인 척도가 아닙니다.
램프율(Ramp rate)(이번 주 CTL 대 7일 전)은 별도의 자체 척도를 가집니다: 🔴은 주 +8 초과하면 과중한 훈련 부하 — 단순한 "좋은 진전"이 아니라 실제 부상 위험. 🟢 +3 to +8은 올바르게 진행됨, 🟡 −2 to +2는 유지 중, 🟠−2 이하는 체력이 떨어지고 있음입니다.
회복 상태(Recovery) 균형은 아침(마지막 회복) 대 최고점(그 날 최고 값)으로 보고하며, 회복 최고는 자연하에 밤 최저보다 높기 때문에 서로 다른 색상 눈금을 사용합니다.
HRV가 정상 범위 아래로 2일 이상 계속되거나 아침 회복이 65% 미만이 2일 이상 이어지면 혈압 측정 것을 권하는 참고 사항을 추가합니다. 지속적으로 낮C는 HRV/회복은 체칭의 실제 생물학적 신호이며, 추가 데이터 지점으로 확인할 가치가 있습니다.
롤링 기준선은 지표를 각각 개별 추적하며, " 특별한 행사" 이벤트이라고 부르는 일일 걸음 수 20,000보 초과는 별도의 통지영역에 저장해 이례치가 평소 평균을 뛰어지지 않도록 해 줍니다.
날짜를 날짜 순으로 처리하세요. 기준선은 "캘린더 날짜의 값"이 아니라 "어느 시점에 실행되었나"입니다. 이후 날짜가지만 이전 누락일을 뒤늦게 보료로 채우면 그 날짜의 기준선 비교가 약간 어긋날 수 있습니다. 일반적인 스케줄 일일 사용에서 문제가 없지만, 사국을 보충할 때 염두에 두세요.
이 섹션들이 나타나지 않으려면 런던에서의 Sleep 및 Recovery API 구독이 필요합니다. 구독이 없으면 다이제스트는 여전히 생성하지만 그 섹션은 오류를 내지 않고 "데이터 없음"이라고 표시됩니다.
CLI: suunto-mcp daily-digest 2026-04-20 [--seed-ctl 42 --seed-atl 38]. MCP 도구: generate_daily_digest.
문제 해결
항상 먼저 npm run doctor를 실행하세요 — 대부분 문제를 자동으로 지적합니다.
동작 중 see | 의미 | 건강 방식 |
Claude가 오류를 반환하거나 | 아직 연결되지 않은 부분있습니다 |
|
운동 목록이 통이 비었 | 워치가 아직 동기화되지않음 | 휴대폰에서 Suunto 앱을 열고 동기화가 완료될 때까지 기다리세요 |
“Not authenticated” 오류 | 페어링 단계가 완료되지 않았습니다 |
|
로그인했지만 아무 변화없 | 브라우저 탭이 Suunto가 확인하는 대신 닫힘 또는 시간 초과 | 사용중인 Suunto 탭 모두 닫고 |
"Token request failed" 또는 400 오류 | Client Secret 또는 Redirect URI가 apizone과 일치하지 않음 | apizone → 프로필 → OAuth 앱 앱 설정창으로 이동해 두 값이 정확히 일치하는지 확인 |
모든 요청에서 "401" 오류 | 구독 키가 잘못됨 또는 값 불불 | apizone → 프로필 → 구독 목록에서 Primary Key를 다시표시해 복사 |
운동 목록에서 "403 Forbidden" | Developer API 구독이 없음 | apizone 로그인하고 활성 상태임을 확인 |
sleep/recovery/activity가 "not found" / 회복 / 활동이 "not found"를 호출 반환 | 그들 각각 별도 구독이 필요함 | apizone에서 Sleep, Recovery 또는 Daily Activity API 신청 |
Apple 로그인 후 SSL 오류 | Apple 로그인 Suunto에 알려진 문제점 | 오류 탭을 닫고 터미널에 표시 인증 URL 바 |
"State mismatch" 오류 | 첫 번째 인증 흐름이 반도 완료되지 않은 상태에서 다른 흐름 발생 | 인증 관련 링크/탭을 모두 발생시키고 |
| Node.js 버전이 낮거나 점에 설치 못함 |
|
Terminal "EADDRINUSE" 표시 때 타임포인트 | 다른 프로세스가 포트 8421 을 사용하고 있습니다 | 시스템 재시작, 또는 |
가이드 업로드 실패 "owner" 오류 |
| apizone → 내 앱 → 정확한 이름 확인 후 ENV를 수정하고 Claude다시 시작 = 4 |
가이드 푸시했지만 워치에 표시하지않음 | 워치가 휴대폰과 동기화되지 전 | Suunto 앱을 열어 동기화; 별다른 조작없이 나타하기 |
FAQ
안전한가요? Suunto가 계정을 잠가 못하게 하나요? Suunto가 자체 활용 도구 사람들이 연결할 수 있도록 만들 API로, 정식으로 허용되어 있습니다. 정확하게 의도된 용도로 사용하는 것입니다.
데이터가 내 컴퓨터 밖으로 나가나요? 데이터는 컴퓨터와 Suunto 서버 사이에서만 직접 왕복합니다. Suunto MCP는 단지 다리 역할를 하는 다리입니다. Claude가 운동 기록을 물어볼 때 이동 흐름은 Claude → Suunto MCP(당신의 시스템에서) → Suunto 서버 → 다시 넘어갑니다. 제3자 서비스는 사용자 데이터를 볼 수 없도록 하세요.
어떤 Suunto 워치와 동작하나요? Suunto 앱과 동기화되는 모든 시계: Race, Vertical, 9 Peak Propeak Pro Peak Pro, Wing, Ocean 및 구형 모델에서 모두 지원됩니다. Suunto 앱에 나타나는 시계라면 이 프로젝트를 통해 작동합니다.
새 운동을 기록할 때 뭘 해야 하나요? 그냥 Claude에게 물으세요. Suunto로부터 항상 라이브 데이터를 가져옵니다.
사용 중단/연결 해제 얐으면 어떻게 하나? 아래 연결 해제를 참조하세요. 1분 이내에 접근을 완전히 취소할 수 있습니다.
Claude 아닌 다른 AI 앱에서도 사용 가능 애플? 챀이 사용해서 가능합니다. MCP를 지원하는 모든 것은 Claude Code, Cursor, Windsurf 등 포함.
Suunto 앱 유저명과 이메일이 다릅니니다. 혹 관계? apizone 로그인은 이메일 주소로 사용하세요. 인증이 완료되면 사용자 이름이 나타나게 됩니다.
모든 데이터는 사용자 컴퓨터와 Suunto의 서버 사이에서 직접 흐릅니다. 제3자 서버도, 분석 도구도 없습니다.
로그인 자격 증명은
~/.suunto-mcp/tokens.json에 로컬로 저장됩니다 — 어디에도 업로드되지 않습니다.Suunto는 apizone → 프로필 → Authorized applications에서 연결된 앱을 "suunto-mcp"로 표시합니다. 언제든지 그곳에서 연결을 해제할 수 있습니다.
AI는 질문에 대해 명시적으로 요청한 데이터만 볼 수 있습니다 — 전체 기록 전체를 한 번에 보는 것을 아닙니다.
연결 해제
액세스를 완전히 제거하려면:
apizone.suunto.com에 로그인 → 프로필 → Authorized applications → suunto-mcp를 제거하세요. Suunto는 즉시 연결을 중단합니다.
로컬 자격 증명을 삭제하세요:
rm -f ~/.suunto-mcp/tokens.jsonClaude 구성에서
"suunto"블록을 저거하고 Claude를 다시 시작합니다.
Pairs well with health-skill
googlarz/hhealth-skill — 증상 분류. 및 건강 Q&A를 위한 Claude 스킬 — 을 관리하고 있다면 Suunto MCP가 자도 한도에 훈련·수면·회복 데이터의 라이브 피드를 제공해 줍니다. 이 둘이 함께하면 "이번 주 회복 점수를 보면 내일 인터벌 세션을 이어가도 될까?" 같은 질문에 실제 숫자로 답할 수 있습니다.
같은 조합은 질문뿐 아니라 운동 계획에도 딱 맞습니다. Claude는 세션을 작성하기 전에 실제 HRV와 수면 상태를 확인하고, 컨디션이 안 좋은 날에는도 '일반적인 날'처럼 하드하게 부하를 주는 대신 계획을 낮춰 조정한 뒤 push_workout_guide로 그 결과를 바로 기계 손목 시장에 밀어 넣을 수 있습니다. 바로 요청해 보세요 — "수술 회복 상태를 확인하고 오늘의 체육관 세션을 계획을 만들어 줘" — 두 서비스를 연결했다면 추가 설정이 필요한 것은 없습니다.
완전한 첼절한 프로그레시브 오버로드(progressive overload) 컨설팅 기능을 원한다면 — 즉 한번 합니다가 아니라 주 단위로 계속 반복되는 — 필요한 googlarz/gym-skill을 설치하고 /gym setup을 한 번 만 실행 후, 앞으로 /gym plan//gym today//gym log//gym review를 수행하세요.
고급
~/.claude/mcp_config.json를 편집하고 10단계 pyổi에서의 "suunto" 블록과 동일한 추가합니다. 그리고 claude mcp list를 실행하여 적재되었는지 확인합니다.
빌드가 다 되어 있다면 Claude가 없다고 하고도 suunto 데이터를 직접 조회할 수 있습니다.
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운동 이벤트를 포트 8422에서 받아 그 도착마다 기록하는 HTTP 수신기를 시작합니다. 인터넷에 노우출 (cloudflared, ngrok, 자체 서버 중 선택) 한 다음, URL을 apizone → webhooks에 등록을 하세요.
한 대부분의 사용자에게는 이 기능은 건너뛰어도 됩니다 — Claude에게 온디맨드로 요청해도 더 간단합니다.
Suunto 로그인 토큰을 파일 대신 macOS 키체인이나 Windows 자격 증명 관리자 같은 OS의 키체인에 저장하려면:
SUUNTO_TOKEN_STORAGE=keychain npm install @napi-rs/keyring
SUUNTO_TOKEN_STORAGE=keychain npm run authClaude는 올바른 도구를 자동으로 선택합니다 — 그럼 당신 생도 잘 알 필요가 없습니다. 궁금한 사람들에게 도움이 되도록:
Workouts
Tool | What it does |
| 날짜/운동 종목 필터가 있는 최근 운동 목록 |
| 하나의 운동에 대한 전체 요약 |
| 시계열: 심박수, 페이스, 고도, 절대 파워, 초당 GPS |
| Raw FIT 파일을 구조화한 데이터로 디코딩 |
| 지도·Strava·코스 플레닝을 위한 GPX 경로 익스포트 |
24/7 건강 어 (apizone의 개인 제품 구독이 필요합니다)
Tool | What it does |
| 걸음 수, 활동 칼로리, 일일 심박수 |
| 수면 단계, 수면 시간, 수면 점수 |
| 회복 점수, HRV, 스트레스 밸러스 |
| 지정한 기간을 통한 일일 통계들이나 집계 |
경로
Tool | What it does |
| 계정에 저장된 경로 |
| 경로을 GPX로 내보내기 |
업로드 & 가이드 운동 (데이터 쓰기 — 계정으로 다시 전송)
Tool | What it does |
| FIT/GPX 파일을 새 운동으로 업로드 |
| 업로드가 처리 완료 충족 여부 확인 |
| 체계적인 운동 구성(동작, 무게, 사용 휴식, 반복)을 SuuntoPlus 가이드로 밀어주기 — |
크레딧
Suunto API – 그 API를 모두에게 개방한 것에 감사합니다.
Model Context Protocol — 이 제품이 사용하는 표준
fit-file-parser— FIT binary decode
라이선스
MIT — 사용하고, 포크하고, 개선할 수 있습니다.
Available Tools
25 toolsdelete_guideDelete SuuntoPlus guideADestructiveIdempotent
Permanently deletes one SuuntoPlus Guide from the user's account by id. Use list_guides to find the id. This removes it from the Suunto app / apizone catalogue; it does not reach into the watch to un-pin a copy already synced there. Write operation (irreversible).
| Name | Required | Description | Default |
|---|---|---|---|
| guideId | Yes | Guide id, from list_guides or from a previous push_*_guide response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so safety is partly covered. The description adds valuable behavioral context beyond that: permanence, irreversibility, and the important limitation that it does not un-pin a copy on the watch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences with zero filler; the core action and its id lookup guidance are front-loaded, and the watch-copy caveat is a single clarifying clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter destructive tool with no output schema, the description covers the action, the id source, the irreversibility, and the key side-effect boundary, which is everything an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single guideId parameter is already documented with its provenance. The description only reiterates 'by id' and points to list_guides, adding little beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (deletes), resource (one SuuntoPlus Guide), and scope (by id, from the user's account) in the first sentence, immediately distinguishing it from sibling push_*_guide and list_guides.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to use list_guides to find the id, and clearly scopes what the operation does and does not affect (account/catalogue removal vs. a synced watch copy). Nothing about when to invoke it is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_routeExport route as GPXARead-only
Exports a saved Suunto route as a GPX 1.1 XML string. Suitable for import into navigation apps (Komoot, Strava, Garmin Connect, etc.). Use list_routes to discover valid route IDs. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| routeId | Yes | Route ID returned by list_routes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so 'Read-only' is largely a restatement. The description earns credit beyond that by disclosing the concrete return type (GPX 1.1 XML string) and the interoperability intent, which the annotations do not cover. No auth or rate-limit notes, but none are needed for this read-only export.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the operation and output format, followed by relevance and prerequisite. Every sentence carries distinct information with no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly fills the gap by stating the return value is a GPX 1.1 XML string. Combined with the prerequisite pointer and read-only status, an agent has everything needed to call this one-parameter tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single routeId parameter is already documented in the schema as 'Route ID returned by list_routes.' The description's 'Use list_routes to discover valid route IDs' essentially repeats that provenance rather than adding format or constraint detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource ('Exports a saved Suunto route') and even names the output format (GPX 1.1 XML string), which is unusually specific. It does not, however, explicitly differentiate itself from the sibling export_workout_gpx, leaving the agent to infer the route-vs-workout distinction from the resource name alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when the output is useful ('import into navigation apps such as Komoot, Strava, Garmin Connect') and names the prerequisite discovery tool (list_routes). It stops short of an explicit when-not or an alternative export tool comparison, but the usage context is well conveyed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_workout_gpxExport workout as GPXARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/exportGpx) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Would return the workout's GPS route as a GPX 1.1 XML string. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses the exact failure mode (401 OperationNotFound from /v2/workout/exportGpx), that the error surfaced will be 'endpoint unavailable', and that this is not an auth issue — precisely the context an agent needs to avoid misdiagnosing. It also states the would-be return format (GPX 1.1 XML string) and confirms read-only, adding value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The unavailability notice is front-loaded, which is the right priority, and the remaining clauses are informative rather than filler. Slightly wordy, but every sentence carries signal about state or behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-param, read-only tool with full schema coverage, the description covers what an agent needs: current unavailability, why it fails, and what it would return. Nothing material is missing even without an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single workoutKey parameter is fully documented in the schema (opaque, discovered via list_workouts, SuuntoNotFoundError on invalid key). The description adds nothing about the parameter, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource and output format: exports a workout's GPS route as a GPX 1.1 XML string. An agent immediately knows what it would do. It does not, however, distinguish itself from the sibling export_route or explain how the two differ, which is the one clarity gap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong current-state guidance: the endpoint returns 'endpoint unavailable' and this is not an authentication problem, so an agent should not retry or chase credentials. It stops short of naming an alternative (e.g. get_workout_fit) for obtaining GPS data while the endpoint is broken.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_daily_digestGenerate daily health digestADestructiveIdempotent
Builds a color-coded daily health digest (steps, sleep, recovery balance, HRV, and a training-load model) for one date and appends it as markdown to a history file. Suunto's API has no fitness/fatigue endpoints, so this computes CTL (42-day fitness), ATL (7-day fatigue), and TSB (form) from each workout's tss.trainingStressScore using standard exponential time constants, persisting the running values in a local sidecar file (SUUNTO_DIGEST_AVERAGES_PATH env var, default ~/.suunto-mcp/averages.json) since there's nowhere else to store them. Running-average baselines (all days so far) per metric are also tracked there, with a separate baseline bucket for 'party nights' (>20,000 steps) so those don't skew the normal-day average. Requires Sleep and Recovery API subscriptions on apizone for the sleep/recovery sections to populate — falls back to 'no data' text for sections without a subscription rather than erroring. Write operation (updates the sidecar file and appends to the history file).
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced. | |
| seedAtl | No | Same as seedCtl but for Fatigue (ATL). Only used on the very first digest ever run. | |
| seedCtl | No | Only used on the very first digest ever run (no prior sidecar file). Anchors the starting Fitness (CTL) value to the number shown on the user's watch instead of cold-starting at 0. Ask the user for their watch's displayed Fitness value if this is their first digest. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations (which only say non-read-only, destructive, idempotent, open-world). It discloses the CTL/ATL/TSB computation from tss.trainingStressScore, the sidecar file and env var used for persistence, the baseline bucketing for 'party nights', the subscription-dependent fallback, and explicitly labels itself a write operation that appends to a history file.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but dense, and every sentence carries required information given the tool's complexity. It is front-loaded with the purpose, then proceeds to computation, persistence, prerequisites, and side effects in a logical order with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers behavior, side effects, prerequisites, and fallbacks for a complex tool with no output schema. Remaining gaps are minor: the history file location/format and what the call returns to the caller are not described, though the sidecar path is.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds domain context for the date (via the workload) but says nothing about seedCtl/seedAtl beyond what the schema already documents, so it does not meaningfully extend parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: builds a color-coded daily health digest covering steps, sleep, recovery, HRV and a training-load model for one date. No sibling tool does anything comparable, so differentiation is inherent, and the side effects (sidecar update, markdown append) are stated up front.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: one date per call, requires Sleep and Recovery API subscriptions for those sections, and falls back to 'no data' instead of erroring. It does not name an alternative tool or an explicit when-not-to-use condition, but there is no overlapping sibling to route against.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_activityGet daily activityARead-only
Returns the 24/7 activity samples for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample) from the /247samples API, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } } — 144 rows for a full day, one per 10 minutes (138 or 150 on the days the clocks change). A day without synced data returns []. Use list_daily_activity for a date range. Requires 24/7 Activity API subscription on apizone. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial behavior beyond that — 144 rows at one per 10 minutes, 138/150 rows on DST change days, empty array for unsynced days, and the local-time stamping of each sample. This is exactly the extra context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but well-structured: day scope, source API, return shape, row count, DST exception, empty case, alternative, prerequisite, and read-only marker all in one sentence. The return-shape detail is front-loaded enough to be usable, though the em-dash clause is heavy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return value: array of objects with timestamp (ISO 8601 + offset) and entryData fields with units, plus row count and the empty-day case. An agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the date parameter already documents format, pattern, examples, and the partial-today behavior, so the schema carries the load. The description's restatement of local-day semantics adds little beyond what the parameter description already states, matching the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (returns 24/7 activity samples for one local calendar day) with a precisely scoped resource, underlying API endpoint, and day definition. It explicitly names the sibling list_daily_activity as the range alternative, letting an agent distinguish it without reading any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear routing rule ('Use list_daily_activity for a date range') and a precondition (requires 24/7 Activity API subscription on apizone). It does not restate the today/future partial-data caveat here, though the schema parameter description covers it, so usage context is clear but not fully self-contained.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_activity_statisticsGet daily activity statisticsARead-only
Returns aggregated daily step count and energy consumption (joules) from the /247 API for the given datetime range. Response is an array of AggregatedActivityData objects, each with a Name ('stepcount' or 'energyconsumption'), Aggregation ('sum'), and Sources array containing per-device Samples with TimeISO8601 and Value. The window must be less than 28 days (exactly 28 is rejected). Samples with null Value indicate no data synced for that day. Each daily Sample is stamped local noon (TimeISO8601 like 2026-09-27T12:00:00+02:00); a one-day window (startdate = enddate = D) was observed returning the samples for D and the day after, so select samples by the date in TimeISO8601 rather than summing the response. Prefer this tool over list_daily_activity when you need totals rather than intraday time-series. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| enddate | Yes | End datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate. | |
| startdate | Yes | Start datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint/openWorldHint; the description goes far beyond them with the hard 28-day window limit, null-Value semantics (no data synced that day), local-noon timestamp stamping, and the observed one-day-window off-by-one quirk with an explicit workaround (select samples by TimeISO8601 date rather than summing). It also restates read-only, which is consistent with, not contradicting, the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and data source, then return shape, constraints, edge cases, and sibling routing in that order. Sentences are dense but each carries distinct operational information; nothing is restated filler despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of describing the return value and does so precisely: an array of AggregatedActivityData with Name, Aggregation, and Sources/Samples shape. Combined with the range constraint and timestamp caveat, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds real parameter-relevant meaning: the strict 'less than 28 days, exactly 28 rejected' boundary nuance beyond the schema's looser 'must be less than 28 days after startdate', plus the guidance to select samples by the TimeISO8601 date because of how start/end boundaries behave.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource (aggregated daily step count and energy consumption) and states the backing endpoint (/247 API) plus the required datetime range. It also distinguishes itself from the sibling list_daily_activity by contrasting totals vs. intraday time-series, so an agent can choose without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Prefer this tool over list_daily_activity when you need totals rather than intraday time-series.' The constraint 'window must be less than 28 days (exactly 28 is rejected)' tells the agent when a call will fail, which is actionable selection guidance rather than inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_snapshotGet daily snapshotARead-only
One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller. Output: { date, sleepNightOf, sleep, recovery, activity, workouts, errors }. sleep describes the NIGHT THAT LED INTO the date (sleepNightOf = the previous date, i.e. sleeps that began between noon on the previous day and noon on the date): { main (the longest non-nap sleep: sleepId, bedtimeStart, bedtimeEnd, durationS, deepS, lightS, remS, score, avgHrv, hrAvg, hrMin, spo2Max, latencyS, wasoS, wakeBeforeOffBedS — all durations in seconds: time to fall asleep, awake after falling asleep, awake in bed before getting up), otherNights (further non-nap sleeps, when the watch split a night), nightSleepS (total of main + otherNights, null when there is none), naps }. Suunto marks any sleep shorter than about 3 hours as a nap, so a short night appears under naps with main null. recovery covers the local calendar day: { samples, low: { balance, at }, high, first, last, morning: { balance, at } (the sample nearest the main sleep's bedtimeEnd — the waking value), atBedtime: { balance, at } (nearest its bedtimeStart, which falls on the previous local day), both null when there is no main sleep or no sample within an hour, stressStateSamples (samples per StressState) } or null without data. low is the day's lowest balance — not necessarily overnight (after an evening workout it can fall in the evening). activity: { steps, energyKcal } for the local day — energyKcal is the daily-statistics energy converted from joules; real days come out around 700-1,500 kcal, well below a resting rate, so it looks like ACTIVE energy rather than a total (not verified against the watch). A value is null, never 0, when Suunto has no sample for the date. workouts: the day's workouts (by their own local date) with { workoutKey, activityId, startLocal, totalTimeS, kcal, hrAvg, hrMax, tss (HR method), guide, hasLaps } — pass a workoutKey with hasLaps to get_workout_laps. Each section is fetched independently: one that fails is null and explained in errors, the others are still valid. With to, returns { from, to, days: [...], errors } instead (errors is shared by the whole range; a failed section is null in every day). Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Optional last day of a range (inclusive, at most 14 days from `date`). The result is then { from, to, days: [one entry per day, in the shape above without errors], errors } — one request per section for the whole range, so prefer it to calling this once per day. | |
| date | Yes | The local calendar day YYYY-MM-DD (the first day when `to` is given). Use yesterday or earlier for a complete day; today's data is partial until the watch has synced, and the night that led into today may still be in progress. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/openWorld, so the description carries the real burden and delivers: per-section independent fetch with partial failure semantics ('one that fails is null and explained in errors, the others are still valid'), the null-never-0 convention, the ~3-hour nap threshold, and the unverified energyKcal caveat. This is well beyond what the annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with a clear purpose sentence, and given the absent output schema most details earn their place. But it is delivered as one dense block of nested parentheticals that is hard to scan, and the shape could have been split into labeled sections.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must describe return values and does so exhaustively: the top-level shape, per-section field lists, range-mode shape, and error behavior. Nothing an agent needs to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3 and the schema already documents both params. The description adds value by documenting the return-shape switch when `to` is present and the local-calendar-day semantics of `date` including the midnight-to-noon sleep attribution window, going slightly past what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening states a specific verb+resource and positions it explicitly as an aggregation: 'One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller.' It then names the exact siblings it replaces (get_sleep, get_recovery, get_daily_activity_statistics, list_workouts), so an agent can distinguish it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use with alternatives named: 'Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand.' It also gives a when-not condition for the date param ('today's data is partial until the watch has synced') and the range alternative ('prefer it to calling this once per day').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recoveryGet recoveryARead-only
Returns recovery-balance samples from the /247samples API for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample), as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } } — 48 half-hourly rows for a full day (46 or 50 on the days the clocks change). A day without recovery data returns []. Use list_recovery for a date range. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, it discloses concrete behaviors: 404 without a Recovery API subscription, [] for a day with no data, 48 half-hourly rows (46/50 on clock-change days), and the local-time stamping. That is rich operational context an agent cannot get from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded, leading with the return shape and following with the routing hint and edge cases; every clause adds operational value. It is a single long sentence rather than cleanly separated, which slightly hurts readability but not content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although there is no output schema, the description fully specifies the return shape, field types, and value ranges (Balance 0.0–1.0, StressState enum mapping) plus the empty-array and subscription-failure cases. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the date format and the today-is-partial caveat, so baseline would be 3. The description adds edge-case meaning: the exact 00:00–23:59 local-day boundary and the clock-change row count that defines a 'full day'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns recovery-balance samples from the /247samples API') and pins the scope to one local calendar day. It explicitly names the sibling it is not (list_recovery), so an agent can distinguish it without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes range queries to list_recovery, and warns that today/future dates return empty or partial payloads, advising yesterday or earlier for complete results. This is clear when-to-use, when-not, and named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleepGet sleepARead-only
Returns the sleeps of one night from the /247samples API. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Plain array with one row per sleep — Suunto re-sends a sleep every time it revises it, and only the longest revision is kept — of { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. IsNap is true for any sleep shorter than about 3 hours, at any time of day, and can flip while a sleep is still being recorded — so it also marks a short fragment of a split night; do not drop rows by IsNap alone. A night can hold several rows (a split night, or a nap beside it): rows are not merged, so decide from BedtimeStart and Duration which belong together. Returns [] when no sleep began in that window, e.g. today's date before tonight. Use list_sleep for a range. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Date YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and open-world access, but the description adds critical behavior: Sleep API subscription requirement, 404 response, revision-deduplication behavior, unmerged split rows, and IsNap flipping. These go well beyond annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense with necessary domain nuance; it front-loads the return type and date semantics. However, it repeats the schema's date explanation and packs multiple caveats into a single paragraph, which slightly hurts scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return array shape, nested fields, and edge cases (empty array, revisions, split nights, IsNap caveats). It also covers auth requirements and sibling routing, leaving no critical gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the date-window semantics, so the baseline is 3. The description adds some distinct value by explicitly mentioning that afternoon naps are filed with the following night and giving multiple bedtime examples, but much of its date explanation repeats the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the sleeps of one night from the /247samples API') and names the sibling alternative ('Use list_sleep for a range'), so an agent can distinguish it immediately from range-based sleep queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes range queries to list_sleep, explains the noon-to-noon date window, notes that last night is filed under yesterday, and states that a subscription is required with 404 otherwise. When and when-not are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_upload_statusGet workout upload statusARead-only
Polls the processing status of a workout upload initiated by upload_workout. Returns status (e.g. 'Queued', 'Processing', 'Processed', 'Error') and the workoutKey once processing completes. Use the returned workoutKey with get_workout for full detail.
| Name | Required | Description | Default |
|---|---|---|---|
| uploadId | Yes | Upload ID returned by upload_workout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it readOnly and openWorld. The description adds concrete return behavior: the set of status values and the fact that workoutKey appears once processing completes, which helps the agent interpret results. It does not cover rate limits or auth, but with annotations present it adds useful context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core purpose, then return values, then next action. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter status tool with no output schema, the description adequately explains what is returned (status values and workoutKey) and how to proceed. Annotations cover safety, and the schema covers the input, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the single uploadId parameter is fully documented as the ID returned by upload_workout. The description reinforces the dependency but adds no syntax or format detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Polls') and resource ('processing status of a workout upload'), identifies the initiating sibling (upload_workout), and distinguishes its output from get_workout. An agent can tell this is a status-checking tool rather than a data-retrieval or upload tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly ties invocation to a prior upload_workout call and directs the agent to use the returned workoutKey with get_workout for full detail. It does not explicitly state when not to call it (e.g., avoid polling repeatedly), but the context and alternative are clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workoutGet workoutARead-only
Returns the base summary for one workout (about 1.6 KB): the same scalar fields as a list_workouts item (times, distance, energy, hrdata, tss/tssList, recoveryTime) plus extensionTypes, the list of data streams Suunto holds for it. It does NOT include laps, HR zones or other extension data — use get_workout_laps for laps and zone times, get_workout_fit for record-level data. Throws SuuntoNotFoundError if the workoutKey is malformed (not 24 hex characters) or does not exist. Use list_workouts to discover valid workoutKey values. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/open-world, and the description adds substantial behavior beyond them: approximate response size (~1.6 KB), the exact field set and extensionTypes, explicit exclusions, and the SuuntoNotFoundError failure mode for malformed or missing keys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the return shape, then exclusions/alternatives, then error behavior, then key discovery. Dense but every clause carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully compensates by describing the returned fields, the non-returned data, response size, and failure modes. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the opaque key and its discovery path. The description adds the malformed-key format detail ('not 24 hex characters') and reinforces the discover-via-list_workouts rule, marginally exceeding the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the base summary for one workout') and enumerates the exact scalar fields returned. It explicitly distinguishes itself from siblings get_workout_laps and get_workout_fit by naming what it does NOT include.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use get_workout_laps for laps/zone times, get_workout_fit for record-level data, and list_workouts to discover valid keys. The condition selecting each alternative is stated, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_fitGet workout FIT dataARead-only
Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON. Default (full=false): compact summary { sport, total_distance_km, avg_heart_rate, training_effect, laps (a COUNT only, not the laps), records_sample: { first, middle, last (one record each), count } }. Set full=true to receive every parsed FIT record and lap — pretty-printed, about 550 KB for a 35-lap strength session, so the result usually spills to a file. For per-lap data use get_workout_laps instead (about 2.5 KB); use full=true only when record-level data is required. An unknown workoutKey fails with a 403 Forbidden error here (not-found on the other workout tools). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | false (default): return compact summary. true: return all parsed FIT records. | |
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, it discloses non-obvious behavior: an unknown workoutKey returns 403 Forbidden HERE but not-found on other workout tools, and large results spill to a file. These are exactly the operational traits annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the default behavior, then the escape hatch, then the error quirk. Dense but every clause carries actionable information (size estimates, error code divergence, sibling pointer) with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so thoroughly, describing both the compact summary fields and the full payload nature. Combined with the error behavior and sibling routing, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further by spelling out the exact shape the full=false summary returns (sport, total_distance_km, records_sample structure) and the size consequence of full=true. This adds meaning beyond the terse schema text, though much of it is return-shape rather than parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON'), and immediately distinguishes itself from siblings by naming get_workout_laps as the per-lap alternative. An agent can tell what this does and how it differs from nearby tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes usage: default compact summary vs full=true for record-level data, with a concrete size signal ('about 550 KB for a 35-lap strength session, so the result usually spills to a file') and a named alternative ('For per-lap data use get_workout_laps instead (about 2.5 KB)'). It even states the exclusivity condition ('use full=true only when record-level data is required').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_lapsGet workout lapsARead-only
Returns the manual laps of one workout as a compact table, plus its training-load fields — the way to read back a guided gym session set by set (push_strength_guide records one lap per set and per rest; push_workout_guide one lap per exercise and one per rest between exercises). A session from push_interval_guide auto-advances and is expected to record no manual laps (unverified), so it should return an empty table. About 2.5 KB for a 35-lap strength session, versus ~550 KB for get_workout_fit full=true. Output: { workoutKey, activityId, startTime (epoch ms), totalTimeS, guide: { id, name } | null (the guide that ran, as recorded by Suunto — not looked up in list_guides, because guides are often deleted afterwards), tss: [{ method (seen so far: 'HR', 'MET'), value }], pte, peakEpoc, recoveryTime (from the workout's summary extension; units not verified, and it can differ from the recoveryTime that list_workouts and get_workout carry), hrZoneTimeS: [zone1..zone5 seconds], feeling (the answer to the watch's 'How was it?' question, passed through as Suunto sends it; null when skipped), lapCount, checks: [{ code, detail }], laps: { cols, rows } }. checks lists reasons not to trust positional reading of the table (empty when clean): 'duplicate-rest' (the same rest label twice in a row — a set lap is missing or a rest was split), 'no-session-complete' (a guided table without its final lap — session ended early, buttons locked or watch restarted), 'unlabelled-laps' (some laps have no guide label), 'no-heart-rate' (no lap has heart rate, e.g. battery mode Tour). laps.cols = [i (1-based), startOffsetS (from workout start), durationS, hrAvg, hrMax, hrMin (bpm), kcal, kind, label]; each row is an array in that order. label is the text of the guide step that was active during the lap (lines joined with ' | '), or null when no guide ran. kind is 'rest' when the label contains 'Next:' at its start or after a '·' (a per-set rest lap reads 'Next: set k/S', or 's target · Next: set k/S' with restMode 'stopwatch'), 'done' for the final 'Session complete' lap, 'step' for any other labelled lap, null when there is no label. A per-set strength guide yields, per exercise, a prep lap, then set 1, rest, set 2, rest, … — 2 × sets laps — and one trailing 'Session complete' lap for the whole session; a prep lap and a set lap look alike in the label, so tell them apart by position. Real sessions can deviate (skipped or repeated rest laps), so check the labels rather than only counting. A workout without manual laps (unguided gym, cycling) returns lapCount 0 and laps.rows [] — not an error. Call list_workouts first for the workoutKey.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | The 24-character workoutKey returned by list_workouts. Anything else fails with a not-found error without calling Suunto. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial context the annotations cannot supply: payload size, the checks codes that flag untrustworthy positional reads, the fact that real sessions deviate (skipped/repeated rests), the caveat that recoveryTime can differ from list_workouts/get_workout, and that guide is recorded by Suunto rather than looked up because guides are often deleted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and the sibling comparison before diving into output detail, so the most decision-relevant content comes first. It is dense and delivered as one long block, but with no output schema the detail is load-bearing rather than padding; slightly better visual structure would help.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining the return shape and does so exhaustively: field-by-field output, laps.cols ordering, label/kind derivation rules, and the checks codes. It also warns about positional-reading pitfalls, leaving nothing an agent needs to interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is already documented there, including the 24-character constraint and not-found failure mode. The description's 'Call list_workouts first for the workoutKey' mostly restates the schema's provenance note, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the manual laps of one workout as a compact table, plus its training-load fields') and immediately scopes the use case to guided gym sessions read back set by set. It also distinguishes itself from get_workout_fit by quantifying the size difference (~2.5 KB vs ~550 KB), so an agent can separate the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing context: use it for push_strength_guide and push_workout_guide sessions, expect no laps from push_interval_guide, and fall back to get_workout_fit for the full payload. It also states the prerequisite ('Call list_workouts first for the workoutKey') and clarifies that an empty table is not an error, removing the most likely false-negative inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workout_samplesGet workout samplesARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/samples) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Use get_workout_fit with full=true for record-level data (heart rate etc.), or get_workout_laps for laps. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| workoutKey | Yes | Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint/openWorldHint; the description adds the critical behavioral fact that the endpoint currently returns 401 OperationNotFound and fails, that this is not an auth failure, and that the tool is retained for future restoration. That is exactly the kind of operational context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with 'UNAVAILABLE', then the failure mode, then the alternatives, then the retention rationale. Every clause earns its place; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description supplies everything needed: it is broken right now, why, and what to call instead. Nothing an agent needs to avoid misusing this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single workoutKey parameter is already richly documented (opaque, discover via list_workouts, throws SuuntoNotFoundError). The description adds nothing about parameters, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description makes clear this tool retrieves workout sample (record-level) data for a given workout, and it distinguishes itself from siblings by naming get_workout_fit and get_workout_laps as the working alternatives. It is slightly indirect — the functional purpose is inferred from the routing sentence rather than stated as a standalone verb+resource — but an agent can still tell what it is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit, unambiguous routing: the endpoint is rejected, the call fails with 'endpoint unavailable', this is not an authentication problem, and the agent should use get_workout_fit with full=true for record-level data or get_workout_laps for laps. Both the when-not and the alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_daily_activityList daily activityARead-only
Returns 24/7 activity samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } }. Days without synced data are simply absent. Use get_daily_activity for a single day or get_daily_activity_statistics for aggregated daily step/energy totals. Requires 24/7 Activity API subscription on apizone. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals). | |
| from | Yes | Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, it discloses the output shape (array of timestamp + entryData with HR, StepCount, EnergyConsumption), the absence-instead-of-error behavior for unsynced days, chronology, and the subscription requirement. This is unusually rich behavioral context for a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One long sentence but front-loaded and dense: resource and request first, output shape second, alternatives and constraints last. Every clause carries information, though the parenthetical nested object definition makes it heavier to parse than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description fully specifies the return structure, ordering, missing-day behavior, and the API subscription gate. Combined with the 100%-covered input schema, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents format, inclusivity, and size guidance, so the baseline is 3. The description adds genuine param-level semantics: intervals are interpreted in the local time the watch stamped on each sample, and results are ordered chronologically, which the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource (returns 24/7 activity samples from /247samples) with explicit scope (local calendar days [from, to] inclusive). It directly distinguishes itself from the sibling tools get_daily_activity (single day) and get_daily_activity_statistics (aggregated totals), so an agent can route without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use this tool versus the two alternatives, names those alternatives, and adds a hard prerequisite (24/7 Activity API subscription on apizone) plus a range-size preference. Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_guidesList SuuntoPlus guidesARead-only
Returns all SuuntoPlus Guides (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, newest first. Each item includes id, name, description, owner, localDate, and usage. Use the id with delete_guide, or with push_*_guide's guideId param to update an existing guide instead of creating a new one. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, and the description redundantly confirms 'Read-only'. It adds genuine context beyond annotations: the ordering (newest first) and the fact that it returns ALL guides with no pagination/limit caveat mentioned. No auth or rate-limit detail, but nothing contradicts annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the verb+resource+ordering, followed by the returned fields and the actionable id usage. No filler; every sentence carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fills the gap by enumerating returned fields and ordering, and it explains the follow-up call pattern with delete_guide and push_*_guide. Combined with annotations covering the safety profile, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline of 4 applies. The description correctly implies no filtering (returns all guides on the account) and details the fields present on each returned item (id, name, description, owner, localDate, usage), which compensates for the absent output schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Returns all SuuntoPlus Guides') and scopes the sources (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, plus ordering (newest first). An agent can distinguish this from sibling list_* tools without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent downstream: use the id with delete_guide, or with push_*_guide's guideId to update an existing guide rather than create a new one. There is no competing 'list guides' sibling, so no when-not-to-use exclusion exists, but the context for use is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recoveryList recoveryARead-only
Returns recovery-balance samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } }. Days without recovery data are simply absent. Use get_recovery for a single day. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output. | |
| from | Yes | Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, and the description redundantly restates read-only but adds real value beyond them: the Recovery API subscription requirement and the 404 behavior without it, the chronological ordering guarantee, and the silent omission of empty days. It stops short of pagination or rate-limit detail, so 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behavior and return shape in one dense sentence, then adds short supporting sentences for the alternative and the subscription constraint. The parenthetical balance/StressState enumeration is long but earns its place because there is no output schema to carry it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return structure, ordering, missing-day behavior, and the auth/error profile, so nothing an agent needs to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds semantics the schema does not: that days are interpreted in the local time the watch stamped on each sample, and that the output is a plain array. This meaningfully clarifies the temporal boundary beyond the raw date pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Returns) and resource (recovery-balance samples) with precise scope: local calendar days [from, to] inclusive, chronological ordering, and the exact return shape. It explicitly contrasts with get_recovery for a single day, so an agent can distinguish it from siblings without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative explicitly ('Use get_recovery for a single day') and gives the selecting condition (single day vs. range). It also warns days without data are simply absent, so the agent will not misread an empty stretch as an error.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_routesList routesARead-only
Returns all routes saved in the user's Suunto account. Each route: id, description, visibility, distance (m), start/end coordinates, waypoint count. Use export_route to get the GPX track for navigation. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so 'Read-only' largely repeats structured data. However, the description adds genuinely useful context beyond annotations by describing the per-route payload (id, description, visibility, distance in m, start/end coordinates, waypoint count), compensating for the absence of an output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, none wasted: purpose, return shape, and routing to the sibling tool, with the primary purpose front-loaded. Optimal size for a simple list operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, describing the returned route fields is exactly the right compensation and is done here. The only minor gap is absence of pagination/volume hints for an 'all routes' call, but overall the definition is complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is nothing to disambiguate; baseline for a zero-parameter tool is 4. No parameter-related confusion is possible here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Returns all routes'), the resource, and the scope ('saved in the user's Suunto account'), then enumerates the returned fields. It is immediately distinguishable from siblings like export_route without needing the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to the right alternative: 'Use export_route to get the GPX track for navigation,' making the boundary between listing and exporting clear. No explicit when-not guidance is given, but the alternative is named with its triggering condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sleepList sleepARead-only
Returns the sleeps of the nights [from, to] inclusive from the /247samples API, ordered chronologically by bedtime. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Same rows as get_sleep, one per sleep (revisions collapsed): { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. Nights without recorded sleep are simply absent. Use get_sleep for a single night. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Last bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness. | |
| from | Yes | First bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld; the description adds substantial behavioral context beyond them: the noon-to-noon 'night' filing rule, chronological ordering, revision collapsing ('one per sleep'), 404 auth behavior, and that absent nights are simply not present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing, then schema/return detail. The inline entryData field enumeration is dense but justified since no output schema exists. Length is high but most sentences carry distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies the full return shape (timestamp, entryData fields) plus the semantic caveats needed to interpret dates correctly. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds interpretive depth (a date means the NIGHT beginning at noon, 23:00/00:30/03:00 bedtimes all map to one date, naps file with the following night). That said, it largely restates the schema's own 'date went to bed, not woke up' note.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the sleeps of the nights') with explicit scope (from/to, /247samples API, ordered chronologically by bedtime). It distinguishes itself from the sibling get_sleep by naming it and its different use case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Use get_sleep for a single night.' It also states a prerequisite ('Requires Sleep API subscription on apizone; returns 404 without it') and notes that missing nights are silently omitted rather than errors.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_subscriptionsList webhook subscriptionsARead-only
UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/subscriptions) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error rather than returning a list. Would return the active webhook subscriptions as an array of { id, eventType, callbackUrl, createdAt }. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds the critical behavioral fact that the gateway rejects the endpoint with a 401 OperationNotFound and that the call surfaces an 'endpoint unavailable' error. It also specifies the intended return shape { id, eventType, callbackUrl, createdAt }, which is far beyond annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences that each carry distinct information: the failure, the intended return shape, and the rationale for keeping the tool. The structure is front-loaded with the unavailability. Slight redundancy between the first sentence's error description and the parenthetical, but no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description covers everything an agent needs: current failure mode, expected error behavior, and the intended return payload. Nothing actionable is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero properties, so the baseline is 4; there is nothing for the description to disambiguate. It does not add parameter detail, but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the exact resource (active webhook subscriptions at /v2/subscriptions) and what it would return, and no sibling tool covers subscriptions, so it is trivially distinguishable. It also front-loads that the endpoint is currently unavailable, which is the single most important fact about this tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent the call will fail with an 'endpoint unavailable' error rather than returning data, which is effectively a strong 'do not use' signal, and explains the tool is retained for future restoration. It stops short of naming an alternative for listing subscriptions, but no sibling offers that capability.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workoutsList workoutsARead-only
Returns the user's recent Suunto workouts ordered newest-first (Workout API v3). Each item: workoutKey (string id), activityId (numeric activity code — there is no separate plain-language 'sport' field; use get_workout_fit for the parsed FIT file's session.sport if a sport name is needed), startTime (epoch ms), totalTime (s), totalDistance (m), totalAscent (m), totalDescent (m), energyConsumption (kilocalories, not 'totalCalories'), hrdata: { avg, max } (workout heart rate — hrdata.max is the account's overall max HR, use hrdata.workoutMaxHR for this specific workout's peak). Auto-paginates with offset-based pagination until limit is reached or no more workouts exist. Each item also embeds SummaryExtension (including apps[]: the SuuntoPlus guide that ran, if any) and IntensityExtension (HR-zone times). Use get_workout_laps for the lap table of a single workout. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout. | |
| since | No | ISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size. | |
| until | No | ISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/open-world, and the description adds genuine behavioral detail beyond them: auto-pagination semantics ('until limit is reached or no more workouts exist'), plus field-level traps (hrdata.max is the account's overall max HR, not the workout peak; energyConsumption is not totalCalories; no plain-language sport field exists). These gotchas materially change how an agent interprets results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense paragraph, front-loaded with the core action before field details. It is long, but with no output schema the field-level exposition earns its place; the sole weakness is that field descriptions and usage hints are interleaved rather than separated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema in structured form, the description compensates by enumerating the returned shape (workoutKey, activityId, startTime, totalTime, distance, ascent/descent, energy, hrdata, SummaryExtension, IntensityExtension). An agent has enough to call it and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents limit, since, and until thoroughly. The description adds only the pagination caveat ('auto-paginates... until limit is reached'), which the schema also states, so it does not meaningfully exceed the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Returns/list), resource (user's recent Suunto workouts), and ordering (newest-first), with versioning (Workout API v3). An agent can immediately distinguish it from get_workout (single) and get_workout_laps (lap table).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to alternatives for adjacent needs ('use get_workout_fit for the parsed FIT file's session.sport', 'Use get_workout_laps for the lap table of a single workout'). It gives clear context for related lookups but never states the inverse boundary (e.g. list vs. fetch a specific workout) or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_interval_guidePush interval guide to watchADestructive
Pushes an interval/cardio guide (warmup, timed or distance-based work intervals, recoveries, optional repeats) to the user's Suunto account via the SuuntoPlus Guide Cloud API. Unlike push_workout_guide (manual lap-per-exercise), interval segments auto-advance by elapsed time or distance — hands-off during a run or ride. Each segment can show a target heart-rate range alongside live HR. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. Same delivery caveat as push_workout_guide: appears after the phone's next normal Suunto app sync, no live push. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. '4x4 VO2max'. | |
| blocks | Yes | Ordered list of blocks. A block with times>1 repeats its segments as a unit (e.g. 4x[interval,recovery]) — put only the segments that repeat inside it; warmup/cooldown go in their own times=1 blocks before/after. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write/destructive/openWorld/non-idempotent, so the safety profile is covered. The description adds genuinely new context beyond them: the exact-match SUUNTO_APP_NAME env var requirement and the delivery caveat (no live push; appears after the next normal sync). It stops short of explaining the destructive aspect — that supplying guideId overwrites an existing guide — which the destructiveHint=true flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence, followed by comparison, environment prerequisite, and delivery caveat. It is dense but every sentence carries distinct information; the 'Write operation.' tail is mildly redundant with annotations but otherwise there is little waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive write tool with no output schema and full schema coverage, the definition covers purpose, alternative routing, environment requirement, and delivery latency. The main remaining gap is not spelling out the overwrite behavior when guideId is supplied, but overall an agent has what it needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (date, title, blocks/segments, guideId) is already richly documented. The description describes the segment/block model conceptually (warmup, intervals, recoveries, repeats, target HR) but adds no syntax or format details beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Pushes an interval/cardio guide ... to the user's Suunto account') plus the underlying mechanism (SuuntoPlus Guide Cloud API). It explicitly contrasts itself with the sibling push_workout_guide, so an agent can distinguish it without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative (push_workout_guide) and gives the exact condition that selects this tool: interval segments auto-advance by elapsed time or distance for a hands-off run/ride, versus manual lap-per-exercise. It also supplies the required SUUNTO_APP_NAME precondition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_strength_guidePush strength guide to watchADestructive
Pushes a resistance-training guide to the user's Suunto account via the SuuntoPlus Guide Cloud API — the tool to use for gym sessions. Per exercise: a prep step (self-paced stopwatch showing the plate breakdown if given, otherwise the weight/sets detail, plus the exercise name and live HR; a lap press starts the exercise), then with lapGranularity 'perSet' (default) each set is its own step ended by a lap press, and each rest between sets is its own step showing 'Next: set k/S'. restMode 'countdown' (default) counts down restSec and auto-advances into the next set with a vibration; 'stopwatch' counts up and waits for a lap press. lapGranularity 'perExercise' gives one step per exercise after its prep, with no between-set rests and no per-set laps. Every prep, set and rest is its own lap and the guide ends with one extra 'Session complete' step, so a perSet session records 2 × (total sets) + 1 laps. Read them back after the workout with get_workout_laps — its labels are the step texts. Requires SUUNTO_APP_NAME to exactly match the app name registered on apizone.suunto.com. Without guideId a new guide is created on every call (see list_guides / delete_guide to tidy up); with guideId that guide is overwritten. There is no live push to the watch: it appears after the phone's next normal Suunto app sync. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. 'Push A'. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. | |
| restMode | No | Rest between sets. 'countdown' (default): counts down from restSec and auto-advances into the next set. 'stopwatch': counts up and waits for a lap press — the user paces it. Has no effect with lapGranularity 'perExercise' (no between-set rests). Before/between exercises is always a self-paced stopwatch. | countdown |
| exercises | Yes | ||
| lapGranularity | No | 'perSet' (default, recommended): one step per set plus one per rest, so laps bound every set/rest individually — needed to read per-set HR and duration from the synced workout. 'perExercise': one step per whole exercise instead, like push_workout_guide — shorter Guide list, coarser data. | perSet |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false) by disclosing non-obvious behavior: no live push to the watch (appears on next phone sync), the SUUNTO_APP_NAME exact-match requirement, create-on-every-call without guideId vs overwrite with it, and the lap-recording formula 2×(total sets)+1. This is exactly the kind of context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and nearly every clause carries functional information (lap math, sync behavior, mode interactions). It is nonetheless a dense single block of ~200 words with no formatting, which makes it slower to parse than a structured layout would for a tool this complex.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex write tool with no output schema, the description covers the write semantics, idempotency caveat, environment prerequisite, sync timing, and readback path, leaving little an agent would need to call it correctly. Return values are appropriately delegated to get_workout_laps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 83% (>80%), so the schema already documents most parameters and the baseline is 3. The description adds genuine cross-parameter meaning beyond the schema: restMode's interaction with lapGranularity, the prep-step/lap flow, and the plate-vs-detail display logic, which helps the agent reason about effects the per-field schema does not connect.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Pushes a resistance-training guide to the user's Suunto account') and explicitly positions itself against siblings ('the tool to use for gym sessions', references to push_workout_guide, list_guides, delete_guide, get_workout_laps). An agent can distinguish this from push_workout_guide and push_interval_guide without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear when-to-use routing ('the tool to use for gym sessions') and conditional guidance for the guideId create-vs-overwrite behavior, with pointers to list_guides/delete_guide for cleanup and get_workout_laps for readback. It does not explicitly state when to prefer push_workout_guide over this tool beyond the terse 'like push_workout_guide' aside, so it stops short of full alternative selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_workout_guidePush workout guide to watchADestructive
Pushes a text-step workout guide to the user's Suunto account via the SuuntoPlus Guide Cloud API. Each exercise becomes one step, advanced by a lap-button press on the watch. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. There is no live push to the watch itself — delivery depends on the phone's normal Suunto app sync. In testing it showed up on the watch after the next ordinary sync with no manual pinning needed; if it doesn't appear, check the Suunto app under SuuntoPlus Guides and pin it there. For gym sessions prefer push_strength_guide: it records one lap per set and per rest, which get_workout_laps can read back. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Session date YYYY-MM-DD. | |
| title | Yes | Short session name shown in the Suunto app, e.g. 'Push A'. | |
| guideId | No | If provided, updates this existing guide instead of creating a new one. | |
| exercises | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-idempotent write (readOnlyHint=false, destructiveHint=true, openWorldHint=true), and the description adds substantial context beyond that: no live push to the watch, delivery depends on the phone's next normal sync, and a fallback pinning procedure. It also discloses the guideId update-vs-create behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in sentence one, followed by mechanics, constraints, troubleshooting, and sibling routing in a logical order. It is on the longer side and the troubleshooting sentence could be trimmed, but each sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with no output schema, the description covers everything needed: the required env var, that the operation is a create-or-update depending on guideId, the lack of a live push, the sync dependency, and the correct sibling for gym sessions. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so date/title/exercises/guideId are mostly documented structurally. The description adds meaning beyond the schema by explaining that each exercise becomes one watch step advanced by a lap-button press, which clarifies how the exercises array is consumed. It doesn't add syntax detail for date or guideId.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Pushes a text-step workout guide') and names the exact mechanism (SuuntoPlus Guide Cloud API). It also distinguishes itself from the two sibling pushers by explaining that exercises map to lap-button steps, which push_strength_guide and push_interval_guide do differently.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'For gym sessions prefer push_strength_guide' with the reason (one lap per set/rest, readable by get_workout_laps). It also states the precondition (SUUNTO_APP_NAME must match the registered name) and what to do on failure (pin under SuuntoPlus Guides).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_workoutUpload workout fileA
Uploads a workout file to the user's Suunto account. Provide the absolute path to the file on disk. The file is pushed to Suunto and appears in the app after processing (usually a few seconds). Returns an uploadId you can poll with get_upload_status. Suunto's own upload API docs state only .fit (binary) is currently supported for this endpoint — a .gpx path is still accepted here (sent as application/gpx+xml) in case that changes, but treat it as unverified; use .fit for a workout that must reliably show up. Write operation.
| Name | Required | Description | Default |
|---|---|---|---|
| comment | No | Longer notes for the workout. Optional. | |
| privacy | No | Visibility. DEFAULT uses the account's default setting. | DEFAULT |
| filePath | Yes | Absolute path to the .fit or .gpx file on disk. | |
| description | No | Short workout title shown in the Suunto app. Optional. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the closing 'Write operation.' is largely redundant. The description earns credit for behavior beyond the annotations: server-side processing delay before the workout appears, and the return of an uploadId that must be polled via get_upload_status.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action, path requirement, and polling workflow are front-loaded in the first sentences; the trailing .fit/.gpx caveat is long but carries real decision-relevant information. Slightly verbose, nothing clearly wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by explaining the uploadId return and the polling path. Missing secondary details (size limits, auth/permission requirements, failure behavior), which matters for an open-world, non-idempotent write.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuinely new semantics: the endpoint officially supports only .fit binary, the .gpx path is accepted but unverified behavior. It restates the absolute-path requirement, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Uploads a workout file to the user's Suunto account') and clearly separates this from siblings like push_workout_guide and export_workout_gpx, which move structured guides or export data rather than uploading a file from disk.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear conditions for choosing a format ('use .fit for a workout that must reliably show up', .gpx is unverified) and names the follow-up tool (get_upload_status). It stops short of comparing this tool against other upload/push siblings, so no explicit when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.18.0- Added
get_daily_snapshot
9 tool updates
v0.15.1- Changed
generate_daily_digest1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — Suunto syncs once daily, so today's data is usually incomplete."New value: +"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced."
- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_daily_activity_statistics3 fields changed- changed
Input schema / properties / enddate / descriptionPrevious value: -"End datetime in ISO-8601 format (e.g. 2026-04-30T23:59:59). Must be within 28 days of startdate."New value: +"End datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate." - changed
Input schema / properties / enddate / examplesPrevious value: -[ - "2026-04-30T23:59:59" -]New value: +[ + "2026-04-27T23:59:59" +] - changed
Input schema / properties / startdate / descriptionPrevious value: -"Start datetime in ISO-8601 format (e.g. 2026-04-01T00:00:00). Data is stored in UTC."New value: +"Start datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins."
- Added
get_workout_laps - Changed
list_daily_activity1 field changed- changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals)."
- Changed
list_recovery1 field changed- changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output."
- Changed
push_strength_guide2 fields changed- changed
Input schema / properties / exercises / items / properties / detail / descriptionPrevious value: -"Display string shown on the exercise's set steps and on the prep screen before it — include weight and sets, e.g. '60kg 3x10'."New value: +"Display string shown on the exercise's set steps, and on the prep screen before it unless 'plates' is given — include weight and sets, e.g. '60kg 3x10'." - added
Input schema / properties / exercises / items / properties / platesAdded value: +{ + "description": "Per-side plate breakdown for barbell exercises, e.g. '2x20+1x5/side' — shown on the prep screen instead of detail, since that's when the bar actually gets loaded. Omit for non-barbell exercises (dumbbell, machine, bodyweight, cable); compute the math yourself before calling this tool, it isn't done here.", + "type": "string" +}
3 tool updates
v0.15.0- Added
delete_guide - Added
list_guides - Added
push_strength_guide
2 tool updates
v0.14.4- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
2 tool updates
v0.14.1- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."
- Changed
list_sleep2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404."New value: +"First bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"Last bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
7 tool updates
v0.14.0- Added
export_route - Added
generate_daily_digest - Added
get_upload_status - Added
list_routes - Added
push_interval_guide - Added
push_workout_guide - Added
upload_workout
1 tool update
v0.10.0- Added
get_daily_activity_statistics
11 tool updates
v0.9.2- Changed
export_workout_gpx1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
get_daily_activity1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
- Changed
get_recovery1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
- Changed
get_sleep1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Wake-up date YYYY-MM-DD. Example: 2026-04-20."New value: +"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."
- Changed
get_workout1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
get_workout_fit1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first."
- Changed
get_workout_samples1 field changed- changed
Input schema / properties / workoutKey / descriptionPrevious value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
- Changed
list_daily_activity2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_recovery2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_sleep2 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404." - changed
Input schema / properties / to / descriptionPrevious value: -"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
- Changed
list_workouts3 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum number of workouts to return (1–1000). Defaults to 25."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout." - changed
Input schema / properties / since / descriptionPrevious value: -"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z."New value: +"ISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size." - changed
Input schema / properties / until / descriptionPrevious value: -"ISO 8601 upper bound on startTime (inclusive)."New value: +"ISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window."
7 tool updates
v0.9.1- Changed
get_daily_activity3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
get_recovery3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
get_sleep3 fields changed- added
Input schema / properties / date / examplesAdded value: +[ + "2026-04-20" +] - added
Input schema / properties / date / maxLengthAdded value: +10 - added
Input schema / properties / date / minLengthAdded value: +10
- Changed
list_daily_activity6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_recovery6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_sleep6 fields changed- added
Input schema / properties / from / examplesAdded value: +[ + "2026-04-01" +] - added
Input schema / properties / from / maxLengthAdded value: +10 - added
Input schema / properties / from / minLengthAdded value: +10 - added
Input schema / properties / to / examplesAdded value: +[ + "2026-04-30" +] - added
Input schema / properties / to / maxLengthAdded value: +10 - added
Input schema / properties / to / minLengthAdded value: +10
- Changed
list_workouts2 fields changed- added
Input schema / properties / since / examplesAdded value: +[ + "2026-04-01T00:00:00Z" +] - added
Input schema / properties / until / examplesAdded value: +[ + "2026-04-30T23:59:59Z" +]
11 tool updates
v0.9.0- Changed
export_workout_gpx2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_daily_activity3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_recovery3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_sleep3 fields changed- changed
Input schema / properties / date / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Wake-up date YYYY-MM-DD. Example: 2026-04-20." - added
Input schema / properties / date / formatAdded value: +"date" - added
Input schema / properties / date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
get_workout2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_workout_fit3 fields changed- changed
Input schema / properties / full / descriptionPrevious value: -"If true, returns ALL parsed records (large). Default false returns a summary + sampled records."New value: +"false (default): return compact summary. true: return all parsed FIT records." - added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
get_workout_samples2 fields changed- added
Input schema / properties / workoutKey / descriptionAdded value: +"Unique workout identifier from list_workouts." - added
Input schema / properties / workoutKey / minLengthAdded value: +1
- Changed
list_daily_activity6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD (inclusive)"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD (inclusive)"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_recovery6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_sleep6 fields changed- changed
Input schema / properties / from / descriptionPrevious value: -"YYYY-MM-DD"New value: +"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01." - added
Input schema / properties / from / formatAdded value: +"date" - added
Input schema / properties / from / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / to / descriptionPrevious value: -"YYYY-MM-DD"New value: +"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30." - added
Input schema / properties / to / formatAdded value: +"date" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
list_workouts8 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Max workouts to return."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25." - added
Input schema / properties / limit / maximumAdded value: +1000 - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / limit / typePrevious value: -"number"New value: +"integer" - changed
Input schema / properties / since / descriptionPrevious value: -"ISO 8601 datetime — only workouts on/after this time."New value: +"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z." - added
Input schema / properties / since / formatAdded value: +"date-time" - changed
Input schema / properties / until / descriptionPrevious value: -"ISO 8601 datetime — only workouts on/before this time."New value: +"ISO 8601 upper bound on startTime (inclusive)." - added
Input schema / properties / until / formatAdded value: +"date-time"
12 tool updates
v0.1.0- First observed
export_workout_gpx - First observed
get_daily_activity - First observed
get_recovery - First observed
get_sleep - First observed
get_workout - First observed
get_workout_fit - First observed
get_workout_samples - First observed
list_daily_activity - First observed
list_recovery - First observed
list_sleep - First observed
list_subscriptions - First observed
list_workouts
TDQS
Scored across 25 tools
Most tools have clearly distinct purposes and the descriptions explicitly route between overlapping ones (get_daily_activity vs list_daily_activity vs get_daily_activity_statistics, get_sleep vs list_sleep, get_recovery vs list_recovery, and the get_workout/get_workout_fit/get_workout_laps trio). The single-day/get vs range/list pairs are genuinely near-duplicates and could be misselected, but the descriptions actively steer the agent and the three clearly-labelled UNAVAILABLE tools reduce confusion rather than add it.
All 25 tools follow a consistent snake_case verb_noun pattern (list_*, get_*, push_*, export_*, upload_*, delete_*, generate_*). Verbs map predictably to read vs write operations, and there are no mixed conventions or camelCase deviations.
25 tools is on the heavy side for a single-account fitness/health API. The breadth of the Suunto domain (sleep, recovery, activity, workouts, routes, guides, upload, digest) justifies much of it, but three unavailable endpoints are dead weight and the get/list single-vs-range pairs are redundant surface that bloats the set.
The surface covers the full read lifecycle for sleep, recovery, activity, workouts, routes, and guides, plus write operations for uploads and guide management and an aggregation tool. Minor gaps exist (e.g. no route creation, no user/profile or subscription management beyond a broken read, no guide editing beyond overwrite), and three endpoints are non-functional, but core workflows are complete.
Maintenance
Related MCP Connectors
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server for Polar Signals Cloud continuous profiling platform, enabling AI assistants to analyze CPU performance, memory usage, and identify optimization opportunities in production systems.9-
- FlicenseNot gradedqualityDmaintenanceEnables ChatGPT to access and analyze personal Garmin health data including daily steps, heart rate, calories, sleep duration, and body battery levels. Collects data via webhook from Garmin devices and provides health insights through natural language queries.2-
- AlicenseAqualityNot gradedmaintenanceEnables interaction with Siemens Polarion requirements management system through natural language. Supports authentication, project management, work item queries, document access, and requirements analysis.9MIT
- AlicenseNot gradedqualityDmaintenanceConnects WHOOP fitness data to Claude Desktop, enabling natural language queries about workouts, recovery, sleep patterns, and physiological cycles with secure OAuth authentication and local data storage.61 npm27MIT