A Model Context Protocol server that lets Claude Code (and any MCP client) query your Oura Ring data through the official Oura API v2.
Strong tool definitions with comprehensive schemas and descriptions. All 16 tools have clear verb-noun naming (get_*, create_*, list_*, etc.) and detailed parameter documentation. Input schemas are well-structured with enums, format constraints, and descriptions. However, output schemas are not explicitly documented in the visible code, only inferred from implementation. Error handling is present but generic. Tool descriptions average ~150 chars, within the 10-1024 baseline. Parameters consistently include type, description, and constraints (e.g., date format regex, enum values for 'prefer'). No security issues detected (no secrets in params). Composition is clean: each tool has one responsibility, and tools chain well (e.g., list_tags → get_tag, create_annotation → list_annotations). Minor gaps: no explicit output schema documentation, no dry-run/confirmation for destructive ops (delete_annotation), and no pagination support for list_tags/list_annotations despite potentially large result sets.
Analyze trends in health metrics over a date range. Computes rolling averages, slopes, and trend directions for sleep, readiness, and activity scores.
Compare health metrics between two date ranges. Useful for before/after analysis of lifestyle changes.
Create a new locally-stored annotation (context entry). Annotations are used to record health events, meals, workouts, stress, illness, or other contextual information.
Create a new tag for a specific date. Tags can be used to mark events, workouts, or other significant moments.
Delete a locally-stored annotation by ID.
Fetch activity data for a date range. Returns compact activity records with scores and contributors, or raw API rows if verbose=true.
Output schemas not explicitly documented. Tool descriptions state what is returned (e.g., 'compact records with scores and contributors') but the exact field structure is not visible in the provided code. LLMs cannot plan downstream tool calls without knowing response field names and types.
Destructive tool (delete_annotation) lacks confirmation or dry-run support. Agents can permanently delete annotations without a safety gate. No recovery mechanism documented.
List tools (list_tags, list_annotations) lack pagination parameters (limit, offset, cursor) and do not document result count limits. Large result sets could exhaust context windows or violate API response size constraints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | 2026-07-28+ | v2 |
Fetch merged daily summaries (sleep, readiness, activity) for a date range. Returns compact records with scores and key contributors, or raw API rows if verbose=true.
Fetch heart rate data for a datetime range. Returns compact heartrate records or raw API rows if verbose=true. Maximum 30-day range per request.
Fetch readiness data for a date range. Returns compact readiness records with scores and contributors, or raw API rows if verbose=true.
Fetch session data (guided sessions, workouts) for a date range. Returns compact session records or raw API rows if verbose=true.
Fetch sleep data for a date range. Returns compact sleep records with scores and contributors, or raw API rows if verbose=true.
Fetch a single tag by ID. Returns the tag with its type and any associated enhanced_tags from Oura.
List all locally-stored annotations (context entries) for a date range. Annotations are user-created notes about health events, meals, workouts, etc.
List all tags for a date range. Returns tags with their types and associated enhanced_tags from Oura.
Synchronize Oura Ring data from the API into the local SQLite database. Fetches sleep, readiness, activity, heartrate, and session data for a specified date range.
Update an existing locally-stored annotation. Can modify the text, tag type, or date range.
Error handling is generic (try-catch wrapping with name + message). No recovery guidance provided. E.g., if sync_oura_data fails due to API rate limit, the error should suggest retry timing or fallback to local data.
Parameter descriptions for 'prefer' enum are clear, but no guidance on when to use 'api' vs 'auto' vs 'local' in practical scenarios. LLMs may not understand the trade-offs (freshness vs latency vs offline capability).