Skip to main content
Glama
Skylight MCP Server
by dwooods

Skylight MCP Server

An MCP (Model Context Protocol) server for the Skylight Calendar. Lets Claude (including Claude Duet, via the hosted mode) read and plan against your family calendar, chores, lists, meals and rewards.

Unofficial. This project is not affiliated with or endorsed by Skylight. Skylight has no public API; this talks to the same private endpoints their own apps use, discovered by observing app traffic. It can stop working or be blocked at any time, without notice. Use it with your own account, at your own risk, and keep request volume modest.

Sign-in reuses the Skylight mobile app's own OAuth flow: it presents the app's client ID (skylight-mobile) and redirect, because Skylight issues no client of its own to third parties. Skylight's Terms of Service prohibit access by means other than its supported interfaces and reverse engineering (§5.4), and let Skylight suspend accounts with or without cause (§16). Using this project is a risk to the Skylight account you sign in with, not only to the integration.

Forked from TheEagleByte/skylight-mcp (MIT). The sign-in and credential-store design follows kamilio/skylight-calendar-agent (MIT). See THIRD_PARTY_NOTICES.md.

Features

  • Calendar: read events and connected calendars; create, update and delete events

  • Planning: one-call week overview, overlap detection, free-slot search, bulk meal planning

  • Meals (Plus): see, add, rename, move and delete scheduled meals; browse and edit recipes

  • Messages: sending to specific devices, scheduling, repeating, voice notes, editing a message that was sent to specific profiles (the app's edit form does not allow changing recipients), and read-aloud (the option exists on send_message but was not tested live).

  • Chores and tasks: read, create, update and delete chores; add to the task box

  • Lists: read, create, update and delete lists and items

  • Family: read profiles, devices and household info

  • Rewards (Plus): read points and rewards; create, update, redeem and delete

See What is supported for what is tested, what is not, and what the hosted server leaves out.

Related MCP server: skylight-mcp

Quick Start

You need Node 20+, a Skylight account, and an MCP client (Claude desktop, Claude Code, or any other). Nothing to clone or build. Run the npx commands from any normal folder, not from inside a clone of this repo (see Troubleshooting).

Do I need the hosted server? Probably not. The steps below give you the local server: it runs on your own computer while your MCP client is open and exposes every tool. The hosted server (a Cloudflare Worker) is optional. You only need it if Claude Duet or Claude on another device has to reach Skylight when this computer is off. It means cloning the repo, a free Cloudflare account, npx wrangler login, npm run worker:setup, and a second sign-in, and it exposes read and write tools plus a short list of deletes (chores, lists, list items, rewards, recipes, meal sittings, messages; not calendar events). Do the local setup first; see Hosted server (Claude Duet, Claude on other devices) if you need it later.

1. Run the setup

npx -y @davidwoods/skylight-mcp init

init asks for your timezone (it offers the one your computer uses), runs the browser sign-in, finds your frame from your account, saves the frame ID and timezone to a small settings file, runs doctor, and prints the lines to paste into your MCP client. If your account has more than one frame it asks which; if it cannot list frames it asks for the number from the address bar (https://ourskylight.com/my-skylight/<number>; see Finding your Frame ID).

The sign-in works like this: init prints a Skylight URL and offers to open it: press Enter and your browser opens it (or open the URL yourself). Sign in there. The browser bounces through https://ourskylight.com/welcome?code=... and on to the home page too fast to copy. Get the link from your browser history: Cmd-Y (Mac) / Ctrl-H (PC), search welcome?code, right-click the Skylight result dated today (top of the list; older ones are earlier sign-ins and will not work), Copy link address, and paste it when init asks. Your password never touches this program; only the resulting OAuth tokens are stored, encrypted with a key in the macOS Keychain (plain 0600 file on Linux/Windows). macOS may ask once to allow Keychain access. If the Keychain is unusable, init stops; it never falls back to plaintext on macOS.

The settings file holds the frame ID and timezone only: no token, no host. It lives in ~/Library/Application Support/skylight-mcp/config.json (macOS), %APPDATA%\skylight-mcp\config.json (Windows) or ~/.config/skylight-mcp/config.json (elsewhere), mode 0600, and an unrecognised key makes the server refuse to start. Environment variables (SKYLIGHT_FRAME_ID, SKYLIGHT_TIMEZONE) override it. Run init again to change either value.

2. Add to your MCP client

Claude desktop (Settings → Desktop app → Local MCP servers → Edit config; older versions: Settings → Developer → Edit Config), or any client that uses mcp.json:

{
  "mcpServers": {
    "skylight": {
      "command": "npx",
      "args": ["-y", "@davidwoods/skylight-mcp"]
    }
  }
}

Claude Code:

claude mcp add skylight -- npx -y @davidwoods/skylight-mcp

Restart the client fully (Cmd-Q on Mac), then ask it "what's on the family calendar this week?"

3. Check it any time

npx -y @davidwoods/skylight-mcp doctor

doctor checks Node, the frame ID, the timezone, your sign-in and one real call to Skylight, and says what to fix. It never prints tokens or your frame ID. Add --offline to skip the network call.

What you can sync, and what this server can do

Skylight's Sync Calendar screen offers these. From the app's screen; the "this server" column is what changes here.

Option in Skylight

Add it

Manage it with this server

Calendar URL (team, school, league, iCloud published calendar)

skylight-mcp calendars add, or in the app

Rename, link to profiles, remove, list

Google, Outlook/Hotmail/Live, iCloud account, Cozi, TeamSnap

Sign in inside the Skylight app (cannot be done here)

List only

US Holidays, Individual Events

In the app

List only

Calendars from a subscription link are one-way: Skylight reads them and cannot write back.

Add a team, school or league calendar

npx -y @davidwoods/skylight-mcp calendars add

Paste the calendar's address when asked (the link ending in .ics, or starting with webcal://). Nothing is shown as you paste, and the address never goes into your shell history, a chat, or a log: it is a secret, because anyone with the link can read that calendar. Skylight fetches the feed itself, names the calendar from it, and the events appear on your frame. This is a command and deliberately not an MCP tool. To stop syncing one, ask your assistant to remove it (delete_source_calendar, which previews first), or remove it in the Skylight app. Google, Outlook, iCloud and Cozi accounts are connected in the Skylight app, not here.

Manual setup (without init)

If you would rather not use init, or it fails, set the two values yourself and sign in with the lower-level commands. Find your frame ID as above; the timezone is an IANA name such as America/Chicago and must be set: it defaults to America/New_York, and event times come out wrong anywhere else.

# macOS / Linux
export SKYLIGHT_FRAME_ID=your_frame_id
export SKYLIGHT_TIMEZONE=America/New_York
# Windows PowerShell:  $env:SKYLIGHT_FRAME_ID="your_frame_id"; $env:SKYLIGHT_TIMEZONE="America/New_York"
npx -y @davidwoods/skylight-mcp auth login
npx -y @davidwoods/skylight-mcp auth complete   # then paste the welcome?code= link

Terminal variables are not inherited by your MCP client. Put them in the client's env block instead: "env": {"SKYLIGHT_FRAME_ID": "your_frame_id", "SKYLIGHT_TIMEZONE": "America/New_York"} (Claude Code: -e SKYLIGHT_FRAME_ID=... -e SKYLIGHT_TIMEZONE=...). auth status and auth logout do what they say.

From source (contributors)

git clone https://github.com/dwooods/skylight-mcp.git
cd skylight-mcp && npm install && npm run build
node dist/index.js auth login    # same steps as above, using node dist/index.js

In the client config use "command": "node", "args": ["/path/to/skylight-mcp/dist/index.js"].

Windows (partly verified)

Verified on one Windows machine (Node 24): npx runs the package, doctor --offline works, auth login and auth complete finish the real sign-in, the credential is saved to %APPDATA%\skylight-mcp\credential.json, and the Claude desktop app runs the server from the config below and reads real calendar data. Not yet verified: doctor's Skylight check on Windows (it was broken on every platform in 1.7.0 and is fixed in 1.8.0), the live test suite, and worker:setup.

  • npx is a .cmd file on Windows, so in a client config use "command": "cmd", "args": ["/c", "npx", "-y", "@davidwoods/skylight-mcp"].

  • Set variables in PowerShell like this, then run the command on the next line: $env:SKYLIGHT_FRAME_ID="your_frame_id"; $env:SKYLIGHT_TIMEZONE="America/New_York".

  • In Windows Terminal you can hold Ctrl and click the sign-in URL. In the history search, right-click the result dated today and choose Copy link address.

  • The sign-in is stored unencrypted in %APPDATA%\skylight-mcp\credential.json. There is no Keychain equivalent wired in, and Windows ignores Unix 0600 permissions. Only your Windows user profile protects it.

Troubleshooting

Symptom

Likely cause and fix

'skylight-mcp' is not recognized (Windows) or skylight-mcp: command not found

You ran npx from inside a clone of this repo, so npx tried to run the local project, whose command is not linked. cd to any other folder and run it again. From a clone, use node dist/index.js instead.

Server fails to start, mentions configuration

No frame ID: run init (or doctor to see what is missing). An invalid settings file also stops the server; doctor names the problem.

"Not signed in"

Run auth login then auth complete. Logins expire after 10 minutes.

macOS Keychain error

The server refuses to fall back to plaintext. Unlock the Keychain or allow access when prompted.

Events show at the wrong hour

SKYLIGHT_TIMEZONE unset (defaults to New York). Set your zone.

Tools missing after an update

Fully quit and reopen the client; it caches the tool list. For a hosted connector use its "Refresh tools list".

Worked yesterday, fails today

Skylight has no public API and may have changed. Run doctor, then check the issues.

First five things to ask Claude

Once doctor is clean, try these in order. The first three only read. The last two show how the write guards work, so you see them before anything lands on your Skylight display.

  1. "What's on our family calendar this week?" Reads events (get_calendar_events). If times are off by hours, your SKYLIGHT_TIMEZONE is wrong.

  2. "Give me an overview of the week and point out any conflicts." One call that merges events, chores, meals and lists (get_week_overview, find_conflicts).

  3. "When are we all free for 90 minutes on Saturday?" Finds gaps around the fixed events (find_free_slots).

  4. "Plan dinners for Monday to Thursday, but do a dry run first." Shows what would be written and which slots are already filled (plan_week_meals). Nothing is written until you say so, and filled slots are never overwritten. Needs Skylight Plus.

  5. "Draft a message to everyone saying dinner is at 6, but don't send it yet." The send tool previews the exact text and posts nothing until Claude is told to confirm. Messages show on your display, so say yes only when you mean it.

If a tool you expected is missing, see the Troubleshooting table, and check "What is supported" for tools that are local-only or Plus-only.

Instructions for AI

Copy this into your AI's custom instructions or system prompt:

You have access to the Skylight MCP server. Skylight is a smart family calendar display that shows calendars, chores, grocery lists, meals, and rewards. Use the Skylight tools to help manage family schedules and organization.

Tips:

  • Call get_family_members before assigning chores to get member names

  • Grocery items default to the main grocery list if no list specified

  • Dates accept "today", "tomorrow", day names, or YYYY-MM-DD format

  • Some tools (rewards, meals, photos) require Skylight Plus subscription

Prerequisites

  • Node.js 20+

  • A Skylight account with an active subscription

  • Your Skylight Frame ID (see Finding your Frame ID)

Authentication

Sources are tried in this order:

  1. SKYLIGHT_TOKEN - an explicit token in the environment, if set.

  2. Stored OAuth credential (recommended) - created by skylight-mcp auth login / auth complete. The access token is refreshed automatically; refresh tokens rotate and the rotated token is persisted.

  3. SKYLIGHT_EMAIL + SKYLIGHT_PASSWORD (deprecated) - the server replays Skylight's web login form itself. This works but puts your password in your MCP client config in plaintext. Prefer the browser sign-in above.

If none is present the server fails with instructions rather than starting.

The browser sign-in is the mobile app's flow, not one Skylight offers to third parties: the server opens Skylight's own sign-in page with the app's client ID (skylight-mobile), PKCE (S256) and a state check, and you paste back the ourskylight.com/welcome address it lands on. Your password never reaches this project. Skylight could change or block this flow at any time.

Where the credential lives:

Platform

Location

Protection

macOS

~/Library/Application Support/skylight-mcp/credential.enc.json

AES-256-GCM; key in Keychain (skylight-mcp.encryption-key)

Linux / other

$XDG_CONFIG_HOME/skylight-mcp/credential.json (default ~/.config/skylight-mcp/)

0600 file in a 0700 directory, no encryption

Windows

%APPDATA%\\skylight-mcp\\credential.json

Not encrypted. Windows ignores 0600; only your user profile's own permissions protect it. Untested, see below.

If the Keychain is unavailable on macOS the server refuses to read or write the credential; it never silently downgrades to plaintext.

Finding your Frame ID

The frame ID is the household identifier. The easy way: after signing in, the Skylight web app lands on https://ourskylight.com/my-skylight/<number>. That number is your frame ID. Treat it as a secret.

The hard way, if that URL doesn't appear:

  1. Use a proxy tool (Proxyman, Charles, or mitmproxy)

  2. Capture any API request from the Skylight app

  3. Look at the URL path: /api/frames/{frameId}/...

  4. Example: /api/frames/abc123/chores → frame ID is abc123

Configuration

Variable

Required

Description

SKYLIGHT_TOKEN

No

Explicit API token; overrides the stored credential

SKYLIGHT_AUTH_TYPE

No

bearer (default) or basic (only with SKYLIGHT_TOKEN)

SKYLIGHT_EMAIL

No (deprecated)

Fallback email/password login

SKYLIGHT_PASSWORD

No (deprecated)

Fallback email/password login

SKYLIGHT_FRAME_ID

Yes, unless saved by init

Your household frame ID; overrides the settings file

SKYLIGHT_TIMEZONE

No

Default timezone; overrides the settings file (default: America/New_York)

Auth Notes

  • The API host is pinned to https://app.ourskylight.com. No environment variable or .env file can redirect requests (and the bearer token) elsewhere.

  • auth logout deletes the local credential only; Skylight has no public way to revoke a session, so change your password if a credential may have leaked.

  • Skylight has no official API. This uses the same OAuth client the Skylight app uses, and it may break or be blocked at any time.

Hosted server (Claude Duet, Claude on other devices)

The same code also runs as a remote MCP server on Cloudflare Workers, which is how Claude Duet (and any Claude client that can't reach your Mac) connects. One Worker is both the OAuth authorization server Claude talks to and the MCP resource server. Signing in is the same browser-paste flow as the CLI; your Skylight password never reaches the Worker, and the Skylight tokens are kept encrypted in the OAuth grant, not in a database you manage.

CAUTION

The hosted server can change and delete things other people own. Whoever (or whatever) holds the connection can create, edit and delete anything in the connected Skylight frame, including events on every Google calendar connected to it, not only the shared family one. That includes another person's personal Google calendar if it is connected to Skylight: a delete or edit there is made at Google, shows on their phone, and cannot be undone from this server. Google records the change as made by the account that is connected to Skylight, not by you or by the AI. Deleting a repeating event with scope all removes the whole series, past and future. Claude Duet does not ask before a destructive tool call, and the preview step is a parameter the model sets, not something the server enforces. Limits that do hold: 60 changes an hour, at most 10 of them deletes, and events from subscribed feeds are read-only. Check which calendars your frame syncs (get_source_calendars) before you connect a client you do not supervise, and remove delete_calendar_event from HOSTED_DESTRUCTIVE_ALLOWLIST if that is more access than you want to give.

Which tools the hosted server exposes, and why

The hosted server registers all read and create/update tools, plus these deletes: delete_chore, delete_list, delete_list_item, delete_reward, delete_recipe, delete_meal_sitting, delete_task_box_item, delete_message and delete_calendar_event (events created in Skylight or on a Google calendar, and repeating ones with an explicit scope; never subscribed feeds). It does not register delete_source_calendar, delete_label or photo uploads. The local (stdio) server registers everything. This is a deliberate choice, not a limitation of the Worker:

  • The hosted server is what Claude Duet drives proactively, sometimes unattended. Every allowlisted delete previews and deletes nothing unless confirm: true. That flag is set by the model, not by a person: the server cannot tell whether anyone said yes, and some clients do not prompt before a tool runs. The model is meant to show the exact target and wait for a yes, and it can be told to in its instructions, but nothing here enforces it. The server's hard limits are the write limiter (60 changes an hour, at most 10 deletes) and the fixed allowlist.

  • delete_source_calendar (removing a synced calendar) and adding a feed stay local-only: a feed address is a secret and a wider, rarer change than deleting one event.

  • Photo tools are uploads the Worker has no reason to carry.

The allowlist is one list, HOSTED_DESTRUCTIVE_ALLOWLIST in src/worker/mcp.ts. Add or remove a tool name there and redeploy. For full parity set HOSTED_EFFECTS to ["read", "write", "destructive"] and photos: true in the same file. Every tool's classification lives in src/tools/registry.ts, so you can also carve out a profile of your own (read-only, for example, is ["read"]).

If you run both servers in the Claude desktop app, Claude sees two sets of mostly duplicate tools and may use either for writes. Disable the local one in Settings → Connectors when you do not need calendar deletes or photo tools, or say "use the local Skylight server" when you do.

Deploy (once)

You need a free Cloudflare account. From a clone of this repo:

npm install
npx wrangler login
npm run worker:setup        # add -- --dry-run first to see the steps

worker:setup creates your KV namespace, writes a gitignored wrangler.local.jsonc with your real ID (the committed wrangler.jsonc keeps a placeholder, so nothing account-specific can be committed), asks you for a sign-in passphrase, deploys, sets WORKER_URL, deploys again and prints the connector URL. Re-deploy later with npm run worker:deploy:local.

Upgrading a Worker deployed before 1.13.1: add the change counter to your wrangler.local.jsonc (a new setup gets it automatically), then deploy:

"durable_objects": { "bindings": [{ "name": "WRITE_LIMITER", "class_name": "WriteLimiter" }] },
"migrations": [{ "tag": "v1-write-limiter", "new_sqlite_classes": ["WriteLimiter"] }],

Without it the Worker still runs, but its change limit counts in memory and limits nothing across requests. After a deploy, make a change and look for "limiter":"durable" in the Worker's logs.

Doing it by hand instead:

cp wrangler.jsonc wrangler.local.jsonc            # gitignored: your real IDs live only here
npx wrangler kv namespace create OAUTH_KV         # paste the id into wrangler.local.jsonc, not wrangler.jsonc
npx wrangler secret put SETUP_PASSPHRASE -c wrangler.local.jsonc   # 12+ chars; required to link an account
npm run worker:deploy:local                       # prints the Worker's URL
npx wrangler secret put WORKER_URL -c wrangler.local.jsonc   # paste that URL (origin only, no path)
npm run worker:deploy:local

WORKER_URL must be exactly the public origin of the Worker; every token is bound to it. It is a secret rather than a vars entry so the server's address is not published with the source.

Connect from Claude

In Claude (or Duet) → Settings → Connectors → Add custom connector:

  • Name: Skylight

  • URL: https://skylight-mcp.<your-subdomain>.workers.dev/mcp

Claude opens the consent page. Enter the setup passphrase, your frame ID and timezone, then follow the two-step Skylight sign-in and paste the redirect URL. Connectors are shared across your Claude account, so Duet sees it too.

The server also serves /setup (these steps, for the host it runs on) and /version (just the version number, handy for confirming a redeploy took).

What is stored where

Thing

Where

Protection

Skylight access + refresh tokens

OAuth grant props in OAUTH_KV

Encrypted by workers-oauth-provider; the key is derived from the token Claude holds, so KV alone is not enough

PKCE verifier during sign-in

Upstream transaction in OAUTH_KV

Bound to your browser by a __Host- cookie; single use; 10-minute TTL

Setup passphrase

Worker secret

Never in the repo or wrangler.jsonc

Nothing else

The Worker has no database and no logs of tokens

To revoke: remove the connector in Claude (revokes the grant), or npx wrangler kv key list --binding OAUTH_KV and delete, or change your Skylight password.

What is supported

Status vocabulary, used honestly:

  • Live-tested: run against a real Skylight frame by this project, with the result checked by reading back.

  • Inherited: came from the upstream project and works there, but this project has not re-run it live.

  • Mocked only: covered by this project's mocked tests; not yet run against real data.

Skylight has no public API. Everything below can break when Skylight ships a web release, which happens without notice. The web app version and API version last captured are recorded in the repository's build log.

Area

What works

Hosted server (Claude Duet)

Status

Calendar

Read events and source calendars; create (with profiles), update, delete events

All, delete included (preview first; never subscribed feed events). Removing a synced calendar or a label is local only

Read, create, update and delete live-tested, including repeating events (edit scopes one and all; delete scopes one, future and all), all-day series and a one-off event written to a Google calendar. Not yet live: a series written to Google

Planning

Week overview, conflicts, free slots, bulk meal plan

All four

All four live-tested (conflicts and free slots as reads; the bulk meal plan through the hosted server)

Meals (Plus)

Read categories and meals; create, rename, move, delete one-off meals

All, delete included

Live-tested

Recipes (Plus)

Read, create, update, delete recipes; push ingredients to the grocery list

All, delete included

Inherited

Messages

Read; post to everyone or to named profiles (silent by default); edit text and sender (everyone-messages only); delete

All four, delete included

Live-tested

Chores and routines

Read (routines marked, Up for Grabs included); create, update, delete chores; mark one occurrence of a routine or recurring chore done or not done

All, delete included

Read, create and delete live-tested; completion captured live, tool not yet run live; the rest inherited

Task box

List items; add a task; delete a template by id

Yes, delete included

List and delete live-tested; add inherited

Lists

Read lists and items; create, update, delete lists and items

All, delete included

Inherited

Family and devices

Profiles with IDs, avatars, colours, household info, devices

Yes

Profiles live-tested; the rest inherited

Rewards (Plus)

Read points (by profile) and rewards; create, update, redeem, unredeem, delete

All, delete included

Points read, create and delete live-tested; the rest inherited

Photos (Plus)

List albums

No

Inherited

Not supported

Nothing here is hidden behind a flag. It is either unavailable from Skylight or not yet captured.

  • Messages: sending to specific devices, scheduling, repeating, voice notes, and read-aloud (the option exists on send_message but was not tested live). Deleting works but the app has no delete button.

  • Meals: editing a repeating meal (refused), repeat rules other than weekly, deleting a meal that was edited on its own after being in a series (refused), saving a meal to the recipe box from the edit form, and Skylight's own "Plan Meals" feature.

  • Task box: editing or completing tasks, and saving a routine template to it.

  • Chores: completing a one-off (non-recurring) chore, Skip, daily or monthly routine schedules (only the weekly format has been captured), and editing a recurring chore's date, time, assignee or stars. Un-completing a routine cannot reduce its longest_streak. Whether "this and future" from a later day keeps the earlier days has not been checked (the capture started from the first day).

  • Profiles: creating or editing them. Read-only.

  • Settings, account, notifications, sleep schedule, device navigation: none of these are exposed.

  • Photos: uploads and anything beyond listing albums.

  • Accounts with more than one frame: the server is pinned to one frame ID.

  • Calendar feeds: adding one is a CLI command, skylight-mcp calendars add, and deliberately not an MCP tool, because the feed address is a secret and a tool argument would put it in the chat transcript. You paste it into a hidden prompt; only the calendar's name and host are printed. Linking a feed to a profile or label, changing which calendar new events are saved to, and adding Google, Outlook, iCloud or Cozi accounts (browser sign-in in the Skylight app) are not supported.

  • Credentials: sign-in, sign-out and token access are CLI commands (skylight-mcp auth ...) and are deliberately not MCP tools.

Keeping this honest

Every tool must appear in the tables below with the effect it really has, and a test fails if one is missing or mislabelled. When you add, change or remove a tool, update this section in the same change.

Available Tools

Effects: read changes nothing; write creates or edits and can be edited again; destructive cannot be undone from the API. The hosted server registers read and write tools plus a fixed list of deletes, each preview-first (see "Which tools the hosted server exposes, and why"); delete_source_calendar and delete_label exist on the local server alone.

Every tool refuses an argument it does not know and names it, so a misspelt argument is an error, never a call that quietly ran with defaults.

Planning Tools

Built for "what does the week look like and what is for dinner" questions. One call returns calendar, chores/tasks, meals and lists, merged per day.

Tool

Effect

Description

get_week_overview

read

Per-day events, chores/tasks (status, assignee, points), meals, overdue chores, conflicts and list summaries in one compact call. Omits owner emails and calendar IDs.

find_conflicts

read

Timed events that overlap in a date range. All-day events never conflict. A subscribed feed that lists the same event twice (same start, end and title apart from a trailing note such as "Arrive 20 minutes early") is reported separately as a duplicate, not a conflict.

find_free_slots

read

Gaps of at least N minutes inside a daily window (default 08:00 to 21:00).

plan_week_meals

write

Fill several meal slots at once. dryRun previews; occupied slots are skipped, never overwritten; all entries are validated before anything is written, and the text is checked: a placeholder such as (plan doc URL) refuses a real write, while an over-long name, a dessert over two words, non-ASCII characters or a cooking step in a note are reported as warnings that never block; optional grocery push for recipes. Entries can carry note and description (the app's "Instructions or ingredients" field), attached after the meal is created.

Times are computed in the frame's time zone, including DST changes.

Message Tools

Messages are the notes shown on the frame (Skylight's web app calls them "nudges").

Tool

Effect

Description

get_messages

read

Messages in a date range with time, text, recipients and sender. Never returns the presigned audio URLs.

send_message

write

Post a message to the frame now, on all devices. Previews by default and posts only with confirm: true. Read aloud is off unless asked for. to names the profiles to send to (see get_family_members); omit it for everyone. Optional sender profile. Up to 300 characters. The app has no delete button, but delete_message removes one.

update_message

write

Edit the text (and optionally the sender) of an existing message. Only messages sent to everyone on all devices that don't repeat; others must be edited in the app.

delete_message

destructive

Delete a message. The app has no delete button; this uses DELETE /nudges/{id}, documented by other Skylight clients and verified on a real frame. Available on both the local and hosted servers (the one destructive tool the hosted server offers). Previews unless confirm: true, then reads back and reports success only if the message is gone.

Calendar Tools

Tool

Effect

Description

get_calendar_events

read

Events for a date range

get_source_calendars

read

Connected calendar sources (Google, iCloud, etc.), with each one's role and whether it is editable. Private feed addresses are hidden: only the host is shown

delete_source_calendar

destructive

Stop syncing a subscribed calendar feed (a team, school or league schedule). Preview first, then confirm: true. Its events leave the family calendar and wall display until it is added again. Feeds only (kind: webcal); account calendars are refused. Local server only.

update_source_calendar_profiles

write

Link a subscribed calendar feed to family profiles, or unlink it (the "Link profiles" checkboxes). Preview first, then confirm: true; it sends the complete set so the calendar's label is kept, then reads it back. Feeds only (kind: webcal); a calendar can never be left with no profile or label.

rename_source_calendar

write

Rename a subscribed calendar feed as it appears in Skylight (feeds are named from the feed itself, often at length). Preview first, then confirm: true; reads it back and checks the linked profiles did not change. Feeds only (kind: webcal).

create_calendar_event

write

Add an event. profiles assigns it to named family members. Local times are sent with the frame's UTC offset. repeat (daily or weekly, ends by until or count, at most 104 occurrences) makes a series; a series is only previewed until confirm: true, is created on Skylight's own calendar by default (not written to Google), and is refused for multi-profile. An all-day series (allDay: true, one day per occurrence, endsAt the day after startsAt) is allowed (verified live 2026-11-09 on Skylight's own calendar). calendar (the name of a linked Google calendar, only when asked for) writes a one-off event or a series to that Google calendar instead, shows for everyone who shares it, and is also previewed until confirm: true; it refuses a read-only calendar and one whose account cannot be determined. A one-off event written to Google is verified live (2026-11-09); a series written to Google is not yet. dinner: true makes a free-tier "Dinner plan" instead (Skylight's stand-in for Meals on an account without Plus: an all-day event of kind meal, tagged "Dinner Plan" by Skylight; date only, no profiles, calendar or repeat); shape captured from the web app; the same request body verified live on a free account 2026-11-10 (create, read back, delete), the tool call itself not yet.

update_calendar_event

write

Change an event, including who it is assigned to (profiles). For a repeating event give the occurrence's date and a scope: one (that occurrence only, which becomes its own event) or all (the whole series; overwrites earlier single-occurrence edits). On a series you can change the title, the assignment and the time of day (startsAt and endsAt together, on the occurrence's date); the time change is verified live for both scopes (one detaches that occurrence as its own event; ids change, so re-read before the next call). Notes, location and all-day stay refused. There is no future scope: Skylight's API refuses it. Events on a Google calendar change at Google too.

delete_calendar_event

destructive

Delete one event, or part of a repeating one. Needs the event's date; preview first, then confirm: true. A repeating event needs a scope: one, future (this and later occurrences) or all (the whole series); the preview says which. Events on a Google calendar are deleted at Google too, for everyone who shares it. Refuses subscribed-feed events, non-editable events, an occurrence that was edited on its own, and a repeating event with no scope. Reads the day back to confirm it is gone. Also on the hosted server.

Chore Tools

Tool

Effect

Description

get_chores

read

Chores with their ids, with optional filters (date, assignee, status)

create_chore

write

Create a one-off chore for one family member (assignee required; Skylight rejects a chore with no profile). Repeating tasks: create_routine

update_chore

write

Rename, reschedule, reassign a one-off chore. For recurring chores and routines only a rename and a weekly schedule (days + timeOfDay) are supported; a schedule change needs acknowledgeReset: true because it can reset streak history, and Skylight re-keys the chore (the reply gives the new id). Completion goes through complete_chore.

create_routine

write

Create a weekly routine (morning, afternoon or evening) for one or more profiles, via create_multiple. Optional habit tracking and stars. Weekly schedules only.

complete_chore

write

Mark one occurrence of a routine or recurring chore done, or undo it. Previews unless confirm: true; awards real stars and streaks on the family display. Recurring chores only.

delete_chore

destructive

Delete a chore. Previews unless confirm: true. Recurring chores and routines need scope: future (this day and later) or all (whole series), sent as apply_to. Reads back to confirm. Available on the hosted server too.

Task Tools

Tool

Effect

Description

get_task_box

read

List the task box: reusable chore and routine templates (no assignee or date)

create_task

write

Add a template to the task box

delete_task_box_item

destructive

Delete one Task Box template by ID (shown by get_task_box). Previews unless confirm: true; the preview lists same-name scheduled chores as "link unverified" (a template and a scheduled chore are separate records, and nothing is matched by name). Reads the Task Box back to confirm it is gone.

List Tools

Tool

Effect

Description

get_lists

read

All lists

get_list_items

read

Items in one list

create_list

write

Create a list

update_list

write

Rename or change a list

create_list_item

write

Add an item

update_list_item

write

Edit or tick off an item

delete_list

destructive

Delete a list. Local server only.

delete_list_item

destructive

Delete an item. Local server only.

Family Tools

Tool

Effect

Description

get_family_members

read

Family member profiles, with the IDs and names that to and profiles use

get_frame_info

read

Household/frame information

get_devices

read

Skylight devices

get_labels

read

Calendar labels (team, school year, holiday feed: the groupings that are not family members), each with its count of upcoming events and whether a synced calendar still writes to it, so unused ones are easy to spot

delete_label

destructive

Delete one calendar label (the iOS app can do this; the web app cannot). Preview first, then confirm: true; the preview lists the upcoming events that carry only this label, because those are removed with it, while events that also have a profile or another label stay and lose it. Refuses, even with confirm, a profile (family member) and a label a synced calendar still writes to (that would unsync the calendar). Confirms by reading the label list back. Local server only

get_avatars

read

Available profile avatars

get_colors

read

Available profile colours

Meal Tools

Meals and recipes need Skylight Plus.

Tool

Effect

Description

get_meal_categories

read

Breakfast, Lunch, Dinner, Snack and their IDs

get_meal_sittings

read

Scheduled meals in a date range, with sitting IDs; details: true also prints notes and instructions

create_meal_sitting

write

Schedule a meal on a date (free text or a saved recipe). repeat: "weekly" repeats it every week on that weekday.

update_meal_sitting

write

Rename, re-categorise, or set the note or the instructions (description) of a meal, by sitting ID and its current date; one-offs can also be moved. Repeating meals need scope (one, future, all), are preview-first and need confirm: true; they cannot be moved. one and future return a new sitting ID.

delete_meal_sitting

destructive

Delete a meal. For a repeating meal, scope is one (default), future or all (whole series). Previews unless confirm: true; reports success only when Skylight confirms the removal. A meal edited on its own after being in a series is refused.

get_recipes / get_recipe

read

Browse saved recipes

create_recipe / update_recipe

write

Add or change a recipe

delete_recipe

destructive

Delete a recipe. Local server only.

add_recipe_to_grocery_list

write

Push a recipe's ingredients to the grocery list

Reward Tools

Rewards need Skylight Plus.

Tool

Effect

Description

get_rewards

read

Available rewards

get_reward_points

read

Reward points balance

create_reward

write

Add a reward for one family member (assignee required)

update_reward

write

Change a reward

redeem_reward

write

Redeem a reward, spending points

unredeem_reward

write

Undo a redemption

delete_reward

destructive

Delete a reward. Local server only.

Photo Tools

Needs Skylight Plus. Local server only.

Tool

Effect

Description

get_albums

read

Photo albums

Use as a library (experimental)

The package root is a small read-only library for apps such as a family display. It is experimental: breaking changes are allowed in minor versions, and are documented in the changelog, until a real app has used it for a while. The CLI and the MCP servers are unchanged (skylight-mcp runs dist/index.js).

import { createSkylight } from "@davidwoods/skylight-mcp";

const skylight = createSkylight({
  frameId: "your_frame_id",
  timezone: "America/Los_Angeles",
  credential: yourCredentialStore, // or { token: "..." } for a fixed token that does not refresh
});

const events = await skylight.calendar.events({ from: "2026-11-09", to: "2026-11-15" });

Read methods only: calendar.events, calendar.sources, profiles.list, chores.list, meals.sittings, meals.recipes, meals.categories, lists.list, lists.items. They return plain objects, never raw Skylight records: no emails, event uids, calendar or account ids, or subscription feed addresses (a feed shows only its host; an email-shaped calendar label is replaced). Event ids are opaque: a repeating event's occurrence ids change after a time edit, so do not store or compare them.

Behaviour an importer should plan for:

  • chores.list takes one day ({ date }) or a range ({ from, to }, both included, at most 31 days), plus an optional profile. A repeating chore appears once per day it falls on, and each item's date is that day. The range is not yet verified against live Skylight.

  • One createSkylight client holds one sign-in and caches what it read from your store, including "nothing stored". After completeLogin writes a new credential, or after any AuthenticationError, make a new client.

  • Profile names and colours are cached for up to 5 minutes per client, so a renamed profile can show its old name for up to 5 minutes.

  • If a refreshed credential cannot be written to your store, the call fails with CredentialSaveError (an AuthenticationError, code CREDENTIAL_SAVE_FAILED). Refresh tokens rotate, so the old one in your store is already spent: treat it as signed out and sign in again. The error never includes your store's own message.

  • The library writes no per-request log lines. Errors and warnings still go to console.error.

What is not there, on purpose: writes, deletes, messages, source-calendar and feed management, and any function that takes a URL or a feed address (sign-in lives in the separate setup entry below, which accepts exactly one address: the Skylight redirect you paste). There is no host or fetch option; the API host is fixed in code and an unknown option is refused. Only the package root and /setup are importable (deep imports such as dist/api/client.js fail). The library holds a live sign-in, so it stops accidents and token leaks, not a malicious importer. Verified read-only against a real frame on 2026-11-09 (chores and list items were empty that day).

Signing in from your own app (setup entry, experimental)

An app that keeps its own credential store signs in with the same browser-paste flow as the CLI, through a separate entry. Call it from a setup page only, and protect that page yourself.

import { beginLogin, completeLogin, loginStatus } from "@davidwoods/skylight-mcp/setup";

const { loginUrl } = await beginLogin({ pending });          // show loginUrl; the person signs in at Skylight
await completeLogin({ pending, credential, redirectUrl });   // the https://ourskylight.com/welcome?code=... address they paste
await loginStatus({ credential });                           // { signedIn, expired, expiresAt }
  • pending is your store for the ten-minute pending sign-in: save(value) and an atomic take() (read and delete in one step). credential is the same store you give createSkylight.

  • Nothing secret is returned: the credential is written straight into your store. PKCE (S256) and the state check are always on, and a pending sign-in works once.

  • The pasted address must be the Skylight redirect (https://ourskylight.com/welcome); anything else is refused before any request and is never echoed in an error. There is no host or fetch option.

  • Give each app its own sign-in. Refresh tokens rotate, so two apps sharing one credential break each other. A new sign-in did not interrupt two other sessions on the same account: both kept reading in the minutes after it (2026-11-09) and again about 36 hours later, after at least one token refresh each (2026-11-11), with a further sign-in in between. This is one account observed on two days, not a guarantee from Skylight.

  • Verified against live Skylight under Node on 2026-11-09, and inside the Workers runtime (nodejs_compat) against a stubbed token endpoint. Not yet run with a Durable Object store.

Skylight API calls used

All calls go to https://app.ourskylight.com/api (pinned in code). {f} is the frame ID. "Live" means run against a real frame by this project; everything else came from upstream and has not been re-run. Messages and meal edit/delete send Skylight-Api-Version: 2026-10-15, the version the web app sends; other calls use the client default.

Function

Calls

Calendar

GET/POST /frames/{f}/calendar_events (live), PUT /calendar_events/{id}, DELETE /calendar_events/{id} (live), GET /frames/{f}/source_calendars (live)

Messages

GET /frames/{f}/nudges?after&before, POST /nudges (everyone or category_ids), PATCH /nudges/{id}, DELETE /nudges/{id} (all live)

Meals

GET /meals/categories, GET/POST /meals/sittings, PATCH/DELETE /meals/sittings/{id}/instances/{date} (all live)

Recipes

GET/POST /meals/recipes, GET/PATCH/DELETE /meals/recipes/{id}, POST /meals/recipes/{id}/add_to_grocery_list

Profiles and family

GET /frames/{f}/categories (live), GET /frames/{f}, GET /frames/{f}/devices, GET /api/avatars, GET /api/colors

Chores and routines

GET /frames/{f}/chores (live; include_up_for_grabs), POST /chores, PUT/DELETE /chores/{id} (one-off), PUT /chores/{occurrence id} (flat {summary} or {recurrence_set}; re-keys the chore), DELETE /chores/{occurrence id}?apply_to=future|all, PUT /chores/{series id}/completions (body status complete/pending, instance_date, instance_time), POST /chores/create_multiple. All routine calls captured from the web app; the tools are not yet run live

Task box

GET /frames/{f}/task_box/items (live), POST /frames/{f}/task_box/items, DELETE /frames/{f}/task_box/items/{id} (live)

Lists

GET/POST /lists, GET/PUT/DELETE /lists/{id}, POST /lists/{id}/list_items, PUT/DELETE /lists/{id}/list_items/{itemId}

Rewards

GET/POST /rewards, PATCH/DELETE /rewards/{id}, POST /rewards/{id}/redeem, POST /rewards/{id}/unredeem, GET /reward_points

Photos

GET /frames/{f}/albums (local only)

The planning tools make no calls of their own; they combine the calendar, chore, meal and list calls above.

Example Queries

Once configured, you can ask Claude things like:

  • "What's on my calendar today?"

  • "What chores do I need to do this week?"

  • "Add 'take out trash' to my chores for tomorrow"

  • "What's on the grocery list?"

  • "Add milk to my task list"

  • "Who are the family members on Skylight?"

  • "How many reward points does each person have?"

Development

# Run in development mode (with hot reload)
npm run dev

# Build
npm run build

# Run tests
npm test

# Type check
npm run typecheck

Live tests

npm test uses mocked network calls and is what CI runs. A separate, opt-in suite runs the real tools against your own Skylight frame to catch drift in Skylight's API: read smoke checks, response-shape contract checks, and a create/edit/move/delete round trip on a throwaway meal. It does nothing unless you set SKYLIGHT_LIVE=1, never sends messages, and cleans up after itself. Each test is one file in tests/live/, so adding or removing one is adding or deleting a file. See tests/live/README.md.

SKYLIGHT_FRAME_ID=your_frame_id SKYLIGHT_TIMEZONE=America/Los_Angeles \
SKYLIGHT_LIVE=1 npm run test:live

Each new terminal starts without these variables; if one is missing the suite says which and prints the full command. To keep them, add the export lines to ~/.zshrc (or ~/.bashrc). On Windows PowerShell use setx and open a new window.

Set SKYLIGHT_TIMEZONE to your frame's zone. It defaults to America/New_York, which shifts every date window the suite asks for if your frame is elsewhere. Sign in first with skylight-mcp auth login.

API Documentation

This MCP server is built on top of the reverse-engineered Skylight API. The API endpoints were documented using the skylight-api project, which converts browser network traffic (HAR files) into an OpenAPI specification.

API Resources:

If you discover new API endpoints or find issues with the current documentation, please contribute to the skylight-api repository.

Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository and create a feature branch

  2. Make your changes with clear, descriptive commits

  3. Run tests (npm test) and linting (npm run lint) before submitting

  4. Open a pull request with a description of your changes

Development Setup

git clone https://github.com/dwooods/skylight-mcp.git
cd skylight-mcp
npm install
npm run dev  # Start with hot reload

Areas for Contribution

  • Adding support for new Skylight API endpoints

  • Improving error handling and edge cases

  • Enhancing documentation

  • Writing additional tests

Issues & Support

See SUPPORT.md for what to run first and what must never be pasted into an issue.

  • Bug reports and feature requests: open an issue and pick a template.

  • Security problems: use private vulnerability reporting, not a public issue (see SUPPORT.md).

License

MIT

Disclaimer

This is an unofficial integration, not affiliated with or endorsed by Skylight. The Skylight API is reverse-engineered from observed app and web traffic and may change without notice. Sign-in reuses the mobile app's OAuth client. Skylight's Terms of Service prohibit unsupported access and reverse engineering (§5.4) and allow account suspension (§16); you take that risk for the account you use. This project only exposes features your Skylight subscription includes. Use at your own risk.

Available Tools

30 tools
create_calendar_eventA

Create a new calendar event in Skylight.

Use this when:

  • Scheduling a new event: "Add a dentist appointment on Friday at 2pm"

  • Creating family activities: "Schedule soccer practice every Saturday at 10am"

  • Adding reminders: "Put Mom's birthday on the calendar"

Parameters:

  • summary (required): Event title (e.g., "Dentist Appointment")

  • startsAt (required): Start time in ISO format or natural language

  • endsAt (required): End time in ISO format or natural language

  • allDay: Set to true for all-day events

  • description: Additional notes for the event

  • location: Where the event takes place

  • categoryIds: Family member IDs to associate with the event

Returns: The created event details.

Related: Use get_family_members to get category IDs for assignments.

Inputs: endsAt (required), summary (required), startsAt (required), allDay, +3 more.

create_choreB

Add a new chore to Skylight.

Use this when the user wants to:

  • Add a new task like "empty the dishwasher"

  • Assign chores to family members

  • Create recurring chores

The chore will appear on the Skylight display.

Inputs: summary (required), date, time, assignee, +3 more.

create_listA

Create a new list in Skylight.

Use this when:

  • Creating a new shopping/grocery list

  • Creating a new to-do list

Parameters:

  • label (required): Name of the list (e.g., "Vacation Packing", "Weekly Groceries")

  • kind (required): "shopping" for grocery/shopping lists, "to_do" for task lists

  • color: Optional color for the list

Returns: The created list details.

Inputs: kind (required), label (required), color.

create_list_itemA

Add an item to a Skylight list.

Use this when:

  • Adding something to the grocery list: "Add milk to the shopping list"

  • Creating a to-do item: "Put 'call doctor' on my to-do list"

  • Adding items to any list

Parameters:

  • label (required): The item text (e.g., "Milk", "Call doctor")

  • listId: ID of the list to add to

  • listName: Name of the list to add to (e.g., "Grocery List")

  • section: Category within the list (e.g., "Dairy", "Produce")

If no list is specified, adds to the default grocery list.

Returns: Confirmation of the added item.

Related: Use get_lists to see available lists and their IDs.

Inputs: label (required), listId, section, listName.

create_taskA

Add a task to the Skylight task box.

The task box holds unscheduled tasks that can later be assigned to specific dates.

Use this when the user says:

  • "Add XYZ to my task list"

  • "Remind me to do ABC" (without a specific date)

  • "Put 'clean garage' on the task box"

The task will appear on the Skylight display in the task box.

Inputs: summary (required), emoji, routine, rewardPoints.

delete_calendar_eventA
DestructiveIdempotent

Delete a calendar event from Skylight.

Use this when:

  • Canceling an event: "Remove the dentist appointment"

  • Deleting old events: "Delete the meeting from yesterday"

Parameters:

  • eventId (required): ID of the event to delete (from get_calendar_events)

Note: This permanently removes the event. For recurring events, this may only delete one instance.

Inputs: eventId (required).

delete_choreA
DestructiveIdempotent

Delete a chore from Skylight.

Use this when:

  • Removing an old or irrelevant chore

  • Deleting a chore that was added by mistake

Parameters:

  • choreId (required): ID of the chore to delete (from get_chores)

Note: This permanently removes the chore. For recurring chores, this may only delete one instance.

Inputs: choreId (required).

delete_listA
DestructiveIdempotent

Delete a list from Skylight.

Use this when:

  • Removing an old or unused list

  • Deleting a temporary list

Parameters:

  • listId: ID of the list to delete (use get_lists to find IDs)

  • listName: Name of the list to delete (alternative to listId)

Note: This permanently deletes the list and all its items.

Inputs: listId, listName.

delete_list_itemA
DestructiveIdempotent

Remove an item from a list.

Use this when:

  • Removing an item that was added by mistake

  • Deleting an item instead of marking it complete

Parameters:

  • itemId (required): ID of the item to delete

  • listId (required): ID of the list containing the item

Note: This permanently removes the item. Use update_list_item with status="completed" to check it off instead.

Inputs: itemId (required), listId (required).

find_conflictsA
Read-onlyIdempotent

Find calendar events that overlap in time within a date range. All-day events never count as conflicts.

Returns each overlapping pair with the overlap window, or "none".

Inputs: date, days, dateEnd.

find_free_slotsA
Read-onlyIdempotent

Find free time of at least a given length on each day, between an earliest and latest time, around the calendar's timed events. All-day events are not treated as busy.

Use for "when could we do X this week?" questions.

Inputs: date, days, latest, dateEnd, +2 more.

get_avatarsA
Read-onlyIdempotent

Get available avatar options for Skylight profiles.

Use this when:

  • Setting up a new family member profile

  • Changing someone's profile picture

  • Exploring available avatar options

Returns: List of available avatars with their IDs and details.

Inputs: no named parameters.

get_calendar_eventsA
Read-onlyIdempotent

Get calendar events from Skylight.

Use this to answer questions like:

  • "What's on my calendar today?"

  • "What do we have scheduled this weekend?"

  • "Are there any events on Friday?"

Returns a list of events with their titles, times, and details.

Inputs: date, dateEnd.

get_choresA
Read-onlyIdempotent

Get chores from Skylight.

Use this to answer:

  • "What chores do I need to do today?"

  • "Show me this week's chores"

  • "What's on the chore chart?"

  • "What chores does [name] have?"

Returns chores with their assignees, due dates, and completion status.

Inputs: date, status, dateEnd, assignee, +1 more.

get_colorsA
Read-onlyIdempotent

Get available color options for Skylight profiles and lists.

Use this when:

  • Choosing a color for a family member profile

  • Setting a list color

  • Exploring available color options

Returns: List of available colors with their IDs and hex values.

Inputs: no named parameters.

get_devicesA
Read-onlyIdempotent

List Skylight devices in the household.

Use this to answer:

  • "What Skylight devices do we have?"

  • "How many Skylight frames are connected?"

Inputs: no named parameters.

get_family_membersA
Read-onlyIdempotent

Get family members/profiles from Skylight.

Shows who can be assigned chores and their profile details.

Use this to answer:

  • "Who's in our family on Skylight?"

  • "What family members are set up?"

  • "Who can I assign chores to?"

Inputs: no named parameters.

get_frame_infoA
Read-onlyIdempotent

Get Skylight household/frame information.

Useful for setup verification and debugging.

Use this to answer:

  • "Show Skylight household info"

  • "What's my frame ID?"

Inputs: no named parameters.

get_list_itemsA
Read-onlyIdempotent

Get items from a specific Skylight list.

Use this to answer:

  • "What's on the grocery list?"

  • "Show me my to-do list"

  • "What items are on [list name]?"

Returns items organized by section with their completion status.

Inputs: listName, listType, includeCompleted.

get_listsA
Read-onlyIdempotent

Get all lists from Skylight (grocery lists, to-do lists, etc.).

Use this to see what lists are available before adding items. Returns list names, types (shopping/to_do), and item counts.

Inputs: no named parameters.

get_messagesA
Read-onlyIdempotent

Get messages (Skylight calls them "nudges") shown on the family frame.

Use this when:

  • Checking what has already been posted to the frame

  • Avoiding a duplicate before sending a reminder

Returns: Messages grouped by day with time, text, recipients and sender. Defaults to the last 7 days through the next 7 days. Max 31 days.

Inputs: date, dateEnd.

get_source_calendarsA
Read-onlyIdempotent

Get connected calendar sources synced to Skylight.

Use this to answer:

  • "Which calendars are synced to Skylight?"

  • "What calendar accounts are connected?"

Returns a list of connected calendar sources (Google, iCloud, etc.).

Inputs: no named parameters.

get_week_overviewA
Read-onlyIdempotent

One compact view of the family's week: calendar events, chores and tasks (with status and assignee), planned meals, and list summaries, day by day, plus any scheduling conflicts.

Use this first when planning anything (dinners, errands, who drives). It replaces separate calls to get_calendar_events, get_chores, get_meal_sittings and get_lists for the same range.

Parameters:

  • date: first day (YYYY-MM-DD, 'today', 'monday'...). Default today.

  • days: how many days (1–31). Default 7. Or give dateEnd instead.

  • includeLists: include grocery/to-do list summaries. Default true.

Inputs: date, days, dateEnd, includeLists.

plan_week_mealsA

Schedule several meals in one call - Plus subscription required.

Each entry names a date, a meal (category name like "Dinner", default Dinner), and either a free-text summary ("Thai green curry") or a saved recipeId. A slot that already has a meal is skipped and reported, never overwritten. Use dryRun first to see what would change.

Parameters:

  • meals: list of { date, meal?, summary?, recipeId? }

  • dryRun: report the plan without writing. Default false.

  • addRecipesToGroceryList: for entries with a recipeId, also push that recipe's ingredients to the grocery list. Default false.

Inputs: meals (required), dryRun, addRecipesToGroceryList.

send_messageA

Post a message to the family frame (shown to everyone, on all devices, now).

PERMANENT: Skylight has no way to delete a message, and it appears on the family frame for the whole household immediately.

Two-step by design. Called without confirm it only previews and posts nothing. Show the user the exact text and get a clear yes, then call again with confirm: true. Never pass confirm: true on the first call, and never invent message text the user did not ask for. Read aloud is OFF by default; enable it only if the user asked.

Check get_messages first to avoid posting a duplicate.

Inputs: body (required), from, confirm, readAloud.

update_calendar_eventA

Update an existing calendar event.

Use this when:

  • Changing event time: "Move the dentist appointment to 3pm"

  • Updating event details: "Add location to the meeting"

  • Renaming an event: "Change 'Doctor' to 'Dr. Smith checkup'"

Parameters:

  • eventId (required): ID of the event to update (from get_calendar_events)

  • summary: New title for the event

  • startsAt: New start time (ISO format)

  • endsAt: New end time (ISO format)

  • description: Updated notes

  • location: Updated location

  • categoryIds: Updated family member assignments

Returns: The updated event details.

Inputs: eventId (required), allDay, endsAt, summary, +4 more.

update_choreA

Update an existing chore in Skylight.

Use this when:

  • Marking a chore as complete: "Mark 'dishes' as done"

  • Changing chore assignment: "Reassign the trash to Dad"

  • Updating chore details: "Change the time for the homework chore"

Parameters:

  • choreId (required): ID of the chore (from get_chores)

  • summary: New description for the chore

  • status: "completed" to mark done, "pending" to mark incomplete

  • date: New due date

  • time: New due time

  • assignee: New family member assignment

Returns: The updated chore details.

Inputs: choreId (required), date, time, status, +3 more.

update_listA

Update an existing list's name or settings.

Use this when:

  • Renaming a list

  • Changing a list's type or color

Parameters:

  • listId: ID of the list to update (use get_lists to find IDs)

  • listName: Name of the list to update (alternative to listId)

  • label: New name for the list

  • kind: New type ("shopping" or "to_do")

  • color: New color for the list

Returns: The updated list details.

Inputs: kind, color, label, listId, +1 more.

update_list_itemA

Update a list item (mark complete, rename, move to section).

Use this when:

  • Marking an item as complete: "Check off milk from the list"

  • Renaming an item: "Change 'milk' to '2% milk'"

  • Moving an item to a different section

Parameters:

  • itemId (required): ID of the item to update

  • listId (required): ID of the list containing the item

  • label: New text for the item

  • status: "completed" to check off, "pending" to uncheck

  • section: Move to a different section

Returns: The updated item details.

Inputs: itemId (required), listId (required), label, status, +1 more.

update_messageA

Edit the text (and optionally the sender) of a message already on the frame.

Only messages sent to everyone on all devices and not repeating can be edited; anything else must be edited in the Skylight app. Delivery time and read-aloud setting are kept. The edit is visible on the frame immediately. Get the message ID from get_messages (looks within 31 days either side of today).

Inputs: body (required), messageId (required), from.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 30 tools

    Disambiguation4/5

    Most tools target clearly distinct resources and actions, and descriptions explicitly clarify boundaries like create_task vs create_chore vs create_list_item. The main overlap is get_week_overview duplicating individual getters for calendar, chores, and lists, plus possible confusion between dedicated conflict/free-slot tools and overview features.

    Naming Consistency5/5

    Names consistently use snake_case and a predictable verb_noun pattern: get_*, create_*, update_*, delete_*, plus send_message and plan_week_meals. The special verbs still fit the resource-oriented convention and do not introduce inconsistent casing or styles.

    Tool Count3/5

    The server covers several distinct domains (calendar, chores, lists, messages, meals, profiles/devices), so many CRUD tools are justified. However, 30 tools is heavy for an MCP surface, and some metadata getters or aggregate/individual overlaps could likely be consolidated.

    Completeness3/5

    Calendar events, chores, lists, and list items have full CRUD coverage, and messages are well covered given the permanent-post limitation. Notable gaps remain around tasks (create only, with no standalone update/delete) and meals (planning exists, but retrieval/update/delete lifecycle is thin).

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers