Skip to main content
Glama

Suunto MCP

CI License: MIT suunto-mcp MCP server

Bring your Suunto watch into the conversation.

⏳ Status: awaiting API access. I've applied for a Suunto apizone API key and am waiting on approval. Until then, the code is implemented end-to-end against the documented Suunto API surface but has not been verified against a live account. Expect to file at least one issue once real credentials land. PRs from anyone with API access already are very welcome.

This is a small bridge that lets AI assistants like Claude read your Suunto training data — runs, hikes, sleep, recovery — so you can just talk to your watch.

Built by a Suunto user (hi 👋) who wanted to ask his coach-shaped chatbot "how was my last long run?" instead of clicking through dashboards — and to plug live training data into a personal health-skill for context-aware health Q&A.


What can you do with it?

Once it's set up, you can ask things like:

  • "How many kilometers did I run this month?"

  • "Compare my last three long runs — was my heart rate drift better?"

  • "Pull the GPX of yesterday's hike and write a short journal entry."

  • "What's my average resting HR trend over the last 2 weeks?"

  • "Find every workout above 160bpm average and show me the route."

  • "Summarize my training week in the style of a coaching report."

The AI does the work. You just ask.

Related MCP server: Garmin MCP Server

Is this for me?

Yes, if you own any modern Suunto watch (Race, Vertical, 9 Peak, 5 Peak, Ocean, etc.) and you sync it to the Suunto app on your phone.

No coding required to use it — just follow the setup below. The hard part (parsing Suunto's API, refreshing tokens, decoding the binary FIT file format) is already done for you.


How it works (in one picture)

Your Suunto watch ─► Suunto app ─► Suunto cloud ─► Suunto MCP ─► Claude (or any MCP client)

This project is the second-to-last box. It speaks Suunto on one side and the Model Context Protocol on the other.


Prerequisites

  • A Suunto watch synced to the Suunto app (your data must already be in Suunto's cloud — this tool reads from there, not the watch directly)

  • Node.js ≥ 20 (nodejs.org — install if needed)

  • An MCP-capable client: Claude Desktop, Claude Code, Cursor, or any MCP-compatible app

  • ~10 minutes if you already have an apizone account, ~25 minutes from scratch

Setup

1. Get a Suunto API key

Suunto opened their platform to all developers in March 2026 — anyone can sign up. Publishing to the Suunto store needs a partner agreement; personal use doesn't.

  1. Go to apizone.suunto.com → Sign up.

  2. Once signed in, click Apps → Create app. Give it any name (e.g. "Personal MCP"). For redirect URI use exactly:

    http://localhost:8421/callback
  3. From the app overview page, copy the Client ID and Client Secret (you may need to click Regenerate to reveal the secret once).

  4. Click Subscribe to APIs and subscribe your app to all of these products — each is a separate subscription:

    • Workouts API (required)

    • Activity API — for steps, calories, daily HR

    • Sleep API — for sleep stages and score

    • Recovery API — for HRV / recovery score

    • Subscriptions API — for webhook management

    Without a subscription, calls to that product return 403/404.

  5. Go to your user profile → Subscriptions tab and copy the primary subscription key. This is the Ocp-Apim-Subscription-Key that Suunto's Azure API Management gateway requires on every call.

🛟 If you can't find a value, run npm run doctor after step 3 below — it will tell you exactly which one is missing or wrong.

2. Install

git clone https://github.com/googlarz/suunto-mcp
cd suunto-mcp
npm install
npm run build

A Dockerfile is also included for containerized deployments and for glama.ai's automated introspection checks.

3. Configure

cp .env.example .env
$EDITOR .env   # paste the 3 values from step 1

4. Pair your Suunto account

npm run auth

Your browser opens automatically to Suunto's authorization page. Click Authorize. The page redirects back to a local success screen and tokens are saved to ~/.suunto-mcp/tokens.json (mode 0600). You only do this once — the server refreshes tokens automatically.

If the browser doesn't open, copy the URL from the terminal manually. Set SUUNTO_NO_BROWSER=1 to disable the auto-open behavior.

5. Verify it works

npm run doctor

This runs an end-to-end health check: Node version, env vars, network reachability, token freshness, a live list_workouts probe, and which 24/7 products you're subscribed to. Fix any ✗ lines before moving on.

6. Plug into Claude

Claude Desktop

Edit (creating if missing):

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Claude Code

Edit ~/.claude/mcp_config.json (or run claude mcp add if your version supports the CLI flow).

Config (works for both)

Once published to npm (no clone needed):

{
  "mcpServers": {
    "suunto": {
      "command": "npx",
      "args": ["-y", "suunto-mcp"],
      "env": {
        "SUUNTO_CLIENT_ID": "...",
        "SUUNTO_CLIENT_SECRET": "...",
        "SUUNTO_SUBSCRIPTION_KEY": "..."
      }
    }
  }
}

From a local clone:

{
  "mcpServers": {
    "suunto": {
      "command": "node",
      "args": ["/absolute/path/to/suunto-mcp/dist/index.js"],
      "env": {
        "SUUNTO_CLIENT_ID": "...",
        "SUUNTO_CLIENT_SECRET": "...",
        "SUUNTO_SUBSCRIPTION_KEY": "..."
      }
    }
  }
}

Restart Claude. Quick sanity check — ask:

"What was my most recent workout?"

If you get a real answer with sport, distance, and date, you're connected.


Example conversation

You:    Compare my last three long runs. Has my heart-rate drift improved?

Claude: Pulling your recent workouts… (calls list_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.

Tools exposed to the AI

Workouts

Tool

What it does

list_workouts

Recent workouts, filter by date range, auto-paginates

get_workout

Full summary for one workout

get_workout_samples

Time-series HR / pace / altitude / power / GPS

get_workout_fit

Downloads the FIT file and returns parsed, structured JSON

export_workout_gpx

GPX track export — for maps, Strava, route planning

24/7 health data (requires the Activity / Sleep / Recovery API products to be enabled on your apizone subscription)

Tool

What it does

get_daily_activity

Steps, calories, daily HR for a single day

list_daily_activity

Steps, calories, daily HR for a date range

get_sleep

Sleep stages, duration, score for a night

list_sleep

Sleep data over a date range

get_recovery

Recovery / HRV / stress for a single day

list_recovery

Recovery data over a date range

Webhooks

Tool

What it does

list_subscriptions

Active webhook subscriptions on the account

The AI picks the right one for your question. You don't need to know which.


Optional: CLI

Query your Suunto data directly from the terminal — no AI client needed. Useful for scripting, quick checks, or piping into jq.

# After npm run build (or npm install -g suunto-mcp once published):

suunto-mcp list-workouts --since 2026-04-01 --limit 10
suunto-mcp get-workout <workoutKey>
suunto-mcp get-sleep 2026-04-20
suunto-mcp list-sleep --from 2026-04-01 --to 2026-04-30
suunto-mcp list-recovery --from 2026-04-01 --to 2026-04-30
suunto-mcp export-workout-gpx <workoutKey> > route.gpx

All commands output JSON to stdout:

# Most recent workout's sport and distance
suunto-mcp list-workouts --limit 1 | jq '.payload[0] | {sport, km: (.totalDistance/1000)}'

# Average sleep score over the last week
suunto-mcp list-sleep --from 2026-04-14 --to 2026-04-20 \
  | jq '[.payload[].sleepScore] | add/length'

Run suunto-mcp --help for the full command list.


Optional: webhooks

Suunto can push notifications to you the moment a new workout finishes syncing — no polling.

npm run webhook

This starts a tiny HTTP receiver on port 8422 that logs every event to ~/.suunto-mcp/webhooks.ndjson. Expose it to the public internet (cloudflared, ngrok, your own VPS) and register the URL in your Suunto app settings.

For most personal setups, skip this. Polling on demand is simpler.


Pairs well with health-skill

If you already use googlarz/health-skill — a Claude skill for symptom triage, lab interpretation, and lifestyle guidance — Suunto MCP gives it a live feed of your training, sleep, and recovery data. Together they answer questions like "is my resting HR drift this week consistent with the cold I had?" or "given my recovery scores, should I keep this week's intervals?" with real numbers instead of guesses.

Privacy

As of v0.1:

  • All data flows directly between your machine and Suunto's API. No third-party servers, no analytics.

  • Tokens are stored locally at ~/.suunto-mcp/tokens.json (mode 0600), or in your OS keychain if you opted in.

  • Suunto sees that an app called "Suunto MCP" is authorized on your account (visible in apizone → user profile → Authorized applications).

  • The AI only sees data it explicitly requests via tools or resources.

If a future version offers a hosted-proxy option for non-tech users, this section will be updated explicitly. The default will always remain local-first.


Troubleshooting

Run npm run doctor first — it pinpoints most issues automatically.

Symptom

Likely cause

Fix

Missing required env vars

.env not loaded or not filled in

cp .env.example .env, fill it, retry

Not authenticated / SuuntoNotAuthenticatedError

Tokens missing

Run npm run auth

Token request failed: 400

Wrong client secret, or redirect URI doesn't match apizone exactly

Re-copy from apizone, ensure http://localhost:8421/callback is registered

SuuntoAuthError (401) on every call

Subscription key wrong or expired

Re-copy primary key from apizone → user profile → Subscriptions

SuuntoForbiddenError (403) on list_workouts

App not subscribed to the Workouts product

apizone → your app → Subscribe to APIs → Workouts

404 on get_sleep / get_recovery / get_daily_activity

App not subscribed to that 24/7 product

Subscribe in apizone (each product is separate)

Empty workout list

Watch hasn't synced to the Suunto cloud

Open Suunto app on your phone, wait for sync

npm run auth hangs / browser never opens

Port 8421 already in use, or running headless

lsof -i :8421 to check; set SUUNTO_NO_BROWSER=1 and copy URL manually

OAuth callback page says "State mismatch"

Started a second auth flow before the first finished

Close all auth tabs and run npm run auth once

Tokens "disappear" after switching to keychain

File-based tokens don't migrate automatically

Re-run npm run auth after enabling keychain

Disconnecting / cleanup

To remove access:

  1. Revoke the OAuth grant on Suunto's side — log in to apizone → user profile → Authorized applications → remove your app. Suunto stops honoring the tokens immediately.

  2. Delete local tokens:

    rm -f ~/.suunto-mcp/tokens.json

    If you were using the keychain backend, delete the entry named suunto-mcp / tokens in your OS keychain (Keychain Access on macOS, etc.).

  3. Remove the MCP entry from your Claude config and restart Claude.

  4. Optional — delete your apizone app if you no longer want it listed as a registered application.


MCP Resources (ambient context)

In addition to tools, the server exposes resources — passive data the client can pull without the model having to call a tool:

URI

What

suunto://recent/workout

Most recent workout summary

suunto://today/sleep

Last night's sleep

suunto://today/recovery

Today's recovery / HRV

suunto://today/activity

Today's steps / calories / HR

suunto://this-week/summary

Aggregated training totals for the current ISO week

Clients that surface MCP resources (Claude Desktop, Cursor) will let you attach these directly into a conversation — useful for "given my recovery today, should I…" style questions.

Reliability

  • Automatic retries with exponential backoff + jitter on 429, 500, 502, 503, 504 (up to 4 attempts).

  • Retry-After header is honored when Suunto returns one.

  • Auto-pagination in list_workouts — keeps fetching pages until your limit is met or there's nothing left.

  • Token refresh is automatic — the access token is silently re-issued before each request if it's within 60 seconds of expiry.

  • Concurrent-refresh deduplication — multiple parallel calls share a single in-flight refresh, so Suunto never sees a double refresh_token grant (which would invalidate the older token and log you out).

  • Structured error types — SuuntoAuthError, SuuntoForbiddenError, SuuntoNotFoundError, SuuntoRateLimitError, SuuntoApiError, SuuntoNotAuthenticatedError, SuuntoTokenError. Lets clients distinguish "re-authenticate" from "wait and retry" from "this resource doesn't exist."

Token storage

By default, tokens are written to ~/.suunto-mcp/tokens.json with file mode 0600. For stronger protection, opt into the OS keychain (macOS Keychain, Linux libsecret, Windows Credential Manager):

SUUNTO_TOKEN_STORAGE=keychain npm install @napi-rs/keyring
SUUNTO_TOKEN_STORAGE=keychain npm run auth

The keychain backend is an optional dependency — npm install will not fail if it can't be built on your platform; it just falls back to the file-based default.

Health check

npm run doctor

Output:

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 302)
  ✓  Pairing                          paired (user: dawid), token expires in 47 min
  ✓  API probe (list_workouts)        received 1 workout (latest: 1714137600000)
  ✓  Daily activity product           subscribed
  !  Sleep product                    not subscribed on apizone
  ✓  Recovery product                 subscribed

Run this whenever something feels off. It pinpoints the exact failing layer (Node, env, network, auth, API quota, missing product subscription).

Tests

npm test

40 unit + integration tests cover:

  • OAuth URL building, code exchange, refresh, token-expiry refresh logic

  • Concurrent-refresh deduplication (4 parallel calls → 1 token request)

  • Token storage (round-trip, file permissions, missing-file fallback, parent-dir creation)

  • API client: bearer + subscription-key headers, retry on 429/500 with Retry-After, no retry on 4xx, byte-stream downloads

  • Structured error types (SuuntoAuthError, SuuntoForbiddenError, SuuntoNotFoundError, SuuntoRateLimitError)

  • list_workouts auto-pagination across multiple pages

  • FIT integration: parser accepts a minimum-valid byte stream, rejects garbage and empty input

  • FIT summary extraction, empty-FIT handling, record sampling

  • MCP resources: enumeration, dispatch, today's-date wiring, week aggregation

  • Config loading, env overrides, missing-credential errors

CI runs on Node 20 and 22 on every push and PR.

PRs welcome.


Credits

License

MIT. Use it, fork it, improve it.

Available Tools

25 tools
delete_guideDelete SuuntoPlus guideA
DestructiveIdempotent

Permanently deletes one SuuntoPlus Guide from the user's account by id. Use list_guides to find the id. This removes it from the Suunto app / apizone catalogue; it does not reach into the watch to un-pin a copy already synced there. Write operation (irreversible).

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

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so safety is partly covered. The description adds valuable behavioral context beyond that: permanence, irreversibility, and the important limitation that it does not un-pin a copy on the watch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences with zero filler; the core action and its id lookup guidance are front-loaded, and the watch-copy caveat is a single clarifying clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter destructive tool with no output schema, the description covers the action, the id source, the irreversibility, and the key side-effect boundary, which is everything an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single guideId parameter is already documented with its provenance. The description only reiterates 'by id' and points to list_guides, adding little beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (deletes), resource (one SuuntoPlus Guide), and scope (by id, from the user's account) in the first sentence, immediately distinguishing it from sibling push_*_guide and list_guides.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent to use list_guides to find the id, and clearly scopes what the operation does and does not affect (account/catalogue removal vs. a synced watch copy). Nothing about when to invoke it is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_routeExport route as GPXA
Read-only

Exports a saved Suunto route as a GPX 1.1 XML string. Suitable for import into navigation apps (Komoot, Strava, Garmin Connect, etc.). Use list_routes to discover valid route IDs. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
routeIdYesRoute ID returned by list_routes.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so 'Read-only' is largely a restatement. The description earns credit beyond that by disclosing the concrete return type (GPX 1.1 XML string) and the interoperability intent, which the annotations do not cover. No auth or rate-limit notes, but none are needed for this read-only export.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the operation and output format, followed by relevance and prerequisite. Every sentence carries distinct information with no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly fills the gap by stating the return value is a GPX 1.1 XML string. Combined with the prerequisite pointer and read-only status, an agent has everything needed to call this one-parameter tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single routeId parameter is already documented in the schema as 'Route ID returned by list_routes.' The description's 'Use list_routes to discover valid route IDs' essentially repeats that provenance rather than adding format or constraint detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Exports a saved Suunto route') and even names the output format (GPX 1.1 XML string), which is unusually specific. It does not, however, explicitly differentiate itself from the sibling export_workout_gpx, leaving the agent to infer the route-vs-workout distinction from the resource name alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context for when the output is useful ('import into navigation apps such as Komoot, Strava, Garmin Connect') and names the prerequisite discovery tool (list_routes). It stops short of an explicit when-not or an alternative export tool comparison, but the usage context is well conveyed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_workout_gpxExport workout as GPXA
Read-only

UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/exportGpx) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Would return the workout's GPS route as a GPX 1.1 XML string. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.

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

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses the exact failure mode (401 OperationNotFound from /v2/workout/exportGpx), that the error surfaced will be 'endpoint unavailable', and that this is not an auth issue — precisely the context an agent needs to avoid misdiagnosing. It also states the would-be return format (GPX 1.1 XML string) and confirms read-only, adding value beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The unavailability notice is front-loaded, which is the right priority, and the remaining clauses are informative rather than filler. Slightly wordy, but every sentence carries signal about state or behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-param, read-only tool with full schema coverage, the description covers what an agent needs: current unavailability, why it fails, and what it would return. Nothing material is missing even without an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single workoutKey parameter is fully documented in the schema (opaque, discovered via list_workouts, SuuntoNotFoundError on invalid key). The description adds nothing about the parameter, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb, resource and output format: exports a workout's GPS route as a GPX 1.1 XML string. An agent immediately knows what it would do. It does not, however, distinguish itself from the sibling export_route or explain how the two differ, which is the one clarity gap.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives strong current-state guidance: the endpoint returns 'endpoint unavailable' and this is not an authentication problem, so an agent should not retry or chase credentials. It stops short of naming an alternative (e.g. get_workout_fit) for obtaining GPS data while the endpoint is broken.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_daily_digestGenerate daily health digestA
DestructiveIdempotent

Builds a color-coded daily health digest (steps, sleep, recovery balance, HRV, and a training-load model) for one date and appends it as markdown to a history file. Suunto's API has no fitness/fatigue endpoints, so this computes CTL (42-day fitness), ATL (7-day fatigue), and TSB (form) from each workout's tss.trainingStressScore using standard exponential time constants, persisting the running values in a local sidecar file (SUUNTO_DIGEST_AVERAGES_PATH env var, default ~/.suunto-mcp/averages.json) since there's nowhere else to store them. Running-average baselines (all days so far) per metric are also tracked there, with a separate baseline bucket for 'party nights' (>20,000 steps) so those don't skew the normal-day average. Requires Sleep and Recovery API subscriptions on apizone for the sleep/recovery sections to populate — falls back to 'no data' text for sections without a subscription rather than erroring. Write operation (updates the sidecar file and appends to the history file).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced.
seedAtlNoSame as seedCtl but for Fatigue (ATL). Only used on the very first digest ever run.
seedCtlNoOnly used on the very first digest ever run (no prior sidecar file). Anchors the starting Fitness (CTL) value to the number shown on the user's watch instead of cold-starting at 0. Ask the user for their watch's displayed Fitness value if this is their first digest.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Far exceeds the annotations (which only say non-read-only, destructive, idempotent, open-world). It discloses the CTL/ATL/TSB computation from tss.trainingStressScore, the sidecar file and env var used for persistence, the baseline bucketing for 'party nights', the subscription-dependent fallback, and explicitly labels itself a write operation that appends to a history file.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but dense, and every sentence carries required information given the tool's complexity. It is front-loaded with the purpose, then proceeds to computation, persistence, prerequisites, and side effects in a logical order with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers behavior, side effects, prerequisites, and fallbacks for a complex tool with no output schema. Remaining gaps are minor: the history file location/format and what the call returns to the caller are not described, though the sidecar path is.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds domain context for the date (via the workload) but says nothing about seedCtl/seedAtl beyond what the schema already documents, so it does not meaningfully extend parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: builds a color-coded daily health digest covering steps, sleep, recovery, HRV and a training-load model for one date. No sibling tool does anything comparable, so differentiation is inherent, and the side effects (sidecar update, markdown append) are stated up front.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operating context: one date per call, requires Sleep and Recovery API subscriptions for those sections, and falls back to 'no data' instead of erroring. It does not name an alternative tool or an explicit when-not-to-use condition, but there is no overlapping sibling to route against.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_daily_activityGet daily activityA
Read-only

Returns the 24/7 activity samples for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample) from the /247samples API, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } } — 144 rows for a full day, one per 10 minutes (138 or 150 on the days the clocks change). A day without synced data returns []. Use list_daily_activity for a date range. Requires 24/7 Activity API subscription on apizone. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint; the description adds substantial behavior beyond that — 144 rows at one per 10 minutes, 138/150 rows on DST change days, empty array for unsynced days, and the local-time stamping of each sample. This is exactly the extra context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but well-structured: day scope, source API, return shape, row count, DST exception, empty case, alternative, prerequisite, and read-only marker all in one sentence. The return-shape detail is front-loaded enough to be usable, though the em-dash clause is heavy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully specifies the return value: array of objects with timestamp (ISO 8601 + offset) and entryData fields with units, plus row count and the empty-day case. An agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the date parameter already documents format, pattern, examples, and the partial-today behavior, so the schema carries the load. The description's restatement of local-day semantics adds little beyond what the parameter description already states, matching the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (returns 24/7 activity samples for one local calendar day) with a precisely scoped resource, underlying API endpoint, and day definition. It explicitly names the sibling list_daily_activity as the range alternative, letting an agent distinguish it without reading any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear routing rule ('Use list_daily_activity for a date range') and a precondition (requires 24/7 Activity API subscription on apizone). It does not restate the today/future partial-data caveat here, though the schema parameter description covers it, so usage context is clear but not fully self-contained.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_daily_activity_statisticsGet daily activity statisticsA
Read-only

Returns aggregated daily step count and energy consumption (joules) from the /247 API for the given datetime range. Response is an array of AggregatedActivityData objects, each with a Name ('stepcount' or 'energyconsumption'), Aggregation ('sum'), and Sources array containing per-device Samples with TimeISO8601 and Value. The window must be less than 28 days (exactly 28 is rejected). Samples with null Value indicate no data synced for that day. Each daily Sample is stamped local noon (TimeISO8601 like 2026-09-27T12:00:00+02:00); a one-day window (startdate = enddate = D) was observed returning the samples for D and the day after, so select samples by the date in TimeISO8601 rather than summing the response. Prefer this tool over list_daily_activity when you need totals rather than intraday time-series. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
enddateYesEnd datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate.
startdateYesStart datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnlyHint/openWorldHint; the description goes far beyond them with the hard 28-day window limit, null-Value semantics (no data synced that day), local-noon timestamp stamping, and the observed one-day-window off-by-one quirk with an explicit workaround (select samples by TimeISO8601 date rather than summing). It also restates read-only, which is consistent with, not contradicting, the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and data source, then return shape, constraints, edge cases, and sibling routing in that order. Sentences are dense but each carries distinct operational information; nothing is restated filler despite the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full burden of describing the return value and does so precisely: an array of AggregatedActivityData with Name, Aggregation, and Sources/Samples shape. Combined with the range constraint and timestamp caveat, an agent has everything needed to call and interpret this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds real parameter-relevant meaning: the strict 'less than 28 days, exactly 28 rejected' boundary nuance beyond the schema's looser 'must be less than 28 days after startdate', plus the guidance to select samples by the TimeISO8601 date because of how start/end boundaries behave.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource (aggregated daily step count and energy consumption) and states the backing endpoint (/247 API) plus the required datetime range. It also distinguishes itself from the sibling list_daily_activity by contrasting totals vs. intraday time-series, so an agent can choose without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Prefer this tool over list_daily_activity when you need totals rather than intraday time-series.' The constraint 'window must be less than 28 days (exactly 28 is rejected)' tells the agent when a call will fail, which is actionable selection guidance rather than inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_daily_snapshotGet daily snapshotA
Read-only

One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller. Output: { date, sleepNightOf, sleep, recovery, activity, workouts, errors }. sleep describes the NIGHT THAT LED INTO the date (sleepNightOf = the previous date, i.e. sleeps that began between noon on the previous day and noon on the date): { main (the longest non-nap sleep: sleepId, bedtimeStart, bedtimeEnd, durationS, deepS, lightS, remS, score, avgHrv, hrAvg, hrMin, spo2Max, latencyS, wasoS, wakeBeforeOffBedS — all durations in seconds: time to fall asleep, awake after falling asleep, awake in bed before getting up), otherNights (further non-nap sleeps, when the watch split a night), nightSleepS (total of main + otherNights, null when there is none), naps }. Suunto marks any sleep shorter than about 3 hours as a nap, so a short night appears under naps with main null. recovery covers the local calendar day: { samples, low: { balance, at }, high, first, last, morning: { balance, at } (the sample nearest the main sleep's bedtimeEnd — the waking value), atBedtime: { balance, at } (nearest its bedtimeStart, which falls on the previous local day), both null when there is no main sleep or no sample within an hour, stressStateSamples (samples per StressState) } or null without data. low is the day's lowest balance — not necessarily overnight (after an evening workout it can fall in the evening). activity: { steps, energyKcal } for the local day — energyKcal is the daily-statistics energy converted from joules; real days come out around 700-1,500 kcal, well below a resting rate, so it looks like ACTIVE energy rather than a total (not verified against the watch). A value is null, never 0, when Suunto has no sample for the date. workouts: the day's workouts (by their own local date) with { workoutKey, activityId, startLocal, totalTimeS, kcal, hrAvg, hrMax, tss (HR method), guide, hasLaps } — pass a workoutKey with hasLaps to get_workout_laps. Each section is fetched independently: one that fails is null and explained in errors, the others are still valid. With to, returns { from, to, days: [...], errors } instead (errors is shared by the whole range; a failed section is null in every day). Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoOptional last day of a range (inclusive, at most 14 days from `date`). The result is then { from, to, days: [one entry per day, in the shape above without errors], errors } — one request per section for the whole range, so prefer it to calling this once per day.
dateYesThe local calendar day YYYY-MM-DD (the first day when `to` is given). Use yesterday or earlier for a complete day; today's data is partial until the watch has synced, and the night that led into today may still be in progress.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly/openWorld, so the description carries the real burden and delivers: per-section independent fetch with partial failure semantics ('one that fails is null and explained in errors, the others are still valid'), the null-never-0 convention, the ~3-hour nap threshold, and the unverified energyKcal caveat. This is well beyond what the annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with a clear purpose sentence, and given the absent output schema most details earn their place. But it is delivered as one dense block of nested parentheticals that is hard to scan, and the shape could have been split into labeled sections.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must describe return values and does so exhaustively: the top-level shape, per-section field lists, range-mode shape, and error behavior. Nothing an agent needs to call or interpret this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the schema already documents both params. The description adds value by documenting the return-shape switch when `to` is present and the local-calendar-day semantics of `date` including the midnight-to-noon sleep attribution window, going slightly past what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb+resource and positions it explicitly as an aggregation: 'One call for "how was this day, and the night before it": the aggregation the other tools leave to the caller.' It then names the exact siblings it replaces (get_sleep, get_recovery, get_daily_activity_statistics, list_workouts), so an agent can distinguish it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use with alternatives named: 'Use this instead of combining get_sleep, get_recovery, get_daily_activity_statistics and list_workouts by hand.' It also gives a when-not condition for the date param ('today's data is partial until the watch has synced') and the range alternative ('prefer it to calling this once per day').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recoveryGet recoveryA
Read-only

Returns recovery-balance samples from the /247samples API for one local calendar day (00:00–23:59 in the local time the watch stamped on each sample), as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } } — 48 half-hourly rows for a full day (46 or 50 on the days the clocks change). A day without recovery data returns []. Use list_recovery for a date range. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesCalendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint/openWorldHint annotations, it discloses concrete behaviors: 404 without a Recovery API subscription, [] for a day with no data, 48 half-hourly rows (46/50 on clock-change days), and the local-time stamping. That is rich operational context an agent cannot get from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded, leading with the return shape and following with the routing hint and edge cases; every clause adds operational value. It is a single long sentence rather than cleanly separated, which slightly hurts readability but not content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description fully specifies the return shape, field types, and value ranges (Balance 0.0–1.0, StressState enum mapping) plus the empty-array and subscription-failure cases. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents the date format and the today-is-partial caveat, so baseline would be 3. The description adds edge-case meaning: the exact 00:00–23:59 local-day boundary and the clock-change row count that defines a 'full day'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Returns recovery-balance samples from the /247samples API') and pins the scope to one local calendar day. It explicitly names the sibling it is not (list_recovery), so an agent can distinguish it without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes range queries to list_recovery, and warns that today/future dates return empty or partial payloads, advising yesterday or earlier for complete results. This is clear when-to-use, when-not, and named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sleepGet sleepA
Read-only

Returns the sleeps of one night from the /247samples API. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Plain array with one row per sleep — Suunto re-sends a sleep every time it revises it, and only the longest revision is kept — of { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. IsNap is true for any sleep shorter than about 3 hours, at any time of day, and can flip while a sleep is still being recorded — so it also marks a short fragment of a split night; do not drop rows by IsNap alone. A night can hold several rows (a split night, or a nap beside it): rows are not merged, so decide from BedtimeStart and Duration which belong together. Returns [] when no sleep began in that window, e.g. today's date before tonight. Use list_sleep for a range. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesDate YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only and open-world access, but the description adds critical behavior: Sleep API subscription requirement, 404 response, revision-deduplication behavior, unmerged split rows, and IsNap flipping. These go well beyond annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense with necessary domain nuance; it front-loads the return type and date semantics. However, it repeats the schema's date explanation and packs multiple caveats into a single paragraph, which slightly hurts scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully specifies the return array shape, nested fields, and edge cases (empty array, revisions, split nights, IsNap caveats). It also covers auth requirements and sibling routing, leaving no critical gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents the date-window semantics, so the baseline is 3. The description adds some distinct value by explicitly mentioning that afternoon naps are filed with the following night and giving multiple bedtime examples, but much of its date explanation repeats the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Returns the sleeps of one night from the /247samples API') and names the sibling alternative ('Use list_sleep for a range'), so an agent can distinguish it immediately from range-based sleep queries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes range queries to list_sleep, explains the noon-to-noon date window, notes that last night is filed under yesterday, and states that a subscription is required with 404 otherwise. When and when-not are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_upload_statusGet workout upload statusA
Read-only

Polls the processing status of a workout upload initiated by upload_workout. Returns status (e.g. 'Queued', 'Processing', 'Processed', 'Error') and the workoutKey once processing completes. Use the returned workoutKey with get_workout for full detail.

ParametersJSON Schema
NameRequiredDescriptionDefault
uploadIdYesUpload ID returned by upload_workout.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it readOnly and openWorld. The description adds concrete return behavior: the set of status values and the fact that workoutKey appears once processing completes, which helps the agent interpret results. It does not cover rate limits or auth, but with annotations present it adds useful context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core purpose, then return values, then next action. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter status tool with no output schema, the description adequately explains what is returned (status values and workoutKey) and how to proceed. Annotations cover safety, and the schema covers the input, so nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the single uploadId parameter is fully documented as the ID returned by upload_workout. The description reinforces the dependency but adds no syntax or format detail beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Polls') and resource ('processing status of a workout upload'), identifies the initiating sibling (upload_workout), and distinguishes its output from get_workout. An agent can tell this is a status-checking tool rather than a data-retrieval or upload tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly ties invocation to a prior upload_workout call and directs the agent to use the returned workoutKey with get_workout for full detail. It does not explicitly state when not to call it (e.g., avoid polling repeatedly), but the context and alternative are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_workoutGet workoutA
Read-only

Returns the base summary for one workout (about 1.6 KB): the same scalar fields as a list_workouts item (times, distance, energy, hrdata, tss/tssList, recoveryTime) plus extensionTypes, the list of data streams Suunto holds for it. It does NOT include laps, HR zones or other extension data — use get_workout_laps for laps and zone times, get_workout_fit for record-level data. Throws SuuntoNotFoundError if the workoutKey is malformed (not 24 hex characters) or does not exist. Use list_workouts to discover valid workoutKey values. Read-only.

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

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover read-only/open-world, and the description adds substantial behavior beyond them: approximate response size (~1.6 KB), the exact field set and extensionTypes, explicit exclusions, and the SuuntoNotFoundError failure mode for malformed or missing keys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the return shape, then exclusions/alternatives, then error behavior, then key discovery. Dense but every clause carries distinct information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully compensates by describing the returned fields, the non-returned data, response size, and failure modes. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents the opaque key and its discovery path. The description adds the malformed-key format detail ('not 24 hex characters') and reinforces the discover-via-list_workouts rule, marginally exceeding the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Returns the base summary for one workout') and enumerates the exact scalar fields returned. It explicitly distinguishes itself from siblings get_workout_laps and get_workout_fit by naming what it does NOT include.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: use get_workout_laps for laps/zone times, get_workout_fit for record-level data, and list_workouts to discover valid keys. The condition selecting each alternative is stated, not implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_workout_fitGet workout FIT dataA
Read-only

Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON. Default (full=false): compact summary { sport, total_distance_km, avg_heart_rate, training_effect, laps (a COUNT only, not the laps), records_sample: { first, middle, last (one record each), count } }. Set full=true to receive every parsed FIT record and lap — pretty-printed, about 550 KB for a 35-lap strength session, so the result usually spills to a file. For per-lap data use get_workout_laps instead (about 2.5 KB); use full=true only when record-level data is required. An unknown workoutKey fails with a 403 Forbidden error here (not-found on the other workout tools). Read-only.

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

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, it discloses non-obvious behavior: an unknown workoutKey returns 403 Forbidden HERE but not-found on other workout tools, and large results spill to a file. These are exactly the operational traits annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then the default behavior, then the escape hatch, then the error quirk. Dense but every clause carries actionable information (size estimates, error code divergence, sibling pointer) with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so thoroughly, describing both the compact summary fields and the full payload nature. Combined with the error behavior and sibling routing, nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes further by spelling out the exact shape the full=false summary returns (sport, total_distance_km, records_sample structure) and the size consequence of full=true. This adds meaning beyond the terse schema text, though much of it is return-shape rather than parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Downloads the workout's binary FIT file from Suunto and returns it parsed to JSON'), and immediately distinguishes itself from siblings by naming get_workout_laps as the per-lap alternative. An agent can tell what this does and how it differs from nearby tools without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes usage: default compact summary vs full=true for record-level data, with a concrete size signal ('about 550 KB for a 35-lap strength session, so the result usually spills to a file') and a named alternative ('For per-lap data use get_workout_laps instead (about 2.5 KB)'). It even states the exclusivity condition ('use full=true only when record-level data is required').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_workout_lapsGet workout lapsA
Read-only

Returns the manual laps of one workout as a compact table, plus its training-load fields — the way to read back a guided gym session set by set (push_strength_guide records one lap per set and per rest; push_workout_guide one lap per exercise and one per rest between exercises). A session from push_interval_guide auto-advances and is expected to record no manual laps (unverified), so it should return an empty table. About 2.5 KB for a 35-lap strength session, versus ~550 KB for get_workout_fit full=true. Output: { workoutKey, activityId, startTime (epoch ms), totalTimeS, guide: { id, name } | null (the guide that ran, as recorded by Suunto — not looked up in list_guides, because guides are often deleted afterwards), tss: [{ method (seen so far: 'HR', 'MET'), value }], pte, peakEpoc, recoveryTime (from the workout's summary extension; units not verified, and it can differ from the recoveryTime that list_workouts and get_workout carry), hrZoneTimeS: [zone1..zone5 seconds], feeling (the answer to the watch's 'How was it?' question, passed through as Suunto sends it; null when skipped), lapCount, checks: [{ code, detail }], laps: { cols, rows } }. checks lists reasons not to trust positional reading of the table (empty when clean): 'duplicate-rest' (the same rest label twice in a row — a set lap is missing or a rest was split), 'no-session-complete' (a guided table without its final lap — session ended early, buttons locked or watch restarted), 'unlabelled-laps' (some laps have no guide label), 'no-heart-rate' (no lap has heart rate, e.g. battery mode Tour). laps.cols = [i (1-based), startOffsetS (from workout start), durationS, hrAvg, hrMax, hrMin (bpm), kcal, kind, label]; each row is an array in that order. label is the text of the guide step that was active during the lap (lines joined with ' | '), or null when no guide ran. kind is 'rest' when the label contains 'Next:' at its start or after a '·' (a per-set rest lap reads 'Next: set k/S', or 's target · Next: set k/S' with restMode 'stopwatch'), 'done' for the final 'Session complete' lap, 'step' for any other labelled lap, null when there is no label. A per-set strength guide yields, per exercise, a prep lap, then set 1, rest, set 2, rest, … — 2 × sets laps — and one trailing 'Session complete' lap for the whole session; a prep lap and a set lap look alike in the label, so tell them apart by position. Real sessions can deviate (skipped or repeated rest laps), so check the labels rather than only counting. A workout without manual laps (unguided gym, cycling) returns lapCount 0 and laps.rows [] — not an error. Call list_workouts first for the workoutKey.

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

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint; the description adds substantial context the annotations cannot supply: payload size, the checks codes that flag untrustworthy positional reads, the fact that real sessions deviate (skipped/repeated rests), the caveat that recoveryTime can differ from list_workouts/get_workout, and that guide is recorded by Suunto rather than looked up because guides are often deleted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose and the sibling comparison before diving into output detail, so the most decision-relevant content comes first. It is dense and delivered as one long block, but with no output schema the detail is load-bearing rather than padding; slightly better visual structure would help.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full burden of explaining the return shape and does so exhaustively: field-by-field output, laps.cols ordering, label/kind derivation rules, and the checks codes. It also warns about positional-reading pitfalls, leaving nothing an agent needs to interpret results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter is already documented there, including the 24-character constraint and not-found failure mode. The description's 'Call list_workouts first for the workoutKey' mostly restates the schema's provenance note, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Returns the manual laps of one workout as a compact table, plus its training-load fields') and immediately scopes the use case to guided gym sessions read back set by set. It also distinguishes itself from get_workout_fit by quantifying the size difference (~2.5 KB vs ~550 KB), so an agent can separate the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing context: use it for push_strength_guide and push_workout_guide sessions, expect no laps from push_interval_guide, and fall back to get_workout_fit for the full payload. It also states the prerequisite ('Call list_workouts first for the workoutKey') and clarifies that an empty table is not an error, removing the most likely false-negative inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_workout_samplesGet workout samplesA
Read-only

UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/workout/samples) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error; it is not an authentication problem. Use get_workout_fit with full=true for record-level data (heart rate etc.), or get_workout_laps for laps. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.

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

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint/openWorldHint; the description adds the critical behavioral fact that the endpoint currently returns 401 OperationNotFound and fails, that this is not an auth failure, and that the tool is retained for future restoration. That is exactly the kind of operational context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with 'UNAVAILABLE', then the failure mode, then the alternatives, then the retention rationale. Every clause earns its place; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with no output schema, the description supplies everything needed: it is broken right now, why, and what to call instead. Nothing an agent needs to avoid misusing this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single workoutKey parameter is already richly documented (opaque, discover via list_workouts, throws SuuntoNotFoundError). The description adds nothing about parameters, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description makes clear this tool retrieves workout sample (record-level) data for a given workout, and it distinguishes itself from siblings by naming get_workout_fit and get_workout_laps as the working alternatives. It is slightly indirect — the functional purpose is inferred from the routing sentence rather than stated as a standalone verb+resource — but an agent can still tell what it is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit, unambiguous routing: the endpoint is rejected, the call fails with 'endpoint unavailable', this is not an authentication problem, and the agent should use get_workout_fit with full=true for record-level data or get_workout_laps for laps. Both the when-not and the alternatives are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_daily_activityList daily activityA
Read-only

Returns 24/7 activity samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { HR (bpm), StepCount, EnergyConsumption (joules, as in get_daily_activity_statistics) } }. Days without synced data are simply absent. Use get_daily_activity for a single day or get_daily_activity_statistics for aggregated daily step/energy totals. Requires 24/7 Activity API subscription on apizone. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals).
fromYesStart date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint/openWorldHint annotations, it discloses the output shape (array of timestamp + entryData with HR, StepCount, EnergyConsumption), the absence-instead-of-error behavior for unsynced days, chronology, and the subscription requirement. This is unusually rich behavioral context for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One long sentence but front-loaded and dense: resource and request first, output shape second, alternatives and constraints last. Every clause carries information, though the parenthetical nested object definition makes it heavier to parse than it needs to be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description fully specifies the return structure, ordering, missing-day behavior, and the API subscription gate. Combined with the 100%-covered input schema, an agent has everything needed to call and interpret this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents format, inclusivity, and size guidance, so the baseline is 3. The description adds genuine param-level semantics: intervals are interpreted in the local time the watch stamped on each sample, and results are ordered chronologically, which the schema does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource (returns 24/7 activity samples from /247samples) with explicit scope (local calendar days [from, to] inclusive). It directly distinguishes itself from the sibling tools get_daily_activity (single day) and get_daily_activity_statistics (aggregated totals), so an agent can route without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states exactly when to use this tool versus the two alternatives, names those alternatives, and adds a hard prerequisite (24/7 Activity API subscription on apizone) plus a range-size preference. Nothing about selection is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_guidesList SuuntoPlus guidesA
Read-only

Returns all SuuntoPlus Guides (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, newest first. Each item includes id, name, description, owner, localDate, and usage. Use the id with delete_guide, or with push_*_guide's guideId param to update an existing guide instead of creating a new one. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, and the description redundantly confirms 'Read-only'. It adds genuine context beyond annotations: the ordering (newest first) and the fact that it returns ALL guides with no pagination/limit caveat mentioned. No auth or rate-limit detail, but nothing contradicts annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the verb+resource+ordering, followed by the returned fields and the actionable id usage. No filler; every sentence carries operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fills the gap by enumerating returned fields and ordering, and it explains the follow-up call pattern with delete_guide and push_*_guide. Combined with annotations covering the safety profile, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline of 4 applies. The description correctly implies no filtering (returns all guides on the account) and details the fields present on each returned item (id, name, description, owner, localDate, usage), which compensates for the absent output schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Returns all SuuntoPlus Guides') and scopes the sources (from push_workout_guide/push_interval_guide/push_strength_guide) on the user's account, plus ordering (newest first). An agent can distinguish this from sibling list_* tools without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent downstream: use the id with delete_guide, or with push_*_guide's guideId to update an existing guide rather than create a new one. There is no competing 'list guides' sibling, so no when-not-to-use exclusion exists, but the context for use is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_recoveryList recoveryA
Read-only

Returns recovery-balance samples from the /247samples API for the local calendar days [from, to] inclusive (in the local time the watch stamped on each sample), ordered chronologically, as a plain array of { timestamp (ISO 8601 with UTC offset), entryData: { Balance (0.0–1.0 recovery balance), StressState (0=Invalid, 1=Relaxing, 2=Active, 3=Passive, 4=Stressful) } }. Days without recovery data are simply absent. Use get_recovery for a single day. Requires Recovery API subscription on apizone; returns 404 without it. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output.
fromYesStart date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, and the description redundantly restates read-only but adds real value beyond them: the Recovery API subscription requirement and the 404 behavior without it, the chronological ordering guarantee, and the silent omission of empty days. It stops short of pagination or rate-limit detail, so 4 rather than 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core behavior and return shape in one dense sentence, then adds short supporting sentences for the alternative and the subscription constraint. The parenthetical balance/StressState enumeration is long but earns its place because there is no output schema to carry it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully specifies the return structure, ordering, missing-day behavior, and the auth/error profile, so nothing an agent needs to call or interpret this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds semantics the schema does not: that days are interpreted in the local time the watch stamped on each sample, and that the output is a plain array. This meaningfully clarifies the temporal boundary beyond the raw date pattern.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Returns) and resource (recovery-balance samples) with precise scope: local calendar days [from, to] inclusive, chronological ordering, and the exact return shape. It explicitly contrasts with get_recovery for a single day, so an agent can distinguish it from siblings without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative explicitly ('Use get_recovery for a single day') and gives the selecting condition (single day vs. range). It also warns days without data are simply absent, so the agent will not misread an empty stretch as an error.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_routesList routesA
Read-only

Returns all routes saved in the user's Suunto account. Each route: id, description, visibility, distance (m), start/end coordinates, waypoint count. Use export_route to get the GPX track for navigation. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so 'Read-only' largely repeats structured data. However, the description adds genuinely useful context beyond annotations by describing the per-route payload (id, description, visibility, distance in m, start/end coordinates, waypoint count), compensating for the absence of an output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, none wasted: purpose, return shape, and routing to the sibling tool, with the primary purpose front-loaded. Optimal size for a simple list operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, describing the returned route fields is exactly the right compensation and is done here. The only minor gap is absence of pagination/volume hints for an 'all routes' call, but overall the definition is complete enough to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so there is nothing to disambiguate; baseline for a zero-parameter tool is 4. No parameter-related confusion is possible here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Returns all routes'), the resource, and the scope ('saved in the user's Suunto account'), then enumerates the returned fields. It is immediately distinguishable from siblings like export_route without needing the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to the right alternative: 'Use export_route to get the GPX track for navigation,' making the boundary between listing and exporting clear. No explicit when-not guidance is given, but the alternative is named with its triggering condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sleepList sleepA
Read-only

Returns the sleeps of the nights [from, to] inclusive from the /247samples API, ordered chronologically by bedtime. A date means the NIGHT of that date: every sleep that began between 12:00 (noon) on it and 12:00 the next day, in the local time the watch stamped on the sleep — so 23:00, 00:30 and 03:00 bedtimes all belong to the same date, and an afternoon nap is filed with the night after it. Last night is therefore filed under yesterday's date. Same rows as get_sleep, one per sleep (revisions collapsed): { timestamp (= BedtimeStart, ISO 8601 with UTC offset), entryData: { SleepId, IsNap, BedtimeStart, BedtimeEnd, Duration (s), DeepSleepDuration, LightSleepDuration, REMSleepDuration (s), SleepQualityScore, AvgHRV (ms), HRAvg, HRMin (bpm), … } }. Nights without recorded sleep are simply absent. Use get_sleep for a single night. Requires Sleep API subscription on apizone; returns 404 without it. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesLast bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness.
fromYesFirst bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnly/openWorld; the description adds substantial behavioral context beyond them: the noon-to-noon 'night' filing rule, chronological ordering, revision collapsing ('one per sleep'), 404 auth behavior, and that absent nights are simply not present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and routing, then schema/return detail. The inline entryData field enumeration is dense but justified since no output schema exists. Length is high but most sentences carry distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the full return shape (timestamp, entryData fields) plus the semantic caveats needed to interpret dates correctly. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds interpretive depth (a date means the NIGHT beginning at noon, 23:00/00:30/03:00 bedtimes all map to one date, naps file with the following night). That said, it largely restates the schema's own 'date went to bed, not woke up' note.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Returns the sleeps of the nights') with explicit scope (from/to, /247samples API, ordered chronologically by bedtime). It distinguishes itself from the sibling get_sleep by naming it and its different use case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Use get_sleep for a single night.' It also states a prerequisite ('Requires Sleep API subscription on apizone; returns 404 without it') and notes that missing nights are silently omitted rather than errors.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_subscriptionsList webhook subscriptionsA
Read-only

UNAVAILABLE — Suunto's API gateway currently rejects this endpoint (/v2/subscriptions) with 401 OperationNotFound on the account it was tested with (September 2026), so the call fails with an 'endpoint unavailable' error rather than returning a list. Would return the active webhook subscriptions as an array of { id, eventType, callbackUrl, createdAt }. Kept so the tool starts working again if Suunto restores the endpoint. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint; the description adds the critical behavioral fact that the gateway rejects the endpoint with a 401 OperationNotFound and that the call surfaces an 'endpoint unavailable' error. It also specifies the intended return shape { id, eventType, callbackUrl, createdAt }, which is far beyond annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences that each carry distinct information: the failure, the intended return shape, and the rationale for keeping the tool. The structure is front-loaded with the unavailability. Slight redundancy between the first sentence's error description and the parenthetical, but no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only tool with no output schema, the description covers everything an agent needs: current failure mode, expected error behavior, and the intended return payload. Nothing actionable is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero properties, so the baseline is 4; there is nothing for the description to disambiguate. It does not add parameter detail, but none is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the exact resource (active webhook subscriptions at /v2/subscriptions) and what it would return, and no sibling tool covers subscriptions, so it is trivially distinguishable. It also front-loads that the endpoint is currently unavailable, which is the single most important fact about this tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent the call will fail with an 'endpoint unavailable' error rather than returning data, which is effectively a strong 'do not use' signal, and explains the tool is retained for future restoration. It stops short of naming an alternative for listing subscriptions, but no sibling offers that capability.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_workoutsList workoutsA
Read-only

Returns the user's recent Suunto workouts ordered newest-first (Workout API v3). Each item: workoutKey (string id), activityId (numeric activity code — there is no separate plain-language 'sport' field; use get_workout_fit for the parsed FIT file's session.sport if a sport name is needed), startTime (epoch ms), totalTime (s), totalDistance (m), totalAscent (m), totalDescent (m), energyConsumption (kilocalories, not 'totalCalories'), hrdata: { avg, max } (workout heart rate — hrdata.max is the account's overall max HR, use hrdata.workoutMaxHR for this specific workout's peak). Auto-paginates with offset-based pagination until limit is reached or no more workouts exist. Each item also embeds SummaryExtension (including apps[]: the SuuntoPlus guide that ran, if any) and IntensityExtension (HR-zone times). Use get_workout_laps for the lap table of a single workout. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout.
sinceNoISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size.
untilNoISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover read-only/open-world, and the description adds genuine behavioral detail beyond them: auto-pagination semantics ('until limit is reached or no more workouts exist'), plus field-level traps (hrdata.max is the account's overall max HR, not the workout peak; energyConsumption is not totalCalories; no plain-language sport field exists). These gotchas materially change how an agent interprets results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single dense paragraph, front-loaded with the core action before field details. It is long, but with no output schema the field-level exposition earns its place; the sole weakness is that field descriptions and usage hints are interleaved rather than separated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema in structured form, the description compensates by enumerating the returned shape (workoutKey, activityId, startTime, totalTime, distance, ascent/descent, energy, hrdata, SummaryExtension, IntensityExtension). An agent has enough to call it and interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents limit, since, and until thoroughly. The description adds only the pagination caveat ('auto-paginates... until limit is reached'), which the schema also states, so it does not meaningfully exceed the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Returns/list), resource (user's recent Suunto workouts), and ordering (newest-first), with versioning (Workout API v3). An agent can immediately distinguish it from get_workout (single) and get_workout_laps (lap table).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to alternatives for adjacent needs ('use get_workout_fit for the parsed FIT file's session.sport', 'Use get_workout_laps for the lap table of a single workout'). It gives clear context for related lookups but never states the inverse boundary (e.g. list vs. fetch a specific workout) or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

push_interval_guidePush interval guide to watchA
Destructive

Pushes an interval/cardio guide (warmup, timed or distance-based work intervals, recoveries, optional repeats) to the user's Suunto account via the SuuntoPlus Guide Cloud API. Unlike push_workout_guide (manual lap-per-exercise), interval segments auto-advance by elapsed time or distance — hands-off during a run or ride. Each segment can show a target heart-rate range alongside live HR. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. Same delivery caveat as push_workout_guide: appears after the phone's next normal Suunto app sync, no live push. Write operation.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesSession date YYYY-MM-DD.
titleYesShort session name shown in the Suunto app, e.g. '4x4 VO2max'.
blocksYesOrdered list of blocks. A block with times>1 repeats its segments as a unit (e.g. 4x[interval,recovery]) — put only the segments that repeat inside it; warmup/cooldown go in their own times=1 blocks before/after.
guideIdNoIf provided, updates this existing guide instead of creating a new one.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write/destructive/openWorld/non-idempotent, so the safety profile is covered. The description adds genuinely new context beyond them: the exact-match SUUNTO_APP_NAME env var requirement and the delivery caveat (no live push; appears after the next normal sync). It stops short of explaining the destructive aspect — that supplying guideId overwrites an existing guide — which the destructiveHint=true flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, followed by comparison, environment prerequisite, and delivery caveat. It is dense but every sentence carries distinct information; the 'Write operation.' tail is mildly redundant with annotations but otherwise there is little waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive write tool with no output schema and full schema coverage, the definition covers purpose, alternative routing, environment requirement, and delivery latency. The main remaining gap is not spelling out the overwrite behavior when guideId is supplied, but overall an agent has what it needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (date, title, blocks/segments, guideId) is already richly documented. The description describes the segment/block model conceptually (warmup, intervals, recoveries, repeats, target HR) but adds no syntax or format details beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Pushes an interval/cardio guide ... to the user's Suunto account') plus the underlying mechanism (SuuntoPlus Guide Cloud API). It explicitly contrasts itself with the sibling push_workout_guide, so an agent can distinguish it without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (push_workout_guide) and gives the exact condition that selects this tool: interval segments auto-advance by elapsed time or distance for a hands-off run/ride, versus manual lap-per-exercise. It also supplies the required SUUNTO_APP_NAME precondition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

push_strength_guidePush strength guide to watchA
Destructive

Pushes a resistance-training guide to the user's Suunto account via the SuuntoPlus Guide Cloud API — the tool to use for gym sessions. Per exercise: a prep step (self-paced stopwatch showing the plate breakdown if given, otherwise the weight/sets detail, plus the exercise name and live HR; a lap press starts the exercise), then with lapGranularity 'perSet' (default) each set is its own step ended by a lap press, and each rest between sets is its own step showing 'Next: set k/S'. restMode 'countdown' (default) counts down restSec and auto-advances into the next set with a vibration; 'stopwatch' counts up and waits for a lap press. lapGranularity 'perExercise' gives one step per exercise after its prep, with no between-set rests and no per-set laps. Every prep, set and rest is its own lap and the guide ends with one extra 'Session complete' step, so a perSet session records 2 × (total sets) + 1 laps. Read them back after the workout with get_workout_laps — its labels are the step texts. Requires SUUNTO_APP_NAME to exactly match the app name registered on apizone.suunto.com. Without guideId a new guide is created on every call (see list_guides / delete_guide to tidy up); with guideId that guide is overwritten. There is no live push to the watch: it appears after the phone's next normal Suunto app sync. Write operation.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesSession date YYYY-MM-DD.
titleYesShort session name shown in the Suunto app, e.g. 'Push A'.
guideIdNoIf provided, updates this existing guide instead of creating a new one.
restModeNoRest between sets. 'countdown' (default): counts down from restSec and auto-advances into the next set. 'stopwatch': counts up and waits for a lap press — the user paces it. Has no effect with lapGranularity 'perExercise' (no between-set rests). Before/between exercises is always a self-paced stopwatch.countdown
exercisesYes
lapGranularityNo'perSet' (default, recommended): one step per set plus one per rest, so laps bound every set/rest individually — needed to read per-set HR and duration from the synced workout. 'perExercise': one step per whole exercise instead, like push_workout_guide — shorter Guide list, coarser data.perSet

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false) by disclosing non-obvious behavior: no live push to the watch (appears on next phone sync), the SUUNTO_APP_NAME exact-match requirement, create-on-every-call without guideId vs overwrite with it, and the lap-recording formula 2×(total sets)+1. This is exactly the kind of context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded and nearly every clause carries functional information (lap math, sync behavior, mode interactions). It is nonetheless a dense single block of ~200 words with no formatting, which makes it slower to parse than a structured layout would for a tool this complex.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex write tool with no output schema, the description covers the write semantics, idempotency caveat, environment prerequisite, sync timing, and readback path, leaving little an agent would need to call it correctly. Return values are appropriately delegated to get_workout_laps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 83% (>80%), so the schema already documents most parameters and the baseline is 3. The description adds genuine cross-parameter meaning beyond the schema: restMode's interaction with lapGranularity, the prep-step/lap flow, and the plate-vs-detail display logic, which helps the agent reason about effects the per-field schema does not connect.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Pushes a resistance-training guide to the user's Suunto account') and explicitly positions itself against siblings ('the tool to use for gym sessions', references to push_workout_guide, list_guides, delete_guide, get_workout_laps). An agent can distinguish this from push_workout_guide and push_interval_guide without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear when-to-use routing ('the tool to use for gym sessions') and conditional guidance for the guideId create-vs-overwrite behavior, with pointers to list_guides/delete_guide for cleanup and get_workout_laps for readback. It does not explicitly state when to prefer push_workout_guide over this tool beyond the terse 'like push_workout_guide' aside, so it stops short of full alternative selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

push_workout_guidePush workout guide to watchA
Destructive

Pushes a text-step workout guide to the user's Suunto account via the SuuntoPlus Guide Cloud API. Each exercise becomes one step, advanced by a lap-button press on the watch. Requires SUUNTO_APP_NAME env var to exactly match the app name registered on apizone.suunto.com. There is no live push to the watch itself — delivery depends on the phone's normal Suunto app sync. In testing it showed up on the watch after the next ordinary sync with no manual pinning needed; if it doesn't appear, check the Suunto app under SuuntoPlus Guides and pin it there. For gym sessions prefer push_strength_guide: it records one lap per set and per rest, which get_workout_laps can read back. Write operation.

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

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a non-idempotent write (readOnlyHint=false, destructiveHint=true, openWorldHint=true), and the description adds substantial context beyond that: no live push to the watch, delivery depends on the phone's next normal sync, and a fallback pinning procedure. It also discloses the guideId update-vs-create behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in sentence one, followed by mechanics, constraints, troubleshooting, and sibling routing in a logical order. It is on the longer side and the troubleshooting sentence could be trimmed, but each sentence carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write tool with no output schema, the description covers everything needed: the required env var, that the operation is a create-or-update depending on guideId, the lack of a live push, the sync dependency, and the correct sibling for gym sessions. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, so date/title/exercises/guideId are mostly documented structurally. The description adds meaning beyond the schema by explaining that each exercise becomes one watch step advanced by a lap-button press, which clarifies how the exercises array is consumed. It doesn't add syntax detail for date or guideId.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Pushes a text-step workout guide') and names the exact mechanism (SuuntoPlus Guide Cloud API). It also distinguishes itself from the two sibling pushers by explaining that exercises map to lap-button steps, which push_strength_guide and push_interval_guide do differently.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'For gym sessions prefer push_strength_guide' with the reason (one lap per set/rest, readable by get_workout_laps). It also states the precondition (SUUNTO_APP_NAME must match the registered name) and what to do on failure (pin under SuuntoPlus Guides).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upload_workoutUpload workout fileA

Uploads a workout file to the user's Suunto account. Provide the absolute path to the file on disk. The file is pushed to Suunto and appears in the app after processing (usually a few seconds). Returns an uploadId you can poll with get_upload_status. Suunto's own upload API docs state only .fit (binary) is currently supported for this endpoint — a .gpx path is still accepted here (sent as application/gpx+xml) in case that changes, but treat it as unverified; use .fit for a workout that must reliably show up. Write operation.

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

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the write profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the closing 'Write operation.' is largely redundant. The description earns credit for behavior beyond the annotations: server-side processing delay before the workout appears, and the return of an uploadId that must be polled via get_upload_status.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action, path requirement, and polling workflow are front-loaded in the first sentences; the trailing .fit/.gpx caveat is long but carries real decision-relevant information. Slightly verbose, nothing clearly wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by explaining the uploadId return and the polling path. Missing secondary details (size limits, auth/permission requirements, failure behavior), which matters for an open-world, non-idempotent write.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuinely new semantics: the endpoint officially supports only .fit binary, the .gpx path is accepted but unverified behavior. It restates the absolute-path requirement, which the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Uploads a workout file to the user's Suunto account') and clearly separates this from siblings like push_workout_guide and export_workout_gpx, which move structured guides or export data rather than uploading a file from disk.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear conditions for choosing a format ('use .fit for a workout that must reliably show up', .gpx is unverified) and names the follow-up tool (get_upload_status). It stops short of comparing this tool against other upload/push siblings, so no explicit when-not-to-use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.18.0
    • Addedget_daily_snapshot
  2. 9 tool updatesv0.15.1
    • Changedgenerate_daily_digest1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — Suunto syncs once daily, so today's data is usually incomplete."New value: +"Calendar date YYYY-MM-DD to summarize. Use yesterday or earlier — today's data is usually partial until the watch has synced."
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
    • Changedget_daily_activity_statistics3 fields changed
      • changedInput schema / properties / enddate / description
        Previous value: -"End datetime in ISO-8601 format (e.g. 2026-04-30T23:59:59). Must be within 28 days of startdate."New value: +"End datetime in ISO-8601 format, same forms as startdate (e.g. 2026-04-27T23:59:59). Must be less than 28 days after startdate."
      • changedInput schema / properties / enddate / examples
        Previous value: -[
        -  "2026-04-30T23:59:59"
        -]New value: +[
        +  "2026-04-27T23:59:59"
        +]
      • changedInput schema / properties / startdate / description
        Previous value: -"Start datetime in ISO-8601 format (e.g. 2026-04-01T00:00:00). Data is stored in UTC."New value: +"Start datetime in ISO-8601 format, with or without a UTC offset (e.g. 2026-04-01T00:00:00 or 2026-04-01T00:00:00+02:00). An offset written +0200, as `date +%z` prints it, is rewritten to +02:00 because Suunto rejects the former."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."New value: +"Calendar date YYYY-MM-DD (a local day, in the local time the watch stamped on each sample). Data arrives when the watch syncs, so today's is usually partial — the API answers 200 with an empty or partial payload for today and future dates rather than an error (confirmed live). Use yesterday or earlier for complete results."
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD of the night, NOT the wake-up date: sleeps that began between noon on this date and noon the next day (in the local time the watch stamped on each sample), so a bedtime shortly after midnight — even 03:00 — still belongs to the previous date. Last night's sleep is under yesterday's date, not today's; today's date is empty until tonight's sleep begins."
    • Addedget_workout_laps
    • Changedlist_daily_activity1 field changed
      • changedInput schema / properties / to / description
        Previous value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 3–7 days: a day is ~15 KB, so 30 days is ~450 KB (use get_daily_activity_statistics for longer totals)."
    • Changedlist_recovery1 field changed
      • changedInput schema / properties / to / description
        Previous value: -"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer about 14 days or less: a day is ~4 KB of output."
    • Changedpush_strength_guide2 fields changed
      • changedInput schema / properties / exercises / items / properties / detail / description
        Previous value: -"Display string shown on the exercise's set steps and on the prep screen before it — include weight and sets, e.g. '60kg 3x10'."New value: +"Display string shown on the exercise's set steps, and on the prep screen before it unless 'plates' is given — include weight and sets, e.g. '60kg 3x10'."
      • addedInput schema / properties / exercises / items / properties / plates
        Added value: +{
        +  "description": "Per-side plate breakdown for barbell exercises, e.g. '2x20+1x5/side' — shown on the prep screen instead of detail, since that's when the bar actually gets loaded. Omit for non-barbell exercises (dumbbell, machine, bodyweight, cable); compute the math yourself before calling this tool, it isn't done here.",
        +  "type": "string"
        +}
  3. 3 tool updatesv0.15.0
    • Addeddelete_guide
    • Addedlist_guides
    • Addedpush_strength_guide
  4. 2 tool updatesv0.14.4
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily, so today's data is usually incomplete — but the API responds 200 with an empty or partial payload for today/future dates, it does not throw SuuntoNotFoundError (confirmed live). Use yesterday or earlier for complete results."
  5. 2 tool updatesv0.14.1
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."New value: +"Date YYYY-MM-DD the person went to bed (bedtime), NOT the wake-up date — a bedtime shortly after midnight still counts as the previous date. To get 'last night's sleep' as of right now, use yesterday's date, not today's. Suunto syncs once daily — use yesterday or earlier for reliable results."
    • Changedlist_sleep2 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404."New value: +"First bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Must be ≤ to. Nights without recorded sleep are silently omitted, not 404."
      • changedInput schema / properties / to / description
        Previous value: -"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."New value: +"Last bedtime date YYYY-MM-DD, inclusive (the date the person went to bed, not woke up — see get_sleep). Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
  6. 7 tool updatesv0.14.0
    • Addedexport_route
    • Addedgenerate_daily_digest
    • Addedget_upload_status
    • Addedlist_routes
    • Addedpush_interval_guide
    • Addedpush_workout_guide
    • Addedupload_workout
  7. 1 tool updatev0.10.0
    • Addedget_daily_activity_statistics
  8. 11 tool updatesv0.9.2
    • Changedexport_workout_gpx1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
    • Changedget_daily_activity1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
    • Changedget_recovery1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Calendar date YYYY-MM-DD. Example: 2026-04-20."New value: +"Calendar date YYYY-MM-DD. Suunto syncs once daily — today or future dates typically return SuuntoNotFoundError; use yesterday or earlier for reliable results."
    • Changedget_sleep1 field changed
      • changedInput schema / properties / date / description
        Previous value: -"Wake-up date YYYY-MM-DD. Example: 2026-04-20."New value: +"Wake-up date YYYY-MM-DD. Keyed to the morning the session ended, not when it started. Suunto syncs once daily — use yesterday or earlier for reliable results."
    • Changedget_workout1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
    • Changedget_workout_fit1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first."
    • Changedget_workout_samples1 field changed
      • changedInput schema / properties / workoutKey / description
        Previous value: -"Unique workout identifier from list_workouts."New value: +"Opaque server-assigned string returned by list_workouts. Not guessable or constructable — always discover via list_workouts first. Passing an invalid key throws SuuntoNotFoundError."
    • Changedlist_daily_activity2 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without synced data are silently omitted, not 404."
      • changedInput schema / properties / to / description
        Previous value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
    • Changedlist_recovery2 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"Start date YYYY-MM-DD, inclusive. Must be ≤ to. Days without recovery data are silently omitted, not 404."
      • changedInput schema / properties / to / description
        Previous value: -"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"End date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
    • Changedlist_sleep2 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01."New value: +"First wake-up date YYYY-MM-DD, inclusive. Must be ≤ to. Nights without recorded sleep are silently omitted, not 404."
      • changedInput schema / properties / to / description
        Previous value: -"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30."New value: +"Last wake-up date YYYY-MM-DD, inclusive. Future dates are accepted but produce no entries. Prefer ranges ≤ 30 days for responsiveness."
    • Changedlist_workouts3 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of workouts to return (1–1000). Defaults to 25."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25. Pagination is automatic across API pages; set to 1 for the single most-recent workout."
      • changedInput schema / properties / since / description
        Previous value: -"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z."New value: +"ISO 8601 lower bound on startTime (inclusive). Filters on workout start time; omit for all time. Pagination is automatic so since does not affect page size."
      • changedInput schema / properties / until / description
        Previous value: -"ISO 8601 upper bound on startTime (inclusive)."New value: +"ISO 8601 upper bound on startTime (inclusive). Omit to include workouts up to the present. Combine with since to target a specific window."
  9. 7 tool updatesv0.9.1
    • Changedget_daily_activity3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedget_recovery3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedget_sleep3 fields changed
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-04-20"
        +]
      • addedInput schema / properties / date / maxLength
        Added value: +10
      • addedInput schema / properties / date / minLength
        Added value: +10
    • Changedlist_daily_activity6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_recovery6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_sleep6 fields changed
      • addedInput schema / properties / from / examples
        Added value: +[
        +  "2026-04-01"
        +]
      • addedInput schema / properties / from / maxLength
        Added value: +10
      • addedInput schema / properties / from / minLength
        Added value: +10
      • addedInput schema / properties / to / examples
        Added value: +[
        +  "2026-04-30"
        +]
      • addedInput schema / properties / to / maxLength
        Added value: +10
      • addedInput schema / properties / to / minLength
        Added value: +10
    • Changedlist_workouts2 fields changed
      • addedInput schema / properties / since / examples
        Added value: +[
        +  "2026-04-01T00:00:00Z"
        +]
      • addedInput schema / properties / until / examples
        Added value: +[
        +  "2026-04-30T23:59:59Z"
        +]
  10. 11 tool updatesv0.9.0
    • Changedexport_workout_gpx2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_daily_activity3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_recovery3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Calendar date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_sleep3 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"YYYY-MM-DD"New value: +"Wake-up date YYYY-MM-DD. Example: 2026-04-20."
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_workout2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_workout_fit3 fields changed
      • changedInput schema / properties / full / description
        Previous value: -"If true, returns ALL parsed records (large). Default false returns a summary + sampled records."New value: +"false (default): return compact summary. true: return all parsed FIT records."
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedget_workout_samples2 fields changed
      • addedInput schema / properties / workoutKey / description
        Added value: +"Unique workout identifier from list_workouts."
      • addedInput schema / properties / workoutKey / minLength
        Added value: +1
    • Changedlist_daily_activity6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD (inclusive)"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD (inclusive)"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_recovery6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD"New value: +"Start date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD"New value: +"End date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_sleep6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"YYYY-MM-DD"New value: +"First wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-01."
      • addedInput schema / properties / from / format
        Added value: +"date"
      • addedInput schema / properties / from / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / to / description
        Previous value: -"YYYY-MM-DD"New value: +"Last wake-up date YYYY-MM-DD, inclusive. Example: 2026-04-30."
      • addedInput schema / properties / to / format
        Added value: +"date"
      • addedInput schema / properties / to / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedlist_workouts8 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Max workouts to return."New value: +"Maximum number of workouts to return (1–1000). Defaults to 25."
      • addedInput schema / properties / limit / maximum
        Added value: +1000
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / limit / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / since / description
        Previous value: -"ISO 8601 datetime — only workouts on/after this time."New value: +"ISO 8601 lower bound on startTime (inclusive). Example: 2026-04-01T00:00:00Z."
      • addedInput schema / properties / since / format
        Added value: +"date-time"
      • changedInput schema / properties / until / description
        Previous value: -"ISO 8601 datetime — only workouts on/before this time."New value: +"ISO 8601 upper bound on startTime (inclusive)."
      • addedInput schema / properties / until / format
        Added value: +"date-time"
  11. 12 tool updatesv0.1.0
    • First observedexport_workout_gpx
    • First observedget_daily_activity
    • First observedget_recovery
    • First observedget_sleep
    • First observedget_workout
    • First observedget_workout_fit
    • First observedget_workout_samples
    • First observedlist_daily_activity
    • First observedlist_recovery
    • First observedlist_sleep
    • First observedlist_subscriptions
    • First observedlist_workouts

TDQS

A4.3/5.0

Scored across 25 tools

Disambiguation4/5

Most tools have clearly distinct purposes and the descriptions explicitly route between overlapping ones (get_daily_activity vs list_daily_activity vs get_daily_activity_statistics, get_sleep vs list_sleep, get_recovery vs list_recovery, and the get_workout/get_workout_fit/get_workout_laps trio). The single-day/get vs range/list pairs are genuinely near-duplicates and could be misselected, but the descriptions actively steer the agent and the three clearly-labelled UNAVAILABLE tools reduce confusion rather than add it.

Naming Consistency5/5

All 25 tools follow a consistent snake_case verb_noun pattern (list_*, get_*, push_*, export_*, upload_*, delete_*, generate_*). Verbs map predictably to read vs write operations, and there are no mixed conventions or camelCase deviations.

Tool Count3/5

25 tools is on the heavy side for a single-account fitness/health API. The breadth of the Suunto domain (sleep, recovery, activity, workouts, routes, guides, upload, digest) justifies much of it, but three unavailable endpoints are dead weight and the get/list single-vs-range pairs are redundant surface that bloats the set.

Completeness4/5

The surface covers the full read lifecycle for sleep, recovery, activity, workouts, routes, and guides, plus write operations for uploads and guide management and an aggregation tool. Minor gaps exist (e.g. no route creation, no user/profile or subscription management beyond a broken read, no guide editing beyond overwrite), and three endpoints are non-functional, but core workflows are complete.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server for Polar Signals Cloud continuous profiling platform, enabling AI assistants to analyze CPU performance, memory usage, and identify optimization opportunities in production systems.
    9
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables ChatGPT to access and analyze personal Garmin health data including daily steps, heart rate, calories, sleep duration, and body battery levels. Collects data via webhook from Garmin devices and provides health insights through natural language queries.
    2
    -