Model Context Protocol

Agent integrations (MCP)

Connect Plately to ChatGPT, Claude, Cursor, or any MCP-compatible client. Every tool runs as the authenticated user — per-user data is enforced by Row-Level Security.

Endpoint

MCP Streamable HTTP endpoint

https://plately.site/mcp

The endpoint speaks MCP over Streamable HTTP. POST requests must sendAccept: application/json, text/event-stream(compatible MCP clients do this automatically).

OAuth setup

Auth is OAuth 2.1 — external clients discover, register, and obtain user-scoped tokens automatically via Supabase Auth as the authorization server. There is no manual API key to paste; the client walks you through sign-in on your first connection.

  1. In your MCP client (ChatGPT, Claude Desktop, Cursor, etc.) add a new Custom MCP server and paste the endpoint above.
  2. The client discovers Plately's authorization server at/.well-known/oauth-protected-resourceand opens a browser window.
  3. Sign in to Plately (or create an account) — the login page preserves the consent redirect via next=.
  4. On the consent screen at /.lovable/oauth/consent, approve the client. It receives an access token scoped to your user.
  5. All future tool calls act as you; Row-Level Security enforces access to your profile, plans, meal logs, weight, water, and subscription.
Never paste your app-session bearer token or a Supabase key as the "API key" — MCP tokens must go through the OAuth flow. Copied session tokens are rejected (missing client_id claim).

Login redirects (next= behavior)

When an MCP client opens Plately for consent, an unauthenticated visitor is sent to/login with a?next= parameter that carries the full consent URL (including authorization_id).

  • Same-origin only. next is validated as a relative path on plately.site; anything else is dropped and the user lands on the dashboard.
  • Consumed on every auth path. Password sign-in, email sign-up (emailRedirectTo), and Google OAuth (redirect_uri) all honor next, so users always return to the consent screen — never the app home page.
  • Approve or deny then bounces back to the MCP client via the authorization server's redirect URL. Nothing sensitive is placed in the URL.
  • If you visit /login without next, sign-in goes to /dashboard as usual.

Available tools

get_profileGet profile
user-scoped
read-only

Return the signed-in user's Plately profile (name, goal, targets, preferences).

Input

No parameters.

Output

{ profile: { id, full_name, goal, daily_calorie_target, food_preference, ... } }
get_today_planGet today's diet plan
user-scoped
read-only

Most recently generated AI diet plan (title, calories, meals, tips, highlights).

Input

No parameters.

Output

{ plan: { id, title, daily_calories, plan_data: DietPlan, created_at } } | text: 'No diet plan generated yet.'
generate_diet_planGenerate AI diet plan
user-scoped
write

Generate a personalized 1-day plan accounting for allergies and medical conditions. Returns BMI, macros, 5 tips, personalized health highlights (good/safe/avoid), and breakfast/lunch/snack/dinner. Enforces one plan per 5AM→5AM day; if a plan already exists it is returned with reused: true.

Input

  • age* : integer 5–110
  • gender* : male | female | other
  • weight_kg* : number 20–300
  • height_cm* : number 80–250
  • goal* : weight_loss | weight_gain | maintenance | muscle_gain
  • activity_level* : sedentary | light | moderate | active | very_active
  • food_preference* : veg | non-veg | jain | vegan
  • cuisine : indian | gujarati | south-indian | punjabi | globaldefault: indian
  • allergies : string ≤500e.g. 'peanuts, dairy'
  • diseases : string ≤500e.g. 'diabetes, fatty liver'
  • language : string ≤8en, hi, gu, mr, ta, te, bn, es, ar

Output

{ plan: DietPlan, plan_id: uuid, reused: boolean } — DietPlan = { title, daily_calories, macros, bmi, bmi_category, tips[], health_highlights[], days[{ day, meals: {breakfast,lunch,snack,dinner} }] }
list_meal_logsList meal logs
user-scoped
read-only

Logged meals for a given date (defaults to today).

Input

  • date : YYYY-MM-DDdefaults to today

Output

{ meals: MealLog[] }
log_mealLog a meal
user-scoped
write

Add a meal entry (recalculates remaining calories in the app).

Input

  • name* : string 1–120
  • meal_type* : breakfast | lunch | dinner | snack
  • calories* : number 0–5000
  • protein_g : number 0–500
  • carbs_g : number 0–1000
  • fat_g : number 0–500
  • date : YYYY-MM-DD

Output

{ meal: MealLog }
log_weightLog body weight
user-scoped
write

Save a weight entry (kg).

Input

  • weight_kg* : number 20–400
  • date : YYYY-MM-DD

Output

{ entry: WeightLog }
set_water_glassesSet water glasses (today)
user-scoped
write

Upsert today's water intake (glasses). Idempotent.

Input

  • glasses* : integer 0–50

Output

{ entry: WaterLog }
get_subscription_statusGet subscription status
user-scoped
read-only

Current Plately subscription (plan, status, renewal date).

Input

No parameters.

Output

{ subscription: { plan, status, current_period_end } | null }

Example: generate_diet_plan over MCP

A full round-trip from an MCP client (ChatGPT / Claude / Cursor) callinggenerate_diet_plan, followed by the structured response the tool returns. This is exactly the shape you'll receive — use it to preview how highlights and the daily meal schedule are formatted.

1. Tool call (MCP JSON-RPC)

POST https://plately.site/mcp
Authorization: Bearer <oauth-access-token>
Accept: application/json, text/event-stream
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "generate_diet_plan",
    "arguments": {
      "age": 34,
      "gender": "male",
      "weight_kg": 82,
      "height_cm": 176,
      "goal": "weight_loss",
      "activity_level": "moderate",
      "food_preference": "veg",
      "cuisine": "indian",
      "allergies": "peanuts",
      "diseases": "type 2 diabetes, fatty liver",
      "language": "en"
    }
  }
}

2. Tool response (result.structuredContent)

{
  "plan_id": "0a4c1e9b-77d2-4c1a-9c1f-8a2f6b0d1e42",
  "reused": false,
  "plan": {
    "title": "Diabetes-friendly veg day for steady weight loss",
    "daily_calories": 1750,
    "macros": { "protein_g": 110, "carbs_g": 170, "fat_g": 55 },
    "bmi": 26.5,
    "bmi_category": "Overweight",
    "tips": [
      "Eat protein first at every meal to blunt glucose spikes.",
      "Swap white rice for millet or quinoa at lunch.",
      "Walk 10–15 min after each main meal.",
      "Keep dinner light and finish by 8 PM.",
      "Hydrate: 8–10 glasses of water spread across the day."
    ],
    "health_highlights": [
      {
        "title": "Won't spike blood sugar",
        "detail": "Low-GI grains (oats, millet) + protein pairing keeps post-meal glucose steady.",
        "tag": "good",
        "related": "type 2 diabetes"
      },
      {
        "title": "Liver-friendly fats",
        "detail": "Uses olive oil, nuts (no peanuts), and avoids fried food to reduce fatty liver load.",
        "tag": "good",
        "related": "fatty liver"
      },
      {
        "title": "Peanut-free — safe",
        "detail": "All snacks and gravies use almonds/cashews or seeds instead of peanuts.",
        "tag": "safe",
        "related": "peanuts"
      },
      {
        "title": "Avoid added sugar & sweetened drinks",
        "detail": "Skip mithai, packaged juice, and sugary chai — they undo the calorie deficit.",
        "tag": "avoid",
        "related": "type 2 diabetes"
      }
    ],
    "days": [
      {
        "day": "Today",
        "meals": {
          "breakfast": {
            "name": "Vegetable oats chilla with mint chutney",
            "items": [
              "2 oats-besan chillas with grated carrot & spinach",
              "2 tbsp mint-coriander chutney (no peanuts)",
              "1 cup unsweetened masala chai"
            ],
            "calories": 380
          },
          "lunch": {
            "name": "Millet thali with dal & sabzi",
            "items": [
              "2 bajra rotis",
              "1 katori moong dal tadka",
              "1 katori bhindi masala (olive oil)",
              "1 bowl cucumber-tomato salad",
              "150 g low-fat curd"
            ],
            "calories": 560
          },
          "snack": {
            "name": "Roasted chana & almonds",
            "items": [
              "30 g roasted chana",
              "10 almonds",
              "1 cup green tea"
            ],
            "calories": 210
          },
          "dinner": {
            "name": "Paneer bhurji with sautéed greens",
            "items": [
              "120 g paneer bhurji (low-oil)",
              "1 bowl sautéed palak & beans",
              "1 multigrain roti",
              "Warm water with lemon"
            ],
            "calories": 600
          }
        }
      }
    ]
  }
}

Reused plans: if the user already generated a plan in the current 5 AM → 5 AM window, the same shape returns withreused: true and the existingplan_id — no new AI call is made.

Errors

  • Not authenticated — the OAuth token is missing or expired; reconnect.
  • You already have a plan for today...generate_diet_plan returns your existing plan with reused: true.
  • AI rate limit reached / AI credits exhausted — retry later or top up workspace credits.
  • Validation errors follow Zod format: [{ path, message, code }].

Try it — live MCP call

Sign in required. This runs the same server logic the MCP tool executes and records the call in your profile's MCP history.

Try it — generate_diet_plan
Preview the exact response an MCP client sees. This calls the same server logic as the tool.