# CPAP MCP Server

[![PyPI version](https://badge.fury.io/py/cpap-mcp.svg)](https://badge.fury.io/py/cpap-mcp)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A Model Context Protocol (MCP) server that exposes the [cpap-py](https://github.com/dynacylabs/cpap-py) library functionality, enabling AI models to analyze ResMed CPAP data and provide therapy insights.

## Overview

This MCP server allows AI assistants to:

- 📤 **Upload CPAP data archive** - Accept base64-encoded ZIP archive from SD card
- 📊 **Parse therapy data** - Read EDF files (BRP, PLD, SAD, EVE, CSL, STR) and device settings
- 📈 **Analyze sessions** - Access detailed metrics like AHI, leak rates, pressure statistics
- 🔍 **Query events** - Retrieve apneas, hypopneas, flow limitations, and other respiratory events
- 📉 **View waveforms** - Access time-series data for pressure, flow, and SpO2
- 💡 **Generate recommendations** - Provide therapy effectiveness analysis and optimization suggestions
- ⚙️ **Propose settings changes** - Create validated settings adjustment proposals with safety checks

## Features

### File Management
- `upload_archive` - Upload ZIP archive containing CPAP data with directory structure
- `list_uploaded_files` - View all uploaded files
- `clear_uploaded_files` - Reset and clear the working directory

### Device & Session Information
- `get_devices` - Get device serial numbers, models, and firmware versions
- `get_sessions` - Retrieve therapy sessions with filtering options
- `get_session_details` - Get comprehensive session information
- `get_summary_statistics` - Aggregate statistics across multiple sessions

### Detailed Analysis
- `get_session_events` - Retrieve respiratory and device events
- `get_session_pressure_data` - Access pressure waveform data
- `get_session_flow_data` - Access flow waveform data
- `get_session_spo2_data` - Access blood oxygen saturation data

### Settings & Recommendations
- `get_device_settings` - View current CPAP device configuration
- `analyze_therapy_effectiveness` - Get insights and optimization recommendations
- `propose_pressure_adjustment` - Generate validated pressure change proposal
- `propose_comfort_improvements` - Generate validated comfort settings proposal
- `get_validation_errors` - View data parsing errors and warnings
- `export_all_data` - Export complete dataset as JSON

## Quick Start

### Prerequisites

- Python 3.10 or higher
- An MCP-compatible AI client (e.g., Claude Desktop)

### Installation

#### From PyPI (Recommended)

```bash
pip install cpap-mcp
```

#### From Source

For development or to use the latest unreleased features:

```bash
# Clone with submodules
git clone --recursive https://github.com/dynacylabs/cpap-mcp.git
cd cpap-mcp

# If already cloned without --recursive:
git submodule update --init --recursive

# Install in development mode
pip install -e .
```

Or use the installation script:

```bash
chmod +x install.sh
./install.sh
```

### Verification

Test that the server starts correctly:

```bash
python -m cpap_mcp.server
```

The server should start and wait for MCP client connections via stdio. Press Ctrl+C to stop.

### Troubleshooting Installation

**Import errors**: Ensure dependencies are installed:
```bash
pip install mcp pydantic numpy pandas pyedflib
```

**Submodule issues**: Reinitialize submodules:
```bash
git submodule update --init --recursive
```

## Configuration

### Claude Desktop

Add to your Claude Desktop configuration file:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "cpap-mcp": {
      "command": "python",
      "args": ["-m", "cpap_mcp.server"],
      "cwd": "/path/to/cpap-mcp"
    }
  }
}
```

Or if installed globally:

```json
{
  "mcpServers": {
    "cpap-mcp": {
      "command": "cpap-mcp"
    }
  }
}
```

### Other MCP Clients

The server uses stdio transport, making it compatible with any MCP client. Start it with:

```bash
python -m cpap_mcp.server
```

## Usage

### 1. Prepare CPAP Data Archive

First, create a ZIP archive of your CPAP SD card data:

**Option A: Use the helper script**
```bash
python examples/create_archive.py /path/to/sdcard --encode
```

This creates:
- `cpap_data.zip` - ZIP archive of all SD card files
- `cpap_data.zip.b64` - Base64 encoded version ready for upload

**Option B: Manual creation**
```bash
# On macOS/Linux
cd /Volumes/RESMED  # or wherever your SD card is mounted
zip -r cpap_data.zip DATALOG/ STR.edf Identification.tgt SETTINGS/

# On Windows
# Right-click the SD card contents → Send to → Compressed (zipped) folder
```

The ZIP should contain the SD card's directory structure:
```
DATALOG/
  20240101/
    20240101_220030_BRP.edf
    20240101_220030_EVE.edf
    20240101_220030_PLD.edf
    20240101_220030_SAD.edf
  20240102/
    ...
SETTINGS/
  STI_20240101_000000.tgt
STR.edf
Identification.tgt
```

### 2. Upload to AI Assistant

**User**: "I have CPAP data to analyze. I'll upload a ZIP archive."

**AI**: "Please provide the base64-encoded ZIP archive."

*User provides the base64 content from the .b64 file*

The AI will use the `upload_archive` tool to extract and process your data.

### 3. Analyze Therapy Data

Once the archive is uploaded, ask questions like:

- "Show me my therapy sessions from the last 30 days"
- "What's my average AHI?"
- "Show me nights where I had high leak rates"
- "Get detailed events from my session on January 15th"
- "What are my current CPAP pressure settings?"

### 3. Get Recommendations

**User**: "Analyze my therapy effectiveness and give me recommendations"

The AI will use `analyze_therapy_effectiveness` to provide:
- Compliance metrics (hours of usage)
- AHI control assessment
- Leak performance analysis
- Specific recommendations for improvement

## Example Interaction

```
User: I want to upload my CPAP data and get some insights.

AI: I'll help you analyze your CPAP data. Please provide a ZIP archive 
of your SD card data encoded in base64.

User: [uploads ZIP archive using base64 encoding]

AI: [uses upload_archive tool]
Successfully extracted 45 files from your archive. Let me analyze your data.
[uses get_devices, get_sessions, analyze_therapy_effectiveness]

I found 30 nights of therapy data. Here's what I discovered:

**Compliance**: You're using your CPAP for an average of 6.8 hours per 
night with 93% compliance (28/30 nights > 4 hours). Excellent!

**Therapy Effectiveness**: Your average AHI is 2.3 events/hour, which 
is excellent control (target is <5).

**Leak Performance**: Average leak rate is 18 L/min, which is good. 
Only 2 nights had high leak issues.

**Recommendations**: 
- Your therapy is working very well overall
- Continue with current pressure settings
- On Jan 15 and Jan 22, you had higher leaks - check mask fit on 
  those nights if this persists

Would you like me to look at any specific sessions in detail?
```

## Tool Reference

### upload_archive
```json
{
  "content": "<base64-encoded-zip-content>"
}
```

### get_sessions
```json
{
  "start_date": "2024-01-01",
  "end_date": "2024-01-31",
  "min_duration_hours": 4.0
}
```

### get_session_events
```json
{
  "session_id": "1234567890_20240115_220030",
  "event_type": "OA"  // Optional: OA, CA, H, FL, etc.
}
```

### analyze_therapy_effectiveness
```json
{
  "days": 30
}
```

### propose_pressure_adjustment
```json
{
  "target_pressure": 12.0,
  "reason": "AHI remains elevated at 8.5 events/hour, increase pressure to improve therapy effectiveness"
}
```

### propose_comfort_improvements
```json
{
  "enable_epr": true,
  "epr_level": 3,
  "enable_ramp": true,
  "ramp_time": 20
}
```

## Data Privacy

- All uploaded files are stored in a temporary directory
- Files are only kept in memory during the session
- Use `clear_uploaded_files` to explicitly remove data
- No data is sent to external services
- All analysis happens locally

## Understanding the Data

### Key Metrics

- **AHI** (Apnea-Hypopnea Index): Events per hour. <5 is excellent, 5-15 is mild, 15-30 is moderate, >30 is severe
- **AI** (Apnea Index): Apneas per hour
- **HI** (Hypopnea Index): Hypopneas per hour
- **Leak Rate**: Air leakage in L/min. <24 L/min is acceptable
- **Pressure**: Delivered pressure in cmH2O
- **SpO2**: Blood oxygen saturation percentage

### Event Types

- **OA**: Obstructive Apnea
- **CA**: Central Apnea
- **H**: Hypopnea
- **FL**: Flow Limitation
- **RE**: RERA (Respiratory Effort Related Arousal)
- **VS**: Vibratory Snore

## Development

### Running tests

```bash
pip install -e ".[dev]"
pytest
```

### Code formatting

```bash
black src/
ruff check src/
```

## Architecture

### Project Structure

```
cpap-mcp/
├── src/cpap_mcp/
│   ├── __init__.py          # Package initialization
│   └── server.py            # Main MCP server (17 tools)
├── examples/
│   ├── encode_file.py       # Helper to encode files for upload
│   └── test_client.py       # Test client for server verification
├── submodules/
│   └── cpap-py/             # Core CPAP parsing library
├── tests/                   # Comprehensive test suite
├── pyproject.toml           # Project configuration & dependencies
└── README.md                # This file
```

### Technical Design

- **Protocol**: Model Context Protocol (MCP) via stdio
- **Language**: Python 3.10+
- **Dependencies**: mcp, pydantic, numpy, pandas, pyedflib
- **Storage**: Temporary directories for uploaded files
- **State Management**: Global reader instance with lazy loading

### Data Flow

1. **User uploads files** → Base64 decoded → Stored in temp directory
2. **CPAPReader initialized** → Scans directory structure
3. **AI queries data** → Tools invoke CPAPReader methods
4. **Results serialized** → JSON responses to AI
5. **AI interprets** → Natural language responses to user

The server wraps the cpap-py library and exposes its functionality through MCP tools. It handles:
- File upload and storage in temporary directories
- CPAPReader initialization and management
- Data serialization for JSON responses
- Error handling and validation

## Troubleshooting

### "Working directory not initialized"
Make sure to upload files using `upload_file` before trying to access data.

### "Session not found"
Use `get_sessions` first to get valid session IDs, then pass those IDs to other tools.

### Large data responses
Use `sample_limit` parameter when requesting waveform data to avoid overwhelming responses.

### Parser errors
Ensure you've uploaded all required files from your SD card, especially:
- STR.edf (session summary file)
- DATALOG directory with dated folders
- EDF files in each dated folder

## Contributing

Contributions welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Submit a pull request

## License

MIT License - see LICENSE file for details

## Credits

Built on top of [cpap-py](https://github.com/dynacylabs/cpap-py) by Dynacy Labs.

## Support

For issues and questions:
- GitHub Issues: https://github.com/dynacylabs/cpap-mcp/issues
- Email: info@dynacylabs.com

---

**Note**: This tool is for informational purposes only and should not replace medical advice. Always consult with your healthcare provider or sleep specialist for therapy adjustments.