Oura MCP Server
MCP (Model Context Protocol) server that enables AI assistants to access your Oura Ring health data through OAuth2-authenticated API calls.
Built for seamless integration with Poke and other MCP-compatible clients. Deploy to Railway for production use or run locally for development.
Features
OAuth2 with PKCE - Secure authentication with automatic token refresh
9 MCP Tools - Access sleep, readiness, activity, heart rate, workouts, and more
Dual Transport Support - Both SSE and Streamable HTTP transports
Token Encryption - AES-256-GCM encryption for OAuth tokens at rest
Smart Caching - Reduce API calls with intelligent data caching
Rate Limiting - Built-in protection against API quota exhaustion
ngrok Support - Easy remote access for mobile and cloud integrations
Prerequisites
Node.js 18 or higher
Oura Ring (all generations supported - Gen 2, Gen 3, and Gen 4)
Oura account with API access
Railway account (recommended for production deployment) or ngrok (for local development)
Installation
Clone the repository:
Install dependencies:
Copy the example environment file:
Generate required secrets:
Quick Start - Railway Deployment (Recommended)
Step 1: Deploy to Railway
Click the button below to deploy to Railway:
Or manually:
Go to Railway
Create new project from GitHub repo
Connect your fork of this repository
Generate required secrets locally:
In Railway dashboard, add environment variables:
AUTH_TOKEN- Your generated auth tokenTOKEN_ENCRYPTION_KEY- Your generated encryption keyNODE_ENV- Set toproductionCORS_ORIGIN- Set to*or your specific domainPORT- Leave unset (Railway will auto-assign)
Wait for deployment to complete and note your Railway URL (e.g.,
https://your-app.up.railway.app)
Step 2: Register Oura OAuth Application
Go to https://cloud.ouraring.com/oauth/applications
Click "Create New Application"
Fill in:
Application Name: "Personal MCP Server" (or your choice)
Redirect URI:
https://your-app.up.railway.app/oauth/callbackScopes: Select all available scopes
Save the Client ID and Client Secret
Step 3: Configure OAuth Credentials in Railway
Add these environment variables in Railway dashboard:
OURA_CLIENT_ID- Your Oura client IDOURA_CLIENT_SECRET- Your Oura client secretOURA_REDIRECT_URI-https://your-app.up.railway.app/oauth/callback
Railway will automatically redeploy with the new configuration.
Local Development Setup
Step 1: Set up ngrok
Install and authenticate ngrok:
Start ngrok tunnel:
Note your ngrok URL (e.g.,
https://your-domain.ngrok.dev)
Step 2: Configure Environment Variables
Copy .env.example to .env and configure:
Usage
Starting the Server
Build the TypeScript code:
Start the server:
For development with auto-reload:
Connecting Your Oura Account
Open your browser to your server's
/oauth/authorizeendpoint:Railway:
https://your-app.up.railway.app/oauth/authorizengrok:
https://your-domain.ngrok.dev/oauth/authorizeLocal:
http://localhost:3001/oauth/authorize
Log in to your Oura account
Approve the requested permissions
You'll be redirected back with a success message
Connecting to MCP Clients
Poke
Open Poke app
Go to Settings → Integrations → Add Integration
Select "Model Context Protocol (MCP)"
Enter:
Name: Oura
Server URL:
https://your-app.up.railway.app/sse(or your deployment URL)API Key: Your
AUTH_TOKENfrom environment variables
Tap "Add Integration"
The server supports both SSE and Streamable HTTP transports for maximum compatibility.
Other MCP Clients
Configure your MCP client with:
Server URL:
https://your-app.up.railway.app/sse(or your deployment URL)API Key (Bearer Token): Your
AUTH_TOKENfrom environment variables
Available MCP Tools
1. get_personal_info
Get user's personal information and ring details.
2. get_sleep_summary
Get sleep data for a date range.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DDinclude_hrv(optional): boolean
3. get_readiness_score
Get daily readiness scores.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DD
4. get_activity_summary
Get activity data for a date range.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DD
5. get_heart_rate
Get heart rate data in 5-minute intervals.
Parameters:
start_datetime(required): ISO 8601 formatend_datetime(optional): ISO 8601 format
6. get_workouts
Get workout sessions.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DD
7. get_sleep_detailed
Get detailed sleep period data with heart rate and HRV.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DD
8. get_tags
Get user-created tags and notes.
Parameters:
start_date(required): YYYY-MM-DDend_date(optional): YYYY-MM-DD
9. get_health_insights
Get AI-powered insights based on recent data.
Parameters:
days(optional): Number of days to analyze (default: 7)
API Endpoints
Health Check
Returns server status, OAuth connection status, and cache statistics.
OAuth Endpoints
MCP Endpoints
The server supports both transport modes:
Streamable HTTP (recommended for Poke):
Classic SSE:
Security
Token Encryption
All OAuth tokens are encrypted at rest using AES-256-GCM encryption.
Authentication
MCP endpoints require Bearer token authentication:
Rate Limiting
MCP endpoints: 100 requests per 15 minutes per IP
Oura API: 5000 requests per day (tracked automatically)
CORS
Configure allowed origins in .env with CORS_ORIGIN.
Logging
The server uses structured logging with configurable log levels:
error- Only critical errors (recommended for production)warn- Warnings and errorsinfo- Key operations, warnings, and errors (default)debug- Full verbosity including request/response bodies
Configure via the LOG_LEVEL environment variable:
What gets logged at each level:
Error: Authentication failures, API errors, OAuth failures, rate limits
Warn: Invalid API key attempts, missing SSE sessions
Info: SSE connections, tool executions, OAuth operations, MCP method calls
Debug: Full JSON-RPC requests/responses, connection lifecycle events
Troubleshooting
OAuth Callback Failed
Verify redirect URI matches exactly in Oura app settings
Ensure your server is accessible (Railway deployed or ngrok running for local)
Check
OURA_CLIENT_IDandOURA_CLIENT_SECRETare correctConfirm
OURA_REDIRECT_URImatches your deployment URL
Token Refresh Failed
Verify
TOKEN_ENCRYPTION_KEYis set correctly and hasn't changedCheck
tokens.jsonfile exists and is readableEnsure refresh token hasn't been revoked in Oura account
For Railway: Check that persistent storage is enabled
Rate Limit Exceeded
Caching is built-in with 5-minute default TTL
Reduce polling frequency in your MCP client
Check rate limit headers in API responses
Monitor usage at
/healthendpoint
Railway-Specific Issues
Server not starting:
Check Railway logs for errors
Verify all required environment variables are set
Ensure
PORTvariable is NOT set (Railway auto-assigns)Check build logs for TypeScript compilation errors
OAuth redirect failing:
Verify
OURA_REDIRECT_URIuses your Railway domainCheck that Railway deployment is public (not private networking only)
Ensure HTTPS is used in redirect URI (Railway provides this automatically)
Tokens not persisting:
Railway provides persistent storage by default for
tokens.jsonCheck application logs for file write errors
Verify disk usage hasn't exceeded limits
Local Development Issues
ngrok connection issues:
Restart ngrok tunnel
Update
OURA_REDIRECT_URIif ngrok URL changedVerify ngrok authentication token is valid
Check ngrok isn't blocked by firewall
Development
Project Structure
Running Tests
Type Checking
Linting
Deployment Options
Option 1: Railway (Recommended)
Cost: Free tier available, pay-as-you-grow
Setup Time: ~5 minutes
Benefits:
Always available (24/7 uptime)
Automatic deployments from GitHub
Built-in HTTPS
No server management required
Persistent storage for tokens
Best for: Production use, mobile access, sharing with others
Option 2: Local Development
Cost: Free (ngrok free tier)
Setup Time: ~10 minutes
Benefits:
Complete data privacy (tokens stay local)
No hosting costs
Full control over environment
Limitations:
Requires computer to be running
ngrok URL changes on restart (free tier)
Best for: Development, testing, personal use
Option 3: Cloud VM (VPS)
Deploy to DigitalOcean, AWS EC2, Google Cloud, etc.
Always available with static IP
More control but requires server management
Option 4: Docker
Can be deployed to any Docker-compatible platform (Fly.io, Render, etc.)
License
MIT
Support
For issues or questions:
GitHub Issues: https://github.com/meimakes/oura-mcp-server/issues
Oura API Docs: https://cloud.ouraring.com/docs
MCP Protocol: https://modelcontextprotocol.io
Contributing
Contributions are welcome! Please read CONTRIBUTING.md for details.