Garmin Dynamic MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GARMIN_API_KEY | No | Set this in the server's env instead of using the OS keychain. The key is then stored in a plain-text configuration file. | |
| GARMIN_MCP_NO_UPDATE_CHECK | No | Set to 1 to disable the daily PyPI update check. | |
| GARMIN_MCP_ENABLE_SENSITIVE | No | Set to 1 to enable sensitive endpoints such as nutrition and menstrual-cycle endpoints, which are disabled by default. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Read-only access to the user's own Garmin Connect data (Personal API). Call list_endpoints first to see which endpoints exist and which parameters they take, then call get(path, params, fields). Use fields (dotted paths such as 'activityType.typeKey') to receive only the fields you need. Distances are in meters, durations in seconds, speeds in m/s. Do the aggregation (sums, averages, grouping by day) yourself on the returned rows.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_endpointsA | List the Garmin Personal API endpoints this server can call, with their parameters. query: optional case-insensitive text matched against path and summary (e.g. "sleep"). Each entry has: path, summary, params (name, location 'path' or 'query', required, type), verified (whether the endpoint was tested against a real account), disabled (sensitive endpoints are off unless GARMIN_MCP_ENABLE_SENSITIVE=1) and, when known, max_range_days (longer date ranges are split automatically). Date parameters use YYYY-MM-DD. If the answer contains update_available, tell the user once (version and how to update). |
| getA | Call one Garmin Personal API endpoint (GET only) and return compact JSON. path: an endpoint path exactly as listed by list_endpoints (with the {placeholders}).
params: values for that endpoint's path and query parameters, e.g.
{"startDate": "2026-11-01", "endDate": "2026-11-09"}. For the activity search endpoint,
|
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 2 tools
The two tools have clearly distinct roles: list_endpoints is pure discovery/metadata (path, params, verified, disabled flags) while get performs the actual API call against a path returned by discovery. There is no overlap in purpose, and the descriptions make the list-then-call workflow explicit.
Both names are lowercase snake_case imperative verbs, so the surface is consistent in style. However, 'get' is a bare generic verb that doesn't name its resource, unlike the well-formed 'list_endpoints', creating a minor asymmetry.
Two tools is deliberately thin but correct for a dynamic proxy pattern: one discovery tool plus one universal caller covers an entire API surface without per-endpoint tool bloat. It sits just under the typical 3-15 range but each tool clearly earns its place.
For a read-only personal-fitness API, the discovery-plus-GET design covers the whole surface, and range splitting, field filtering, truncation notes, and sensitive-endpoint gating are all handled. The gaps are the absence of any write/mutation operations and no dedicated auth or status check beyond the 'verified' flag.