Developers
Celestial MCP server
Celestial exposes a Model Context Protocol (MCP) server so AI agents can read and write a person's own Celestial data on their behalf. Every call is authenticated as a real Celestial user and scoped to that user's rows — there is no anonymous access and no cross-account access.
Endpoint
Streamable HTTP
https://www.celestial-app.life/mcpTransport: MCP Streamable HTTP. POST requests must send Accept: application/json, text/event-stream.
Authentication
OAuth 2.1 with dynamic client registration and PKCE. Clients discover the authorization server from /.well-known/oauth-protected-resource, register themselves, and send the user through Celestial's consent screen. The issued access token is forwarded on every tool call, and database access runs as that user under row-level security.
- Claude / ChatGPT: add a custom connector with the URL above and complete the sign-in prompt.
- Cursor / Codex: add an MCP server entry of type
httppointing at the same URL. - Copied app session tokens are rejected — only tokens minted through the OAuth flow are accepted.
Rate limits and logging
- 30 tool calls per minute and 500 per hour, per user.
- 10 per minute for
add_diary_entryandget_daily_affirmation(these write or generate content). - Over the limit, a tool returns an error result reading “Rate limit reached… Please wait and try again.” — retry after the window rolls over.
- Each call is logged with the tool name, outcome, duration and a truncated error only. Diary text, profile answers and access tokens are never written to the log, and the log is readable only by the user it belongs to.
Tools
get_profile
Get my Celestial profile
Display name, zodiac sign, birth details, timezone and onboarding state for the signed-in user.
Input
{} — no argumentsExample request (tools/call params)
{ "name": "get_profile", "arguments": {} }Example structured response
{
"profile": {
"display_name": "Paul",
"zodiac_sign": "Scorpio",
"birth_date": "1990-11-07",
"birth_time": "07:20",
"birth_place": "Dublin, Ireland",
"timezone": "Europe/Paris",
"onboarding_complete": true
}
}list_diary_entries
List my diary entries
Most recent entries, newest first. Notes are decrypted server-side for the owner only.
Input
limit: integer 1–30 (default 7)Example request (tools/call params)
{ "name": "list_diary_entries", "arguments": { "limit": 3 } }Example structured response
{
"entries": [
{ "id": "8f2…", "entry_date": "2026-08-18", "mood": "steady", "energy": 4,
"moment": "gratitude", "note": "Grateful for a quiet morning." },
{ "id": "1a7…", "entry_date": "2026-08-17", "mood": "tender", "energy": 2,
"moment": "hard_day", "note": "Long day, felt stretched thin." }
]
}search_diary_entries
Search and summarise my diary
Filter by date range, mood and emotion keywords, then return matches plus a computed summary. Keyword matching happens after decryption, so encrypted notes are searchable without ever being stored in plaintext.
Input
from: YYYY-MM-DD · to: YYYY-MM-DD · keywords: string[] (max 10) · moods: string[] (max 10) · limit: 1–60 (default 30)Example request (tools/call params)
{
"name": "search_diary_entries",
"arguments": {
"from": "2026-08-01",
"to": "2026-08-18",
"keywords": ["anxious", "tired", "grateful"],
"limit": 30
}
}Example structured response
{
"summary": {
"matches": 6,
"scanned": 18,
"date_range": { "from": "2026-08-03", "to": "2026-08-18" },
"mood_distribution": { "tender": 3, "steady": 2, "bright": 1 },
"average_energy": 3.2,
"recurring_themes": [ { "word": "sleep", "count": 4 }, { "word": "work", "count": 3 } ],
"highlights": [
{ "entry_date": "2026-08-14", "mood": "tender",
"excerpt": "Anxious before the review, calmer once I wrote it down…" }
]
},
"entries": [ /* full matching entries, newest first */ ]
}add_diary_entry
Add a diary entry
Creates or updates the entry for a date. The note is encrypted with AES-256-GCM before it is stored. Limited to 10 calls per minute.
Input
mood: string (required) · energy: 1–5 (default 3) · note: string ≤2000 chars · entry_date: YYYY-MM-DDExample request (tools/call params)
{
"name": "add_diary_entry",
"arguments": { "mood": "hopeful", "energy": 4, "note": "Started the morning walk again." }
}Example structured response
{ "entry": { "id": "c31…", "entry_date": "2026-08-18", "mood": "hopeful", "energy": 4 } }get_daily_affirmation
Get today's affirmation
Today's reading, affirmation and focus for the user's local date. Generated from the live sky and recent diary if not cached yet. Limited to 10 calls per minute.
Input
refresh: boolean (default false) — regenerate instead of using the cached readingExample request (tools/call params)
{ "name": "get_daily_affirmation", "arguments": { "refresh": false } }Example structured response
{
"reading": {
"reading_date": "2026-08-18",
"reading": "The Moon in Capricorn steadies the week…",
"affirmation": "I build slowly, and what I build holds.",
"focus": "One unfinished thing, finished today."
}
}get_weekly_reflection
Get my latest weekly reflection
The most recent synthesised week: narrative, growth themes, attention points, next steps, affirmation.
Input
{} — no argumentsExample request (tools/call params)
{ "name": "get_weekly_reflection", "arguments": {} }Example structured response
{
"reflection": {
"week_start": "2026-08-10",
"narrative": "This week moved from scattered to settled…",
"growing": ["Consistency with mornings"],
"attention": ["Rest before the week's midpoint"],
"next_steps": ["Write one gratitude line before bed"],
"affirmation": "Steadiness is a skill I am practising.",
"stats": { "entries": 5, "streak": 12, "avg_energy": 3.4 }
}
}get_horoscope_advice
Get this week's horoscope advice
Current sky read for the user's sign, plus growth themes and next steps from their latest weekly reflection when one exists.
Input
{} — no argumentsExample request (tools/call params)
{ "name": "get_horoscope_advice", "arguments": {} }Example structured response
{
"advice": {
"sign": "Scorpio",
"sky": { "date": "2026-08-18", "moon_phase": "Waxing Gibbous", "summary": "Sun in Leo, Moon in Capricorn…" },
"sky_advice": "The Moon moves through Capricorn — momentum you start now carries further than usual.",
"weekly_reflection": { "week_start": "2026-08-10", "next_steps": ["Write one gratitude line before bed"] }
}
}Privacy
Diary notes and questionnaire answers are stored encrypted with AES-256-GCM and are decrypted only inside a request carrying that user's own verified token. Granting an agent access means that agent can read those decrypted entries — revoke it at any time by disconnecting the connector.