icloud-reminders-mcp
Provides tools to read and write Apple Reminders via iCloud CalDAV, allowing management of reminder lists and individual reminders.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@icloud-reminders-mcplist today's reminders from my Work list"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
icloud-reminders-mcp
A local MCP server that gives an AI agent (e.g. Claude Code) read + write access to Apple Reminders over iCloud CalDAV — no Mac required. It talks only to Apple's servers and the local MCP client, and manages the same reminder lists that sync to your iPhone/iPad, including lists shared via Family Sharing.
Reminders are VTODO items in CalDAV; each reminder list is a task-capable
calendar collection. Calendar events (VEVENT), Contacts, Mail, and Notes are
out of scope.
Viability depends on your account. Since iOS 13 / macOS 10.15, Apple
moved Reminders to a newer (CloudKit) store. Only reminder lists that were
never "upgraded" to the new format remain reachable over CalDAV. On some
accounts that is zero lists. Run scripts/doctor.py (below) once before
relying on this — it is a go/no-go probe. Apple may remove CalDAV access at
any time; this is an undocumented, partially-compliant surface.
Why CalDAV (and not pyicloud)
Apple exposes no REST/JSON API for Reminders. CalDAV (RFC 4791) is the only
official-protocol, cross-platform route. Auth is a static app-specific
password — no interactive 2FA, no token refresh. We deliberately avoid
pyicloud (a private web API that broke on Apple's SRP-6a auth change).
Related MCP server: Apple Reminders MCP Server
Requirements
Python 3.11+
An Apple ID with an app-specific password (see below)
uv(recommended) orpip+venv
Install
git clone https://github.com/Lingnik/icloud-reminders-mcp
cd icloud-reminders-mcp
uv venv && uv pip install -e ".[dev]"Generate an app-specific password
Sign in at appleid.apple.com.
Sign-In & Security → App-Specific Passwords → Generate.
Label it (e.g.
icloud-reminders-mcp). You getxxxx-xxxx-xxxx-xxxx.This is the kill switch: revoke it there to instantly cut access. Changing your Apple ID password also invalidates it.
An app-specific password is all-or-nothing — it grants access to your whole iCloud account at Apple's end, not just Reminders. Treat it as a secret, and see SECURITY.md.
Configure
Configuration is via environment variables only (never committed). Copy
.env.example to .env and fill it in, or — preferred on a
host with 1Password CLI — keep the
real values in 1Password and inject them at launch:
# ~/.secrets holds op:// references, not secrets:
# ICLOUD_USERNAME="op://<vault>/icloud-reminders-mcp/username"
# ICLOUD_APP_PASSWORD="op://<vault>/icloud-reminders-mcp/password"
op run --env-file ~/.secrets -- icloud-reminders-mcpVariable | Required | Default | Purpose |
| yes | — | Apple ID email |
| yes | — | App-specific password ( |
| no |
| Root URL; the library discovers your account's |
| no |
| Enable the destructive |
| no | (all) | Comma-separated list names the server may touch |
| no |
| Per-request timeout (seconds) |
Go/no-go probe
Run once against your real account to confirm CalDAV reachability and a full create → read → complete → delete round-trip:
op run --env-file ~/.secrets -- python scripts/doctor.py --list "Reminders"It fails loudly if no VTODO-capable list is found, and reports which fields survived the round-trip. It is never run in CI. After it succeeds, confirm the throwaway reminder appeared (and cleared) on your iPhone.
Use with Claude Code
Add to your MCP config (e.g. ~/.claude/mcp.json or via claude mcp add).
Using 1Password so no secret is written into the config file:
{
"mcpServers": {
"icloud-reminders": {
"command": "op",
"args": [
"run", "--env-file", "/home/you/.secrets", "--",
"uv", "--directory", "/home/you/git/icloud-reminders-mcp", "run",
"icloud-reminders-mcp"
]
}
}
}If you would rather put values inline (less safe), set them under "env" and
call uv directly:
{
"mcpServers": {
"icloud-reminders": {
"command": "uv",
"args": ["--directory", "/home/you/git/icloud-reminders-mcp", "run", "icloud-reminders-mcp"],
"env": {
"ICLOUD_USERNAME": "you@icloud.com",
"ICLOUD_APP_PASSWORD": "xxxx-xxxx-xxxx-xxxx",
"REMINDERS_ALLOW_DELETE": "false"
}
}
}
}Tools
Tool | Type | Purpose |
| read | Reminder lists ( |
| read | Filter by list / completed / due range; paginated ( |
| read | One reminder by uid |
| write | New VTODO (title, list, due, notes, priority, url) |
| write | Mark complete |
| write | Patch fields; preserves everything it doesn't manage |
| destructive | Gated by |
Reminder JSON shape (normalized from VTODO):
{
"uid": "…", "list_id": "…", "list_name": "Family TODOs", "list_url": "…",
"title": "…", "notes": "…|null",
"due": "2026-07-10T09:00:00-07:00|2026-07-10|null", "due_all_day": false,
"completed": false, "completed_at": "…|null",
"priority": 0, "priority_label": "none|low|medium|high",
"percent_complete": 0, "url": "…|null",
"created": "…", "modified": "…", "etag": "…"
}Notes on the model:
Lists are keyed by
list_id(stable, URL-derived), withlist_nameas a mutable label. Tools accept either an id or a name.Priority is the raw iCalendar 0–9 integer plus a friendly label. Apple's UI only has none/low/medium/high and will collapse arbitrary integers to 1/5/9 when you edit in the app — fidelity beyond the four buckets is not guaranteed.
Updates preserve unknown properties.
update_reminder/complete_reminderparse the existing VTODO and mutate only known fields, soRRULE,VALARM,RELATED-TO(subtasks), andX-APPLE-*extensions survive. Editing recurrence/subtasks is not supported in v1 (they're preserved, not managed).Update field semantics: an omitted/null field is left unchanged; pass an empty string (
"") to clearnotes,due, orurl.
Development
uv run ruff check .
uv run pytestTests are network-free: pure mapping/config unit tests plus a fake-CalDAV layer exercising discovery filtering, pagination, ETag-conflict retry, and delete gating. Fixtures are synthetic — never captured from a real account.
Troubleshooting
No lists found / empty. Most likely the CloudKit-upgrade issue above. Try a list you know is old, or one freshly created that you have not migrated.
401 / auth rejected. You're using your Apple ID password, not an app-specific password, or it was revoked/expired. Generate a new one.
PROPFIND hangs / flaky connects. A known iCloud quirk on dual-stack hosts; try forcing IPv4 or IPv6 (e.g. disable one stack, or set a hosts/route preference) and retry. Raise
ICLOUD_REQUEST_TIMEOUTif needed.A field didn't stick. iCloud may normalize or drop properties on write. The doctor script's round-trip report tells you what your account actually preserves.
License
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Lingnik/icloud-reminders-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server