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.
git clone https://github.com/meimakes/oura-mcp-server.git
cd oura-mcp-server
npm install
cp .env.example .env
openssl rand -hex 32
openssl rand -hex 32
## Quick Start - Railway Deployment (Recommended)
### Step 1: Deploy to Railway
1. Click the button below to deploy to Railway:
[](https://railway.app/new/template?template=https://github.com/meimakes/oura-mcp-server)
Or manually:
- Go to [Railway](https://railway.app)
- Create new project from GitHub repo
- Connect your fork of this repository
2. Generate required secrets locally:
```bash
# Generate AUTH_TOKEN
openssl rand -hex 32
# Generate TOKEN_ENCRYPTION_KEY
openssl rand -hex 32
AUTH_TOKEN - Your generated auth tokenTOKEN_ENCRYPTION_KEY - Your generated encryption keyNODE_ENV - Set to productionCORS_ORIGIN - Set to * or your specific domainPORT - Leave unset (Railway will auto-assign)https://your-app.up.railway.app)https://your-app.up.railway.app/oauth/callbackAdd 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/callbackRailway will automatically redeploy with the new configuration.
ngrok config add-authtoken YOUR_NGROK_TOKEN
ngrok http 3001
https://your-domain.ngrok.dev)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, debug
npm run build
npm start
For development with auto-reload:
npm run dev
/oauth/authorize endpoint:
https://your-app.up.railway.app/oauth/authorizehttps://your-domain.ngrok.dev/oauth/authorizehttp://localhost:3001/oauth/authorizehttps://your-app.up.railway.app/sse (or your deployment URL)AUTH_TOKEN from environment variablesThe server supports both SSE and Streamable HTTP transports for maximum compatibility.
Configure your MCP client with:
https://your-app.up.railway.app/sse (or your deployment URL)AUTH_TOKEN from environment variablesGet user’s personal information and ring details.
Get sleep data for a date range.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDinclude_hrv (optional): booleanGet daily readiness scores.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDGet activity data for a date range.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDGet heart rate data in 5-minute intervals.
Parameters:
start_datetime (required): ISO 8601 formatend_datetime (optional): ISO 8601 formatGet workout sessions.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDGet detailed sleep period data with heart rate and HRV.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDGet user-created tags and notes.
Parameters:
start_date (required): YYYY-MM-DDend_date (optional): YYYY-MM-DDGet AI-powered insights based on recent data.
Parameters:
days (optional): Number of days to analyze (default: 7)GET /health
Returns server status, OAuth connection status, and cache statistics.
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)
The server supports both transport modes:
Streamable HTTP (recommended for Poke):
POST /sse - JSON-RPC requests with direct responses
Classic SSE:
GET /sse - Establish SSE connection
POST /message - Send JSON-RPC requests via session
All OAuth tokens are encrypted at rest using AES-256-GCM encryption.
MCP endpoints require Bearer token authentication:
Authorization: Bearer YOUR_AUTH_TOKEN
Configure allowed origins in .env with CORS_ORIGIN.
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 bodiesConfigure via the LOG_LEVEL environment variable:
LOG_LEVEL=info # Default - balanced logging
LOG_LEVEL=error # Production - minimal output
LOG_LEVEL=debug # Development - verbose debugging
What gets logged at each level:
OURA_CLIENT_ID and OURA_CLIENT_SECRET are correctOURA_REDIRECT_URI matches your deployment URLTOKEN_ENCRYPTION_KEY is set correctly and hasn’t changedtokens.json file exists and is readable/health endpointServer not starting:
PORT variable is NOT set (Railway auto-assigns)OAuth redirect failing:
OURA_REDIRECT_URI uses your Railway domainTokens not persisting:
tokens.jsonngrok connection issues:
OURA_REDIRECT_URI if ngrok URL changedoura-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.md
npm test
npm run typecheck
npm run lint
docker build -t oura-mcp-server .
docker run -p 3001:3001 --env-file .env oura-mcp-server
Can be deployed to any Docker-compatible platform (Fly.io, Render, etc.)
MIT
For issues or questions:
Contributions are welcome! Please read CONTRIBUTING.md for details.