Skip to main content
Glama
slaat

Garmin Connect Workouts MCP

create_garmin_workout

Create structured Garmin Connect workouts from typed steps, including pace, HR, power, cadence targets, repeat interval blocks, and swim-specific settings. Returns new workout ID and Connect link.

Instructions

Create a new structured workout in Garmin Connect from typed steps: durations, pace/HR/power/cadence targets, repeat blocks for intervals, and swim-specific stroke/equipment/pool-length fields. Use to add a workout; to change one that exists, use update_garmin_workout instead. Returns the new workoutId and a Connect link. Returns a re-auth message, not an exception, if no valid session exists. Example: [{kind:'step', intensity:'warmup', duration:{type:'time', value:10, unit:'min'}}, {kind:'repeat', iterations:5, steps:[...]}].

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesWorkout name, shown in Garmin Connect and on the device.
sportNoSport for this workout: running, cycling, or swimming. Governs which target types apply and whether stroke/equipment/poolLength are used. Defaults to running.running
stepsYesThe ordered list of steps and repeat blocks that make up the workout, in the order they should be performed.
poolLengthNoSwimming only - pool length for this workout, e.g. 25. Only valid when sport is 'swimming'.
poolLengthUnitNoSwimming only - unit for poolLength. Defaults to 'm' when poolLength is given without a unit.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • changedInput schema / properties / name / description
      Previous value: -"Workout name."New value: +"Workout name, shown in Garmin Connect and on the device."
    • addedInput schema / properties / poolLength
      Added value: +{
      +  "description": "Swimming only - pool length for this workout, e.g. 25. Only valid when sport is 'swimming'.",
      +  "exclusiveMinimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / poolLengthUnit
      Added value: +{
      +  "description": "Swimming only - unit for poolLength. Defaults to 'm' when poolLength is given without a unit.",
      +  "enum": [
      +    "m",
      +    "yd"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / sport / description
      Added value: +"Sport for this workout: running, cycling, or swimming. Governs which target types apply and whether stroke/equipment/poolLength are used. Defaults to running."
    • changedInput schema / properties / steps / description
      Previous value: -"The ordered list of steps and repeat blocks that make up the workout."New value: +"The ordered list of steps and repeat blocks that make up the workout, in the order they should be performed."
    • changedInput schema / properties / steps / items / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "duration": {
      -        "anyOf": [
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "type": {
      -                "const": "time",
      -                "type": "string"
      -              },
      -              "unit": {
      -                "enum": [
      -                  "sec",
      -                  "min",
      -                  "hour"
      -                ],
      -                "type": "string"
      -              },
      -              "value": {
      -                "description": "e.g. 10",
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "value",
      -              "unit"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "type": {
      -                "const": "distance",
      -                "type": "string"
      -              },
      -              "unit": {
      -                "enum": [
      -                  "m",
      -                  "km",
      -                  "mi"
      -                ],
      -                "type": "string"
      -              },
      -              "value": {
      -                "description": "e.g. 1.5",
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "value",
      -              "unit"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "type": {
      -                "const": "lapButton",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "type": {
      -                "const": "calories",
      -                "type": "string"
      -              },
      -              "value": {
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "value"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "End when heart rate crosses a threshold, e.g. warm up until HR > 130.",
      -            "properties": {
      -              "bpm": {
      -                "type": "number"
      -              },
      -              "compare": {
      -                "description": "End when HR is below (lt) or above (gt) bpm.",
      -                "enum": [
      -                  "lt",
      -                  "gt"
      -                ],
      -                "type": "string"
      -              },
      -              "type": {
      -                "const": "heartRate",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "bpm",
      -              "compare"
      -            ],
      -            "type": "object"
      -          }
      -        ],
      -        "description": "How the step ends."
      -      },
      -      "intensity": {
      -        "enum": [
      -          "warmup",
      -          "active",
      -          "rest",
      -          "cooldown"
      -        ],
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "step",
      -        "type": "string"
      -      },
      -      "name": {
      -        "description": "Shown on the watch, e.g. 'Threshold 1'.",
      -        "type": "string"
      -      },
      -      "notes": {
      -        "description": "Free-text note shown on the watch.",
      -        "type": "string"
      -      },
      -      "target": {
      -        "anyOf": [
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "type": {
      -                "const": "none",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "Zone 1 recovery, 2 aerobic/base, 3 tempo, 4 threshold, 5 VO2max.",
      -            "properties": {
      -              "type": {
      -                "const": "hrZone",
      -                "type": "string"
      -              },
      -              "zone": {
      -                "maximum": 5,
      -                "minimum": 1,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "zone"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "Explicit heart rate range in bpm.",
      -            "properties": {
      -              "high": {
      -                "type": "number"
      -              },
      -              "low": {
      -                "type": "number"
      -              },
      -              "type": {
      -                "const": "hrBpm",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "low",
      -              "high"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "Pace range. `fast` is the quicker bound. A single pace is widened by 10 s.",
      -            "properties": {
      -              "fast": {
      -                "description": "M:SS, e.g. '4:00'",
      -                "type": "string"
      -              },
      -              "slow": {
      -                "description": "M:SS. Optional - if omitted, 10 s/unit slower than `fast` is used.",
      -                "type": "string"
      -              },
      -              "type": {
      -                "const": "pace",
      -                "type": "string"
      -              },
      -              "unit": {
      -                "enum": [
      -                  "min/km",
      -                  "min/mi"
      -                ],
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "fast",
      -              "unit"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "Cycling power in watts.",
      -            "properties": {
      -              "high": {
      -                "type": "number"
      -              },
      -              "low": {
      -                "type": "number"
      -              },
      -              "type": {
      -                "const": "power",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "low",
      -              "high"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "description": "Cadence range (rpm / spm).",
      -            "properties": {
      -              "high": {
      -                "type": "number"
      -              },
      -              "low": {
      -                "type": "number"
      -              },
      -              "type": {
      -                "const": "cadence",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "type",
      -              "low",
      -              "high"
      -            ],
      -            "type": "object"
      -          }
      -        ],
      -        "description": "Intensity target for the step. Omit or use {type:'none'} for no target."
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "intensity",
      -      "duration"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "A real interval block. Prefer this over repeating steps by hand - the watch then shows a rep counter.",
      -    "properties": {
      -      "iterations": {
      -        "minimum": 2,
      -        "type": "integer"
      -      },
      -      "kind": {
      -        "const": "repeat",
      -        "type": "string"
      -      },
      -      "steps": {
      -        "description": "Steps repeated as a block, e.g. an interval plus its recovery.",
      -        "items": {
      -          "$ref": "#/properties/steps/items"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "iterations",
      -      "steps"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "duration": {
      +        "anyOf": [
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "type": {
      +                "const": "time",
      +                "type": "string"
      +              },
      +              "unit": {
      +                "enum": [
      +                  "sec",
      +                  "min",
      +                  "hour"
      +                ],
      +                "type": "string"
      +              },
      +              "value": {
      +                "description": "e.g. 10",
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "value",
      +              "unit"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "type": {
      +                "const": "distance",
      +                "type": "string"
      +              },
      +              "unit": {
      +                "enum": [
      +                  "m",
      +                  "km",
      +                  "mi"
      +                ],
      +                "type": "string"
      +              },
      +              "value": {
      +                "description": "e.g. 1.5",
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "value",
      +              "unit"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "type": {
      +                "const": "lapButton",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "type": {
      +                "const": "calories",
      +                "type": "string"
      +              },
      +              "value": {
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "value"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "End when heart rate crosses a threshold, e.g. warm up until HR > 130.",
      +            "properties": {
      +              "bpm": {
      +                "type": "number"
      +              },
      +              "compare": {
      +                "description": "End when HR is below (lt) or above (gt) bpm.",
      +                "enum": [
      +                  "lt",
      +                  "gt"
      +                ],
      +                "type": "string"
      +              },
      +              "type": {
      +                "const": "heartRate",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "bpm",
      +              "compare"
      +            ],
      +            "type": "object"
      +          }
      +        ],
      +        "description": "How the step ends."
      +      },
      +      "equipment": {
      +        "description": "Swimming only - equipment used for this step (fins, kickboard, paddles, pull_buoy, snorkel). Only valid when the workout's sport is 'swimming'.",
      +        "enum": [
      +          "fins",
      +          "kickboard",
      +          "paddles",
      +          "pull_buoy",
      +          "snorkel"
      +        ],
      +        "type": "string"
      +      },
      +      "intensity": {
      +        "enum": [
      +          "warmup",
      +          "active",
      +          "rest",
      +          "cooldown"
      +        ],
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "step",
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Shown on the watch, e.g. 'Threshold 1'.",
      +        "type": "string"
      +      },
      +      "notes": {
      +        "description": "Free-text note shown on the watch.",
      +        "type": "string"
      +      },
      +      "stroke": {
      +        "description": "Swimming only - the stroke for this step. 'any' = any stroke, 'im' = individual medley. Only valid when the workout's sport is 'swimming'.",
      +        "enum": [
      +          "any",
      +          "backstroke",
      +          "breaststroke",
      +          "drill",
      +          "fly",
      +          "free",
      +          "im"
      +        ],
      +        "type": "string"
      +      },
      +      "target": {
      +        "anyOf": [
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "type": {
      +                "const": "none",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "Zone 1 recovery, 2 aerobic/base, 3 tempo, 4 threshold, 5 VO2max.",
      +            "properties": {
      +              "type": {
      +                "const": "hrZone",
      +                "type": "string"
      +              },
      +              "zone": {
      +                "maximum": 5,
      +                "minimum": 1,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "zone"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "Explicit heart rate range in bpm.",
      +            "properties": {
      +              "high": {
      +                "type": "number"
      +              },
      +              "low": {
      +                "type": "number"
      +              },
      +              "type": {
      +                "const": "hrBpm",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "low",
      +              "high"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "Pace range. `fast` is the quicker bound. A single pace is widened by 10 s.",
      +            "properties": {
      +              "fast": {
      +                "description": "M:SS, e.g. '4:00'",
      +                "type": "string"
      +              },
      +              "slow": {
      +                "description": "M:SS. Optional - if omitted, 10 s/unit slower than `fast` is used.",
      +                "type": "string"
      +              },
      +              "type": {
      +                "const": "pace",
      +                "type": "string"
      +              },
      +              "unit": {
      +                "enum": [
      +                  "min/km",
      +                  "min/mi"
      +                ],
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "fast",
      +              "unit"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "Cycling power in watts.",
      +            "properties": {
      +              "high": {
      +                "type": "number"
      +              },
      +              "low": {
      +                "type": "number"
      +              },
      +              "type": {
      +                "const": "power",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "low",
      +              "high"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "description": "Cadence range (rpm / spm).",
      +            "properties": {
      +              "high": {
      +                "type": "number"
      +              },
      +              "low": {
      +                "type": "number"
      +              },
      +              "type": {
      +                "const": "cadence",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "type",
      +              "low",
      +              "high"
      +            ],
      +            "type": "object"
      +          }
      +        ],
      +        "description": "Intensity target for the step. Omit or use {type:'none'} for no target."
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "intensity",
      +      "duration"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "A real interval block. Prefer this over repeating steps by hand - the watch then shows a rep counter.",
      +    "properties": {
      +      "iterations": {
      +        "minimum": 2,
      +        "type": "integer"
      +      },
      +      "kind": {
      +        "const": "repeat",
      +        "type": "string"
      +      },
      +      "steps": {
      +        "description": "Steps repeated as a block, e.g. an interval plus its recovery.",
      +        "items": {
      +          "$ref": "#/properties/steps/items"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "iterations",
      +      "steps"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. First observedv1.0.0

TDQS

A4.5/5.0
Behavior4/5

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

Annotations carry only a title (no readOnly/destructive/idempotence hints), so the description bears the full behavioral burden. It discloses the return payload (workoutId and a Connect link) and a distinctive error mode (re-auth message rather than an exception for missing sessions). It does not cover idempotency or name-uniqueness behavior, but for a create action the mutating side effect is self-evident.

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 front-loaded: purpose, then routing, then return value, then error behavior, then example. Every sentence earns its place and there is no filler. The example makes it moderately long, but that length is justified by the nested complexity of the steps parameter.

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, the description supplies return values and auth-failure behavior, and the schema covers all parameters at 100%. The only notable gap is not pointing the agent to the authenticate_garmin sibling when the re-auth message is received; otherwise the definition is complete for a complex, write-side tool with minimal annotations.

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. The description adds value beyond the schema through a concrete step/repeat-block example and a summarizing list of target types, which materially helps an agent construct the deeply nested 'steps' parameter correctly.

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 ('Create a new structured workout in Garmin Connect') and enumerates the content scope: durations, pace/HR/power/cadence targets, repeat blocks, and swim-specific fields. It explicitly names the sibling it is not, update_garmin_workout, so an agent can route correctly without inspecting 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?

'Use to add a workout; to change one that exists, use update_garmin_workout instead' is explicit when-to-use and when-not-to-use with a named alternative. The create-vs-update decision is the key routing ambiguity among the siblings, and it is resolved directly.

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