iCloud Reminders and Calendar MCP Server

iCloud Reminders and Calendar MCP Server

Lets Claude read and manage your iCloud Reminders and Calendar through a custom MCP connector, enabling natural language queries and actions.

Category
Visit Server

README

iCloud Reminders and Calendar MCP Server

Lets Claude read and manage your iCloud Reminders and Calendar through a custom MCP connector — ask Claude "what's on my groceries list" or "add milk and eggs" or "What do I need to do today" from any Claude client, including the iPhone app.

Architecture

Claude (iPhone/desktop/web)
        |  HTTPS + API key
        v
Anthropic's cloud infrastructure
        |  HTTPS
        v
EC2 instance (Caddy: auto HTTPS via sslip.io + Let's Encrypt)
        |  localhost
        v
Python MCP server (this repo)
        |  CalDAV
        v
iCloud (your Reminders)

Custom MCP connectors are reached by Anthropic's cloud, not by your device directly — so the server has to be genuinely public, not just reachable on your home network. This deployment gets that for $0/month (within AWS free tier) using:

  • EC2 free tier (750 hrs/month for 12 months) instead of a paid VPS
  • sslip.io for a free "domain" (no purchase, no signup) instead of a real registered domain
  • Caddy for free automatic HTTPS via Let's Encrypt
  • CalDAV to talk to iCloud directly — no Mac, no AppleScript required

Why CalDAV instead of AppleScript

Apple Reminders has no public REST API. AppleScript works but only runs locally on a Mac. CalDAV is an open standard Apple also supports for Calendar/Reminders sync, reachable from any OS or cloud server with just an Apple ID and an app-specific password — which is what makes a Mac-free, cloud-hosted version of this possible at all.


Setup

1. Generate an app-specific Apple ID password

  1. Go to https://appleid.apple.com and sign in
  2. Sign-In and Security → App-Specific Passwords → generate one
  3. Save it — you'll need it in step 4. This is not your normal Apple ID password, and can be revoked independently at any time.

2. Launch an EC2 instance

  1. AWS Console → EC2 → Launch instance
  2. Choose Ubuntu Server (latest LTS), instance type t3.micro or t2.micro (free tier eligible)
  3. Create or select a key pair (for SSH access) — download the .pem file
  4. Security group: allow inbound SSH (22) from your IP, and HTTP (80) + HTTPS (443) from anywhere (0.0.0.0/0) — port 80 is needed briefly for Let's Encrypt's verification, Caddy handles the rest
  5. Launch it

3. Attach an Elastic IP (so the address doesn't change on reboot)

  1. EC2 → Elastic IPs → Allocate Elastic IP address
  2. Actions → Associate → select your instance
  3. Note this IP — you'll need it for the sslip.io hostname

4. SSH in and set up the server

ssh -i your-key.pem ubuntu@YOUR-ELASTIC-IP

sudo apt update
sudo apt install -y python3-venv python3-pip git

git clone https://github.com/YOUR_USERNAME/reminders-mcp.git
cd reminders-mcp

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

cp .env.example .env
nano .env   # fill in APPLE_ID, APPLE_APP_PASSWORD, and a generated MCP_API_KEY

Generate a strong API key with:

python3 -c "import secrets; print(secrets.token_urlsafe(32))"

5. Install and configure Caddy

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

Edit the Caddyfile to use your actual Elastic IP (dots replaced with dashes), e.g. if your IP is 54.123.45.67:

sudo nano /etc/caddy/Caddyfile
54-123-45-67.sslip.io {
    handle_path /REPLACE_WITH_YOUR_MCP_API_KEY/* {
      reverse_proxy localhost:8787 {
        header_up x-api-key "YOUR_MCP_API_KEY"
      }
    }
    respond 404
}
sudo systemctl restart caddy

Caddy will automatically get a free HTTPS certificate for that hostname the first time it starts — no manual steps needed.

6. Set up the systemd service (so it survives reboots)

sudo cp reminders-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable reminders-mcp
sudo systemctl start reminders-mcp
sudo systemctl status reminders-mcp   # confirm it's running

7. Test it's reachable

curl -i https://54-123-45-67.sslip.io/{YOUR_MCP_API_KEY}/mcp

{YOUR_MCP_API_KEY} will be extracted from the path and Caddy will inject it as a request header. A response other than a connection error means it's working (a 406 here is expected and fine — it just means the request wasn't a full valid MCP handshake, which curl alone won't do).

8. Add the connector on claude.ai

Custom connectors can only be added via a browser or Claude Desktop — not from the iPhone app directly. Once added, it's usable everywhere, including mobile.

  1. Go to claude.ai → Customize → Connectors → "+" → Add custom connector
  2. Name: iCloud Reminders
  3. URL: https://54-123-45-67.sslip.io/{YOUR_MCP_API_KEY}/mcp
  4. Click Add, then enable it in a conversation

9. Use it from your iPhone

Open the Claude app, start a conversation, enable the connector from the "+" menu if it isn't already, and try:

  • "What's on my Groceries list?"
  • "Add milk and eggs to Groceries"
  • "Mark milk as done on Groceries"
  • "What do I need to do today?"

Tools this server exposes

Tool What it does
list_reminder_lists() Names of all your iCloud Reminders lists
get_pending_reminders(list_name) Incomplete items in a given list
add_reminder(list_name, title) Adds a new reminder to an existing list
complete_reminder(list_name, title) Marks an item done

Note: add_reminder requires the list to already exist — create it once in the Reminders app on any Apple device and it syncs to iCloud automatically. Reliably creating brand-new top-level lists via CalDAV varies across iCloud accounts, so it's left as a one-time manual step.

Security

  • The server requires a valid YOUR_MCP_API_KEY header in every request path — without it, requests are rejected with 401. Treat this key like a password.
  • Your Apple app-specific password only grants limited access and can be revoked anytime from appleid.apple.com without touching your main password.
  • The EC2 security group only allows inbound 22/80/443 — the MCP server's actual port (8787) is only reachable via localhost, through Caddy.
  • Never commit your real .env file — .gitignore is already set up to exclude it. Only .env.example (placeholder values) should be in git.

Cost

Within the AWS Free Tier (first 12 months): $0/month.

  • EC2 t3.micro/t2.micro: free (750 hrs/month covers 24/7 use)
  • Elastic IP: free while attached to a running instance
  • sslip.io hostname: free, no signup
  • Let's Encrypt certificate via Caddy: free, auto-renewing

After free tier expires, EC2 alone runs roughly $7–9/month if left running continuously — stop the instance when not in use to avoid ongoing charges.

Troubleshooting

  • Caddy fails to get a certificate → confirm port 80 is open in your security group (Let's Encrypt needs it briefly for verification), and that the sslip.io hostname matches your Elastic IP exactly.
  • 401 Unauthorized from your own curl test → double-check the YOUR_MCP_API_KEY in URL https://54-123-45-67.sslip.io/{YOUR_MCP_API_KEY}/mcp matches MCP_API_KEY in .env exactly, no trailing whitespace.
  • Service won't start → sudo journalctl -u reminders-mcp -e to see the actual error; usually a missing/incorrect .env value.
  • Claude says the connector won't connect → confirm you can reach the HTTPS URL from a browser or curl first, before troubleshooting on the Claude side.

Next steps

  • Add a Calendar tool (get_todays_events) using the same CalDAV connection, so Claude can start combining "what's on my calendar" with "what's on my todo list" into a single daily briefing.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured