Multiple features and fixes#6
Open
velazcod wants to merge 30 commits into
Open
Conversation
velazcod
commented
Dec 24, 2025
- Profiles
- Sync tool for mcp
- Expand the data for workout activities, body metrics and sleep
- HTTP/SSE network transport support for MCP server
Add warning() method to ProgressReporter class to fix AttributeError when activities_iterator.py calls self.progress.warning() during sync.
Pass prompt_mfa callback to AuthClient.login() so users with 2FA enabled are prompted for their MFA code. Previously, prompt_mfa defaulted to None which caused login to silently fail for 2FA accounts.
Sync detailed exercise data (sets, reps, weight) for strength training activities from Garmin Connect. This enables tracking workout volume and progression over time. Changes: - Add ExerciseSet model for storing exercise data (category, name, reps, weight) - Extend Activity model with activity_type, distance, calories, elevation fields - Add exerciseSets API endpoint to ActivitiesAccessor - Extract and store exercise sets during activity sync - Calculate strength summary (total_sets, total_reps, total_weight_kg) - Add CLI backfill command for existing activities - Add activity details backfill status to CLI status command - Fix activities sync date order to match iterator (newest-first) - Add database schema migration for existing databases
- Add ActivitySplit model for storing lap data (distance, speed, HR, elevation, cadence, GPS) - Add splits extraction and storage methods in extractors.py and db.py - Update sync to fetch splits for cardio activities (running, cycling, walking, swimming, rowing) - Add backfill-splits CLI command for existing cardio activities - Update documentation with activity_splits table and analysis queries
Implement new health data types for expanded tracking: Body Composition: - New BodyComposition model with weight, BMI, body fat %, body water %, bone mass, muscle mass, visceral fat, metabolic age from smart scales - Add body_composition metric module with dataclasses and parser - Batch sync via /weight-service/weight/range endpoint - BODY_COMPOSITION enum value in MetricType Enhanced Sleep Data: - Add sleep_score (0-100) and sleep_score_qualifier (POOR/FAIR/GOOD/EXCELLENT) - Add sleep_bedtime and sleep_wake_time as ISO timestamp strings - Add sleep_need_minutes for target sleep duration - Add skin_temp_deviation_c from overnight skin temperature sensor - Custom parse_sleep_data() to capture top-level API fields Database: - Schema migration adds new columns to daily_health_metrics - Body composition CRUD operations with existence checking - Updated _metric_to_dict() with computed Fahrenheit conversion Sync Manager: - Body composition uses single batch API call for date range - Proper separation of batch vs date-by-date metric syncing
- Update _sync_activity_splits to calculate and store total distance, calories, and elevation from splits into the activities table - Fix calculate_splits_summary to include INTERVAL splits (used by treadmill activities), not just ACTIVE - Add backfill_activity_distance_from_splits method for existing data
Enable isolated profile directories with separate tokens and databases for multi-user scenarios. CLI argument takes priority over env var, with ~/.garmy/ as default fallback. Backwards compatible.
- Add --transport option (stdio, http, sse) with stdio as default - Add --host and --port options for network transports - Add security warnings when exposing server on all interfaces - Validate transport and port settings in MCPConfig - Update CLI help with network transport examples and SSH tunneling
Enable AI assistants to fetch fresh data from Garmin Connect via the --enable-sync flag. The new tool supports syncing up to 30 days of data and requires valid saved authentication tokens. Changes: - Add enable_sync and profile_path settings to MCPConfig - Add sync_health_data tool with last_days, metrics, and user_id params - Add --enable-sync CLI flag to garmy-mcp server command
Introduces a complete workout management system for creating, listing, scheduling, and deleting Garmin Connect workouts via the API and MCP server. New workouts module (src/garmy/workouts/): - WorkoutBuilder: Fluent API for constructing workouts with steps, repeats, targets (power/HR/cadence), and strength exercise support - WorkoutClient: CRUD operations for Garmin Connect workout-service API - WorkoutSerializer: Bidirectional conversion between models and Garmin JSON - Models: Workout, WorkoutStep, RepeatGroup, EndCondition, Target dataclasses - Constants: SportType, StepType, EndConditionType, TargetType, IntensityType Exercise name fuzzy matching (src/garmy/workouts/exercises.py): - ExerciseMatcher with hybrid token + Levenshtein matching algorithm - 800+ exercises across 30+ categories from Garmin FIT SDK - 150+ common aliases (e.g., "bench press" -> BARBELL_BENCH_PRESS) - Auto-resolution in MCP create_workout tool for user-friendly names MCP server enhancements: - list_workouts, get_workout, create_workout, schedule_workout, delete_workout - search_exercises tool for exercise discovery (no auth required) - --enable-workouts flag and GARMY_ENABLE_WORKOUTS env var
- Fix EndConditionType.REPS ID from 8 to 10 to match Garmin API - Fix weight unit parsing to respect unit returned by API (was double-converting) - Improve get_workout output to use 'reps' field instead of 'duration_seconds' for rep-based steps - Improve create_workout documentation to make reps parameter prominent for AI agents The REPS end condition was incorrectly mapped to ID 8, but Garmin's API uses ID 10. This caused reps-based exercises to be parsed as 'lap.button' when reading workouts back. Weight values were also being double-converted because the code assumed kg but Garmin returns the actual unit.
The Garmin mobile app has a bug where it doesn't convert kilogram values to the user's display preference. Previously, the serializer always converted weight to kilograms before sending to the API. While the web interface handled this correctly, the mobile app displayed the raw kg value with the wrong unit label (e.g., 83.9 lbs instead of 185 lbs).
jtpatters
added a commit
to jtpatters/garmy
that referenced
this pull request
Feb 18, 2026
SQLAlchemy autoflush was triggering NOT NULL constraint violations when merging timeseries entries with NaN float values. Wrap the batch loop in session.no_autoflush and add math.isnan() check alongside the existing None check to skip invalid entries before they reach the database. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SpO2 as a new metric with daily summary extraction and hourly timeseries data. Expand HRV with sleep-period timeseries readings and baseline range fields. Fix pre-existing HRV parser bug where lastNight5MinHigh was mapped to the wrong snake_case key. All changes verified with live Garmin API data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store training load/status and endurance score in a dedicated performance_metrics table since these update after activities rather than on a fixed daily schedule. Includes new metric classes, extractors, sync routing, MCP tool docs, and database schema documentation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…trics Backfill metrics from PR1 (SpO2, HRV) and PR2 (resting HR, intensity minutes, floors) that were missing from the README table, and add PR3 metrics (training status, endurance score). Also update the package docstring in metrics/__init__.py to list all new metric classes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix timeseries sync crash on NULL/NaN values
Add SpO2 metric and enable HRV timeseries/baseline storage
Feature/daily aggregate metrics
Feature/post activity metrics
Adds typed access to Garmin Health Snapshot recordings (the on-demand ~2-minute multi-metric reading captured on the watch) via a new GraphQL endpoint on connectapi.garmin.com/graphql-gateway/graphql. - New HealthSnapshot/HealthSnapshotSummary/HealthSnapshotZone dataclasses and HealthSnapshotAccessor exposed as client.health_snapshots, with raw/get/range/latest/for_date methods. Range queries auto-chunk past the API's 31-day cap. - LocalDB: HEALTH_SNAPSHOT MetricType plus three tables (health_snapshots, health_snapshot_summaries, health_snapshot_zones) with merge-based upsert. SyncManager routes HEALTH_SNAPSHOT through a dedicated batch path, matching the body-composition pattern. - MCP: table descriptions and health-data guide updated; HEALTH_SNAPSHOT added to the sync_health_data tool's available metrics list. ECG was also investigated but no public Garmin Connect endpoint could be found via probing or community sources, so it is not included here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.