Click on "Install 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 MCP Servershow me my sleep score from last night"
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.
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:
git clone https://github.com/meimakes/oura-mcp-server.git
cd oura-mcp-serverInstall dependencies:
npm installCopy the example environment file:
cp .env.example .envGenerate required secrets:
# Generate AUTH_TOKEN
openssl rand -hex 32
# Generate TOKEN_ENCRYPTION_KEY
openssl rand -hex 32Quick 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:
# Generate AUTH_TOKEN
openssl rand -hex 32
# Generate TOKEN_ENCRYPTION_KEY
openssl rand -hex 32In 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:
ngrok config add-authtoken YOUR_NGROK_TOKENStart ngrok tunnel:
ngrok http 3001Note your ngrok URL (e.g.,
https://your-domain.ngrok.dev)
Step 2: Configure Environment Variables
Copy .env.example to .env and configure:
# MCP Server Authentication
AUTH_TOKEN=<generated-token>
# Oura OAuth Credentials
OURA_CLIENT_ID=<your-client-id>
OURA_CLIENT_SECRET=<your-client-secret>
OURA_REDIRECT_URI=https://your-domain.ngrok.dev/oauth/callback
# Server Configuration
PORT=3001
NODE_ENV=development
# Token Encryption
TOKEN_ENCRYPTION_KEY=<generated-key>
# CORS Origin
CORS_ORIGIN=*
# Logging (optional)
LOG_LEVEL=info # Options: error, warn, info, debugUsage
Starting the Server
Build the TypeScript code:
npm run buildStart the server:
npm startFor development with auto-reload:
npm run devConnecting 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
GET /healthReturns server status, OAuth connection status, and cache statistics.
OAuth Endpoints
GET /oauth/authorize - Start OAuth flow
GET /oauth/callback - OAuth callback (automatic)
GET /oauth/status - Get connection status (requires auth)
POST /oauth/disconnect - Disconnect and clear tokens (requires auth)MCP Endpoints
The server supports both transport modes:
Streamable HTTP (recommended for Poke):
POST /sse - JSON-RPC requests with direct responsesClassic SSE:
GET /sse - Establish SSE connection
POST /message - Send JSON-RPC requests via sessionSecurity
Token Encryption
All OAuth tokens are encrypted at rest using AES-256-GCM encryption.
Authentication
MCP endpoints require Bearer token authentication:
Authorization: Bearer YOUR_AUTH_TOKENRate 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:
LOG_LEVEL=info # Default - balanced logging
LOG_LEVEL=error # Production - minimal output
LOG_LEVEL=debug # Development - verbose debuggingWhat 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
oura-mcp-server/
├── src/
│ ├── index.ts # Main server file
│ ├── oauth/
│ │ ├── handler.ts # OAuth flow handler
│ │ └── tokens.ts # Token management
│ ├── mcp/
│ │ ├── server.ts # MCP protocol implementation
│ │ └── tools.ts # Tool definitions
│ ├── oura/
│ │ ├── client.ts # Oura API client
│ │ └── types.ts # TypeScript types
│ ├── utils/
│ │ ├── encryption.ts # Token encryption
│ │ ├── cache.ts # Data caching
│ │ └── validation.ts # Input validation
│ └── middleware/
│ ├── auth.ts # Authentication middleware
│ └── errorHandler.ts # Error handling
├── .env # Environment variables (gitignored)
├── tokens.json # Encrypted tokens (gitignored)
├── package.json
├── tsconfig.json
└── README.mdRunning Tests
npm testType Checking
npm run typecheckLinting
npm run lintDeployment 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
docker build -t oura-mcp-server .
docker run -p 3001:3001 --env-file .env oura-mcp-serverCan 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.
This server cannot be installed
Resources
Looking for Admin?
Admins can modify the Dockerfile, update the server description, and track usage metrics. If you are the server author, to access the admin panel.