Self-hosted CPAP analytics with optional AI-assisted interpretation. A modernized workflow companion to OSCAR.
URSA-OSCAR reads ResMed AirSense CPAP data and provides:
- Browser-based daily and trend analysis
- Multivariate statistical analysis (partial correlation, lag analysis)
- Predictive modeling with explicit confidence intervals
- Provider-ready PDF reports with methodology disclosure
- Optional AI assistant (Claude, OpenAI, Gemini, OpenRouter, Groq, local LLMs) grounded in your data via MCP tools
It does this as a self-hosted Docker stack. Your CPAP data never leaves your hardware unless you point an external AI provider at it.
OSCAR is the gold standard for desktop CPAP analysis. URSA-OSCAR isn't a replacement — it addresses different workflow needs: 24/7 automated ingestion, longitudinal statistical analysis beyond OSCAR's scope, conversational query interface, and clinician-ready report generation.
If you're satisfied with OSCAR's desktop workflow, you don't need URSA-OSCAR. If you want web access, automation, AI integration, or analytical capabilities OSCAR doesn't provide, URSA-OSCAR is built for that.
All screenshots below are captured from a live URSA-OSCAR 1.1.x stack against real CPAP data. The architecture diagram is a hand-authored SVG of the actual four-container topology.
New to Docker? Don't start here. Go to INSTALL.md for a full sequential walkthrough — your platform's guide explains every step, including a "what is Docker?" concepts page if you want to understand what you're doing.
Familiar with Docker? Three commands:
# Get the compose file
curl -fsSL https://raw.githubusercontent.com/burrellka/URSA-OSCAR/main/infra/docker-compose.production.yml -o docker-compose.yml
# Edit the two volumes: blocks (api + watcher) to point at your data folder
# and CPAP backup folder. The comment block at the top of the file has
# per-OS path examples (Windows / macOS / Linux).
docker compose pull && docker compose up -dThen visit http://localhost:5063. First visit lands on /setup — pick an operator password (≥12 chars, no recovery, store in a password manager). The api container auto-generates its own Fernet master key, JWT signing secret, and service tokens on first boot. No manual key ceremony.
Per-platform walkthroughs (sequential, with what-success-looks-like at each step):
| Platform | Guide |
|---|---|
| Windows 11 + Docker Desktop | Docs/install/windows.md |
| macOS + Docker Desktop | Docs/install/macos.md |
| Linux + Docker Engine | Docs/install/linux.md |
| TrueNAS SCALE + Dockge | Docs/install/truenas.md |
| Synology / QNAP NAS | Docs/install/synology.md |
| Troubleshooting | Docs/install/troubleshooting.md |
| Concepts (what is Docker / a container / a bind mount) | Docs/install/concepts.md |
Optional second-day add-on — connect claude.ai or Claude Code as an external AI client via MCP + OAuth: Docs/install/mcp-optional-addon.md. Set it up after the analytics stack is running. The default compose has it commented out; you opt in.
Once URSA-OSCAR is running, the in-app /help page has 37 topics covering every feature in detail.
Four containers sharing a single /data volume:
- api — FastAPI backend, DuckDB analytics, AI proxy, PDF generation, sole writer of the database (per ADR-004)
- web — nginx + React 18 + uPlot UI
- mcp — Model Context Protocol server (FastMCP + SSE + OAuth 2.1 + PKCE), exposes 17 analytical tools to AI assistants
- watcher — auto-import daemon that polls a bind-mounted CPAP source and triggers async imports
Single-tenant by design. See frontend/src/help/content/arch-single-tenant.md for the trust boundary discussion.
The full architecture deep-dive lives in Docs/30-developer-guide.md and the in-app Help → Architecture and deployment section.
Everything URSA-OSCAR does is documented in-app at /help. 37 topics across 7 sections:
| Section | Topics | Browse on GitHub |
|---|---|---|
| Getting started | 4 | frontend/src/help/content/ |
| Using URSA-OSCAR | 8 | feature-by-feature guides |
| Understanding the data | 5 | what AHI / pressure / leak metrics mean |
| Methodology | 6 | every statistical method, verbatim with PDF reports |
| Architecture and deployment | 5 | single-tenant, network security, multi-instance, deployment |
| Troubleshooting | 5 | import, watcher, AI chat, MCP, password recovery |
| About URSA-OSCAR | 4 | credits, license, version, future direction |
The same Help content is queryable by AI assistants via the get_help_topic MCP tool — they can read URSA-OSCAR's own documentation when answering questions about it.
Maintainer-facing docs:
- Docs/30-developer-guide.md — repo layout, container roles, request walkthroughs, schema, build / test / deploy
- Docs/17-oauth-setup.md — connecting a claude.ai Custom Connector
- Docs/35-migration-0.12-to-0.13.md — upgrade from pre-1.0 versions
- Docs/architect-decisions/ — ADRs (no Tailwind, MCP-as-thin-proxy, DuckDB concurrency, MCP template adoption)
URSA was built around a specific problem: CPAP therapy generates structured data nightly, but turning that data into sustained understanding (what is working, what is not, what to try next) requires consistent interpretation that most patients can't do alone. Sleep clinics see patients briefly every few months. The patient lives with the therapy every night. URSA closes that gap by making the data continuously available to an AI conversation the patient drives.
URSA's data layer is exposed through the Model Context Protocol. Any MCP-capable AI client (Claude, Claude Code, or other compatible clients) can connect to a URSA deployment and read the operator's nightly data, sleep studies, treatment history, and manual logs in real time. The operator typically configures a dedicated AI conversation with a focused system prompt describing their condition, history, and goals, plus relevant clinical artifacts (sleep study reports, titration data, equipment specifications). That conversation then serves as an ongoing informed thinking partner: interpreting trends, flagging anomalies, helping the operator prepare for sleep clinic appointments, and explaining what the data is actually showing.
The conversation is not a replacement for clinical care. It is a specialized AI surface with sustained access to the operator's own data, doing what the operator alone cannot reliably do every morning without help: synthesize last night's numbers against the prior weeks, notice patterns, and translate raw data into questions worth asking a clinician.
This is the use case that motivated the project. The operator built URSA after years of intermittent CPAP success, multiple machines and masks, periods of giving up entirely, with OSCAR providing the data but no path to consistent interpretation. With URSA connected to a properly-prompted Claude conversation, that interpretation became sustained and routine, and the therapy started working.
Not every deployment can expose a public MCP endpoint. Some users run URSA on a home network behind NAT, without Cloudflare Tunnel or equivalent, and have no easy way to connect an external AI client.
For those deployments, URSA includes a built-in AI assistant accessible from the web UI. The assistant uses any compatible LLM provider (Anthropic, OpenAI-compatible cloud providers, or a local model running via LM Studio, Ollama, or any OpenAI-compatible local endpoint). The assistant has access to the same data the external client would have access to through MCP, so the in-app experience is functionally equivalent.
The in-app assistant is the fallback path. The external MCP-connected conversation is the primary path. Both work; the external path delivers more capability because external clients (particularly Claude with project knowledge and longer context windows) can carry richer operator-specific context than the in-app surface can hold.
The pattern lets a CPAP patient operate as their own informed advocate. Sleep clinics see patients for fifteen minutes every six months. The patient lives with the therapy every night. URSA plus a properly configured AI conversation closes the asymmetry: the patient walks into their appointment with weeks of synthesized data, specific questions about specific nights, and a clear sense of what they've already tried.
The architectural pattern that enables this, MCP-exposed analytical data accessible to specialized AI conversations, is documented as a reusable template at github.com/burrellka/mcp-server-template. URSA is the reference implementation of that pattern for sleep apnea therapy.
- A medical device. Not FDA / CE / TGA-cleared. Not a substitute for clinical judgment. Not a diagnostic tool.
- A multi-tenant system. Single operator, single instance. Households with multiple CPAP users run multiple instances (documented pattern).
- A cloud service. Self-hosted only. No cloud sync, no SaaS option.
- A replacement for OSCAR. Different workflow, different audience.
URSA-OSCAR is built on the file-format work of the OSCAR project — the open-source CPAP data viewer that figured out how to read ResMed's proprietary SD card format. Without OSCAR, this wouldn't exist. The "OSCAR" in URSA-OSCAR is that attribution.
URSA-OSCAR is independent of the OSCAR project — different codebase, different deployment model (self-hosted server vs. desktop application), different feature scope. URSA-OSCAR is downstream of OSCAR's file-format work, not a fork or replacement.
GPL-3.0 license matches OSCAR's, preserving the copyleft.
URSA-OSCAR is licensed under GNU GPL-3.0-or-later. The full license text is in LICENSE; the project copyright notice and OSCAR-project acknowledgement is in COPYRIGHT.
URSA-OSCAR is currently maintained by a single developer. Contributions are welcome but should align with the architectural posture documented in frontend/src/help/content/arch-overview.md and the ADRs.
- Bugs and feature requests — GitHub Issues
- Security issues — SECURITY.md (don't file public issues)
- Contribution guide — CONTRIBUTING.md
Pull requests should reference an issue first for anything beyond a typo or clear bug fix. The developer guide is the easiest entry point for understanding how a change spans the four containers.
- The OSCAR community for showing what CPAP analytics could be, and for years of reverse-engineering ResMed's SD card format
- Anthropic for Claude, used heavily as a development collaborator during URSA-OSCAR's construction
- The open-source ecosystem URSA-OSCAR builds on: Python, FastAPI, DuckDB, pyedflib, MNE, NumPy / SciPy / pandas / scikit-learn, WeasyPrint, FastMCP, React 18, Vite, TypeScript, uPlot, lucide-react, react-markdown + KaTeX + highlight.js, passlib + python-jose, httpx, the Anthropic and OpenAI Python SDKs
Not affiliated with ResMed, the OSCAR project, Anthropic, OpenAI, Google, or any other entity referenced in URSA-OSCAR's code or documentation.





