Garmin Training MCP
This read-only MCP server lets an AI client access Garmin Connect activity and wellness data through five tools.
List activities within up to 366 days, with pagination and metrics such as distance, duration, speed/pace, heart rate, and power.
Get a single activity’s summary plus paginated split summaries; GPS tracks and detailed samples are unsupported in v1.
Get sleep duration, stages, scores, and sleep/wake timestamps for up to 31 days.
Get overnight/weekly HRV averages, baseline, and status for up to 31 days.
Get daily steps, resting heart rate, stress, and Body Battery for up to 31 days.
Return structured statuses, warnings, missing-date information, and unavailable-field markers while preserving Garmin-local date semantics.
Provides read-only access to Garmin Connect training and wellness data through the Garmin Personal API, including activities, activity details and split summaries, sleep, HRV, and daily summaries such as steps, resting heart rate, stress, and Body Battery.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Garmin Training MCPHow did my sleep and HRV look over the past week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Garmin Training MCP
Read your Garmin activities, sleep, HRV and daily health summaries in Codex or Claude Code. The server runs locally on macOS and uses Garmin's official Python client and the official MCP Python SDK.
This project is unofficial and is not affiliated with Garmin.
Install
You need macOS, Python 3.12 or newer, uv, and a Garmin Connect Personal API Key. The examples use Python 3.13.
Check that the PyPI package launches:
uvx --python 3.13 --from garmin-training-mcp==0.1.1 garmin-mcp --helpYou don't need to clone the repository. uvx downloads the package and dependencies
on first launch, then uses its cache. garmin-training-mcp is the package name;
garmin-mcp is the command it provides.
Related MCP server: garmin-mcp
Connect your client
Create a key on the Garmin Personal API Key page.
Replace YOUR_GARMIN_PERSONAL_API_KEY below with your key in your local configuration.
Keep it out of Git, chat messages and shared examples.
Codex
Add this entry to ~/.codex/config.toml, or update the existing garmin-training entry:
[mcp_servers.garmin-training]
command = "uvx"
args = ["--python", "3.13", "--from", "garmin-training-mcp==0.1.1", "garmin-mcp"]
[mcp_servers.garmin-training.env]
GARMIN_PERSONAL_API_KEY = "YOUR_GARMIN_PERSONAL_API_KEY"Codex allows 60 seconds per tool call by default. If Garmin calls time out, add
tool_timeout_sec = 180 under [mcp_servers.garmin-training], before the .env
table. See the Codex timeout settings.
Claude Code and other JSON clients
Add this entry under mcpServers in your client's configuration.
Claude Code uses ~/.claude.json for user settings.
{
"mcpServers": {
"garmin-training": {
"type": "stdio",
"command": "uvx",
"args": [
"--python", "3.13",
"--from", "garmin-training-mcp==0.1.1",
"garmin-mcp"
],
"env": {
"GARMIN_PERSONAL_API_KEY": "YOUR_GARMIN_PERSONAL_API_KEY"
}
}
}
}If your client can't find uvx, run command -v uvx in Terminal and use the full
executable path as command. Keep the package name in args as shown.
Fully quit and reopen your client, then try:
Use Garmin to compare my last two runs. What was my average pace?
Use Garmin to summarize my sleep from the last seven days.
Check the results against Garmin Connect. --help confirms installation;
a successful Garmin tool call confirms authentication.
Save the key in a separate file
If you prefer to keep the key out of client configuration, run:
uvx --python 3.13 --from garmin-training-mcp==0.1.1 garmin-mcp setupThe prompt hides your input and saves the key to:
~/Library/Application Support/garmin-training-mcp/personal-api-keyUse the client examples above with the env block or .env table removed.
An environment key overrides this file; an empty value is an error.
Available tools
Tool | Returns |
| Activities in a date range, with distance, duration, speed, HR and power where available |
| Activity metrics and a page of split summaries |
| Sleep duration, stages, scores and timestamps |
| Overnight and weekly HRV summaries, baseline and status |
| Steps, resting HR, stress and Body Battery |
Fields depend on what Garmin provides for your account and device. Missing data isn't zero. Split summaries may group several splits. GPS tracks, detailed samples and training readiness are unavailable in v1.
Dates use Garmin's calendar dates. Wellness queries accept up to 31 days; activity queries accept up to 366 days. The server returns speed in meters/second, which the AI client can convert to pace. See the capability matrix for coverage and the reference for units, date handling and pagination.
Privacy
The server reads Garmin data and caches bearer tokens locally. It writes no health
data files or telemetry. Keys and tokens are stored as plaintext with owner-only
permissions, outside the repository. The credential directory has mode 700 and
its files have mode 600. Keys in client configuration also need restricted access.
Your AI client can send retrieved health data to its provider and retain it in chat history. Local backups or sync tools may also copy credential files. Review your client's privacy settings. See the security audit for the reviewed controls and limitations.
Test and troubleshoot
For a live check, choose a date with synced activity and wellness data:
uvx --python 3.13 --from garmin-training-mcp==0.1.1 garmin-mcp check --date YYYY-MM-DDThe check prints availability counts and statuses. It needs a saved key file or a
key available in Terminal; Terminal doesn't inherit a key from your client's env block.
An empty date result can mean there is no data for that day.
Problem | What to check |
Server won't start | Run |
| Set the key in client configuration or run |
| Replace an expired or revoked key, then restart. |
| Wait for the reported retry delay before trying again. |
Missing records | Check the date and Garmin Connect sync status. |
The reference covers all error codes.
Updates and development
To upgrade, change the version in your client's args, run --help with that
version, and restart the client. Keep your existing credentials.
For local development, locked dependencies, tests and removal instructions, see
the reference.
uvx resolves dependencies separately from the project's uv.lock.
License
MIT. Dependencies retain their own licenses.
Available Tools
5 toolsget_activityARead-onlyIdempotent
Get summary plus one page of feature/group split summaries, not guaranteed laps.
activity_id is a positive decimal string. Samples/GPS are unsupported in v1: setting either include flag returns an explicit unsupported error. No location data is returned. Follow pagination.next_offset to retrieve more split summaries.
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes | ||
| include_gps | No | ||
| split_limit | No | ||
| split_offset | No | ||
| include_samples | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| records | Yes | |
| end_date | No | |
| timezone | Yes | |
| warnings | No | |
| pagination | No | |
| start_date | No | |
| retrieved_at | Yes | |
| missing_dates | No | |
| date_semantics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, openWorld), so the bar is lower, and the description still adds real context: no GPS/location data is returned, setting either include flag yields an explicit unsupported error, results are paginated, and laps are not guaranteed. It does not mention auth requirements or rate limits, which keeps it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences with no filler, and the core purpose is front-loaded. The opening clause 'not guaranteed laps' is cryptic out of context, but every sentence carries information the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return shape need not be described, and the description covers the important behavioral gaps: unsupported flags, absent location data, and pagination continuation. The remaining gap is page-size/offset semantics for split_limit and split_offset, which neither schema nor description explains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning and it only partly does: it defines activity_id's format (positive decimal string) and the failure behavior of include_gps/include_samples, and implies split_offset via the next_offset instruction. split_limit and split_offset's own semantics (max page size 100, offset bounds) are never explained in prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: retrieves an activity summary plus one page of split summaries, and flags that laps are not guaranteed. The 'feature/group split summaries' phrasing is jargon-heavy, but combined with the tool name and sibling set (list_activities, get_sleep, get_hrv, get_daily_summary) an agent can still tell what this returns and how it differs from a listing tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete usage constraints for the include flags (samples/GPS unsupported in v1, will error) and tells the agent to follow pagination.next_offset — genuinely useful invocation guidance. However it never states when to choose get_activity over list_activities or get_daily_summary, so the sibling routing 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.
get_daily_summaryARead-onlyIdempotent
Daily steps, Garmin resting HR field (bpm), stress and Body Battery if present.
Inclusive ISO range <=31 days, end defaults to start. Garmin restingValue may fall back to absolute minimum HR. Stress/Body Battery retain Garmin's scale.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | ||
| start_date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| records | Yes | |
| end_date | No | |
| timezone | Yes | |
| warnings | No | |
| pagination | No | |
| start_date | No | |
| retrieved_at | Yes | |
| missing_dates | No | |
| date_semantics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description goes beyond them with real interpretive caveats: fields appear only 'if present', Garmin's restingValue may fall back to absolute minimum HR, and stress/Body Battery keep Garmin's native scale. It doesn't say what happens when the 31-day cap is exceeded, but the domain caveats are genuinely useful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: what data first, then the range constraint, then data-quality caveats. Telegraphic style but every sentence carries distinct, non-redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return shape needn't be described, and annotations cover safety, so the description's job is range rules and field interpretation, which it does. The residual gap is sibling routing and the failure mode past 31 days.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description has to carry the load, and it does: ISO date format, inclusive bounds, the 31-day maximum, and end_date defaulting to start_date. Only start_date's role as the anchor of the range is left implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the exact data returned (daily steps, Garmin resting HR in bpm, stress, Body Battery), which distinguishes it from siblings like get_sleep and get_hrv without ambiguity. It omits an explicit verb such as 'returns' and doesn't state the grain (per-day records) outright, but the resource is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives the operative constraint for calling it: an inclusive ISO range capped at 31 days, with end_date defaulting to start_date. It offers no guidance on when to prefer this over get_hrv, get_sleep, or list_activities, so the agent must infer the boundary from the field list alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hrvARead-onlyIdempotent
Reported overnight/weekly HRV averages and optional Garmin baseline/status.
Inclusive ISO range <=31 days, end defaults to start. Values retain Garmin's scale; units and sleep-start/wake-date association need live account verification.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | ||
| start_date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| records | Yes | |
| end_date | No | |
| timezone | Yes | |
| warnings | No | |
| pagination | No | |
| start_date | No | |
| retrieved_at | Yes | |
| missing_dates | No | |
| date_semantics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, open-world semantics, and the description adds genuinely new context: a hard 31-day span limit, the end-date fallback, and a data-quality caveat that units and sleep-start/wake-date association are unverified. That caveat is behaviorally important since it warns the agent the values may not be directly comparable or time-aligned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with what is returned, followed by range rules and caveats. No filler; the only cost is the slightly awkward 'Reported overnight/weekly' phrasing, which takes a moment to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be explained, and the description instead covers the limits an agent could actually get wrong (span cap, default end date, unit ambiguity). What remains unstated is when baseline/status is or isn't included in the response, a minor gap for a read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load, and it does: ISO format, inclusive bounds, max 31-day span, and the end_date → start_date default. It stops short of clarifying null handling for end_date, but both parameters are otherwise meaningfully specified beyond the bare schema patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the specific resource (HRV averages plus optional Garmin baseline/status), which is clearly distinct from siblings like get_sleep and get_daily_summary. The verb is only implied by 'Reported' rather than stated as an explicit action, so it's clear but not maximally crisp.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 31-day inclusive range and 'end defaults to start' give concrete calling constraints, implying a bounded date-range query. However, there is no explicit when-to-use vs. alternative guidance (e.g., HRV vs. get_sleep-derived metrics), leaving selection to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleepARead-onlyIdempotent
Sleep duration/stages in seconds, reported score components and window times.
Inclusive ISO range <=31 days, end defaults to start. Garmin calendarDate is preserved; wake-date versus sleep-start-date association requires live verification.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | ||
| start_date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| records | Yes | |
| end_date | No | |
| timezone | Yes | |
| warnings | No | |
| pagination | No | |
| start_date | No | |
| retrieved_at | Yes | |
| missing_dates | No | |
| date_semantics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, open-world behavior, so the description's added value is the 31-day range ceiling, the end_date default, and the caveat that Garmin calendarDate is preserved while wake-date vs sleep-start-date association needs live verification. That is meaningful operational context an agent cannot get from structured fields. It does not mention failure behavior when the range is exceeded.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what is returned, then the range/default rules, then the calendarDate caveat — no filler. The final sentence is dense and slightly cryptic, but it is one line of real content rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, and the description covers range limits, defaults, and the date-association ambiguity. What is missing is error behavior past 31 days and any timezone note, which matters for a date-scoped sleep query.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameters, and it does: dates are inclusive ISO dates, the range is capped at 31 days, and end_date defaults to start_date. The semantics of both parameters are clarified beyond the bare pattern in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states concretely what is returned: sleep duration/stages in seconds, score components, and window times. That is far more specific than the name alone, though it never explicitly distinguishes this from get_daily_summary, which likely overlaps on sleep content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a hard constraint (inclusive range of at most 31 days, end defaults to start) but no guidance on when to call this instead of get_daily_summary, get_hrv, or other siblings, and no exclusion conditions. The agent must infer the selection rule from sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_activitiesARead-onlyIdempotent
List one activity page (max 100) within <=366 inclusive Garmin-local dates.
sport is a parent activity type key, e.g. running or cycling, not a subtype. Units: meters, seconds, m/s, bpm, watts. Follow pagination.next_offset.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| sport | No | ||
| offset | No | ||
| end_date | Yes | ||
| start_date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| records | Yes | |
| end_date | No | |
| timezone | Yes | |
| warnings | No | |
| pagination | No | |
| start_date | No | |
| retrieved_at | Yes | |
| missing_dates | No | |
| date_semantics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, open-world, so the description's value-add is the page-size ceiling of 100, the 366-day maximum window, and the fact that dates are interpreted as Garmin-local. Those are genuine constraints beyond the annotations, though result ordering and empty-result behavior remain undisclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded lines with no filler; the hard constraints come first and the caveats follow. The "Units" sentence is terse to the point of ambiguity about which fields it applies to, which is a minor structural weakness rather than verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers the key caller-facing constraints for a paginated list tool with 0% schema description coverage. Gaps remain around offset interplay with next_offset and ordering, but nothing essential to a correct first call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden: it clarifies that `sport` is a parent activity type key rather than a subtype and gives examples, and it bounds the date window and page size. `limit` and `offset` semantics are only obliquely implied by "max 100" and "pagination.next_offset", leaving two of five parameters weakly documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List one activity page") plus concrete scope constraints (max 100, <=366 inclusive Garmin-local dates), which an agent can act on immediately. It implies a paged-collection read distinct from the sibling get_activity, but never names or contrasts with that sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Follow pagination.next_offset" gives real operational guidance for iterating pages, and the sport note steers callers away from passing subtypes. However, there is no statement of when to use this tool versus get_activity or get_daily_summary, and no prerequisites or exclusions are given.
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.
5 tool updates
v0.1.0- First observed
get_activity - First observed
get_daily_summary - First observed
get_hrv - First observed
get_sleep - First observed
list_activities
TDQS
Scored across 5 tools
Each tool maps to a distinct resource: activity listing, single-activity detail, sleep, HRV, and daily summary. The only mild overlap is that get_daily_summary, get_sleep, and get_hrv all return daily wellness data, but the descriptions make the boundaries clear (steps/stress vs. sleep stages vs. HRV averages). list_activities vs. get_activity is a standard, unambiguous list/detail pair.
All five names follow the same snake_case verb_noun pattern (list_activities, get_activity, get_sleep, get_hrv, get_daily_summary). The singular/plural distinction (list_activities vs. get_activity) matches the collection-vs-single semantics rather than breaking the convention.
Five focused read-only tools is a lean but defensible scope for a Garmin data server, and each tool earns its place. It sits at the thin end of the ideal 3-15 range given the breadth of the Garmin domain, but nothing is redundant or filler.
The read surface covers activities, sleep, HRV, and daily wellness, but notable gaps remain: workout/course data, training status/readiness, stress-only detail, body composition, and device info are absent. Activity samples/GPS are explicitly unsupported and lap retrieval is not guaranteed, creating potential dead ends for agents wanting intra-activity detail.
Maintenance
Related MCP Connectors
Unofficial Garmin Connect access: sleep, HRV, training, activities, workouts and weight.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Read WHOOP recovery, sleep, cycles, workouts and body measurements.
Your swim, bike and run training: readiness, HRV, sleep, workouts and race predictions. Read-only.
Related MCP Servers
- AlicenseBqualityBmaintenanceEnables retrieval of Garmin Connect data such as activities, sleep, heart rate, and body battery levels using unofficial API through MCP tools.4MIT
- FlicenseNot gradedqualityBmaintenanceProvides read access to Garmin Connect health and training data (sleep, heart rate, stress, HRV, activities) and supports writes like creating workouts, editing activities, and exporting files.-
- AlicenseNot gradedqualityBmaintenanceEnables read-only access to Garmin Connect health, activity, profile, and device data through local stdio or streamable HTTP transports for MCP clients.MIT
- AlicenseNot gradedqualityBmaintenanceGives any MCP client local access to Garmin Connect sleep and nap data, recovery and Body Battery, training readiness and load, running tolerance, VO2 Max, race predictions, gear mileage and running summaries. It runs over stdio or Streamable HTTP and includes a credential-free demo mode with fictional sample data.2MIT