Skip to main content
ClaudeWave

stdio MCP server for iCloud Calendar (CalDAV), with optional Contacts (CardDAV) and Mail (IMAP/SMTP)

MCP ServersOfficial Registry1 stars0 forksGoMITUpdated today
Install in Claude Code / Claude Desktop
Method: Manual · icloud-mcp
Claude Code CLI
git clone https://github.com/ThomasCrouzet/icloud-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "icloud-mcp": {
      "command": "icloud-mcp",
      "env": {
        "ICLOUD_PASSWORD": "<icloud_password>",
        "ICLOUD_MAIL_PASSWORD": "<icloud_mail_password>"
      }
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install the binary first: go install github.com/ThomasCrouzet/icloud-mcp@latest (make sure it ends up on your PATH).
Detected environment variables
ICLOUD_PASSWORDICLOUD_MAIL_PASSWORD
Use cases

MCP Servers overview

# icloud-mcp

[![CI](https://github.com/ThomasCrouzet/icloud-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ThomasCrouzet/icloud-mcp/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/ThomasCrouzet/icloud-mcp)](https://github.com/ThomasCrouzet/icloud-mcp/releases)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

Unified **Apple/iCloud** MCP server for **Calendar, Contacts, and Mail**: one
static Go binary, [Model Context Protocol](https://modelcontextprotocol.io)
JSON-RPC on **stdio**.

**Remote protocols only** (CalDAV, CardDAV, IMAP, SMTP with app-specific
passwords). Not macOS EventKit, AppleScript, browser automation, or a private
Apple API. Runs headless on Linux and macOS; pure Go also builds for Windows
(CI smoke-builds `windows/amd64`; GitHub Release archives ship linux/amd64,
linux/arm64, and darwin/arm64). Suitable for agents and orchestration, not only
a desktop chat app.

**Host-agnostic.** Any MCP client that can spawn a child with an environment and
wire stdin/stdout works: personal agents, Hermes, OpenClaw, IDE bridges,
runners, or other stdio hosts. No preferred model vendor, chat product, or
reseller. Configuration is the process environment only; the binary does not
parse host-specific config files or `.env`.

| Domain | Protocol | Default |
|--------|----------|---------|
| Calendar | CalDAV HTTPS | Always on (read + write unless global read-only) |
| Contacts | CardDAV HTTPS | Off until `ICLOUD_MCP_ENABLE_CONTACTS` |
| Mail read | IMAP TLS | Off until `ICLOUD_MCP_ENABLE_MAIL` |
| Mail mutation | IMAP | Off until Mail + `ICLOUD_MCP_ENABLE_MAIL_WRITE` |
| Mail send | SMTP STARTTLS | Off until Mail + `ICLOUD_MCP_ENABLE_MAIL_SEND` + recipient policy |

Reminders, Notes, Photos, Drive, Messages, and similar apps are **out of scope**
until Apple documents a suitable remote third-party connector. Details:
[Supported scope](#supported-scope).

## Quick start

```bash
go install github.com/ThomasCrouzet/icloud-mcp/cmd/icloud-mcp@latest
# or: make build
# or: make release VERSION=v0.4.0
# or: make release-all VERSION=v0.4.0
```

1. Create an [app-specific password](https://appleid.apple.com) (never the main
   Apple Account password).
2. Export a minimal environment (recommended first deploy: Calendar **read-only**):

```bash
export ICLOUD_EMAIL='you@icloud.com'
export ICLOUD_PASSWORD='your-app-specific-password'
export ICLOUD_MCP_READ_ONLY=true
export ICLOUD_MCP_DEFAULT_TZ=Europe/Paris   # owner IANA zone; default UTC
```

3. Register **command** = absolute path to `icloud-mcp` and this **env** in your
   MCP host (YAML, JSON, TOML, UI, or orchestrator; format is host-specific).
4. Stdio = JSON-RPC; **stderr** = logs and mutation audit. Reload the host after
   env changes.

With that config the process exposes **7 tools** (Calendar reads + local
helpers + `icloud_capabilities`). No Contacts or Mail client is constructed.

Optional domains (still host-agnostic `export` form):

```bash
# Contacts reads (writes also need ICLOUD_MCP_READ_ONLY=false)
export ICLOUD_MCP_ENABLE_CONTACTS=true

# Mail reads: IMAP identity may differ from ICLOUD_EMAIL (e.g. name@icloud.com)
export ICLOUD_MCP_ENABLE_MAIL=true
export ICLOUD_MAIL_ADDRESS='mailbox@icloud.com'
# export ICLOUD_MAIL_PASSWORD='...'   # optional; else copy of ICLOUD_PASSWORD

# Mail mutation (flags / move / trash); independent of send
export ICLOUD_MCP_ENABLE_MAIL_WRITE=true
export ICLOUD_MCP_READ_ONLY=false

# Mail send: requires exact recipient allowlist even under global read-only
export ICLOUD_MCP_ENABLE_MAIL_SEND=true
export ICLOUD_MCP_SMTP_ALLOWED_RECIPIENTS='alice@example.com,bob@example.net'
```

Boot-only `file://` secrets (regular files only, at most 4 KiB, mode 0600 or
stricter; never re-read after start):

```bash
export ICLOUD_EMAIL='file:///run/secrets/icloud-email'
export ICLOUD_PASSWORD='file:///run/secrets/icloud-password'
export ICLOUD_MAIL_ADDRESS='file:///run/secrets/icloud-mail-address'
export ICLOUD_MAIL_PASSWORD='file:///run/secrets/icloud-mail-password'
```

See [.env.example](.env.example) for the full 12-variable contract.

## MCP tools

Maximum **23** tools. Disabled tools are absent from `tools/list`; disabled
domain clients are not constructed.

| Count | When |
|------:|------|
| **10** | Default: Calendar read+write + `icloud_capabilities` |
| **7** | Global read-only, optional domains off (recommended first run) |
| **23** | Contacts + Mail read + mutation + send, read-only off |

`ICLOUD_MCP_READ_ONLY=true` removes every Calendar/Contacts write, every Mail
mutation, and Mail send. It does not enable a disabled read domain.

| Group | Tools |
|-------|--------|
| Global | `icloud_capabilities` |
| Calendar read | `list_calendars`, `search_events`, `get_event`, `find_free_slots`, `validate_event`, `calendar_capabilities` |
| Calendar write | `create_event`, `update_event`, `delete_event` |
| Contacts read | `list_address_books`, `search_contacts`, `get_contact` |
| Contacts write | `create_contact`, `update_contact`, `delete_contact` |
| Mail read | `list_mailboxes`, `search_messages`, `get_message` |
| Mail mutation | `set_message_flags`, `move_message`, `trash_message` |
| Mail send | `send_message` |

**Highlights:** occurrence-aware Calendar update/delete with strong `If-Match`;
Contacts opaque book IDs and vCard 3.0 writes; Mail identity
`(mailbox, UIDVALIDITY, UID)`, PEEK reads, SMTP exact-recipient policy.
`set_message_flags` fails closed with `protocol_error` when CONDSTORE is
advertised and tagged MODIFIED cannot be observed (go-imap beta.8). Full
behavior notes: [docs/caldav-compatibility.md](docs/caldav-compatibility.md),
[docs/carddav-compatibility.md](docs/carddav-compatibility.md),
[docs/mail-compatibility.md](docs/mail-compatibility.md).

**Idempotency:** `create_event` / `create_contact` use server-side UID keys
(`client_uid` or alias `idempotency_key`): a repeat create conflicts if the UID
already exists (never silent overwrite). `update_event` / `update_contact`
optional `idempotency_key` is **process-local only** (in-memory cache, **15
minute TTL**, cleared on process restart). Same key + same params returns the
cached success; same key + different params is `conflict`. Prefer combining
update keys with a strong `etag`. See [docs/error-codes.md](docs/error-codes.md).

## Configuration

Exactly **12** product environment variables:

| Variable | Default | Contract |
|----------|---------|----------|
| `ICLOUD_EMAIL` | none | Required Calendar/Contacts identity. `file://` supported (regular file, <=4 KiB, mode 0600+). |
| `ICLOUD_PASSWORD` | none | Required app-specific password; Mail fallback. `file://` as above. |
| `ICLOUD_MCP_READ_ONLY` | `false` | Global mutation kill switch. |
| `ICLOUD_MCP_LOG_LEVEL` | `info` | Stderr level; accepted forms are documented below. |
| `ICLOUD_MCP_DEFAULT_TZ` | `UTC` | IANA zone for offset-less Calendar inputs and recurring-write fallback. |
| `ICLOUD_MCP_ENABLE_CONTACTS` | `false` | Contacts tools; writes only if not read-only. |
| `ICLOUD_MCP_ENABLE_MAIL` | `false` | Mail reads; requires Mail address/password. |
| `ICLOUD_MAIL_ADDRESS` | none | Full IMAP/SMTP address when Mail is on. `file://` as above. |
| `ICLOUD_MAIL_PASSWORD` | `ICLOUD_PASSWORD` | Optional dedicated Mail app password. `file://` as above. |
| `ICLOUD_MCP_ENABLE_MAIL_WRITE` | `false` | Three IMAP mutation tools. |
| `ICLOUD_MCP_ENABLE_MAIL_SEND` | `false` | `send_message` (independent of Mail write). |
| `ICLOUD_MCP_SMTP_ALLOWED_RECIPIENTS` | none | Required if send requested: exact addresses, or literal `*` (boot warning; prefer exact). |

Booleans accept only unset, `0`, `false`, `1`, or `true`. Invalid values fail at
boot. Config is validated **before** any network access: Mail write/send without
Mail, Mail without address/password, or send without recipient policy are boot
errors (including under read-only for the send policy). Global read-only can
coexist with write/send flags but suppresses their registration.

Log levels are trimmed and case-insensitive: `debug`/`-4`, `info`,
`warn`/`warning`/`2`, and `error`/`4`. Unset or unrecognized values use `info`.

Flags: `-version`; optional `-health 127.0.0.1:port` (loopback-only `/healthz`
and `/status` JSON with domains and rate limits); optional
`-audit-format=json|text` (default `json` mutation audit on stderr).

### Dates

- Calendar **input** `start`/`end`: RFC3339 with offset, or wall clock without
  offset in `ICLOUD_MCP_DEFAULT_TZ`. Prefer no-offset for the user's local time.
  Recurring or explicit-timezone creates write TZID + VTIMEZONE; non-recurring
  timed defaults to UTC `Z` on the wire. All-day uses `VALUE=DATE`.
- Calendar **output**: timed events always use RFC3339 with an explicit numeric
  offset in `ICLOUD_MCP_DEFAULT_TZ` (never bare `Z`). All-day dates are
  `YYYY-MM-DD`. See `calendar_capabilities.outputFormat`.
- Contacts birthdays: write `YYYY-MM-DD` only.
- Mail search: `since` inclusive, `before` exclusive (`YYYY-MM-DD`).

Agent error codes and retry policy: [docs/error-codes.md](docs/error-codes.md).
Host wiring examples: [docs/agent-hosts.md](docs/agent-hosts.md). Product roadmap:
[ROADMAP.md](ROADMAP.md).

## Security (summary)

Untrusted remote text can influence an LLM on the host; labels are not a
boundary. A compromised model can call every **registered** tool. Same model for
every host and vendor.

- **Egress fixed:** Calendar `caldav.icloud.com` / `p[0-9]{1,3}-caldav.icloud.com:443`;
  Contacts matching contacts hosts; IMAP `imap.mail.me.com:993`; SMTP
  `smtp.mail.me.com:587` with mandatory STARTTLS. No configurable destinations,
  no proxy env for DAV, TLS 1.2+ verified.
- **Isolation:** separate credentials, transports/dialers, limiters, semaphores,
  and protocol stacks per domain; no union authenticated HTTP client.
- **Secrets:** redacted (including Basic and SASL PLAIN forms); boot-only
  `file://` reads require mode 0600 or stricter;
ai-agentsapplecaldavcalendarcarddavcontactsgolangicloudimapmcpmodel-context-protocolsmtp

What people ask about icloud-mcp

What is ThomasCrouzet/icloud-mcp?

+

ThomasCrouzet/icloud-mcp is mcp servers for the Claude AI ecosystem. stdio MCP server for iCloud Calendar (CalDAV), with optional Contacts (CardDAV) and Mail (IMAP/SMTP) It has 1 GitHub stars and was last updated today.

How do I install icloud-mcp?

+

You can install icloud-mcp by cloning the repository (https://github.com/ThomasCrouzet/icloud-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is ThomasCrouzet/icloud-mcp safe to use?

+

ThomasCrouzet/icloud-mcp has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.

Who maintains ThomasCrouzet/icloud-mcp?

+

ThomasCrouzet/icloud-mcp is maintained by ThomasCrouzet. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to icloud-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy icloud-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: ThomasCrouzet/icloud-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/thomascrouzet-icloud-mcp)](https://claudewave.com/repo/thomascrouzet-icloud-mcp)
<a href="https://claudewave.com/repo/thomascrouzet-icloud-mcp"><img src="https://claudewave.com/api/badge/thomascrouzet-icloud-mcp" alt="Featured on ClaudeWave: ThomasCrouzet/icloud-mcp" width="320" height="64" /></a>

More MCP Servers

icloud-mcp alternatives