Skip to main content
Glama

Kairos

CI

Website · ▶ Try it in your browser — the actual Python server on Pyodide/WASM, nothing leaves your machine.

when2meet-style scheduling polls — self-hostable, reverse-proxy-auth friendly, agent-first API (OpenAPI + llms.txt + MCP).

Quickstart

uvx --from kairos-scheduler kairos          # SQLite + demo auth on :8003

or with Docker / a real database:

KAIROS_DB_URL=mysql://user:pass@host:3306/db \
KAIROS_AUTH=header SESSION_SECRET=$(openssl rand -hex 32) \
uvx --from 'kairos-scheduler[mysql]' kairos --host 0.0.0.0

Related MCP server: timergy

Features

  • Full-day or time-slot polls, when2meet drag grids, heatmaps

  • Public share links + personal email invites (required/optional participants)

  • Convergence light: collecting → ready / partial / blocked

  • Idempotent smart reminders + per-participant contact audit trail

  • Decide a final date → .ics download + "email everyone" with the file attached

  • Light/dark colorblind-friendly theme (Dalton)

  • Agents: REST API (Bearer), /llms.txt, OpenAPI, Swagger UI, MCP server

  • Reverse-calendar (optional): push candidate slots into the respondent's calendar instead of reading their free/busy — subscribe-able feeds + native iMIP Accept/Maybe/Decline. Off by default (see below).

Reverse the calendar (iMIP) — optional

Instead of asking for calendar access, Kairos can push the candidate slots into the respondent's calendar and let them Accept/Maybe/Decline — capturing what's truly blocking, not mechanical free/busy. Two layers, both opt-in:

  • Candidate feed (KAIROS_FEED=on) — a subscribe-able, disposable .ics calendar of the poll's slots. The per-invite feed (/p/i/<token>/feed.ics) embeds deep-link Accept/Maybe/Decline URLs; tapping one records that slot and lands on the poll page (the instant surface — subscribed feeds refresh slowly, Google ~daily, so never rely on the calendar reflecting a vote quickly).

  • Native iMIP invitations (KAIROS_IMIP=on) — real METHOD:REQUEST invites with Accept/Maybe/Decline buttons. KAIROS_IMIP_ORGANIZER is the mailbox replies route to; it must equal the IMAP mailbox Kairos polls (KAIROS_IMAP_HOST/PORT/USER/PASSWORD/MAILBOX). Schedule POST /api/imip/poll (cron / systemd timer, Bearer auth) to ingest replies; POST /api/polls/{id}/imip-decision sends the decided slot as a native invite.

Cross-client reality (verified live): Outlook and Apple render native Accept/Maybe/Decline; Gmail does not for a Gmail-organized event (Google policy) — the deep-link Accept/Maybe/Decline in the event description covers it, so every client gets one-click RSVP. For native Gmail RSVP, use a non-Gmail (custom-domain) organizer.

Agent-native (no API key): the invite link self-describes — GET /p/i/<token>/agent.json returns the options, your current vote, and the one-click vote URLs (also feed.ics, and /s/<slot>/<yes|maybe|no> to vote). Hand your assistant the link and it RSVPs for you. See /llms.txt.

See docs/design/reverse-calendar-imip.md and issue #23 for the full design.

Deployment model

Kairos trusts identity headers from whatever reverse proxy you already run (KAIROS_AUTH=header): Shibboleth/Apache, oauth2-proxy, Authelia, Cloudflare Access, Tailscale… Respondents never need accounts — share links and invite tokens are self-contained. See kairos/settings.py for all env knobs.

Cookie note for operators: Kairos sets only strictly-necessary cookies (session, signed response-edit token, theme preference) — disclosed on /privacy, no consent banner required (ePrivacy Art. 5(3) / Swiss TCA 45c exemptions). If you add analytics or any third-party embeds to your deployment, that changes — you'll need consent management.

Related MCP Connectors

Related MCP Servers