← Back to home

Setup Guide

Connect your favorite AI to your training history.

Automatic Agent (Cloud Sync)

1. Add the MCP connector

In Claude (desktop, web, or a Claude Project), go to Settings → Connectors → Add custom connector and paste this URL:

https://ai-coach-feed.4pp.se/api/v1/mcp

Give the connector a name (e.g. AI Coach Feed) and save. The connector will appear in your list as disconnected.

2. Click Connect & sign in

After saving, the connector row shows a Connect button — click it. Claude opens the sign-in page for AI Coach Feed. Log in with your app account and grant access.

⚠ Easy to miss

Adding the URL alone does not connect you. You must click Connect and complete the login flow before Claude can access your data.

3. Allow all tools

To avoid Claude asking for confirmation before every tool call, set approval to Always allow:

  1. Open the connector you just added (click its name or the ⚙ icon).
  2. Find the Tools section — it lists all available tools.
  3. Set each tool to Always allow, or use the top-level Allow all toggle if present.
💡 Why this matters

Without this, Claude stops and asks for your approval every time it reads your activities or updates your schedule — which breaks the flow of a coaching conversation. Approving upfront lets the AI work uninterrupted.

4. Start chatting

Open a new conversation in Claude and try one of these starters to verify everything works:

Analyze last week
Analyze my last week of training and give me feedback.
Build a plan
I want to run a 10k under 50 min — help me build a schedule.
Intensity mix
How does my intensity distribution look since last time?
Adjust schedule
Add an extra rest day on Wednesday next week.

Curious about system instructions and full MCP tool schema? See the MCP Overview tab.

Automatic Agent (Cloud Sync)

1. Create your Agent

Open Copilot Studio and create a new Agent. Under Actions, add a new Tool (Connector) and choose "Website URL" or "Custom" depending on your version, using this MCP endpoint:

https://ai-coach-feed.4pp.se/api/v1/mcp

2. Authentication

Set authentication to OAuth 2.0. Use Dynamic identification if available to ensure the agent only accesses your specific data after you sign in.

3. Description — what this connector is for

Paste into the connector's Description field so the agent knows when to use this tool.

AI Coach Feed supplies your AI assistant with your training data (GPS-tracked activities, workouts, schedule). Once connected, your AI can act as your science-based training coach — analyzing your training load, building plans, and adjusting your schedule on your behalf.

4. Instructions — the bootstrap prompt

Paste into the agent's Instructions field. This is a lightweight "bootstrap" that points the agent to the MCP server for full rules.

You are a science-based AI training coach. Your mission is to guide the user toward their training goals — research, plan, and adjust as the data tells you. You have MCP tools that give you access to the user's training history and let you update their training schedule for them.

LANGUAGE: detect the language of the user's first message and reply in that same language for the rest of the conversation.
Start every session with get_coach_overview to see active goals, upcoming events, weekly plan, and recent progress.

Suggested Prompts

Once connected, try asking these to verify the setup:

Analyze last week
Analyze my last week of training and give me feedback.
Build a plan
I want to run a 10k under 50 min — help me build a schedule.
Intensity mix
How does my intensity distribution look since last time?
Adjust schedule
Add an extra rest day on Wednesday next week.
Quick Start (Any AI Chat)

Zero-Setup Workflow

The fastest way to use AI Coach Feed is via manual copy/paste. This works with any AI chat (ChatGPT, Gemini, Claude web, etc.) and requires no technical setup.

  1. Open the App: Go to Settings or open a specific activity.
  2. Copy Everything: Tap "Copy instructions + history" in Settings. This single action copies all the rules and data your AI needs to understand your training.
  3. Paste & Chat: Paste the text into your favorite AI. Your AI now knows your muscle groups, formats, and recent history.
  4. Get Feedback: Ask for an analysis of your week or help with a new training plan.
  5. Sync Back: If the AI gives you a new schedule, copy the code and use "Smart Paste" in the app's schedule view.

Note: For a fully automated experience where the AI can read your data without copy/pasting, see the Claude or Copilot tabs.

What the MCP server delivers

Server Instructions

Returned during MCP initialization. Guides the AI to start with get_coach_overview and follow canonical data formats.

You are a science-based AI training coach.
Analyze training data and help the user reach their goals with evidence-based guidance.
Language rule: detect the user's language and respond in the same language (Swedish -> Swedish, English -> English).
Core Coaching Workflow:
1. Start every session by calling get_coach_overview for an instant picture of active goals, upcoming milestone events/races (with days/weeks countdown), completed sessions from the past 7 days, rolling volume trends (current week, previous week, and 4-week average), and health trends.
   Note: The weekly schedule/plan is completely optional. The user's consistency and movement is the primary foundation—use volume trends and completed sessions to guide feedback.
2. Call get_session_history to analyze historical training load, volume progression, or to list completed sessions over time (cardio & strength) with view="sessions" or view="weekly_summary".
3. Call get_session_details with a session UUID (from recent_sessions or history) to inspect granular 1km splits, intervals, elevation, or strength exercise sets.
4. Call get_exercise_history with an exercise name to analyze PR progression, top sets, and estimated 1RM over time.
Never invent UUIDs: omit "id" when creating new items, and use existing UUIDs returned by get tools to update or delete.
Tools are self-contained with explicit schemas, SI units (kg, meters, seconds), and format validation.
Schedule is the current recurring weekly template. Anything dated in the future is an event or a target date. Activities and workouts are what was actually done. To adjust or remove a weekly session, call upsert_schedule with its existing UUID. To replace the whole schedule at once (e.g. from an external plan), pass { items: [...], replace_all: true }. Never delete and recreate an existing session when updating it.
Workouts in schedule: when scheduling a workout (type: "WORKOUT"), always provide a complete "workout_plan" with exercises, target muscle groups, and sets (syntax: "80kg x 5", "15" bodyweight, "2m" timed) so the user can start and log the workout directly in the mobile app.
Workouts: log strength sessions with exercises, sets, reps, and weights.
Activities: log cardio/endurance sessions with duration, distance, and optional split/interval stats.
Coaching approach: focus on what the user actually completed in recent_sessions and their rolling volume trends (current week vs previous week and 4-week baseline). If the user has an upcoming event or race, help them prepare progressively without imposing rigid schedules unless they ask for one.

Custom Integration

Integrate directly with our REST API using standard OAuth 2.1.

  • API Base: https://ai-coach-feed.4pp.se/api/v1
  • Auth: Bearer Token (OAuth 2.1)
Full MCP Tool Schema

These capabilities are exposed to the AI via the MCP server's tool definitions.

[
  {
    "name": "get_coach_overview",
    "description": "Fetch an integrated coaching snapshot: active goals (top priority first), upcoming milestone events or races (with days and weeks countdown), completed sessions from the past 7 days, rolling volume trends (current week, previous week, and 4-week average), and latest health metrics with 30-day trends in pure structured JSON. All dates are LOCAL calendar dates in `timezone`. USE WHEN: Starting any coaching session to understand the user's current status, goals, and recent activity. Note: Training plan is completely optional—focus on movement and consistency. DO NOT USE FOR: Km-by-km splits, set-by-set exercise details, or multi-month historical progression. PROCEED WITH: Call get_session_details with an \"id\" from recent_sessions for granular split or exercise analysis; call get_schedule to view or update the recurring weekly template; call get_session_history for long-term historical volume trends.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "days_back": {
          "type": "number",
          "description": "Days into the past for recent completed sessions (default 7, min 1, max 30)."
        },
        "days_ahead": {
          "type": "number",
          "description": "Days into the future to look for upcoming events and race targets (default 90, min 1, max 365)."
        },
        "timezone": {
          "type": "string",
          "description": "IANA time zone used to derive local dates and Monday-Sunday calendar weeks (default \"Europe/Stockholm\")."
        }
      }
    },
    "annotations": {
      "title": "Get Coach Overview",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_activity_types",
    "description": "Get user-defined GPS activity types (e.g. 1: Road run, 2: MTB). Call to know valid activity type IDs for filtering or logging cardio sessions. Note: gym sessions use type \"WORKOUT\" and are not in this list.",
    "inputSchema": {
      "type": "object",
      "properties": {}
    },
    "annotations": {
      "title": "Get Activity Types",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_session_history",
    "description": "Fetch historical training load, volume progression, and logged sessions across all sports (running, cycling, strength workouts, etc.) in clean JSON with SI units. Supports view=\"sessions\" (chronological list with UUIDs, distance, duration, notes) or view=\"weekly_summary\" (Mon-Sun aggregated volume tables by sport). USE WHEN: Reviewing training history over time, analyzing volume trends, or searching for past sessions. DO NOT USE FOR: Granular km-by-km splits or set-by-set exercise details of a single session (use get_session_details instead). Note: Training is logged regardless of whether it was scheduled in the optional plan. PROCEED WITH: Call get_session_details with a session \"id\" to inspect full interval or exercise data.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "view": {
          "type": "string",
          "enum": [
            "sessions",
            "weekly_summary"
          ],
          "description": "Which view to return (default \"sessions\"). \"sessions\": chronological list of individual workouts and cardio runs; \"weekly_summary\": week-by-week aggregated volume tables (Mon-Sun)."
        },
        "days": {
          "type": "number",
          "description": "Lookback window in days (default 30, min 1, max 730)."
        },
        "sport": {
          "type": "string",
          "description": "Filter sessions by sport type (e.g. \"RUN\", \"CYCLE\", \"MTB\", \"WALK\", \"WORKOUT\"). Omit to include all sports."
        },
        "limit": {
          "type": "number",
          "description": "Max sessions to return when view is \"sessions\" (default 50, max 200)."
        },
        "timezone": {
          "type": "string",
          "description": "IANA time zone used for local dates and Monday-Sunday week grouping (default \"Europe/Stockholm\")."
        }
      }
    },
    "annotations": {
      "title": "Get Session History",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_session_details",
    "description": "Fetch full details for a single completed session by its UUID (cardio activity or gym workout from get_session_history or get_coach_overview). Automatically detects session type: for cardio activities, returns distance, duration, elevation, speed zones, 1km fixed splits (stats.splits), and user-recorded laps/intervals (stats.intervals); for strength workouts, returns all exercises, target muscle groups, sets (order, reps, weight_kg, duration_seconds), and notes. USE WHEN: Deep-diving into the performance of a specific completed session. DO NOT USE FOR: Browsing multiple sessions or calculating aggregated trends. PROCEED WITH: Call get_exercise_history to analyze long-term progression for a strength exercise found in this workout.",
    "inputSchema": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "description": "Session UUID (activity or workout)."
        }
      }
    },
    "annotations": {
      "title": "Get Session Details",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_exercise_history",
    "description": "Search historical strength workouts for an exercise by name (case- and punctuation-insensitive). Returns one entry per session (newest first) with load_type (WEIGHTED, BODYWEIGHT, TIMED), top_set (set_number = 1-based position within the exercise, order = workout-wide running index, reps, weight_kg, duration_seconds), estimated_1rm_kg (Epley), total_volume_kg, total_reps, max_reps, total_duration_s and PR flags (weight, estimated_1rm, volume, reps, total_reps). USE WHEN: Evaluating long-term strength progression, personal records, or estimating 1RM for a specific exercise. DO NOT USE FOR: Cardio sessions or full workout summaries (use get_session_history or get_session_details).",
    "inputSchema": {
      "type": "object",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "type": "string",
          "description": "Exercise name (e.g. \"Bench press\", \"Knäböj\", \"Squats\")."
        },
        "days": {
          "type": "number",
          "description": "Lookback window in days (default 180, min 1, max 3650)."
        },
        "timezone": {
          "type": "string",
          "description": "IANA time zone for session dates (default \"Europe/Stockholm\")."
        }
      }
    },
    "annotations": {
      "title": "Get Exercise History",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_schedule",
    "description": "Get the user's recurring weekly training schedule template (single schedule per user). Returns plan array of recurring sessions. NOTE: The schedule is an optional weekly template guide—users train with or without a formal plan. For concrete dated events or races, use get_events. Each session has a stable UUID \"id\" for editing or deleting via upsert_schedule. USE WHEN: Inspecting the planned recurring routine. DO NOT USE FOR: Checking what was actually performed (use get_session_history).",
    "inputSchema": {
      "type": "object",
      "properties": {}
    },
    "annotations": {
      "title": "Get Training Schedule",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_schedule",
    "description": "Add, update, or delete items in the user's weekly schedule template, or replace the entire weekly schedule. NOTE: The schedule is an optional weekly template only (do NOT use for one-off dated events or races—use upsert_events). Log completed sessions via upsert_activities or upsert_workouts. Set replace_all: true to replace the entire weekly template (ideal when pasting an AI-generated schedule). Otherwise, provide \"id\" to update an existing session, omit \"id\" to create a new session (duplicate-checked), or pass { \"id\": \"\", \"delete\": true } to delete an item. When updating an item, workout_plan and days_of_week replace previous collections entirely. When type is \"WORKOUT\", workout_plan is required.",
    "inputSchema": {
      "type": "object",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array",
          "description": "Schedule plan items to upsert, create, or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Plan item UUID. Provide existing UUID to edit/delete (validated). Omit when creating a new session."
              },
              "activity_name": {
                "type": "string",
                "description": "Title of the scheduled session (e.g. \"Morgonjogg\", \"Benpass\"). Required when creating a new session."
              },
              "days_of_week": {
                "type": "array",
                "items": {
                  "type": "number"
                },
                "description": "ISO weekdays: 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday, 7=Sunday. Required when creating a new session. When updating, completely replaces previous days."
              },
              "frequency": {
                "type": "string",
                "enum": [
                  "WEEKLY",
                  "DAILY"
                ],
                "description": "Recurrence pattern (WEEKLY or DAILY). Weekly template only."
              },
              "type": {
                "type": "string",
                "enum": [
                  "RUN",
                  "CYCLE",
                  "MTB",
                  "WALK",
                  "HIKE",
                  "TRAIL_RUN",
                  "KAYAK",
                  "SUP",
                  "WORKOUT"
                ],
                "description": "Activity or workout type."
              },
              "scheduled_time": {
                "type": "string",
                "description": "Time of day in 24h format \"HH:MM\" (or null to clear)."
              },
              "description": {
                "type": "string",
                "description": "Details, targets, or workout notes (or null to clear)."
              },
              "workout_plan": {
                "type": "object",
                "description": "Structured workout plan (REQUIRED when type is \"WORKOUT\"). Contains exercises array. When updating, completely replaces the previous workout plan.",
                "properties": {
                  "exercises": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "name"
                      ],
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Exercise name (e.g. \"Bänkpress\")."
                        },
                        "name_normalized": {
                          "type": "string",
                          "description": "Normalized name (optional; derived server-side if omitted)."
                        },
                        "muscle_groups": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "CHEST",
                              "BACK",
                              "SHOULDERS",
                              "BICEPS",
                              "TRICEPS",
                              "FOREARMS",
                              "QUADS",
                              "HAMSTRINGS",
                              "GLUTES",
                              "CALVES",
                              "CORE"
                            ]
                          },
                          "description": "Target muscle groups."
                        },
                        "sets": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "order"
                            ],
                            "properties": {
                              "order": {
                                "type": "number",
                                "description": "Set index (1, 2, 3...)."
                              },
                              "reps": {
                                "type": "number",
                                "description": "Target reps (e.g. 5, 8)."
                              },
                              "weight_kg": {
                                "type": "number",
                                "description": "Target weight in kg (omit/null for bodyweight)."
                              },
                              "duration_seconds": {
                                "type": "number",
                                "description": "Duration in seconds for timed sets (e.g. 60)."
                              },
                              "comment": {
                                "type": "string",
                                "description": "Set notes or cues."
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "target_distance_m": {
                "type": "number",
                "description": "Target distance in meters for cardio (e.g. 5000 for 5 km, 10000 for 10 km). Null to clear."
              },
              "target_duration_s": {
                "type": "number",
                "description": "Target duration in seconds (e.g. 1800 for 30 min, 3600 for 60 min). Null to clear."
              },
              "allow_duplicate": {
                "type": "boolean",
                "description": "Set true to intentionally add a new session even if another session with the same name already exists on that weekday."
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with existing \"id\" to remove this specific schedule item."
              }
            }
          }
        },
        "replace_all": {
          "type": "boolean",
          "description": "If true, replaces the ENTIRE weekly schedule template with the provided items. Ideal when pasting or recreating a full schedule generated by an AI."
        }
      }
    },
    "annotations": {
      "title": "Upsert Schedule",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "delete_schedule",
    "description": "DESTRUCTIVE: Deletes the user's entire training schedule (all plan items). Requires { \"confirm\": true }. To delete individual items instead, call upsert_schedule with { \"id\": \"\", \"delete\": true }.",
    "inputSchema": {
      "type": "object",
      "required": [
        "confirm"
      ],
      "properties": {
        "confirm": {
          "type": "boolean",
          "description": "Explicit confirmation flag. Must be true to proceed."
        }
      }
    },
    "annotations": {
      "title": "Delete Full Schedule",
      "readOnlyHint": false,
      "destructiveHint": true,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_events",
    "description": "Get scheduled milestone events, competitions, races, and training camps. Returns active upcoming events and recent completed events.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "include_completed": {
          "type": "boolean",
          "description": "Include completed events (default true)."
        },
        "completed_limit": {
          "type": "number",
          "description": "Max completed events (default 5)."
        },
        "since_date": {
          "type": "string",
          "description": "Filter completed events on or after ISO date (YYYY-MM-DD)."
        }
      }
    },
    "annotations": {
      "title": "Get Events",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_events",
    "description": "Add, update, or delete milestone events, competitions, and races. Use to register upcoming races with targets or record overall reflections after completion. Set delete: true with id to remove.",
    "inputSchema": {
      "type": "object",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array",
          "description": "Events to upsert or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Event UUID. Omit to create; provide to edit/delete."
              },
              "name": {
                "type": "string",
                "description": "Event name (e.g. \"Göteborgsvarvet\")."
              },
              "description": {
                "type": "string",
                "description": "Race goals or targets (e.g. \"Target: sub 1h45m\")."
              },
              "date": {
                "type": "string",
                "description": "ISO date string (YYYY-MM-DD) or datetime."
              },
              "scheduled_time": {
                "type": "string",
                "description": "Start time (e.g. \"10:00\")."
              },
              "type": {
                "type": "string",
                "enum": [
                  "RUN",
                  "CYCLE",
                  "MTB",
                  "WALK",
                  "HIKE",
                  "TRAIL_RUN",
                  "KAYAK",
                  "SUP",
                  "WORKOUT"
                ],
                "description": "Sport type."
              },
              "completed": {
                "type": "boolean",
                "description": "Whether the event is completed."
              },
              "completed_at": {
                "type": "string",
                "description": "ISO datetime when completed."
              },
              "comment": {
                "type": "string",
                "description": "Overall reflection or result of the race."
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with existing id to delete this event."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Events",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_workouts",
    "description": "Add, update, or delete completed strength / resistance gym workouts in training history. Exercises are automatically registered in the user's catalog. Set delete: true with id to remove a workout.",
    "inputSchema": {
      "type": "object",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array",
          "description": "List of workouts to upsert or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Workout UUID. Optional; omit to create new."
              },
              "name": {
                "type": "string",
                "description": "Workout title (e.g. \"Upper Body Strength\", \"Leg Day\")."
              },
              "performed_at": {
                "type": "string",
                "description": "ISO 8601 datetime or date (e.g. \"2026-10-04T17:00:00Z\")."
              },
              "duration_seconds": {
                "type": "number",
                "description": "Duration in seconds (e.g. 3600 for 1h)."
              },
              "notes": {
                "type": "string",
                "description": "Session notes or reflections."
              },
              "exercises": {
                "type": "array",
                "description": "Exercises performed in this workout.",
                "items": {
                  "type": "object",
                  "required": [
                    "name"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Exercise name (e.g. \"Bänkpress\", \"Squats\")."
                    },
                    "muscle_groups": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "CHEST",
                          "BACK",
                          "SHOULDERS",
                          "BICEPS",
                          "TRICEPS",
                          "FOREARMS",
                          "QUADS",
                          "HAMSTRINGS",
                          "GLUTES",
                          "CALVES",
                          "CORE"
                        ]
                      },
                      "description": "Target muscle groups."
                    },
                    "sets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "order"
                        ],
                        "properties": {
                          "order": {
                            "type": "number",
                            "description": "Workout-wide running index across ALL exercises in this workout (1, 2, 3... continuing from the previous exercise), not a per-exercise set number."
                          },
                          "reps": {
                            "type": "number",
                            "description": "Reps completed (e.g. 8)."
                          },
                          "weight_kg": {
                            "type": "number",
                            "description": "Weight in kg. Omit/null for bodyweight; use 0 only for an explicit 0 kg load."
                          },
                          "duration_seconds": {
                            "type": "number",
                            "description": "Duration in seconds for timed sets (e.g. 45s plank)."
                          },
                          "comment": {
                            "type": "string",
                            "description": "Set notes (e.g. \"RPE 8\")."
                          }
                        }
                      }
                    }
                  }
                }
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with existing id to delete this workout."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Workouts",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_activities",
    "description": "Add, update, or delete completed cardio / endurance sessions in training history (running, cycling, MTB, paddling, hiking). Protects existing GPS tracks from overwrite. Set delete: true with id to remove.",
    "inputSchema": {
      "type": "object",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array",
          "description": "List of cardio activities to upsert or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Activity UUID. Optional; omit to create new."
              },
              "name": {
                "type": "string",
                "description": "Activity title (e.g. \"Morgonjogg 10k\")."
              },
              "started_at": {
                "type": "string",
                "description": "ISO 8601 datetime (e.g. \"2026-10-04T08:00:00Z\")."
              },
              "type": {
                "description": "Activity sport type: string name (e.g. \"RUN\", \"CYCLE\", \"MTB\") or numeric ID from get_activity_types (e.g. 1=RUN, 2=CYCLE)."
              },
              "duration_s": {
                "type": "number",
                "description": "Total duration in seconds."
              },
              "distance_m": {
                "type": "number",
                "description": "Total distance in meters (e.g. 10000 for 10 km)."
              },
              "moving_time_s": {
                "type": "number",
                "description": "Moving time in seconds."
              },
              "elevation_gain_m": {
                "type": "number",
                "description": "Elevation gain in meters."
              },
              "notes": {
                "type": "string",
                "description": "Session notes or reflections."
              },
              "stats": {
                "type": "object",
                "description": "Optional summary stats (avg_speed_ms, max_speed_ms, elevation_loss_m, splits).",
                "properties": {
                  "avg_speed_ms": {
                    "type": "number",
                    "description": "Average speed in m/s (e.g. 3.33 m/s = 5:00 min/km)."
                  },
                  "max_speed_ms": {
                    "type": "number",
                    "description": "Max speed in m/s."
                  },
                  "elevation_loss_m": {
                    "type": "number",
                    "description": "Elevation loss in meters."
                  }
                }
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with existing id to delete this activity."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Activities",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_exercises",
    "description": "Get the user's catalog of known strength exercises and their mapped muscle groups (e.g. Bänkpress -> CHEST, TRICEPS).",
    "inputSchema": {
      "type": "object",
      "properties": {
        "include_archived": {
          "type": "boolean",
          "description": "Include archived/hidden exercises (default false)."
        }
      }
    },
    "annotations": {
      "title": "Get Exercise Register",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_exercises",
    "description": "Add, update muscle mappings, or archive exercises in the user's catalog.",
    "inputSchema": {
      "type": "object",
      "required": [
        "exercises"
      ],
      "properties": {
        "exercises": {
          "type": "array",
          "description": "Exercises to add or update.",
          "items": {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string",
                "description": "Exercise name."
              },
              "muscle_groups": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "CHEST",
                    "BACK",
                    "SHOULDERS",
                    "BICEPS",
                    "TRICEPS",
                    "FOREARMS",
                    "QUADS",
                    "HAMSTRINGS",
                    "GLUTES",
                    "CALVES",
                    "CORE"
                  ]
                },
                "description": "Target muscle groups."
              },
              "archived": {
                "type": "boolean",
                "description": "Set true to archive exercise from suggestions."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Exercises",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "get_health_metrics",
    "description": "Get the user's health metric definitions (weight, waist, calories, water), target values/deadlines, and recent logged measurements.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "days": {
          "type": "number",
          "description": "Days of history entries to return (default 30, max 365)."
        },
        "include_archived": {
          "type": "boolean",
          "description": "Include archived metrics (default false)."
        },
        "metric_id": {
          "type": "string",
          "description": "Optional filter by metric ID (e.g. \"weight\", \"waist\")."
        },
        "limit": {
          "type": "number",
          "description": "Max history entries to return (default 100)."
        }
      }
    },
    "annotations": {
      "title": "Get Health Metrics",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_health_metrics",
    "description": "Create or update health metric definitions (targets, units, reminder periodicity). Set delete: true with id to delete custom metrics.",
    "inputSchema": {
      "type": "object",
      "required": [
        "metrics"
      ],
      "properties": {
        "metrics": {
          "type": "array",
          "description": "List of health metrics to upsert or delete.",
          "items": {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Metric ID (e.g. \"weight\", \"waist\", or custom ID). Omit for auto-slug."
              },
              "name": {
                "type": "string",
                "description": "Display name (e.g. \"Vikt\", \"Midja\")."
              },
              "category": {
                "type": "string",
                "enum": [
                  "BODY_COMP",
                  "MEASUREMENT",
                  "NUTRITION",
                  "CUSTOM"
                ],
                "description": "Metric category."
              },
              "unit": {
                "type": "string",
                "description": "Unit of measurement (e.g. \"kg\", \"cm\", \"kcal\", \"ml\")."
              },
              "target_value": {
                "type": "number",
                "description": "Target goal value (e.g. 75.0)."
              },
              "target_date": {
                "type": "string",
                "description": "Target deadline in ISO 8601 (YYYY-MM-DD)."
              },
              "periodicity": {
                "type": "string",
                "enum": [
                  "NONE",
                  "DAILY",
                  "WEEKLY",
                  "MONTHLY"
                ],
                "description": "Reminder periodicity."
              },
              "reminder_days": {
                "type": "string",
                "description": "Comma-separated day indices (1=Mon..7=Sun, e.g. \"1,3,5\")."
              },
              "reminder_time": {
                "type": "string",
                "description": "24h reminder time (e.g. \"08:00\")."
              },
              "is_archived": {
                "type": "boolean",
                "description": "Archive flag."
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with id to delete a custom metric."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Health Metrics",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "log_health_entries",
    "description": "Log one or more health measurements (weight, waist, calories, water) with ISO 8601 performed_at timestamps. Set delete: true with id to delete an entry.",
    "inputSchema": {
      "type": "object",
      "required": [
        "entries"
      ],
      "properties": {
        "entries": {
          "type": "array",
          "description": "List of health entries to log or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Entry UUID. Omit to create; provide to edit/delete."
              },
              "metric_id": {
                "type": "string",
                "description": "Metric ID (e.g. \"weight\", \"waist\", \"calories\")."
              },
              "value": {
                "type": "number",
                "description": "Recorded numerical value (e.g. 78.5)."
              },
              "performed_at": {
                "type": "string",
                "description": "ISO 8601 timestamp (e.g. \"2026-10-04T08:00:00Z\"). Defaults to now."
              },
              "comment": {
                "type": "string",
                "description": "Optional user note."
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with id to delete this entry."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Log Health Entries",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": false,
      "openWorldHint": false
    }
  },
  {
    "name": "get_goals",
    "description": "Get the user's overarching training and fitness goals. Active goals are ordered by sort_order (0 = primary focus banner on mobile dashboard).",
    "inputSchema": {
      "type": "object",
      "properties": {
        "include_completed": {
          "type": "boolean",
          "description": "Include completed goals (default true)."
        }
      }
    },
    "annotations": {
      "title": "Get Goals",
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "upsert_goals",
    "description": "Add, update, reorder, complete, or delete overarching user ambitions. Provide id to edit/delete, omit id to add. Lower sort_order indicates higher priority.",
    "inputSchema": {
      "type": "object",
      "required": [
        "goals"
      ],
      "properties": {
        "goals": {
          "type": "array",
          "description": "Goals to add, update, or delete.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Goal UUID. Omit to create; provide to edit/delete."
              },
              "text": {
                "type": "string",
                "description": "Goal ambition text (e.g. \"Klara Göteborgsvarvet under 1:45\")."
              },
              "is_completed": {
                "type": "boolean",
                "description": "Mark true when goal is completed."
              },
              "completed_at": {
                "type": "string",
                "description": "ISO datetime when completed."
              },
              "sort_order": {
                "type": "number",
                "description": "Priority sort order (0 = top priority banner)."
              },
              "delete": {
                "type": "boolean",
                "description": "DESTRUCTIVE: Set true with id to delete this goal."
              }
            }
          }
        }
      }
    },
    "annotations": {
      "title": "Upsert Goals",
      "readOnlyHint": false,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  }
]