Suunto MCP

io.github.googlarzPublished by GitHub account googlarzv0.24.0Updated Nov 14, 2026

Suunto watch data (workouts, sleep, recovery, 24/7 activity) for Claude and other AI assistants.

VerifiedSTDIODesktop onlyLocation & LifestyleData & Analytics

Overview

AI-generated overview

Connects Suunto watch data (workouts, sleep, recovery, daily activity) to an AI assistant so you can ask questions about your training and push plans back.

What you can do
  • Query workouts, sleep, recovery and daily activity, including lap-by-lap and heart-rate detail
  • Compute training load, baselines and comparisons across recent sessions
  • Run one-click prompts for a morning briefing, weekly review, gym readiness gate and gym session review
  • Push guided workouts, uploaded FIT files and GPX route exports to the Suunto account
  • Generate a daily health digest written to a local markdown file and keep a session journal
When to use it
Useful if you train with a Suunto watch and want to ask an assistant about your own data in plain language, compare sessions over time, or have a coaching-style plan pushed to your watch.
Requirements
Runs locally via npx with Node.js 20 or newer. Needs a Suunto apizone developer account with an approved Developer API subscription (reported as a 3-4 week wait), plus the SUUNTO_CLIENT_ID, SUUNTO_CLIENT_SECRET and SUUNTO_SUBSCRIPTION_KEY values; sleep, recovery and daily activity need extra subscriptions. A one-time OAuth pairing step is required. A demo mode runs on synthetic data with no credentials or network.
Before you install
Requires OAuth client credentials and a subscription key; the README advises entering them yourself rather than pasting them into chat. Tokens are stored locally by default. Write actions upload workouts and routes, push guides and delete guides, and the digest appends to a local file. Data goes directly to Suunto's servers, and access can be revoked in the apizone profile.

Installation

In SourceWeft

  1. Open Suunto MCP in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

[Suunto MCP]

Suunto MCP

[CI] [npm] [License: MIT] [suunto-mcp MCP server]

Ask Claude anything about your training. Suunto MCP connects your Suunto watch data to Claude so you can just talk to your data instead of clicking through dashboards.

Built by a Suunto user who wanted to ask "how was my last long run?" and get a real answer with numbers — and to feed live training data into a personal AI coach.

🏃 For regular Suunto users: Suunto's API docs say access is for commercial partners only — that's not the full picture. Private users get access too. It just takes 3–4 weeks for approval after you apply. Submit, wait, enjoy. Don't let that disclaimer stop you. ✅


What you can do

Once it's set up, just ask:

  • "How many kilometers did I run this month?"
  • "Compare my last three long runs — has my heart-rate drift improved?"
  • "How did my heart rate hold up set by set in last night's gym session?"
  • "What's my average resting HR trend over the last two weeks?"
  • "Summarize my training week in the style of a coaching report."
  • "I've been feeling off — how do my recovery scores compare to last month?"
  • "Find every workout where I averaged above 160 bpm."
  • "Which of my runs this year had the most elevation?"

Claude figures out what data to pull. You just ask.

It's not just read-only either — Claude can push things to your watch too:

  • "Plan tonight's gym session and send it to my watch."
  • "Upload yesterday's Garmin export as a Suunto workout."
  • "Export my last route as GPX so I can share it."

See What you can push to your watch below.


🤖 Don't want to do this yourself? Let Claude Code install it

If you already have Claude Code, you don't need to run a single terminal command. Just open it and say:

"Please install and set up suunto-mcp from https://github.com/googlarz/suunto-mcp"

Claude Code will clone the repo, run all the install commands, and add everything to your Claude Desktop config — on its own. That's exactly how this project's author set it up: no manual terminal work.

Three things stay yours no matter what, by design, not because of missing tooling:

  1. Creating the apizone.suunto.com account — Claude can't create accounts on your behalf.
  2. The apizone web form (naming your app, revealing your subscription key) — it's your account session; Claude tells you exactly where to click, but can't click there for you.
  3. Clicking "Authorize" during login — that's OAuth working as intended. An app that could approve its own access wouldn't be secure.

Claude will tell you exactly what to do and when for each of these.

If you want to do it manually, keep reading.


What you need

Before starting, make sure you have:

  • A Suunto watch synced to the Suunto app (any modern model — Race, Vertical, 9 Peak, 5 Peak, Ocean, etc.)
  • Claude Desktop (or another MCP-compatible AI app)
  • Node.js — free, download here, choose the "LTS" version
  • Git — free, download here
  • ~5 min to submit + 3–4 week wait for Suunto approval + ~15 min to install

Once it's done, you never redo it.


Setup

Prefer one guided walkthrough with a pacing choice up front (fast path vs. explained-step-by-step) and a proper explanation of how syncing works? See GETTING_STARTED.md. What follows here is the same steps in reference form.

The setup has three parts:

  1. Register with Suunto's developer portal — tells Suunto your app is allowed to read your data
  2. Install and configure — gets the software running on your computer
  3. Connect to Claude — lets the AI find and use it

Try it without an account (demo mode)

Suunto takes 3–4 weeks to approve API access. You don't have to wait to see what this does: with SUUNTO_DEMO=1 the server runs on realistic synthetic data (about 8 weeks, ending today) and needs no Suunto account, no credentials and no network. Only Node.js is required. Add this to the mcpServers block of the Claude Desktop config (the file from Step 9), then restart Claude:

json
{  "mcpServers": {    "suunto-demo": {      "command": "npx",      "args": ["-y", "suunto-mcp"],      "env": { "SUUNTO_DEMO": "1" }    }  }}

What works: every read tool and the four prompts (suunto-morning, suunto-weekly, suunto-gym-today, suunto-gym-review) — workouts with guide-labelled gym laps (three sessions a week, one of them with a planted deviation for compare_workout_to_plan), one or two runs a week with TSS, nightly sleep with stages, score and HRV plus the odd nap, recovery every 30 minutes, daily steps and energy, two routes, three guides, and a small FIT file with heart rate for get_workout_fit and get_workout_rest_profile. Training load, baselines and snapshots are computed from that data by the normal code.

What does not: anything that writes (upload_workout, upload_route, push_*_guide, delete_guide, generate_daily_digest, log_session) writes nothing and only returns a short note on what it would do with real credentials. get_upload_status has no uploads to find.

You can't mistake demo data for real data: every tool result is JSON with a top-level "demo": true (a result that is a list, or text such as a GPX file, comes back as { "demo": true, "data": … }), the server's instructions and the prompts say the data is synthetic, and the startup line says DEMO MODE. Errors are unchanged. npm run doctor with SUUNTO_DEMO=1 just reports that demo mode is on. When your API access arrives, remove SUUNTO_DEMO and follow the setup below. Demo mode applies to the MCP server only, not to the terminal commands.


Part 1: Register with Suunto's developer portal (~5 min to submit, then wait 3–4 weeks)

Suunto has a free developer portal called apizone where you register apps that can access your data. You'll create an account, subscribe to the data plan, and register a small "app" — don't worry, there's nothing to build, it's just a name and a password you make up.

Step 1: Create your apizone account

Go to apizone.suunto.com and sign up or sign in.

Use the same email you use for the Suunto app. If you have a Sports Tracker account, that works too — it's the same login system.

Step 2: Subscribe to the Developer API

After signing in, follow the How to start guide — it walks you through subscribing to the Developer API. This is free and gives you access to your workout history.

Heads up: Suunto's website states that API access is only for commercial partners — ignore that. Private users do get access, it just takes 3–4 weeks for the subscription to be approved. Submit it and wait. It will come through.

You may see other products like "Sleep API", "Recovery API", "Daily Activity API". The Developer API is enough to get started (workouts). Subscribe to the other three as well if you want sleep, recovery, steps, the daily snapshot or the daily digest — they are listed next to the Developer API, and you can also add them later.


⏳ Stop here and wait. Once you've subscribed, Suunto needs to approve your request. This takes 3–4 weeks. You'll get an email when it's done. Come back to Steps 3–4 only after your subscription shows as Active in your apizone profile.


Step 3: Register your app (do this after approval)

You're going to tell Suunto: "I have a small program, here's its name and a secret password — please let it read my data."

  1. Go to your apizone profile page

  2. Scroll down to OAuth application settings

  3. Fill in the form:

    FieldWhat to enter
    App namesuunto-mcp (or anything you like)
    Client secretMake up a unique password — something only you'd know, e.g. alice-suunto-2026 with your own name. Write it down. Don't use this exact example.
    Redirect URIhttp://localhost:8421/callback — copy this exactly
  4. Click Save

After saving, the form shows a Client ID — a long code that Suunto generated for you. Copy it.

What are these three things? — Client ID: your app's username, generated by Suunto — Client Secret: your app's password, chosen by you — Redirect URI: where Suunto sends you back after you approve access — must match exactly, typos break it

The Client Secret is never shown again after you save. If you forget it, just set a new one in the same form.

Step 4: Get your subscription key (do this after approval)

The subscription key is a second passcode that goes on every data request. Here's how to find it:

  1. Still on the apizone profile page
  2. Scroll to the Subscriptions section
  3. Your Developer API subscription is listed there. Next to it you'll see a Primary Key — click the button next to it to reveal it, then copy the key.

Save all three values before continuing — you'll need them in Part 2:

  • Client ID (from the OAuth app form above)
  • Client Secret (the password you made up)
  • Subscription Key (from the Subscriptions section)

Part 2: Install and configure (~10 min, after Suunto approves you)

Used the "Let Claude Code install it" option above? Claude already ran every command below — skip to Part 3. These steps are for anyone doing it by hand.

Step 5: Download the code

Open Terminal on Mac (press ⌘Space and type "Terminal") or Command Prompt on Windows. Then run these commands one at a time:

bash
git clone https://github.com/googlarz/suunto-mcpcd suunto-mcpnpm installnpm run build

This downloads the code, installs what it needs, and builds it. Takes 1–2 minutes. If you see any errors, check the Troubleshooting section.

Step 6: Add your credentials

You'll create a file called .env in the suunto-mcp folder and put your three values in it. Even if Claude is doing the rest of this for you, type these three values in yourself rather than pasting them into the chat — keeps them out of your conversation history.

On Mac:

bash
cp .env.example .envopen -e .env

This copies the template and opens it in TextEdit. Replace each placeholder with your actual values, then save and close.

On Windows:

bash
copy .env.example .envnotepad .env

The file looks like this — replace the parts after the = signs:

SUUNTO_CLIENT_ID=your-client-id-hereSUUNTO_CLIENT_SECRET=your-client-secret-hereSUUNTO_SUBSCRIPTION_KEY=your-subscription-key-here

Save and close the file.

Only if you want to push guided workouts to your watch (see What you can push), add one more line: SUUNTO_APP_NAME=your-app-name-here — it must exactly match the app name you registered on apizone.suunto.com in Step 3, or the watch will reject the upload. Not needed for anything else.

Step 7: Pair your Suunto account
bash
npm run auth

Here's exactly what happens:

① Terminal — you see a long URL printed and the message "Opening Suunto authorization in your browser…"

② Browser opens — Suunto's login page appears. It looks identical to the Suunto app login: email + password fields at the top, then "Sign in with Apple" and "Sign in with Facebook" below. Sign in with whichever you use.

③ Permissions screen — after logging in, a screen appears asking you to approve access for "suunto-mcp". It lists what the app will be able to read (your workouts). Click Authorize.

④ Browser confirmation — the page shows: "Suunto MCP connected. You can close this tab."

⑤ Terminal confirmation — prints: "Paired successfully. Tokens saved."

Done — you won't need to do this again. The connection stays active and renews itself automatically.

Browser didn't open automatically? Copy the long URL from the terminal and paste it into your browser manually.

Step 8: Check everything is working
bash
npm run doctor

This runs a health check. You should see output like:

Suunto MCP — health check
  ✓  Node version             20.18.0 (require ≥ 20)  ✓  Credentials              client_id, client_secret, subscription_key set  ✓  Network → cloudapi-oauth.suunto.com   reachable (HTTP 200)  ✓  Pairing                  paired (user: your-username), token expires in 47 min  ✓  API probe (list_workouts)  received 1 workout

The exact lines vary a little, and more appear for the Sleep, Recovery and Daily Activity products. If any line shows ✗, the message tells you exactly what to fix — resolve it before moving on. A ! is only a warning (for example, an optional product you haven't subscribed to).


Part 3: Connect to Claude Desktop (~5 min)

Used the "Let Claude Code install it" option? This part is done too — Claude edited your config directly. Restart Claude Desktop and jump to Step 11.

Now you'll tell Claude Desktop where to find Suunto MCP.

Step 9: Open the Claude config file

Open this file in a text editor (create it if it doesn't exist yet):

  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Quick way on Mac — run this in Terminal:

bash
mkdir -p ~/Library/Application\ Support/Claude && open -e ~/Library/Application\ Support/Claude/claude_desktop_config.json

Quick way on Windows — run this in Command Prompt:

notepad "%APPDATA%\Claude\claude_desktop_config.json"

(If it asks "file not found — create it?", click Yes.)

Step 10: Add Suunto MCP

First, find the actual path to the suunto-mcp folder. In Terminal, while inside the folder, run:

bash
pwd

It'll print something like /Users/yourname/suunto-mcp. Copy that.

Now paste the following into the config file. Replace /Users/yourname/suunto-mcp with the path you got from pwd, and replace the credential placeholders with your actual values.

If the file already has other servers configured, don't replace the whole file — just add the "suunto" section alongside them. The structure must be valid JSON, so keep all the curly braces balanced. When in doubt, compare your file to the example below.

If the file is empty, paste the whole block as-is.

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"      }    }  }}

To also push guided workouts to your watch, add one more line inside "env": put a comma at the end of the SUUNTO_SUBSCRIPTION_KEY line, then add "SUUNTO_APP_NAME": "your-app-name" (exactly the app name registered on apizone) on a new line after it. If you only ask Claude about your data, you don't need it.

Anything the server needs must be in this "env" block — a .env file is only read by the terminal commands (npm run auth, npm run doctor, the CLI) when you run them from this folder.

Save the file.

Step 11: Test it

Three things, in order — this is the only part of setup nothing can do for you:

  1. Quit Claude Desktop completely. Not just closing the window — ⌘Q on Mac, or right-click the icon in the taskbar → Quit on Windows. Config changes only load on a fresh start.
  2. Reopen Claude Desktop.
  3. Ask it:

    "What was my most recent workout?"

If Claude answers with your actual sport, date, and distance — you're done. If it doesn't, don't guess — go to Troubleshooting.


Example conversation

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.

What data is available

CategoryWhat you can ask aboutRequires
WorkoutsAny recorded activity — runs, hikes, rides, swims, ski tours. Distance, time, heart rate, pace, elevation, power, and lap-by-lap data for guided sessions.Developer API (already subscribed)
SleepSleep duration, stages (light/deep/REM), sleep score.Sleep API subscription on apizone
RecoveryRecovery balance and stress state through the day (HRV comes with the sleep data). Balance is the watch's Resources percentage (0.96 = 96%); stress state 1 = Recovering, 2 = Active. The app's single Recovery state percentage is not in the API.Recovery API subscription on apizone
Daily activitySteps, calories, 24/7 heart rate.Daily Activity API subscription on apizone

To add sleep, recovery, or daily activity: go back to apizone.suunto.com, find each product, and subscribe. Then run npm run doctor to confirm they're active.


What you can push to your watch

Suunto MCP isn't read-only. Claude can also send things back to your account:

You want toAsk ClaudeRequires
Get a gym plan on your wrist"Plan today's workout and send it to my watch"SUUNTO_APP_NAME set (see Step 6)
Upload a workout from another device"Upload this FIT file as a Suunto workout"—
Grab a saved route as GPX"Export my Sunday route as GPX"—

Guided workouts show up as a SuuntoPlus Guide: exercise name and weight/reps on screen, lap button advances to the next one, a stopwatch (not a countdown) between exercises with a preview of what's next, a vibrate when a new exercise starts, and a "session complete" screen at the end. There's no live push to the watch itself — it appears after your phone's next normal Suunto app sync, same as any other watch data.

This pairs naturally with a coaching workflow: describe your goals, equipment, and current lifts to Claude, and it can write a real progressive program and push each session directly — see Pairs well with health-skill below for recovery-aware programming.


Prompts

MCP clients that support prompts (for example Claude Desktop) list these as one-click workflows. Each fills in the exact dates and tells Claude which tools to call.

PromptWhat it doesOptional argument
suunto-morningMorning briefing: last night's sleep, recovery on waking (set against your own recent band), yesterday's load and workouts, how ready today isdate (YYYY-MM-DD, default today)
suunto-weeklyWeekly review: sleep, HRV, recovery and training load against the week before, each gym session against its planendDate (YYYY-MM-DD, default yesterday)
suunto-gym-todayReadiness gate: cut planned intensity 20-30% if last night's HRV or sleep score is below your own recent band (get_baselines), otherwise train as planneddate (YYYY-MM-DD, default today)
suunto-gym-reviewReview of a day's guided gym session: sets done against the plan, deviations with their basis, heart-rate recovery in the rests; says plainly when the numbers are unreliabledate (YYYY-MM-DD, default today)

Daily health digest

Ask Claude "generate my daily digest for yesterday" and it writes a color-coded markdown summary — steps, sleep, recovery balance, HRV, and a training-load model (Fitness/Fatigue/Form) — appended to SUUNTO_HISTORY.md in the folder the server runs from (set SUUNTO_DIGEST_HISTORY_PATH to choose another file).

Fitness (CTL), Fatigue (ATL), and Form (TSB) aren't Suunto API fields — there's no endpoint for them. They're computed here from each workout's real tss.trainingStressScore using standard 42-day/7-day exponential decay, the same math training-load tools like TrainingPeaks use. The running values persist in ~/.suunto-mcp/averages.json (override with SUUNTO_DIGEST_AVERAGES_PATH) since there's nowhere else to keep them.

How close is it to the watch? Checked on one day against the Suunto app: Fatigue matched (11), Form matched (2), Fitness came out about 1 lower (13.1 vs 14). Treat Fitness as ±1 of your watch; seed it from the app if you need it exact.

A few things worth knowing before you rely on it:

  • CTL/ATL start at 0 on first use and take 4–6 weeks to converge to a realistic number — there's no API to read your watch's own displayed Fitness/Fatigue. To skip the cold-start, tell Claude the numbers off your watch on your very first digest ("my watch shows Fitness 42, Fatigue 38, seed the digest with those") — or pass --seed-ctl 42 --seed-atl 38 on the CLI. Only works on the first-ever digest; ignored after that.
  • TSB colors match your watch's own legend (🔵 Optimal >+10, 🟢 Balanced 0 to +10, 🟡 Compromised −10 to 0, 🔴 Strained <−10) — not an invented scale.
  • Ramp rate (this week's CTL vs. 7 days ago) has its own scale: 🔴 above +8/week means you're loading too fast — real injury risk, not just "good progress." 🟢 +3 to +8 is building well, 🟡 −2 to +2 is holding steady, 🟠 below −2 means fitness is slipping.
  • Recovery Balance is reported as morning (the lowest point overnight) vs. peak (the highest point that day) — they use different color scales, since peak is naturally higher than the overnight low.
  • HRV below your normal range for 2+ days in a row, or morning recovery below 65% for 2+ days in a row, adds a note to check your blood pressure — sustained low HRV/recovery is a real physiological signal worth a second data point on.
  • Rolling baselines track each metric separately, with a separate bucket for "party nights" (>20,000 steps) so an outlier day doesn't skew your normal-day average.
  • Run dates in chronological order. The digest refuses a date on or before the last one it processed, so a missed day can't be filled in after a later one has run — the running totals move forward one day at a time.
  • Requires Sleep and Recovery API subscriptions on apizone for those sections to populate — without them, the digest still generates, those sections just say "no data" instead of erroring.

CLI: suunto-mcp daily-digest 2026-04-20 [--seed-ctl 42 --seed-atl 38]. MCP tool: generate_daily_digest.


Troubleshooting

Always run npm run doctor first — it pinpoints most problems automatically.

What you seeWhat it meansHow to fix it
Claude returns an error or nothingSomething isn't connected yetRun npm run doctor and fix any lines with ✗
Empty workout listWatch hasn't synced recentlyOpen the Suunto app on your phone and wait for the sync to complete
"Not authenticated"The pairing step didn't finishRun npm run auth again
You logged in but nothing happenedThe browser tab closed or timed out before Suunto confirmedClose all Suunto tabs and run npm run auth again — click Authorize promptly
"Token request failed" or "400 error"Client Secret or Redirect URI don't match apizoneGo to apizone → profile → OAuth application settings and confirm both values match exactly
"401" error on every requestUsually the subscription key is wrong or incompleteGo to apizone → profile → Subscriptions, reveal and re-copy the Primary Key
"401" with "RateLimitExceeded"Suunto's gateway reports a rate limit as 401Wait about 2 minutes and ask again — the key is fine
"401" with "OperationNotFound", or an error from a hidden legacy toolSuunto no longer serves that endpoint (get_workout_samples, export_workout_gpx, list_subscriptions — hidden unless SUUNTO_ENABLE_LEGACY_TOOLS=1)Nothing to fix on your side; re-pairing will not help
"403 Forbidden" on workoutsDeveloper API subscription isn't activeSign in to apizone and confirm it's listed as Active
Sleep / recovery / activity returns "not found"Those need separate subscriptionsGo to apizone and subscribe to the Sleep, Recovery, or Daily Activity API
Laps missing, doubled or out of order in a guided gym sessionThe watch's buttons were locked, the exercise was restarted, or a lap was pressed outside the guideAsk for get_workout_laps and read its checks list — it says which of these happened; don't trust set-by-set reading while checks is non-empty
A workout has no heart rateHeart-rate tracking was off, e.g. battery mode TourChoose a different battery mode before the workout; the data can't be recovered afterwards
Daily calories look far too lowThe daily-statistics energy looks like active energy, not total (resting + active) — this is not verified against the watchTreat it as active kcal; don't read it as total daily burn
Numbers differ from the Suunto appBalance equals the app's Resources % (0.96 = 96%). The app's single Recovery state % is not available through the API. Fitness (CTL) computed here can be about 1 point off the watchUse the app for Recovery state %; seed the digest from the app if you need CTL exact
Got an SSL error after Apple sign-inKnown Suunto quirk with Apple loginClose the error tab, go back to the auth URL the terminal printed, and continue
"State mismatch" errorA second auth flow started before the first finishedClose all auth-related tabs and run npm run auth fresh
npm run build failed with an errorNode.js version too old or not installedRun node --version — it must be 20 or higher. Reinstall from nodejs.org
Terminal says "EADDRINUSE" or port in useSomething else is using port 8421Restart your computer, or run lsof -i :8421 to see what's using it
Guide upload fails with an "owner" errorSUUNTO_APP_NAME doesn't exactly match your registered app nameCheck apizone → your app → confirm the exact name, fix the env var, restart Claude
Pushed a guide but it's not on the watchWatch hasn't synced with your phone yetOpen the Suunto app and let it sync; it should appear without any extra steps

FAQ

Is this safe? Will Suunto lock my account? Suunto built this API specifically for people to connect their own tools — it's explicitly allowed. You're using it exactly as intended.

Is my data leaving my computer? Your data travels directly between your computer and Suunto's servers. Suunto MCP is just the bridge. When Claude asks about your workouts, it goes: Claude → Suunto MCP (on your machine) → Suunto's servers → back. No third-party services see your data.

Which Suunto watches work? Any watch that syncs to the Suunto app: Race, Vertical, 9 Peak Pro, 9 Peak, 5 Peak, Wing, Ocean, and older models. If it appears in your Suunto app, it works here.

Do I need to do anything when I record a new workout? No. Just ask Claude — it always pulls live data from Suunto.

What if I want to disconnect and stop using this? See Disconnecting below. You can fully revoke access in under a minute.

Can I use this with AI apps other than Claude? Yes — anything that supports MCP: Claude Code, Cursor, Windsurf, and others.

My Suunto app username is different from my email — which do I use? Use your email address to sign in to apizone. Your username will appear once you're authenticated.


Privacy

  • All data flows directly between your computer and Suunto's servers. No third-party servers, no analytics.
  • Your login credentials are stored locally at ~/.suunto-mcp/tokens.json — not uploaded anywhere.
  • Suunto shows your connected app as "suunto-mcp" in apizone → profile → Authorized applications. You can revoke it there at any time.
  • The AI only sees data it explicitly requests for your question — not your entire history at once.

Upgrading

  • npx: npx -y suunto-mcp fetches the newest version on a fresh start; if you pinned a version in args, change it. Restart Claude afterwards.
  • Cloned folder: git pull, npm install, npm run build, then restart Claude.

See CHANGELOG.md for what changed.

Environment variables

Set these in the env block of your Claude config (or in .env for terminal commands).

VariableNeededWhat it does
SUUNTO_CLIENT_ID, SUUNTO_CLIENT_SECRET, SUUNTO_SUBSCRIPTION_KEYyesYour apizone credentials
SUUNTO_DEMOno1 runs the server on synthetic data with no credentials and no network; see "Try it without an account"
SUUNTO_APP_NAMEto push guidesExact app name registered on apizone
SUUNTO_REDIRECT_URInoOAuth callback; default http://localhost:8421/callback (must match apizone)
SUUNTO_TOKEN_PATHnoToken file; default ~/.suunto-mcp/tokens.json
SUUNTO_TOKEN_STORAGEnokeychain to store tokens in the OS keychain
SUUNTO_NO_BROWSERnoDon't open a browser during pairing; copy the URL yourself
SUUNTO_DIGEST_HISTORY_PATH, SUUNTO_DIGEST_AVERAGES_PATHnoWhere the daily digest writes
SUUNTO_CACHE_DIR, SUUNTO_CACHEnoFolder of get_exercise_history's cache (default ~/.suunto-mcp/cache/); SUUNTO_CACHE=off turns the cache off
SUUNTO_JOURNAL_PATHnoThe log_session journal file; default ~/.suunto-mcp/journal.json
SUUNTO_WEBHOOK_SECRET, SUUNTO_WEBHOOK_HOST, SUUNTO_WEBHOOK_LOG, SUUNTO_WEBHOOK_ALLOW_UNSIGNED, PORTwebhook onlySee the Webhooks section

Local files

Besides the tokens, suunto-mcp keeps these on your computer (all under ~/.suunto-mcp/ unless you move them with the variables above; folders 0700, files 0600):

  • cache/<workoutKey>.json — what get_exercise_history derived from a finished guided session (exercises, loads, sets, rest recovery; a few KB, never the raw FIT file). Sessions under 24 hours old are not cached. Safe to delete at any time: it is rebuilt on the next call (rm -rf ~/.suunto-mcp/cache). SUUNTO_CACHE=off stops it being read or written.
  • journal.json — what you told log_session. This is your own record, nothing rebuilds it: delete it (rm -f ~/.suunto-mcp/journal.json) only if you want it gone.

Disconnecting

To fully remove access:

  1. Log in to apizone.suunto.com → profile → Authorized applications → remove suunto-mcp. Suunto immediately stops honoring the connection.
  2. Delete local credentials:
    bash
    rm -f ~/.suunto-mcp/tokens.json
    If you used SUUNTO_TOKEN_STORAGE=keychain, delete the "suunto-mcp" entry in your system keychain instead. The daily digest also keeps ~/.suunto-mcp/averages.json and SUUNTO_HISTORY.md, get_exercise_history keeps ~/.suunto-mcp/cache/ and log_session keeps ~/.suunto-mcp/journal.json — delete them too if you want the health data gone (rm -rf ~/.suunto-mcp/cache ~/.suunto-mcp/journal.json).
  3. Remove the "suunto" block from your Claude config and restart Claude.

Pairs well with health-skill

If you use googlarz/health-skill — a Claude skill for symptom triage and health Q&A — you can connect both to Claude: health-skill handles the health side while Claude reads your training, sleep, and recovery data from Suunto MCP in the same conversation. Together they can answer questions like "given my recovery scores this week, should I keep tomorrow's interval session?" with real numbers.

The same combination works for planning, not just Q&A: Claude can check your actual HRV and sleep before writing a session, scale it back on a bad recovery day instead of a generic one, and push the result straight to your watch with push_strength_guide (gym) or push_interval_guide (cardio). Ask for it directly — "check my recovery and plan today's gym session" — no extra setup beyond having both connected.

To also store your daily step counts in health-skill's own records, run suunto-mcp sync-to-health-skill --health-root <your health folder> (add --person-id for a household member). It copies steps only, and only for days that are finished — today's total is picked up tomorrow.

For the full version — real progressive-overload programming that persists week to week instead of a one-off ask — install googlarz/gym-skill: /gym setup once, then /gym plan//gym today//gym log//gym review going forward.


Advanced

Install from npm instead of cloning the code

The package is published on npm as suunto-mcp, so you can skip Step 5 (no git clone, no build). You still need Node.js 20 or newer and the credentials from Part 1.

Pair your account (replaces Step 7). Run these in a terminal, with your own values:

bash
export SUUNTO_CLIENT_ID=your-client-id SUUNTO_CLIENT_SECRET=your-client-secret SUUNTO_SUBSCRIPTION_KEY=your-subscription-keynpx -p suunto-mcp suunto-mcp-authnpx -p suunto-mcp suunto-mcp-doctor

The first command opens the browser pairing page and saves your tokens to ~/.suunto-mcp/tokens.json; the second checks that everything is connected.

Connect to Claude Desktop (replaces Step 10). Use npx instead of a path to the code:

json
{  "mcpServers": {    "suunto": {      "command": "npx",      "args": ["-y", "suunto-mcp"],      "env": {        "SUUNTO_CLIENT_ID": "your-client-id",        "SUUNTO_CLIENT_SECRET": "your-client-secret",        "SUUNTO_SUBSCRIPTION_KEY": "your-subscription-key"      }    }  }}

The first start downloads the package, so it can take a few seconds. To stay on one version, write "suunto-mcp@<version>" in args (for example the current one from npm). In Claude Code: claude mcp add suunto -e SUUNTO_CLIENT_ID=... -e SUUNTO_CLIENT_SECRET=... -e SUUNTO_SUBSCRIPTION_KEY=... -- npx -y suunto-mcp.

Using with Claude Code instead of Claude Desktop

Run this in a terminal (use your own values and the real path to this folder), then claude mcp list to verify it's loaded:

bash
claude mcp add suunto -e SUUNTO_CLIENT_ID=your-client-id -e SUUNTO_CLIENT_SECRET=your-client-secret -e SUUNTO_SUBSCRIPTION_KEY=your-subscription-key -- node /full/path/to/suunto-mcp/dist/index.js

Add -e SUUNTO_APP_NAME=your-app-name if you want to push guided workouts.

CLI — query your data from the terminal

After building, you can query Suunto data directly without Claude. From the cloned folder use node dist/index.js <command>; with the npm package use npx suunto-mcp <command> (or just suunto-mcp if installed globally):

bash
node dist/index.js list-workouts --limit 10node dist/index.js get-workout <workoutKey>node dist/index.js get-workout-laps <workoutKey>node dist/index.js get-daily-snapshot 2026-04-20node dist/index.js get-daily-snapshot 2026-04-14 --to 2026-04-20node dist/index.js get-sleep 2026-04-20node dist/index.js list-recovery --from 2026-04-01 --to 2026-04-30

Other commands: get-workout-fit, get-training-load, compare-workout, get-workout-rest-profile, list-routes, get-route, export-route, get-daily-activity, list-daily-activity, list-sleep, get-recovery, daily-digest, sync-to-health-skill. Run it with --help for the full list and every option. Output is JSON (pipe into jq for filtering), except export-route, which prints GPX.

Webhooks — get notified the moment a workout syncs
bash
npm run webhook

Starts an HTTP receiver on port 8422 that logs workout events as they arrive. It listens on 127.0.0.1 only, so expose it through a tunnel (cloudflared, ngrok) or a reverse proxy and register the URL in apizone → webhooks.

Set SUUNTO_WEBHOOK_SECRET to the notification secret you configure in apizone's OAuth application settings. Every request is verified against Suunto's X-HMAC-SHA256-Signature header and rejected with 401 if it doesn't match. Without the secret the receiver rejects everything (set SUUNTO_WEBHOOK_ALLOW_UNSIGNED=1 only for local testing). Other options: PORT, SUUNTO_WEBHOOK_HOST (default 127.0.0.1), SUUNTO_WEBHOOK_LOG (default ~/.suunto-mcp/webhooks.ndjson, written private and capped at 100 MB).

Most users can skip this whole section — asking Claude on demand is simpler.

Keychain — store credentials more securely

To store your Suunto login tokens in your OS keychain (macOS Keychain, Windows Credential Manager) instead of a file:

bash
SUUNTO_TOKEN_STORAGE=keychain npm install @napi-rs/keyringSUUNTO_TOKEN_STORAGE=keychain npm run auth
All available tools (reference)

Claude picks the right tool automatically — you don't need to know these. For the curious:

Workouts

ToolWhat it does
list_workoutsRecent workouts, filtered by date
get_workoutSummary numbers for one workout (no laps — use get_workout_laps)
get_daily_snapshotOne call for a whole day: last night's sleep (main sleep, naps), the day's lowest and highest recovery balance (and the value on waking and at bedtime), steps, energy and workouts. Pass to for up to 14 days in one request
get_baselinesYour own recent norms: median and the middle-half band (p25-p75) of the last 14-90 days (default 28, ending the day before date) for sleep duration, sleep score, HRV, recovery on waking, the day's lowest recovery and steps, plus where date sits in it (below / within / above). Quantiles use linear interpolation between order statistics; a band needs 7 days with a value. A missing day is never counted as 0. Not a medical reference. Read-only
get_training_loadFitness (CTL), Fatigue (ATL) and Form (TSB) day by day, plus weekly totals and the 7-day ramp rate, computed from workout TSS (Suunto's API has no such numbers). Up to 120 days ending at date; CTL can be about 1 point off the watch. Read-only — doesn't touch the digest files
get_workout_lapsLap-by-lap table for one workout: time, heart rate, calories and the guide step of each lap — the way to read back a guided gym session set by set; it also reports when the table looks unreliable (a missing or doubled lap, no heart rate)
compare_workout_to_planReads a guided gym session back against its plan: maps the laps to exercises, sets and rests and lists deviations (missing or extra sets and exercises, short or long sets, rests off target, laps outside the guide), each marked with what it rests on (the labels, your plan, or a heuristic). Pass the exercises array you pushed as plan to also check order, set counts and rest targets. With restMode countdown rest overruns are not measurable. Read-only
get_workout_rest_profileHow the heart rate recovered during each rest of a guided gym session. Reads the FIT file's record-level HR and joins it to the guide's laps (exercise, set), so it works with restMode countdown, where the rest lap always lasts exactly its target. Per rest: peak HR (smoothed over 3 samples, searched from 15 s before the rest to 30 s into it, because optical HR lags 20–30 s), HR at the end, total drop, seconds after the peak to fall 10, 20 and 30 bpm, bpm per minute over the first minute, and how many seconds have an HR sample; plus medians per exercise. Also lists the SuuntoPlus app's developer fields found in the FIT (get_workout_fit shows them too). The rest windows are placed on the FIT timeline by the workout start time; not yet checked against a real workout. Optional plan as for compare_workout_to_plan. Read-only
get_exercise_historyProgression of strength exercises across guided sessions: for one exercise (name) or an index of all of them, per session the load (the first NNkg in the guide's text, or the weight you logged), sets done against planned, the guide's rest and the heart-rate recovery after set 1 (end-of-rest HR, drop, seconds to fall 20 bpm), plus a median end-of-rest HR you can use as push_strength_guide's restTargetHr. weeks 1–26 (default 8) ending at date. Weights and reps are what the guide planned, the watch does not record them; log_session corrects that. Each session is read once and its small derived result cached locally; at most 8 uncached sessions are read per call, so the answer says how many are pending — call again until 0, unless a note says calling again will not help (the cache folder is not writable, or sessions keep failing). Names the guide cut to 40 characters are grouped with their longer form only when that is certain, otherwise they stay separate and a note lists them. Writes only the local cache (see Local files), never anything at Suunto
log_sessionRecords what you say actually happened in a session (reps, weight, RPE, notes per exercise) in a local journal file. One entry per workout; logging the same workout again replaces it and returns the old entry. A call with no note, no feeling and no exercises is refused (nothing to log), and unknown fields (such as weight; use kg inside a set) are refused with an error naming the field. get_exercise_history shows it and uses its weights. Never contacts Suunto
get_workout_fitRaw FIT file decoded to structured data (large — full: true is about 550 KB for a strength session)
get_workout_samplesHidden by default — Suunto's servers reject this call (OperationNotFound, checked on one account, September 2026); set SUUNTO_ENABLE_LEGACY_TOOLS=1 to list it; use get_workout_fit
export_workout_gpxHidden by default — Suunto's servers reject this call (OperationNotFound, checked on one account, September 2026); set SUUNTO_ENABLE_LEGACY_TOOLS=1 to list it

24/7 health (requires individual product subscriptions on apizone)

ToolWhat it does
get_daily_activity / list_daily_activitySteps, calories, daily heart rate
get_sleep / list_sleepSleep stages, duration, score
get_recovery / list_recoveryRecovery balance and stress state through the day
get_daily_activity_statisticsAggregated daily stats over a date range

Routes

ToolWhat it does
list_routesYour newest saved routes (Suunto returns at most 5)
get_routeOne route by its ID — works for routes list_routes doesn't show
export_routeExport a route as GPX

Uploads & guided workouts (write — send data back to your account)

ToolWhat it does
upload_workoutUpload a FIT file as a new workout — Suunto's own docs say only FIT is currently supported for this endpoint, despite what you might read elsewhere
upload_routeImport a GPX file as a route (one route per <rte>/<trk>); it shows up in the Suunto app's route library and syncs to the watch for navigation. Takes activities (default running). Imports run one at a time and each route is read back from Suunto (check.verified), so sending several files at once is safe. Cannot be deleted from here — remove it in the app
get_upload_statusCheck whether an upload finished processing
push_workout_guidePush a structured workout (exercises, weights, rest, notifications) as a SuuntoPlus Guide — requires SUUNTO_APP_NAME
push_interval_guidePush an auto-advancing interval/cardio guide (timed or distance-based segments, target HR ranges) — requires SUUNTO_APP_NAME
push_strength_guidePush a per-set strength session (prep stopwatch, set/rest lap tracking, configurable rest mode, 3/6 - 2/3 step titles (exercise/set), optional rest target HR) — requires SUUNTO_APP_NAME
list_guidesList all SuuntoPlus Guides on your account
delete_guidePermanently delete a guide by id

Other

ToolWhat it does
list_subscriptionsHidden by default — Suunto's servers reject this call (OperationNotFound, checked on one account, September 2026); set SUUNTO_ENABLE_LEGACY_TOOLS=1 to list it
generate_daily_digestWrites the daily health digest to SUUNTO_HISTORY.md (see Daily health digest) — a write tool

Credits

License

MIT — use it, fork it, improve it.

Source: README.md at commit 1f162dc

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

9
  1. v0.24.0LatestNov 14, 2026
  2. v0.21.0Oct 29, 2026
  3. v0.20.0Oct 21, 2026
  4. v0.19.2Oct 15, 2026
  5. v0.19.0Oct 7, 2026
  6. v0.18.0Oct 5, 2026
  7. v0.16.0Oct 5, 2026
  8. v0.15.2Oct 2, 2026
  9. v0.15.1Sep 29, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts