Skip to main content
Glama

Draft a training plan

create_training_plan

Draft a goal-based training plan from recent status and a race goal. Use it when no catalog plan fits (recommend_training_plans reports no_good_match) or a coach wants a custom plan. The caller's own athlete_id comes from get_current_user; the caller need not be in a coach roster. Draft-only: writes a cached draft, never the athlete's calendar, and uses one of the caller's daily draft allowances when generation starts. Returns promptly with queued/generating status; get_plan_draft polls progress and ready content. An uncharged allowance_limited result gives retry_at for the same handle. Identical inputs on this connection reuse an active/ready job until consumed or expired; terminal failure permits a new job and a new charge. Returns a draft_id for draft edits and save_training_plan (single-use, expires in 24h, usable only by this account); content_preview holds the first weeks and next_cursor continues in get_plan_draft. Pass exactly one of athlete_id or group_id; group_id drafts a Group Plan Template (saved with save_training_plan save_mode='template_only') from distance, weeks and target_time; race_id and race_date are ignored for groups. workout_preference reflects the coach's choice: 'ai_generate' (default) creates workouts, 'prefer_existing' reuses the org's workout library where it can, 'strict_existing' uses only library workouts and returns status no_existing_workouts when none match.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "create_training_plan"
  }
}

Input Schema

NameRequiredDescriptionDefault
levelNo
weeksNo
race_idNo
distanceNo
group_idNo
race_dateNo
athlete_idNo
start_dateNo
preferencesNo
target_timeNo
workout_preferenceNo

Output Schema

NameRequiredDescriptionDefault
goalNo
draftNo
errorNo
levelNo
weeksNo
statusNo
messageNo
privacyNoPresent when the athlete's settings withhold data.
draft_idNo
group_idNo
retry_atNoEpoch milliseconds; an uncharged allowance-limited job resumes on a poll at or after this instant.
warningsNo
next_stepNoWhat can be done next, for example after a failure.
operationNo
plan_nameNo
athlete_idNo
expires_atNo
group_nameNo
next_stepsNo
assumptionsNo
athlete_pbsNo
goal_sourceNo
next_cursorNoReads the next page; null on the last page.
reason_codeNo
total_weeksNo
member_countNo
retry_at_isoNoThe epoch field beside it as a UTC instant; the local day can differ.
subject_kindNo
user_contentNoFields in this result that people wrote.
changed_cellsNo
phase_outlineNo
expires_at_isoNoThe epoch field beside it as a UTC instant; the local day can differ.
missing_inputsNo
weeks_returnedNo
content_previewNo
generation_stateNoqueued, generating, ready, failed or access_revoked; only ready content is editable/saveable.
truncated_fieldsNoLists cut to fit one response: rows returned and total.
allowance_chargedNoAudit of the stable Redis reservation; retries of this job do not charge again.
duration_in_weeksNo
generated_contentNoFields in this result that NexRex's AI wrote.
weekly_mileage_kmNo
workout_preferenceNo
preferences_appliedNo
session_definitionsNoSessions that several rows of this result share by session_ref.
content_block_fieldsNoColumn names of every content_blocks row, nested blocks rows included.
recommended_start_dateNo
training_principle_org_idNo
training_principle_sourceNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • changedOutput schema / $defs / Activity / properties / content_blocks / anyOf
      Previous value: -[
      -  {
      -    "items": {
      -      "items": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "integer"
      -          },
      -          {
      -            "type": "number"
      -          },
      -          {
      -            "type": "boolean"
      -          },
      -          {
      -            "items": {
      -              "anyOf": [
      -                {
      -                  "type": "string"
      -                },
      -                {
      -                  "type": "integer"
      -                },
      -                {
      -                  "type": "number"
      -                },
      -                {
      -                  "type": "boolean"
      -                },
      -                {
      -                  "type": "null"
      -                }
      -              ]
      -            },
      -            "type": "array"
      -          },
      -          {
      -            "$ref": "#/$defs/LocalizedText"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "type": "array"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "items": {
      +      "items": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "integer"
      +          },
      +          {
      +            "type": "number"
      +          },
      +          {
      +            "type": "boolean"
      +          },
      +          {
      +            "items": {
      +              "anyOf": [
      +                {
      +                  "type": "string"
      +                },
      +                {
      +                  "type": "integer"
      +                },
      +                {
      +                  "type": "number"
      +                },
      +                {
      +                  "type": "boolean"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ]
      +            },
      +            "type": "array"
      +          },
      +          {
      +            "$ref": "#/$defs/LocalizedText"
      +          },
      +          {
      +            "items": {
      +              "type": "array"
      +            },
      +            "type": "array"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "type": "array"
      +    },
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / $defs / Activity / properties / content_blocks / description
      Previous value: -"Interval rows; each row's values follow content_block_fields."New value: +"Workout steps as rows whose values follow content_block_fields; an interval's blocks value is its nested steps as rows in the same columns."
    • changedOutput schema / properties / content_block_fields / description
      Previous value: -"Column names of every content_blocks row."New value: +"Column names of every content_blocks row, nested blocks rows included."
  2. First observed

TDQS

A4.7/5.0
Behavior5/5

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

Going well beyond the readOnly/destructive/idempotent hints, it discloses that this is draft-only, writes a cached draft rather than the athlete's calendar, consumes a daily draft allowance, returns queued/generating promptly, and that allowance_limited is uncharged with a retry_at. It even explains job-reuse behavior for identical inputs on the same connection and when a new job and charge are permitted after terminal failure.

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 with purpose, then eligibility, then behavior, then parameters, and nearly every sentence adds a distinct fact. It is a single dense block, however, and the allowance/retry and draft-lifecycle details are packed together in a way that takes effort to parse.

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 non-destructive but stateful generation tool, it covers side effects, cost, lifecycle, polling handoff to get_plan_draft, and the draft_id handoff to save_training_plan. The remaining gap is the semantics of the individual-mode planning inputs (level, start_date, preferences) and the fact that no parameter is marked required despite an exclusive-or rule.

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?

With 0% schema description coverage across 11 parameters, the description carries the load and does so for the critical ones: exactly one of athlete_id or group_id, group mode describing a Group Plan Template using distance, weeks and target_time, race_id/race_date ignored for groups, and the three-valued workout_preference with its no_existing_workouts outcome. It leaves level, start_date, preferences and the general meaning of weeks/target_time in individual mode undocumented, so it is strong but not exhaustive.

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 sentence names a specific verb and artifact: 'Draft a goal-based training plan from recent status and a race goal.' It also implicitly separates the tool from the catalog-based sibling by naming recommend_training_plans and save_training_plan, so an agent can tell what this tool produces versus what those do.

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 gives an explicit trigger condition ('when no catalog plan fits (recommend_training_plans reports no_good_match) or a coach wants a custom plan') and names the alternative tool by name. It also states the caller need not be in a coach roster, which removes a common precondition guess.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources