Skip to main content
Glama

FormTrace

FormTrace is a personal fitness data hub, starting with a Hevy MCP server. The first version provides training and routine operations alongside workout analytics. Planned work includes MyFitnessPal, an owned health-data backend, Apple Health synchronization from an iPhone, and a broader user interface.

This is an evolving personal project. Results depend on the available records and assumptions; the system is not intended to make medical diagnoses.

Why

Fitness data is scattered across workout, nutrition, and health applications. FormTrace aims to bring that context together and calculate repeatable summaries that an AI assistant or future interface can use. Today, it connects the Hevy training API to an MCP client, so a person can ask for a weekly overview or an exercise's history while retaining visibility into the underlying records. Other sources and cross-source briefings are planned, not implemented.

Related MCP server: hevy-coach-mcp

What it does

  • Summarizes a period of workouts alongside the previous equal-length period.

  • Counts working sets by Hevy's primary muscle group and separately shows secondary involvement.

  • Shows recorded working sets for a particular exercise and details for a workout.

  • Reads workouts, routines, folders, exercise templates, workout events, and exercise history directly from Hevy.

  • Previews and, on request, creates or updates workouts and routines, and creates exercise templates and routine folders.

  • Reports missing classifications, unknown set types, the data source, and when data was fetched.

Hevy's labels are an approximation of which muscles an exercise involves, not a measurement of muscle effort. Secondary involvement overlaps primary sets. A working set count does not establish training intensity or muscle growth. Missing RPE remains missing.

Requirements

  • Python 3.11+ and uv.

  • A Hevy Pro account and a Hevy API key, according to Hevy's API documentation.

  • An MCP client that can run a local stdio server. Remote ChatGPT connectivity is not yet configured.

Quick start

uv sync
cp .env.example .env
# Edit .env locally to add your Hevy API key.
uv run formtrace-mcp

The command starts an MCP server over stdio; it waits for an MCP client rather than opening a human-readable console. Once connected, ask your client to summarize your training for a date range, or search for an exercise and inspect its history.

Alternatively, provide HEVY_API_KEY as an environment variable in your MCP client. Keep it private; do not commit it or paste it into an AI chat.

An example MCP client configuration (replace the directory with your checkout path):

{
  "mcpServers": {
    "formtrace": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/formtrace", "formtrace-mcp"]
    }
  }
}

Clients differ in configuration format and how they find uv; see your client's documentation. The server uses the separate fastmcp package. Its exact dependency versions are recorded in uv.lock.

If you already configured the server under its previous name, replace the fitness-mcp-hub command in your MCP client with formtrace-mcp and retain the path to your checkout. Existing HEVY_API_KEY, FITNESS_TIMEZONE, and FITNESS_CACHE_SECONDS settings remain valid.

The server can write to Hevy when a write tool is called with dry_run=false. The Hevy API key may have broader permissions than the tools expose. Keep it private and rotate it if exposed. FITNESS_TIMEZONE sets the default IANA timezone, currently Europe/Warsaw.

MCP tools

Analytics tool

Purpose

get_training_report(start_date, end_date, timezone, refresh)

Inclusive date-range summary and previous equal-length period. refresh=true bypasses the memory cache.

search_exercises(query)

Find exercise template IDs by name.

get_exercise_progression(exercise_id, start_date, end_date, timezone)

Show recorded working sets, weights, repetitions and RPE for one exercise.

get_workout_details(workout_id)

Inspect the exercises and sets for one workout.

Hevy API tools expose the training-related operations documented by Hevy:

Area

Read tools

Write tools

Profile

get_hevy_profile

—

Workouts

list_hevy_workouts, get_hevy_workout, get_hevy_workout_count, list_hevy_workout_events

create_hevy_workout, update_hevy_workout

Routines

list_hevy_routines, get_hevy_routine

create_hevy_routine, update_hevy_routine

Exercises

list_hevy_exercise_templates, get_hevy_exercise_template, get_hevy_exercise_history

create_hevy_exercise_template

Routine folders

list_hevy_routine_folders, get_hevy_routine_folder

create_hevy_routine_folder

Write tools default to dry_run=true: they return the intended payload and do not contact Hevy. Set dry_run=false only when the user has requested the change. MCP clients may provide their own approval flow; tool annotations are hints rather than an access-control mechanism. New workouts default to private. Workout and routine updates require complete payloads and may overwrite existing fields. Folder creation changes the folder order in Hevy.

Writes are never automatically retried after a timeout or server error because the remote operation may already have succeeded. Check Hevy before retrying. A write attempt invalidates the training snapshot. Deleting workouts, routines, or folders is not exposed because the documented Hevy API currently does not provide those operations. Body measurements remain outside the first version.

Dates use YYYY-MM-DD. A workout is assigned to the local date when it started. Results include the provider and fetch time. A successful empty report is distinct from a source error.

By default, snapshots are cached in memory for five minutes (FITNESS_CACHE_SECONDS=300). Restarting the process clears the cache. Hevy limits workout pages to 10 entries, so a full history may require multiple requests. All pages are fetched; a page failure is surfaced as an error instead of a complete report. Hevy may change while pagination is in progress, so a snapshot is not guaranteed to be atomic.

Development

uv sync
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run mypy src

Tests use fictional JSON fixtures, HTTP mocks, and an isolated stdio server connected to a local mock API; they do not need a Hevy key or write to a real account. They verify MCP output schemas, pagination, retry behavior, and the analytical calculations. A GitHub Actions workflow runs these checks for Python 3.11 and 3.12. Before sharing a development transcript, check it for secrets and health data. The optional Docker setup is for stdio only and has not yet been validated for this version.

Project documentation

Direction

  1. Hevy: the local training and routine integration is implemented. Expand training calculations and start a persistent storage foundation in parallel with nutrition work; protected ChatGPT access remains planned.

  2. MyFitnessPal: investigate viable access or import while building nutrition models and summaries, then expose available nutrition and weight records.

  3. Health backend: build FormTrace models, an API, and durable storage for Apple Health observations.

  4. iOS synchronization: build an iPhone app that reads authorized HealthKit data and sends it to the backend.

  5. Unified analysis: combine training, nutrition, weight, and available health data in repeatable calculations and MCP context.

  6. Recovery and planning: research explainable readiness and personal planning scenarios, then grow the user interface according to actual needs.

This roadmap describes intent, not features already implemented. The project currently targets one user. Hosting, authentication for remote access, multiple users and a web application are future work.

License

FormTrace is licensed under the MIT License.

Available Tools

22 tools
create_hevy_exercise_templateCreate Hevy Exercise TemplateA

Preview or create a custom Hevy exercise. Set dry_run=false to write to Hevy.

Only execute a write when the user has requested it.

Inputs: exercise (required), dry_run. Returns: object

create_hevy_routineCreate Hevy RoutineA

Preview or create a Hevy routine. Set dry_run=false to write to Hevy.

Only execute a write when the user has requested it.

Inputs: routine (required), dry_run. Returns: object

create_hevy_routine_folderCreate Hevy Routine FolderA

Preview or create a routine folder; Hevy inserts it before existing folders.

Set dry_run=false to write; only execute a write when the user has requested it.

Inputs: folder (required), dry_run. Returns: object

create_hevy_workoutCreate Hevy WorkoutA

Preview or create a recorded workout. Set dry_run=false to write to Hevy.

Use timezone-aware timestamps and explicit exercise template IDs. New workouts are private by default. Only execute a write when the user has requested it.

Inputs: workout (required), dry_run. Returns: object

get_exercise_progressionGet Exercise ProgressionB
Read-only

Get recorded working sets for one exercise over inclusive YYYY-MM-DD dates.

Inputs: end_date (required), start_date (required), exercise_id (required), timezone. Returns: note, period, source, sessions, +1 more

get_hevy_exercise_historyGet Hevy Exercise HistoryB
Read-only

Get Hevy's exercise history, optionally filtered by ISO timestamps with timezones.

Inputs: exercise_id (required), end_date, start_date. Returns: data, source

get_hevy_exercise_templateGet Hevy Exercise TemplateB
Read-only

Get one Hevy exercise template, including its muscle classifications.

Inputs: exercise_id (required). Returns: data, source

get_hevy_profileGet Hevy ProfileA
Read-only

Get the authenticated Hevy user's profile and preferred units.

Inputs: no named parameters. Returns: data, source

get_hevy_routineGet Hevy RoutineB
Read-only

Get a saved routine and its exercises by ID.

Inputs: routine_id (required). Returns: data, source

get_hevy_routine_folderGet Hevy Routine FolderC
Read-only

Get a Hevy routine folder by its numeric ID.

Inputs: folder_id (required). Returns: data, source

get_hevy_workoutGet Hevy WorkoutB
Read-only

Fetch one recorded workout directly from Hevy by its ID.

Inputs: workout_id (required). Returns: data, source

get_hevy_workout_countGet Hevy Workout CountB
Read-only

Get the total number of recorded workouts in the Hevy account.

Inputs: no named parameters. Returns: data, source

get_training_reportGet Training ReportA
Read-only

Summarize training and recorded sets by muscle group for inclusive YYYY-MM-DD dates.

Includes the preceding equal-length period. Secondary muscle involvement overlaps primary groups; do not add the counts together. Refresh requests fresh Hevy data.

Inputs: end_date (required), start_date (required), refresh, timezone. Returns: period, source, current, previous, +2 more

get_workout_detailsGet Workout DetailsC
Read-only

Get a workout's exercises and recorded sets to inspect an analytic result.

Inputs: workout_id (required). Returns: source, workout

list_hevy_exercise_templatesList Hevy Exercise TemplatesB
Read-only

Get a page of available Hevy exercise templates; page_size is at most 100.

Inputs: page, page_size. Returns: data, source

list_hevy_routine_foldersList Hevy Routine FoldersB
Read-only

Get a page of Hevy routine folders; page_size is at most 10.

Inputs: page, page_size. Returns: data, source

list_hevy_routinesList Hevy RoutinesB
Read-only

Get a page of saved Hevy routines; page_size is at most 10.

Inputs: page, page_size. Returns: data, source

list_hevy_workout_eventsList Hevy Workout EventsA
Read-only

Get a page of workout update/delete events since an ISO timestamp with timezone.

Inputs: since (required), page, page_size. Returns: data, source

list_hevy_workoutsList Hevy WorkoutsB
Read-only

Get a page of recorded Hevy workouts; page_size is at most 10.

Inputs: page, page_size. Returns: data, source

search_exercisesSearch ExercisesB
Read-only

Find available exercise templates by name and return their IDs.

Inputs: query (required). Returns: source, exercises, truncated, total_matches

update_hevy_routineUpdate Hevy RoutineA
Destructive

Preview or replace a complete routine, including folder, notes, and all exercises.

Set dry_run=false to write; only execute a write when the user has requested it.

Inputs: routine (required), routine_id (required), dry_run. Returns: object

update_hevy_workoutUpdate Hevy WorkoutA
Destructive

Preview or replace a recorded workout. This is a full update, not a partial patch.

Supply all desired fields and an explicit privacy setting. Set dry_run=false to write; only execute a write when the user has requested it.

Inputs: workout (required), workout_id (required), dry_run. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 22 tools

    Disambiguation4/5

    Most tools target a distinct resource+action (workouts, routines, folders, exercise templates) and descriptions clarify the differences. There is minor overlap between get_hevy_workout vs get_workout_details, get_exercise_progression vs get_hevy_exercise_history, and search_exercises vs list_hevy_exercise_templates, but the descriptions give enough signal to choose correctly.

    Naming Consistency4/5

    The dominant pattern is a consistent verb_noun with a hevy_ resource prefix (get_hevy_*, list_hevy_*, create_hevy_*, update_hevy_*). A handful of tools drop the prefix (get_workout_details, get_training_report, search_exercises, get_exercise_progression), which is a minor inconsistency but still readable.

    Tool Count3/5

    At 22 tools this is on the heavy side for a single-domain fitness API wrapper, and the create/update tools are doubled by dry-run semantics. The tools are well-organized and mostly earn their place across four resource types, but the surface is borderline bloated.

    Completeness3/5

    Read and write coverage is strong (list/get/create/update for workouts, routines, folders, templates, plus analytics and events), but delete operations are entirely absent and exercise-template/folder updates are missing. These gaps mean the CRUD lifecycle is not fully closed, though agents can accomplish most core workflows.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      MCP server for the Hevy workout tracker API that allows reading and writing workouts, routines, exercise templates, and body measurements.
      22
      11 npm
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for Hevy that fetches live workout data and computes analytics like e1RM, PRs, volume, and consistency, while enabling writes for routines, folders, and body measurements without modifying workout history.
      46 npm
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Enables access to Hevy strength-training data—workouts, routines, exercise history, and progression—via an MCP server with per-user credential encryption and optional write support.
      16
      Apache 2.0
    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides full access to the Hevy public API, enabling users to manage workouts, routines, routine folders, exercise templates, exercise history, and body measurements through natural language. Supports both local stdio and remote HTTP MCP deployments.
      15 npm
      MIT