Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
SPEEDIANCE_MCP_HOMENoSet SPEEDIANCE_MCP_HOME to use a different folder for the Speediance data directory.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
check_connectionA

Verify the Speediance login is live. Call this FIRST in a session, before any other tool, and stop if it reports connected:false — relay its message (the user must sign in again). A merely expired token is renewed silently when the password was remembered.

get_calendarA

What's scheduled and trained in a month (month = 'YYYY-MM'). Each day carries its trainingPlanList. The raw calendar feed hides completed custom-template sessions, so completed sessions from the history feed are merged in with source:"history"; pass their trainingId to get_session_detail. Reservations (isReservation:true) are scheduled templates. Activity imported from the user's phone health app (walks, rides, other off-machine work that reached Speediance) is listed per day under otherActivities — count it in weekly load, but it isn't a gym session. Speediance only holds what the phone synced; other sources (e.g. a wellness app) may have more.

get_session_detailA

The actual per-exercise log — sets, reps and weight per movement — for ONE completed session. type is optional and advisory: the session type is always resolved from this account's own history, so only sessions you own can be read. resolvedType:false means the id isn't in your history. Rowing/ski sessions add cardio (pace per 500m, speed, watts, calories/min); guided cardio adds per-interval rows, and rowing with recorded telemetry adds rowing — per-block stroke rate, pace, watts and how much of each block stayed inside its target stroke-rate band. Weights are already in displayUnit — never convert.

get_heart_rateB

Second-by-second heart rate for a watch-paired session: average, max, min and a series (downsampled to at most 600 points). available:false when no watch recorded it.

get_training_statsA

Totals between two dates (YYYY-MM-DD, inclusive): gym sessions, strength sessions, training minutes, calories, volume and energy — for questions like "how was my week?".

get_athlete_snapshotA

Everything needed before planning: profile (bodyweight, age, watch), the coaching memory (active facts grouped as constraints{hard, soft} / preferences / goals / observations / conflicts, preferences, ★preferred / ⊘avoided exercises, owned equipment) and recent sessions, plus otherActivities imported from the phone health app (off-machine work — include it in load). Check memory.facts.constraints.hard before building any workout and respect it; raise any memory.facts.conflicts with the user rather than picking one. memory.facts.legacyUnreviewed holds old free-form facts not yet curated: they may still bind — treat injury ones as hard constraints until curated, and curate them promptly with the user.

get_strength_profileB

Per movement trained recently: estimated 1RM (Epley) from its best set, that set, and how the top weight moved across the window. Scans up to the 10 most recent weighted sessions.

compare_sessionsB

Compare a session with an earlier one, per movement: top weight, total reps and volume deltas. previous_training_id=0 picks the most recent earlier session that shares a movement.

suggest_loadA

Suggest a working weight for reps reps leaving rir reps in reserve, from the movement's most recent best set (Epley estimate), falling back to the user's saved load anchor. Reports its basis.

get_muscle_balanceA

Which muscles the recent training actually loaded, and how balanced it was.

Spreads each weighted set's volume over the muscles the library says a movement works: a MAIN muscle takes the full volume, an ASSISTING muscle half. Attributed totals therefore exceed the weight actually lifted — they are shares of attention, not a decomposition of load. Timed and level work (Vita, planks, rowing) carries no volume and is reported as unweightedExercises rather than silently counted as zero.

pushPull and upperLower are ratios: 1.0 is balanced, above 1.0 favours push/upper. notTrained lists muscles with no volume in the window — useful, but read it next to unweightedExercises before concluding a muscle was neglected.

list_exercisesA

Search the Speediance exercise library. Filters: name words (query), body part or muscle (muscle, e.g. "chest", "biceps"), library tab (category), equipment name, kind ("reps", "timed" or "level" for Vita), and owned_only (only moves whose equipment you own — set it with set_preferences(owned_equipment)). Movements needing equipment listed in set_preferences(unusable_equipment) are ALWAYS hidden. ⊘avoided movements are hidden unless include_avoided=true; ★preferred ones sort first. The first call downloads the library (~30 s); later calls use a 24-hour cache.

get_exerciseB

One movement's details: muscles, equipment, whether it's unilateral (one side at a time — matters when building workouts), form description and cues, image and video.

mark_exerciseA

Mark a movement ★preferred, ⊘avoided, or clear it ("none"). Identify it by group_id, or by name when you have no id (an ambiguous name marks nothing and lists candidates). Use when the user makes a LASTING per-exercise preference clear (it always hurts / they love it). Avoided moves are never programmed unless the user asks for them by name. reason: optional short note on why (e.g. 'left shoulder'), shown to you and in the web app.

list_accessoriesA

Speediance's accessory catalog (bars, handles, rope, benches, AeroRow...), deduplicated by name, each flagged owned and usable. Save what the user owns with set_preferences(owned_equipment=[names]).

get_exercise_historyA

EVERY time the user has done ONE movement, oldest -> newest: the "how is my bench press going?" tool. Give the name as the user says it, or a groupId. If several exercises match, nothing is fetched and the reply is {needsPick:true, matches:[...]} — ask which one. One entry per training DAY (same-day sessions combined): topWeight, volume, and minWeight when the day had a range.

list_my_workoutsA

The user's saved custom workout templates. Use a template's code with get_workout, update_workout, delete_workout or schedule_workout.

get_workoutB

A template's full prescription: exercises in order, each set's reps (or seconds), weight, Vita level, side and rest. Weights are in displayUnit.

create_workoutA

Create a custom workout template. exercises is an ordered list of {"name": "..." or "group_id": N, "sets": [...], "rest_seconds": 60}. Sets by movement kind: reps -> {"reps": 10, "weight": 50}; timed -> {"seconds": 45}; Vita (level) -> {"seconds": 30, "level": 12}. Optional per set: "side" 1=left / 2=right (unilateral moves alternate automatically), "rest". Weights are in displayUnit. The template is read back after saving; verified:false means Speediance stored something different — tell the user. Never program a ⊘avoided movement unless asked by name. The reply carries the user's hardConstraints and legacyUnreviewed facts when there are any. Re-check these against the workout before telling the user it's done.

update_workoutA

Edit a template in place (an edit never uses a new slot). template_id is its code (preferred) or numeric id. Omitted fields keep their current value; exercises, when given, replaces the whole list (same format as create_workout) — start from get_workout. Verified by read-back. The reply carries the user's hardConstraints and legacyUnreviewed facts when there are any. Re-check these against the workout before telling the user it's done.

delete_workoutA

Permanently delete a custom template, by code (preferred) or numeric id. Not reversible — only when the user asked for it.

schedule_workoutA

Put a saved template (by code, from list_my_workouts) on a day (YYYY-MM-DD), or take it off with add=false.

unschedule_workoutC

Take a scheduled template off a day (YYYY-MM-DD).

browse_programsA

Speediance's official multi-week programs. Without program_id, lists programs (filtered by query); with program_id, returns that program's details and structure.

get_preferencesA

The coaching memory: goal, training days, session length, load anchors, owned equipment, unusable_equipment (gear they own but CANNOT use — never plan a movement needing it), ★preferred / ⊘avoided exercises, and the ACTIVE curated facts grouped as facts: constraints{hard, soft}, preferences, goals, observations (10 most recent), conflicts, legacyToReview and legacyUnreviewed (old free-form facts not yet curated — they may still bind: treat injury ones as hard constraints until curated, and curate them promptly with the user). Check facts.constraints.hard before building any workout; resolve any conflicts with the user.

set_preferencesA

Update structured preferences (only the fields given change). load_anchors maps group_id -> a known working weight in displayUnit and is MERGED into the saved anchors (other anchors are kept); a weight of null or 0 removes that anchor. owned_equipment is a list of accessory names from list_accessories (it replaces the saved list). unusable_equipment names gear the user OWNS but cannot use (an injury, a bench they can't lie on): movements needing it are hidden from list_exercises and must never be planned. Free-text facts go in remember_fact instead.

remember_factA

Save ONE durable training fact (max 600 characters — split longer ones; nothing is truncated) and tell the user you saved it. kind: constraint (a rule a workout must obey — needs severity: hard = never violate, soft = avoid if possible) | preference (a weight on exercise choice) | goal (a target) | observation (a dated finding, no forward authority). category: injury | equipment | schedule | body | nutrition | note. scope: optional context such as "location:tampa-hotel". supersedes: ids this fact replaces (they are archived in the same write) — use it for corrections and updates instead of adding a second version. expires_days: only for temporary things ("travelling next week" ~7). source: "user" when the user stated it directly, else "inferred" (default). If a near-identical active fact exists nothing is saved and the near-match comes back (saved=false): re-send with supersedes=[its id] if the new one replaces it. Don't store bodyweight/unit (Speediance knows) or load numbers (use set_preferences).

forget_factA

Archive a fact that no longer applies (ids come from get_preferences facts or list_facts). It stays in list_facts(include_archived=true) but leaves every default read. For a fact that changed, prefer remember_fact(..., supersedes=[id]). Forgetting a legacy fact marks it reviewed.

list_factsA

The audit surface for the curated facts, oldest first, with each fact's status, supersedes / supersededBy chain, source and legacy flag. Default: active facts only. include_archived=true returns the full history (superseded, forgotten, expired and legacy facts). Filter by kind (constraint | preference | observation | goal) or category (injury | equipment | schedule | body | nutrition | note).

import_factsA

Bulk-save facts (up to 200), e.g. to curate the legacy facts. Each item is an object with the same fields as remember_fact: text, kind, category, and optional severity, scope, supersedes, expires_days, source. Every single-write rule applies to every item, in order (an item is also deduped against items accepted earlier in the batch). Returns {accepted, deduped: [{input, matched_existing_id}], rejected: [{input, reason}], superseded: [ids], dryRun}. dry_run=true returns the identical report and writes nothing — use it first, show the user, then run it for real.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A3.6/5.0

Scored across 29 tools

Disambiguation4/5

Most tools have clearly distinct purposes (workout CRUD, calendar, analytics, library, fact management). Minor overlaps exist: schedule_workout with add=false duplicates unschedule_workout, and get_athlete_snapshot overlaps get_preferences/get_training_stats, but descriptions explicitly clarify the boundaries. An agent can reliably tell tools apart.

Naming Consistency5/5

All 29 tools use a consistent snake_case verb_noun pattern (list_my_workouts, get_session_detail, create_workout, remember_fact, etc.). No camelCase or mixed-convention outliers. Predictable and readable throughout.

Tool Count3/5

29 tools is heavy for the rubric's ideal range, though the server spans several genuinely broad domains (workout CRUD, calendar/sessions, analytics, exercise library, and a full fact/memory subsystem). Each tool is defensible, but the surface is large enough to feel sprawling, and the fact subsystem alone consumes five tools.

Completeness5/5

Coverage is exceptional: full workout CRUD plus scheduling, calendar and session detail, heart rate, multiple analytics tools, complete exercise-library browse/detail/mark/history, accessories, preferences get/set, and a full fact lifecycle (remember/forget/list/import with audit and supersede chains). No obvious dead ends for the stated coaching purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues