A calendar app answers "what's on Tuesday." It does not answer "where did last month actually go,"
"which two things did I say yes to at the same time," or "how many billable hours were in that block of
calls." MCP Calendar answers those by reading the .ics file your calendar already exports, no
account connected, nothing synced, the file staying on your machine as plain text.
| App | Where |
|---|---|
| Google Calendar | Settings, Import & export, Export. You get a zip; import the .ics inside it. |
| Apple Calendar | File, Export, Export... |
| Outlook (desktop) | File, Save Calendar, format iCalendar (.ics) |
| Outlook / Microsoft 365 (web) | Settings, Calendar, Shared calendars, Publish, then the ICS link (Pro) |
Any other app that publishes a feed URL ending in .ics, or a webcal:// link, works
the same way on Pro. Then:
ics_import {path: "~/Downloads/mike@example.com.ics", name: "work"}
claude mcp add calendar -- npx -y @theluckystrike/mcp-calendar
Cursor and Claude Desktop take the same block, with "calendar" as the key under
mcpServers. There is exactly one network call in the whole server, and only when you pass a
url yourself, with a 12-second timeout, a 5 MB cap, and a refusal on loopback and
private-network addresses.
The parser was written against real exports, not just the RFC 5545 spec: line folding across CRLF, bare
LF and bare CR, escaped commas and semicolons, whole-day events with an exclusive DTEND,
DURATION in place of DTEND, both TZID and UTC times, floating times,
RRULE for daily, weekly, monthly and yearly series with COUNT, UNTIL,
INTERVAL, BYDAY, BYMONTHDAY and BYMONTH,
EXDATE and RDATE exceptions, a RECURRENCE-ID override replacing the
original occurrence instead of appearing twice, STATUS:CANCELLED and
TRANSP:TRANSPARENT. An event the parser cannot read is skipped and counted, not allowed to cost
you the rest of the file.
VTIMEZONE blocks are deliberately ignored. A file's own DST rules are only as fresh as the
app that wrote it, so the server keeps the TZID name and computes every offset from the ICU
data inside Node itself. That is what keeps a weekly 10:00 Warsaw meeting at 10:00 local across the March
clock change instead of drifting to 11:00, and it is why a whole-day event spanning 1 to 3 June is 1 and 2
June: RFC 5545 makes a whole-day DTEND exclusive, and the parser follows the spec rather than
guessing what you meant.
free_busy merges overlapping events into busy blocks and reports the gaps inside your working
hours, day by day; an event marked TRANSP:TRANSPARENT does not count as busy. conflicts
checks every pair of events across every imported calendar at once, with the overlap in minutes, so a client
call that clashes with something on a personal calendar is caught even though the two never lived in the same
place before. events_search finds an event by title, description, location, organiser or
attendee text, and next_event answers "what's next, and how long until it starts."
event_to_time_entry takes one event and returns the exact arguments the time tracker's
entry_add needs: project, task, date and duration read straight off the calendar instead of
retyped from memory. Nothing is guessed about the rate or the project; that mapping is what you supply when
you ask for it, the same way the price tracker and the invoice server hand off data without you restating
it. The prompt plan_my_day chains the whole loop: what is on, what clashes, where the gaps are,
and which finished meetings are worth billing.
It does not connect to a Google or Outlook account: no OAuth, no token, no sync, which also means an
import is a snapshot rather than a live view, and re-importing is how you catch up. It writes new
.ics files through event_export but never edits the calendar it read. Free covers 2
calendars, windows up to 31 days and exports up to 50 events; Pro removes all three limits and adds URL and
webcal feed imports.
Setup per client is on the setup pages. MCP Calendar has the full tool table. It reads its time zone and .ics engine from MCP Timezone Planner, and hands finished meetings to MCP Time Tracker.
No. There is no OAuth, no token and no sync. You export a file, or paste a public feed URL on Pro, and it is read locally. An import is a snapshot, so re-import when the calendar has moved on.
It is not: RFC 5545 makes DTEND exclusive for a whole-day event, so 1 to 3 June means the 1st and the 2nd. This server follows the spec, which is what your calendar app does too.
Yes. VTIMEZONE blocks in the file are ignored on purpose, and every offset is computed from the ICU data inside Node from the TZID name, so a 10:00 Warsaw meeting stays 10:00 local through the March and October changes.
No. event_export writes a new .ics file you can import anywhere, but the server never modifies the calendar it read from.
Up to 5 MB, which is a few thousand events. Export a narrower date range if a full history export is bigger than that.