oura-mcp-server

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.

Deploy on Railway

Features

Prerequisites

Installation

  1. Clone the repository:
    git clone https://github.com/meimakes/oura-mcp-server.git
    cd oura-mcp-server
    
  2. Install dependencies:
    npm install
    
  3. Copy the example environment file:
    cp .env.example .env
    
  4. Generate required secrets: ```bash

    Generate AUTH_TOKEN

    openssl rand -hex 32

Generate TOKEN_ENCRYPTION_KEY

openssl rand -hex 32


## Quick Start - Railway Deployment (Recommended)

### Step 1: Deploy to Railway

1. Click the button below to deploy to Railway:

[![Deploy on Railway](https://railway.app/button.svg)](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
  1. In Railway dashboard, add environment variables:
    • AUTH_TOKEN - Your generated auth token
    • TOKEN_ENCRYPTION_KEY - Your generated encryption key
    • NODE_ENV - Set to production
    • CORS_ORIGIN - Set to * or your specific domain
    • PORT - Leave unset (Railway will auto-assign)
  2. Wait for deployment to complete and note your Railway URL (e.g., https://your-app.up.railway.app)

Step 2: Register Oura OAuth Application

  1. Go to https://cloud.ouraring.com/oauth/applications
  2. Click “Create New Application”
  3. Fill in:
    • Application Name: “Personal MCP Server” (or your choice)
    • Redirect URI: https://your-app.up.railway.app/oauth/callback
    • Scopes: Select all available scopes
  4. Save the Client ID and Client Secret

Step 3: Configure OAuth Credentials in Railway

Add these environment variables in Railway dashboard:

Railway will automatically redeploy with the new configuration.

Local Development Setup

Step 1: Set up ngrok

  1. Install and authenticate ngrok:
    ngrok config add-authtoken YOUR_NGROK_TOKEN
    
  2. Start ngrok tunnel:
    ngrok http 3001
    
  3. Note 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, debug

Usage

Starting the Server

  1. Build the TypeScript code:
    npm run build
    
  2. Start the server:
    npm start
    

For development with auto-reload:

npm run dev

Connecting Your Oura Account

  1. Open your browser to your server’s /oauth/authorize endpoint:
    • Railway: https://your-app.up.railway.app/oauth/authorize
    • ngrok: https://your-domain.ngrok.dev/oauth/authorize
    • Local: http://localhost:3001/oauth/authorize
  2. Log in to your Oura account
  3. Approve the requested permissions
  4. You’ll be redirected back with a success message

Connecting to MCP Clients

Poke

  1. Open Poke app
  2. Go to Settings → Integrations → Add Integration
  3. Select “Model Context Protocol (MCP)”
  4. Enter:
    • Name: Oura
    • Server URL: https://your-app.up.railway.app/sse (or your deployment URL)
    • API Key: Your AUTH_TOKEN from environment variables
  5. Tap “Add Integration”

The server supports both SSE and Streamable HTTP transports for maximum compatibility.

Other MCP Clients

Configure your MCP client with:

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:

3. get_readiness_score

Get daily readiness scores.

Parameters:

4. get_activity_summary

Get activity data for a date range.

Parameters:

5. get_heart_rate

Get heart rate data in 5-minute intervals.

Parameters:

6. get_workouts

Get workout sessions.

Parameters:

7. get_sleep_detailed

Get detailed sleep period data with heart rate and HRV.

Parameters:

8. get_tags

Get user-created tags and notes.

Parameters:

9. get_health_insights

Get AI-powered insights based on recent data.

Parameters:

API Endpoints

Health Check

GET /health

Returns 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 responses

Classic SSE:

GET  /sse                 - Establish SSE connection
POST /message             - Send JSON-RPC requests via session

Security

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_TOKEN

Rate Limiting

CORS

Configure allowed origins in .env with CORS_ORIGIN.

Logging

The server uses structured logging with configurable log levels:

Configure 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:

Troubleshooting

OAuth Callback Failed

Token Refresh Failed

Rate Limit Exceeded

Railway-Specific Issues

Server not starting:

OAuth redirect failing:

Tokens not persisting:

Local Development Issues

ngrok connection issues:

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.md

Running Tests

npm test

Type Checking

npm run typecheck

Linting

npm run lint

Deployment Options

Option 2: Local Development

Option 3: Cloud VM (VPS)

Option 4: Docker

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.)

License

MIT

Support

For issues or questions:

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.