oura-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@oura-mcpshow my sleep and readiness scores for the last 7 days"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Forge mirror. The canonical repository is on GitHub; an identical mirror is kept on Codeberg. Issues and pull requests are handled on GitHub and are disabled on the mirror.
Sleep, readiness, activity, workouts, HRV and resting heart rate from your Oura Ring, exposed to any MCP client. Runs over stdio for local clients or over streamable HTTP behind a shared secret for networked deployment.
Not affiliated with, endorsed by, or sponsored by Ōura Health Oy.
Why another one
Oura deprecated Personal Access Tokens in December 2025. New ones can no longer be created, which quietly broke most existing Oura MCP servers for fresh installations — they authenticate with a PAT. This one is OAuth2 only.
It also handles three things that are easy to get wrong, each of which cost real debugging time:
Oura runs two token endpoints. The published documentation names only
api.ouraring.com/oauth/token, but Oura's infrastructure actually serves
moi.ouraring.com/oauth/v2/ext/oauth-token today. The order matters:
authorization codes are single-use (RFC 6749 §4.1.2),
so a rejected attempt against the wrong endpoint burns the code and makes any
fallback useless. This server tries moi first and falls back to legacy.
Refresh tokens are single-use too. Each refresh returns a new one and invalidates the old. Losing the response means the authorization is dead and must be re-established by hand. Tokens are therefore written atomically before being handed out, and concurrent refreshes are serialised behind a lock.
Date ranges are inclusive here. Oura's own end_date is exclusive, so a
naive single-day request returns nothing. That trap is closed once, in one
place, rather than left for every caller to remember.
Related MCP server: oura-mcp-server
Tools
Tool | Purpose |
| Daily sleep scores with contributors |
| Per-session sleep phases, HRV, lowest heart rate |
| Readiness scores, temperature deviation, recovery index |
| Steps, calories, targets, inactivity |
| Detected and manual workouts with distance and intensity |
| Guided and unguided app sessions |
| User-entered tags (enhanced format) |
| Daily stress and recovery time |
| Resilience level and contributors |
| Nightly blood oxygen and breathing disturbance index |
| Cardiovascular age and VO2 max |
| Heart rate time series, auto-chunked into 30-day windows |
| Account basics |
| Ring generation, size, colour |
| Authorization diagnostics without touching health data |
| Recovery timeline around a single event, in one call |
get_event_window
This is the tool worth having. Give it an event date and a window; it returns a
day-by-day timeline with sleep score, readiness, HRV, resting heart rate, steps
and workouts aligned on an offset_days axis — negative before the event, zero
on the day, positive after.
Day Offset Sleep Ready HRV RHR Steps
2026-09-17 -2 78 84 28 53 2,697
2026-09-18 -1 68 71 26 56 2,439
2026-09-19 +0 58 73 23 52 1,942 <- event
2026-09-20 +1 57 78 30 52 1,782
2026-09-21 +2 83 85 25 52 2,110Answering "how hard did that hit me, and how long did I take to recover" is one call instead of six plus manual joining. Built for correlating hard days — an ultramarathon, a long hike, a flight, a bad night — against what the ring recorded afterwards.
Endpoints requiring an Oura membership or newer hardware degrade gracefully:
they answer {"available": false, "reason": "..."} instead of failing the call.
Setup
1. Register an Oura application
Go to https://developer.ouraring.com/applications — this is the correct portal, and picking the wrong one is the single most common setup failure. Add this redirect URI:
http://localhost:8765/callbackNote the Client ID and Client Secret.
If you also use the Home Assistant Oura integration, one application serves both — just add
https://my.home-assistant.io/redirect/oauthas a second redirect URI.
2. Authorize once
The OAuth flow needs a browser, so it cannot run headless in a container:
export OURA_CLIENT_ID=...
export OURA_CLIENT_SECRET=...
uvx --from oura-mcp oura-mcp --token-store ./tokens.json authThis writes tokens.json with mode 0600.
Keep only one copy in active use. Oura invalidates the refresh token on every use, so two copies of the same file will kill each other the first time either one refreshes. After copying it to a server, delete the local copy.
3a. Run locally over stdio
{
"mcpServers": {
"oura": {
"command": "uvx",
"args": ["--from", "oura-mcp", "oura-mcp", "--token-store", "/path/to/tokens.json", "serve"],
"env": {
"OURA_CLIENT_ID": "...",
"OURA_CLIENT_SECRET": "..."
}
}
}
}3b. Run over HTTP in Docker
Multi-arch images (amd64 and arm64) are published to GHCR:
docker pull ghcr.io/halmsascha/oura-mcp:latestCopy docker-compose.example.yaml to docker-compose.yaml, fill in your
values, then:
mkdir -p data && cp /path/to/tokens.json data/ && chmod 600 data/tokens.json
docker compose up -dClients authenticate with Authorization: Bearer $OURA_MCP_TOKEN:
claude mcp add --transport http oura http://your-host:8000/mcp \
--header "Authorization: Bearer $OURA_MCP_TOKEN"Configuration
Variable | Default | Meaning |
| — | required |
| — | required |
|
| token file location |
|
|
|
| — | shared secret, required for |
|
| bind address |
|
| bind port |
| — | permitted |
|
| logging verbosity |
OURA_MCP_ALLOWED_HOSTS is required when the server is reached under anything
other than localhost. The MCP SDK validates the Host header against DNS
rebinding and otherwise answers 421, which is easy to misread as a network
problem. Set it to the host and port your clients actually use, for example
oura.example.com,192.168.1.10:8000.
/healthz answers without a token so container health checks do not need the
secret. Everything else returns 401 without a valid bearer token.
Security
tokens.jsonholds access and refresh tokens in clear text. It is in.gitignoreand written0600. Do not commit it.Rejected token requests log only the endpoint host, grant type and HTTP status. Response bodies are never logged, because they can contain tokens. A test asserts this.
The HTTP transport has no per-user authentication. The shared secret is the only gate. This is a single-user design: do not expose the port to the internet without something in front of it.
Troubleshooting
Start with get_status. It reports whether credentials are set, whether the
token store exists, and whether authorization actually works — without reading
any health data.
Symptom | Likely cause |
| Redirect URI not registered, or registered in the wrong portal |
| Wrong portal, mismatched redirect URI, or a regenerated client secret |
Token request rejected on refresh | The refresh token was already used. Re-run |
|
|
Some sensors always | Those endpoints need an Oura membership or newer ring hardware |
Empty result for a single day | Should not happen — please open an issue, the inclusive range handling is meant to prevent exactly this |
Development
uv sync --all-extras
uv run pytest
uv run ruff check .
uv run ruff format --check .41 tests cover the inclusive/exclusive date boundary, pagination, heart rate windowing, rate-limit retry and its cap, optional-endpoint degradation, token endpoint ordering, atomic persistence, concurrent refresh, error messages reaching the client, and a regression guard asserting no secret ever reaches the log.
Contributions welcome. Please run the checks above before opening a PR.
AI-Assisted Development
This project was developed with AI assistance (Claude / Claude Code), under the direction and review of Sascha Halm. Architecture decisions, the choice of OAuth-only authentication, and the verification of Oura's undocumented token endpoint were reviewed by a human before being committed.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Multi-tenant hosted MCP server for Oura Ring — 21 read-only tools, OAuth per user.
Connect your Oura Ring account securely in minutes. Enable authorized access to your sleep, activi…
Connect your Oura Ring account to enable secure, authenticated access in your workflows. Generate…
Connect your Oura Ring account and enable access to your wellness data in apps and automations. In…
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for the Oura Ring API v2, providing access to sleep, activity, readiness, heart rate, and workout data via OAuth.593 npm1MIT
- AlicenseNot gradedqualityFmaintenanceEnables AI assistants to query Oura Ring health data (sleep, readiness, activity, heart rate, SpO2, stress) via a remote MCP server.11 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to access Oura Ring health data including sleep, readiness, activity, heart rate, and workouts through MCP tools with OAuth2 authentication.1MIT
- AlicenseAqualityAmaintenanceExposes the Oura API v2 as an MCP server with tools to query all 19 data collections (e.g., sleep, heartrate) with automatic pagination and explicit truncation warnings.6285 PyPIMIT