{"id":28568196,"url":"https://github.com/bes-dev/garmy","last_synced_at":"2025-06-10T16:03:35.062Z","repository":{"id":297942279,"uuid":"994269041","full_name":"bes-dev/garmy","owner":"bes-dev","description":"Python library to interact with Garmin Connect API","archived":false,"fork":false,"pushed_at":"2025-06-08T13:05:56.000Z","size":354,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-06-08T14:20:54.033Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bes-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-01T15:30:31.000Z","updated_at":"2025-06-04T04:11:41.000Z","dependencies_parsed_at":"2025-06-08T14:21:14.098Z","dependency_job_id":"6969202c-038c-41bf-a9e8-632842206ceb","html_url":"https://github.com/bes-dev/garmy","commit_stats":null,"previous_names":["bes-dev/garmy"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bes-dev%2Fgarmy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bes-dev%2Fgarmy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bes-dev%2Fgarmy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bes-dev%2Fgarmy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bes-dev","download_url":"https://codeload.github.com/bes-dev/garmy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bes-dev%2Fgarmy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259106576,"owners_count":22805929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-10T16:01:28.317Z","updated_at":"2025-06-10T16:03:35.045Z","avatar_url":"https://github.com/bes-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Garmy 🏃‍♂️\n\n[![PyPI version](https://badge.fury.io/py/garmy.svg)](https://badge.fury.io/py/garmy)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Tests](https://github.com/bes-dev/garmy/workflows/Tests/badge.svg)](https://github.com/bes-dev/garmy/actions)\n\nAn AI-powered Python library for Garmin Connect API designed specifically for health data analysis and AI agent integration via Model Context Protocol (MCP). Build intelligent health assistants and data analysis tools with seamless access to Garmin's comprehensive fitness metrics.\n\n**Inspired by [garth](https://github.com/matin/garth)** - This project was heavily inspired by the excellent garth library, building upon its foundation with enhanced modularity, type safety, and AI integration capabilities.\n\n## 🎯 Key Features\n\n- **🤖 AI-First Design**: Built specifically for AI health agents and intelligent assistants\n- **🔌 MCP Integration**: Native Model Context Protocol support for seamless AI interactions\n- **🏥 Health Analytics**: Advanced data analysis capabilities for fitness and wellness insights\n- **📊 Rich Metrics**: Complete access to sleep, heart rate, stress, training readiness, and more\n- **🗣️ Natural Language**: Query health data using conversational commands\n- **⚡ Real-time Processing**: Async/await support for high-performance AI applications\n- **🛡️ Type Safe**: Full type hints and runtime validation for reliable AI workflows\n- **🔄 Auto-Discovery**: Automatic metric registration and API endpoint discovery\n\n## 📦 Installation\n\n### Standard Installation\n```bash\npip install garmy\n```\n\n### With MCP Support (Recommended for AI Agents)\n```bash\npip install garmy[mcp]\n```\n\n### Development Installation\n```bash\ngit clone https://github.com/bes-dev/garmy.git\ncd garmy\npip install -e \".[dev,mcp]\"\n```\n\n## 🚀 Quick Start\n\n### AI Agent Example (Recommended)\n\n```python\nfrom garmy import AuthClient, APIClient\nimport asyncio\n\n# Create an AI health agent\nasync def health_agent():\n    auth_client = AuthClient()\n    api_client = APIClient(auth_client=auth_client)\n    \n    # Login using environment variables (secure for AI agents)\n    await auth_client.login_async(\n        email=os.getenv('GARMIN_EMAIL'),\n        password=os.getenv('GARMIN_PASSWORD')\n    )\n    \n    # AI agent can now analyze multiple health metrics concurrently\n    sleep_task = api_client.metrics.get('sleep').get_async()\n    readiness_task = api_client.metrics.get('training_readiness').get_async()\n    hrv_task = api_client.metrics.get('hrv').get_async()\n    \n    sleep_data, readiness_data, hrv_data = await asyncio.gather(\n        sleep_task, readiness_task, hrv_task\n    )\n    \n    # AI analysis logic here\n    health_score = analyze_health_trends(sleep_data, readiness_data, hrv_data)\n    return health_score\n\n# Run AI health agent\nhealth_insights = asyncio.run(health_agent())\n```\n\n### Basic Usage\n\n```python\nfrom garmy import AuthClient, APIClient\n\n# Create clients\nauth_client = AuthClient()\napi_client = APIClient(auth_client=auth_client)\n\n# Login\nauth_client.login(\"your_email@garmin.com\", \"your_password\")\n\n# Get today's training readiness\nreadiness = api_client.metrics.get('training_readiness').get()\nprint(f\"Training Readiness Score: {readiness[0].score}/100\")\n\n# Get sleep data for specific date\nsleep_data = api_client.metrics.get('sleep').get('2023-12-01')\nprint(f\"Sleep Score: {sleep_data[0].overall_sleep_score}\")\n\n# Get multiple days of data\nweekly_steps = api_client.metrics['steps'].list(days=7)\n```\n\n### Async Usage\n\n```python\nimport asyncio\nfrom garmy import AuthClient, APIClient\n\nasync def main():\n    auth_client = AuthClient()\n    api_client = APIClient(auth_client=auth_client)\n    \n    # Login\n    await auth_client.login_async(\"your_email@garmin.com\", \"your_password\")\n    \n    # Get multiple metrics concurrently\n    sleep_task = api_client.metrics.get('sleep').get_async()\n    hr_task = api_client.metrics.get('heart_rate').get_async()\n    \n    sleep_data, hr_data = await asyncio.gather(sleep_task, hr_task)\n\nasyncio.run(main())\n```\n\n## 📊 Available Metrics\n\nGarmy provides access to a comprehensive set of Garmin Connect metrics:\n\n| Metric | Description | Example Usage |\n|--------|-------------|---------------|\n| `sleep` | Sleep tracking data including stages and scores | `api_client.metrics.get('sleep').get()` |\n| `heart_rate` | Daily heart rate statistics | `api_client.metrics.get('heart_rate').get()` |\n| `stress` | Stress level measurements | `api_client.metrics.get('stress').get()` |\n| `steps` | Daily step counts and goals | `api_client.metrics.get('steps').list(days=7)` |\n| `training_readiness` | Training readiness scores and factors | `api_client.metrics.get('training_readiness').get()` |\n| `body_battery` | Body battery energy levels | `api_client.metrics.get('body_battery').get()` |\n| `hrv` | Heart rate variability data | `api_client.metrics.get('hrv').get()` |\n| `respiration` | Respiration rate measurements | `api_client.metrics.get('respiration').get()` |\n| `calories` | Daily calorie burn data | `api_client.metrics.get('calories').get()` |\n| `activities` | Activity summaries and details | `api_client.metrics.get('activities').list(days=30)` |\n| `daily_summary` | Comprehensive daily health summary | `api_client.metrics.get('daily_summary').get()` |\n\n## 🤖 AI Health Agent Integration (MCP)\n\nGarmy is specifically designed for building **AI health agents** and intelligent assistants through native **Model Context Protocol (MCP)** integration. Transform your Garmin health data into actionable insights using natural language interactions.\n\n### What Makes Garmy AI-First?\n\nGarmy isn't just an API wrapper – it's a complete AI health agent platform that enables:\n\n- **🧠 Intelligent Health Analysis**: AI-powered insights into sleep patterns, training readiness, and recovery\n- **🗣️ Natural Language Queries**: Ask questions like \"How was my sleep quality this week?\" or \"Am I ready for training today?\"\n- **📊 Predictive Analytics**: Build AI models that predict optimal training times, recovery needs, and health trends\n- **🔄 Real-time Monitoring**: Create AI agents that continuously monitor health metrics and provide recommendations\n- **🎨 Custom Health Dashboards**: Generate AI-driven visualizations and reports tailored to individual health goals\n- **📱 Multi-modal Integration**: Combine Garmin data with other health sources for comprehensive AI analysis\n\n### MCP Installation\n\n```bash\n# Install Garmy with MCP support\npip install garmy[mcp]\n\n# Verify installation\ngarmy-mcp --help\n```\n\n### MCP Server Setup\n\n#### Option 1: Command Line Interface\n\n```bash\n# Start MCP server for Claude Desktop (STDIO transport)\ngarmy-mcp serve --transport stdio\n\n# Start HTTP server for web clients\ngarmy-mcp serve --transport http --port 8080\n\n# Show server information\ngarmy-mcp info\n\n# List available metrics\ngarmy-mcp metrics\n\n# Test server configuration\ngarmy-mcp test\n```\n\n#### Option 2: Programmatic Usage\n\n```python\nfrom garmy.mcp import GarmyMCPServer, MCPConfig\n\n# Create and configure server\nconfig = MCPConfig.for_production()\nserver = GarmyMCPServer(config)\n\n# Run server\nserver.run(transport=\"stdio\")  # For Claude Desktop\nserver.run(transport=\"http\", port=8080)  # For HTTP clients\n```\n\n### Claude Desktop Configuration\n\n#### Secure Setup (Recommended)\n\nAdd this to your Claude Desktop MCP configuration file:\n\n```json\n{\n  \"mcpServers\": {\n    \"garmy\": {\n      \"command\": \"/path/to/your/venv/bin/python\",\n      \"args\": [\"-m\", \"garmy.mcp\", \"serve\", \"--transport\", \"stdio\"],\n      \"env\": {\n        \"GARMIN_EMAIL\": \"your_email@example.com\",\n        \"GARMIN_PASSWORD\": \"your_password\",\n        \"GARMY_MCP_DEBUG\": \"false\",\n        \"GARMY_MCP_CACHE_ENABLED\": \"true\"\n      }\n    }\n  }\n}\n```\n\n#### Configuration File Locations\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **Linux**: `~/.config/Claude/claude_desktop_config.json`\n\n### Authentication Options\n\nGarmy MCP supports multiple authentication methods:\n\n#### 1. Environment Variables (Most Secure)\n```bash\nexport GARMIN_EMAIL=\"your_email@example.com\"\nexport GARMIN_PASSWORD=\"your_password\"\n```\n- ✅ Credentials never pass through AI servers\n- ✅ Most secure method\n- ✅ Use with: *\"Auto-login to Garmin Connect\"*\n\n#### 2. Manual Input (Less Secure)\n- ⚠️ Credentials may be visible to AI servers\n- ⚠️ Use only when necessary\n- ⚠️ Use with: *\"Log into Garmin Connect with email [email] and password [password]\"*\n\n### AI Health Agent Commands\n\nOnce configured, your AI health agent can interact with Garmin data using natural language. Here are examples of what your AI assistant can do:\n\n#### Intelligent Health Monitoring\n- *\"Analyze my recovery patterns and tell me if I should train today\"*\n- *\"What's my sleep efficiency trend over the past month?\"*\n- *\"Create a personalized training plan based on my readiness scores\"*\n- *\"Identify correlations between my stress and sleep quality\"*\n- *\"Generate a health report with actionable insights\"*\n\n#### Predictive Health Analytics\n- *\"Predict my optimal training windows for next week\"*\n- *\"What factors are affecting my sleep quality most?\"*\n- *\"Alert me when my recovery metrics indicate overtraining\"*\n- *\"Build a model to predict my daily energy levels\"*\n\n#### Conversational Health Queries\n- *\"How am I progressing towards my fitness goals?\"*\n- *\"What's unusual about my health data this week?\"*\n- *\"Compare my current training load to last month\"*\n- *\"Should I adjust my sleep schedule based on my data?\"*\n\n#### Smart Data Export \u0026 Visualization\n- *\"Create an interactive dashboard of my health metrics\"*\n- *\"Export my data in a format suitable for machine learning\"*\n- *\"Generate a health summary for my doctor\"*\n- *\"Build charts showing my progress over time\"*\n\n### MCP Configuration Options\n\n#### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `GARMIN_EMAIL` | Garmin Connect email | None |\n| `GARMIN_PASSWORD` | Garmin Connect password | None |\n| `GARMY_MCP_DEBUG` | Enable debug logging | `false` |\n| `GARMY_MCP_CACHE_ENABLED` | Enable data caching | `false` |\n| `GARMY_MCP_CACHE_SIZE` | Cache size limit | `100` |\n| `GARMY_MCP_MAX_HISTORY_DAYS` | Max historical data | `365` |\n| `GARMY_MCP_DEFAULT_ANALYSIS_PERIOD` | Default analysis period | `30` |\n\n#### Configuration Presets\n\n```python\nfrom garmy.mcp.config import MCPConfig\n\n# Development setup\nconfig = MCPConfig.for_development()\n\n# Production setup  \nconfig = MCPConfig.for_production()\n\n# Minimal setup\nconfig = MCPConfig.minimal()\n```\n\n### Troubleshooting MCP\n\n#### Common Issues\n\n1. **\"Server not responding\"**\n   ```bash\n   # Check if server is running\n   garmy-mcp test\n   \n   # Restart with debug mode\n   GARMY_MCP_DEBUG=true garmy-mcp serve --transport stdio\n   ```\n\n2. **\"Authentication failed\"**\n   ```bash\n   # Verify credentials\n   echo $GARMIN_EMAIL\n   echo $GARMIN_PASSWORD\n   \n   # Test authentication\n   garmy-mcp test --auth\n   ```\n\n3. **\"No data available\"**\n   ```bash\n   # Check available metrics\n   garmy-mcp metrics\n   \n   # Verify date range\n   garmy-mcp test --date 2023-12-01\n   ```\n\n#### Debug Mode\n\nEnable debug logging for troubleshooting:\n\n```bash\n# Enable debug mode\nexport GARMY_MCP_DEBUG=true\n\n# Run server with debug output\ngarmy-mcp serve --transport stdio --debug\n```\n\n## 📊 AI Health Data Analysis\n\n### Building AI Health Models\n\n```python\nfrom garmy import APIClient, AuthClient\nimport pandas as pd\nimport numpy as np\nfrom sklearn.ensemble import RandomForestRegressor\nfrom sklearn.preprocessing import StandardScaler\n\n# Setup AI health analysis pipeline\nauth_client = AuthClient()\napi_client = APIClient(auth_client=auth_client)\nauth_client.login(\"email\", \"password\")\n\n# Gather comprehensive health data for AI model\nasync def build_health_dataset(days=90):\n    # Collect multiple health metrics concurrently\n    tasks = [\n        api_client.metrics.get('sleep').list_async(days=days),\n        api_client.metrics.get('training_readiness').list_async(days=days),\n        api_client.metrics.get('hrv').list_async(days=days),\n        api_client.metrics.get('stress').list_async(days=days),\n        api_client.metrics.get('body_battery').list_async(days=days)\n    ]\n    \n    sleep_data, readiness_data, hrv_data, stress_data, battery_data = await asyncio.gather(*tasks)\n    \n    # Build comprehensive health dataset\n    health_df = pd.DataFrame()\n    # ... merge and process data for AI model training\n    \n    return health_df\n\n# Train AI model to predict training readiness\ndef train_readiness_predictor(health_df):\n    features = ['sleep_score', 'hrv_rmssd', 'stress_avg', 'body_battery_drained']\n    X = health_df[features]\n    y = health_df['training_readiness_score']\n    \n    model = RandomForestRegressor(n_estimators=100, random_state=42)\n    model.fit(X, y)\n    \n    return model\n\n# AI-powered health insights\ndef generate_health_insights(model, current_metrics):\n    predicted_readiness = model.predict([current_metrics])[0]\n    \n    insights = {\n        'readiness_prediction': predicted_readiness,\n        'recommendation': 'high_intensity' if predicted_readiness \u003e 75 else 'recovery',\n        'confidence': model.score(X_test, y_test)\n    }\n    \n    return insights\n```\n\n### AI-Powered Health Monitoring\n\n```python\n# Create an AI health monitoring agent\nclass HealthMonitoringAgent:\n    def __init__(self, api_client):\n        self.api_client = api_client\n        self.health_model = self.load_trained_model()\n    \n    async def daily_health_check(self):\n        \"\"\"Perform daily AI-powered health analysis\"\"\"\n        # Get today's metrics\n        today_data = await self.get_current_metrics()\n        \n        # AI analysis\n        health_score = self.health_model.predict_health_score(today_data)\n        recommendations = self.generate_recommendations(health_score, today_data)\n        alerts = self.check_health_alerts(today_data)\n        \n        return {\n            'health_score': health_score,\n            'recommendations': recommendations,\n            'alerts': alerts,\n            'insights': self.generate_insights(today_data)\n        }\n    \n    def generate_recommendations(self, health_score, data):\n        \"\"\"AI-generated personalized health recommendations\"\"\"\n        if health_score \u003e 80:\n            return \"Great day for high-intensity training!\"\n        elif health_score \u003e 60:\n            return \"Moderate activity recommended. Focus on technique.\"\n        else:\n            return \"Prioritize recovery today. Light movement only.\"\n    \n    async def weekly_health_report(self):\n        \"\"\"Generate comprehensive AI health report\"\"\"\n        week_data = await self.api_client.metrics.get('daily_summary').list_async(days=7)\n        \n        # AI trend analysis\n        trends = self.analyze_trends(week_data)\n        predictions = self.predict_next_week(week_data)\n        \n        return self.format_health_report(trends, predictions)\n\n# Usage\nagent = HealthMonitoringAgent(api_client)\ndaily_insights = await agent.daily_health_check()\nweekly_report = await agent.weekly_health_report()\n```\n\n## 🧑‍💻 Development\n\n### Running Examples\n\nCheck out the `examples/` directory for comprehensive usage examples:\n\n```bash\n# Basic authentication example\npython examples/basic_auth.py\n\n# Sleep analysis demo\npython examples/sleep_demo.py\n\n# Training readiness analysis\npython examples/training_readiness_demo.py\n\n# Comprehensive metrics sync\npython examples/metrics_sync_demo.py\n\n# MCP server demo\npython examples/mcp_integration_demo.py\n```\n\n### Adding Custom Metrics\n\nGarmy's modular architecture makes it easy to add new metrics:\n\n```python\nfrom dataclasses import dataclass\nfrom garmy.core.base import BaseMetric\n\n@dataclass\nclass CustomMetric(BaseMetric):\n    endpoint_path = \"/usersummary-service/stats/custom/{date}\"\n\n    custom_field: int\n    timestamp: str\n    \n    def validate(self) -\u003e bool:\n        \"\"\"Custom validation logic\"\"\"\n        return self.custom_field \u003e 0\n```\n\n### Configuration\n\nCustomize Garmy behavior with configuration:\n\n```python\nfrom garmy.core.config import set_config, GarmyConfig\n\n# Create custom configuration\nconfig = GarmyConfig(\n    request_timeout=30,\n    retries=3,\n    max_workers=10,\n    default_user_agent=\"MyApp/1.0\"\n)\n\n# Apply configuration\nset_config(config)\n\n# Or use environment variables\nimport os\nos.environ['GARMY_REQUEST_TIMEOUT'] = '30'\nos.environ['GARMY_MAX_WORKERS'] = '10'\n```\n\n### Testing\n\n```bash\n# Install development dependencies\nmake install-dev\n\n# Run all tests\nmake test\n\n# Run specific test modules\nmake test-core      # Core functionality\nmake test-auth      # Authentication\nmake test-metrics   # Metrics\nmake test-mcp       # MCP server\n\n# Check code quality\nmake lint\nmake quick-check\n```\n\n## 🔧 Advanced Usage\n\n### Async Operations\n\n```python\nimport asyncio\nfrom garmy import APIClient, AuthClient\n\nasync def analyze_weekly_data():\n    auth_client = AuthClient()\n    api_client = APIClient(auth_client=auth_client)\n    \n    # Async login\n    await auth_client.login_async(\"email\", \"password\")\n    \n    # Fetch multiple metrics concurrently\n    tasks = [\n        api_client.metrics.get('sleep').list_async(days=7),\n        api_client.metrics.get('steps').list_async(days=7),\n        api_client.metrics.get('stress').list_async(days=7)\n    ]\n    \n    sleep_data, steps_data, stress_data = await asyncio.gather(*tasks)\n    \n    return {\n        'sleep': sleep_data,\n        'steps': steps_data,\n        'stress': stress_data\n    }\n\n# Run async analysis\ndata = asyncio.run(analyze_weekly_data())\n```\n\n### Custom Error Handling\n\n```python\nfrom garmy.core.exceptions import APIError, AuthError, GarmyError\n\ntry:\n    auth_client.login(\"wrong_email\", \"wrong_password\")\nexcept AuthError as e:\n    print(f\"Authentication failed: {e}\")\nexcept APIError as e:\n    print(f\"API error: {e}\")\nexcept GarmyError as e:\n    print(f\"General Garmy error: {e}\")\n```\n\n### Rate Limiting \u0026 Retries\n\n```python\nfrom garmy.core.config import set_config, GarmyConfig\n\n# Configure retry behavior\nconfig = GarmyConfig(\n    retries=5,\n    backoff_factor=1.0,\n    max_workers=5  # Limit concurrent requests\n)\nset_config(config)\n```\n\n## 🛡️ Security for AI Health Applications\n\n### AI Agent Security Best Practices\n\n1. **Environment Variables**: Essential for AI agents - store credentials securely outside code\n2. **MCP Security**: Use environment variables in MCP configuration to prevent credential exposure to AI servers\n3. **OAuth Token Management**: Garmy handles OAuth tokens securely with automatic refresh for long-running AI agents\n4. **HTTPS Only**: All communications use HTTPS with certificate verification\n5. **AI Data Privacy**: Health data never leaves your local environment unless explicitly exported\n6. **Secure AI Pipelines**: Design AI workflows that protect sensitive health information\n\n### Best Practices\n\n```python\nimport os\nfrom garmy import AuthClient\n\n# ✅ Good: Use environment variables\nemail = os.getenv('GARMIN_EMAIL')\npassword = os.getenv('GARMIN_PASSWORD')\n\n# ❌ Bad: Hardcode credentials\n# email = \"your_email@example.com\"\n# password = \"your_password\"\n\nauth_client = AuthClient()\nauth_client.login(email, password)\n```\n\n## 📝 API Reference\n\n### Core Classes\n\n- **`AuthClient`**: Handles authentication and session management\n- **`APIClient`**: Main interface for accessing Garmin Connect data\n- **`MetricAccessor`**: Provides access to specific metrics\n- **`GarmyMCPServer`**: MCP server for AI assistant integration\n\n### Configuration Classes\n\n- **`GarmyConfig`**: Main configuration class\n- **`MCPConfig`**: MCP server configuration\n- **`ConfigManager`**: Configuration management utilities\n\n### Metrics Classes\n\nEach metric has its own dataclass with type-safe fields. Examples:\n- **`SleepData`**: Sleep tracking information\n- **`HeartRateData`**: Heart rate statistics\n- **`StepsData`**: Step count and goals\n- **`TrainingReadinessData`**: Training readiness scores\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](DEVELOPMENT.md) for details.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/bes-dev/garmy.git\ncd garmy\n\n# Install in development mode\nmake install-dev\n\n# Run quality checks\nmake ci\n```\n\n### Submitting Changes\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature/new-feature`\n3. Make your changes\n4. Run tests: `make ci`\n5. Submit a pull request\n\n## 🙏 Acknowledgments\n\nGarmy was heavily inspired by the excellent [garth](https://github.com/matin/garth) library by [Matin Tamizi](https://github.com/matin). We're grateful for the foundational work that made this project possible. Garmy builds upon garth's concepts with:\n\n- Enhanced modularity and extensibility\n- Full type safety with mypy compliance\n- Model Context Protocol (MCP) integration for AI assistants\n- Comprehensive async/await support\n- Auto-discovery system for metrics\n- Modern Python architecture and testing practices\n\nSpecial thanks to the garth project and its contributors for pioneering accessible Garmin Connect API access.\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## 👨‍💻 Author\n\n**bes-dev** - [GitHub Profile](https://github.com/bes-dev)\n\n## 🔗 Links\n\n- **Documentation**: [DEVELOPMENT.md](DEVELOPMENT.md)\n- **Examples**: [examples/](examples/)\n- **Issues**: [GitHub Issues](https://github.com/bes-dev/garmy/issues)\n- **PyPI**: [https://pypi.org/project/garmy/](https://pypi.org/project/garmy/)\n\n---\n\n*Garmy makes Garmin Connect data accessible with modern Python practices, type safety, and AI assistant integration via MCP.*","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbes-dev%2Fgarmy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbes-dev%2Fgarmy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbes-dev%2Fgarmy/lists"}