Repository navigation
Releases: Trozz/mcp-icloud
Release list
mcp-icloud 1.2.0
v1.2.0 (2026-10-29)
Refactor
- Build the server on the shared mcp-server-core crate (02d4171)
Documentation
- Upgrading signs every connector in once more; sign-ins end after 90 days (362de53)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.2.0Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.1.1-dev.15
v1.1.1-dev.15 (2026-10-29)
Refactor
- Build the server on the shared mcp-server-core crate (02d4171)
Documentation
- Upgrading signs every connector in once more; sign-ins end after 90 days (362de53)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.1.1-dev.15Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.1.1-dev.14
v1.1.1-dev.14 (2026-10-29)
Refactor
- Build the server on the shared mcp-server-core crate (02d4171)
Documentation
- Upgrading signs every connector in once more; sign-ins end after 90 days (362de53)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.1.1-dev.14Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.1.1-dev.13
v1.1.1-dev.13 (2026-10-18)
Refactor
- Build the server on the shared mcp-server-core crate (02d4171)
Documentation
- Upgrading signs every connector in once more; sign-ins end after 90 days (362de53)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.1.1-dev.13Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.1.0
v1.1.0 (2026-10-18)
Features
- Add shared helpers for MCP prompts (0e61ba2)
- Serve every service's prompts on the combined endpoint (e0b357a)
- Add the triage_inbox prompt to the mail service (0b65aed)
- Add the plan_week prompt to the calendar service (4ed065e)
- Add birthday and duplicate clean-up prompts to the contacts service (9f8aeb2)
- Export a contact as vCard (9cf1828)
- Export a group as vCard (72cdc0c)
- Add MKCALENDAR, PROPPATCH and collection DELETE to the DAV client (a2b29b6)
- Add calendar collection request bodies and fake CalDAV support (9f1fcf0)
- Add create_calendar to the calendar service (b2e04e4)
- Add rename_calendar to the calendar service (dd2acc6)
- Add delete_calendar to the calendar service (07324c6)
- Validate and decode draft attachments (c7dfcae)
- Attach files to new and reply drafts (5b40313)
- Rename and delete mailboxes over IMAP (d5fecc9)
- Add rename_mailbox and delete_mailbox tools (f385c0b)
Documentation
- Drop migration notes for the never-released mail-only server (33c9ec8)
- Document the MCP prompts and check them against the code (b820f07)
- Describe vCard export and check it live (fc00d81)
- Explain calendar management and the check-then-delete gap (9d82197)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.1.0Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.0.1-dev.8
v1.0.1-dev.8 (2026-10-18)
Features
- Add shared helpers for MCP prompts (0e61ba2)
- Serve every service's prompts on the combined endpoint (e0b357a)
- Add the triage_inbox prompt to the mail service (0b65aed)
- Add the plan_week prompt to the calendar service (4ed065e)
- Add birthday and duplicate clean-up prompts to the contacts service (9f8aeb2)
Documentation
- Drop migration notes for the never-released mail-only server (33c9ec8)
- Document the MCP prompts and check them against the code (b820f07)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.0.1-dev.8Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.0.1-dev.11
v1.0.1-dev.11 (2026-10-18)
Features
- Add shared helpers for MCP prompts (0e61ba2)
- Serve every service's prompts on the combined endpoint (e0b357a)
- Add the triage_inbox prompt to the mail service (0b65aed)
- Add the plan_week prompt to the calendar service (4ed065e)
- Add birthday and duplicate clean-up prompts to the contacts service (9f8aeb2)
- Export a contact as vCard (9cf1828)
- Export a group as vCard (72cdc0c)
- Add MKCALENDAR, PROPPATCH and collection DELETE to the DAV client (a2b29b6)
- Add calendar collection request bodies and fake CalDAV support (9f1fcf0)
- Add create_calendar to the calendar service (b2e04e4)
- Add rename_calendar to the calendar service (dd2acc6)
- Add delete_calendar to the calendar service (07324c6)
- Validate and decode draft attachments (c7dfcae)
- Attach files to new and reply drafts (5b40313)
- Rename and delete mailboxes over IMAP (d5fecc9)
- Add rename_mailbox and delete_mailbox tools (f385c0b)
Documentation
- Drop migration notes for the never-released mail-only server (33c9ec8)
- Document the MCP prompts and check them against the code (b820f07)
- Describe vCard export and check it live (fc00d81)
- Explain calendar management and the check-then-delete gap (9d82197)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.0.1-dev.11Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 1.0.0
v1.0.0 (2026-10-18)
Features
- Scaffold workspace and env config reader (6d20928)
- Add PKCE verification and auth guards (247bc07)
- Add typed JWT issue and verify (81b2461)
- Add OAuth metadata and dynamic client registration (9b64f30)
- Validate OAuth authorize requests (7928b7b)
- Add OAuth login page and authorization code issuance (4cdbaee)
- Add OAuth token endpoint with PKCE and replay protection (618e9aa)
- Add bearer auth middleware and application router (3db3574)
- Add TLS serving with file, self-signed and insecure modes (482bb3d)
- Add observability setup and core configuration (fb581c3)
- Scaffold mcp-icloud-mail crate with errors and config (e21e0be)
- Parse messages into views and attachments (26cec7a)
- Build draft, reply and forward messages (9c81aa1)
- Strip Bcc and collect envelope recipients (2be1861)
- Add byte-bounded LRU message cache (cbf440a)
- Add IMAP client with lazy connection, mailbox roles and select (d3504ab)
- Add IMAP search, summaries and cached raw fetch (03e8163)
- Add IMAP flag, move, delete, create and append operations (b94f1f7)
- Add SMTP sender for iCloud with a recording test double (a3e0e1c)
- Add MCP read tools for mailboxes, search, messages, attachments and threads (ea1d7b2)
- Add MCP tools to organise messages and create drafts (1a4eae8)
- Add send_draft tool with Bcc stripping and safe partial-failure handling (98f09b9)
- Serve the mail tools over MCP Streamable HTTP with host and origin checks (18792ec)
- Add service trait and shared MCP mounting to core (60d28c4)
- Serve mail from a unified mcp-icloud binary (ac83894)
- Make each service its own OAuth protected resource (dc652be)
- calendar: Scaffold mcp-icloud-calendar library crate (d636042)
- calendar: Add error kinds and environment configuration (f9bbf7a)
- calendar: Add time zone state and local time resolution (4ef48f6)
- calendar: Add lossless iCalendar content-line layer and synthetic fixtures (3dd3033)
- calendar: Add event model and VEVENT parsing (0908938)
- calendar: Build new events and apply field patches losslessly (a0b4ceb)
- calendar: Expand recurrences and edit single occurrences or the rest of a series (92aea04)
- Parse CalDAV multistatus responses and build request bodies (698fba7)
- Add the CalDAV HTTP client with scoped auth, redirects and retries (94327b2)
- Discover iCloud calendars and validate event ids (cabb665)
- Add calendar read tools and time zone tools (c425676)
- Add create, update and delete event tools (65db480)
- calendar: Mount the calendar service at /calendar in mcp-icloud (b54f7ed)
- Reply to invitations and manage attendees when invitations are enabled (f88a489)
- Add per-service icons and a favicon (b2b73ba)
- Add the shared mcp-icloud-dav crate with the lossless content-line layer (b1ed636)
- Move multistatus parsing into mcp-icloud-dav and read CardDAV properties (5f4c850)
- Move the DAV client and home discovery into mcp-icloud-dav (8ae1df0)
- Add the contacts service crate with its configuration and errors (a1714f4)
- Read iCloud vCards and their Apple labels (226caa7)
- Build and patch vCards without touching unrelated lines (973bfbc)
- Search contacts by words or phone number (0070f01)
- Discover the iCloud address book (d7e3614)
- Keep an in-memory contacts index current with sync-collection (b10a119)
- Add the contacts read tools (b52ef8e)
- Add the contact write tools (b6a1f80)
- Add the group tools (251beed)
- Serve iCloud contacts at /contacts (b9182a6)
- Add read-only services and a write audit log around every MCP handler (bfc6b90)
- Add ICLOUD_READ_ONLY and AUDIT_LOG_PATH to mcp-icloud (1b90144)
- Add a combined MCP handler that serves several services' tools under service prefixes (019b889)
- Serve every service's tools together at /mcp (d5dfe0d)
- Work out the next birthdays and dates of contacts (08299c4)
- List upcoming birthdays and anniversaries with upcoming_dates (d4f5449)
- Find likely duplicate contacts (3c92282)
- Merge duplicate contacts (7102370)
- Copy a contact's photo onto another contact (fa94cc2)
Bug Fixes
- Drop form-action from login page CSP so redirect after login is not blocked (7891adc)
- Harden login limiter with /64 keying, global ceiling and trusted proxies (f4a0bde)
- Show redirect host and unverified client name on login page (a9a2d04)
- Compare SHA-256 digests in ct_eq so input length does not leak (b367f1b)
- Tighten authorize, token and tracing correctness (26ee90e)
- Assert concrete attachment size and label delete metric DELETE_MESSAGES (a3c8fad)
- Never log IMAP credentials by capping async_imap at info (8776fe9)
- Surface tagged NO/BAD on UID SEARCH and match completions by tag (6d1fef9)
- Bound IMAP connect and commands with timeouts (4350163)
- Back off for 60 s after a rejected IMAP login (40f54b1)
- Refresh the mailbox list once before reporting an unknown target (2ca9049)
- Never send a draft twice by serializing sends and reading drafts live (5ac20ee)
- Strip Bcc with whitespace before the colon and verify by re-parsing (abfd70a)
- Return uidvalidity from compose tools and get_thread and order threads by instant (9a40cea)
- Finish send_draft after SMTP even if the request is cancelled (cbfb241)
- Drop span-scoped log directives that bypass the async_imap cap (e094aaf)
- Do not promise raw protocol data in the unsafe log warning (5c6e3ae)
- Ignore RUSTSEC-2023-0071 in cargo-deny, rsa is unused for signing (7dc4bd7)
- Lock the shared cargo registry cache in multi-arch docker builds (08c8b6b)
- Avoid panics on multibyte addresses and extreme durations in ical parsing (a15103f)
- Keep whole days when moving an all-day event across a DST change (f6e03e6)
- Report truncated in find_free_time when series expansion is capped (6daa4af)
- Refuse series start moves over exceptions and splitting received invitations (c6fdd0c)
- Rebuild the display name only when the name or organization actually changes (bd75365)
- Accept urn:uuid remove_ids in update_group (4a7f9a6)
- Stop quoting content in parse errors and reject invalid content lines (5b8f0c0)
- Make contact searches without letters or digits match nobody (b74042c)
- Skip the write when update_group changes nothing (724e21e)
- Report unparseable groups as unreadable and log skipped multiget entries (ef702fa)
- Narrow an existing audit log file to mode 0600 (5c9e9d6)
- Keep merge_contacts answering when a PUT returns no ETag (cc8242d)
Documentation
- Add README and MIT license (70521b3)
- Rewrite README for the unified mcp-icloud server (62928f0)
- Clarify respond_to_invitation is not registered when invites are disabled (9df4ee2)
- Document the contacts service (5f70244)
- Add the contacts log target to the LOG_LEVEL example (c0c95b7)
- Add the mdBook documentation site with a CI build and link check (5626d1f)
- Write the documentation site pages (70e0f7c)
- Correct error kinds, mail mailbox defaults and phone matching rule (b231a56)
- Shorten the README and point to the documentation site (563de2b)
- Point usage, release notes and version script at the documentation site (871c41f)
- Say which fields of merged contacts are not kept (41e2f4f)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:1.0.0Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them. /mcp serves every enabled service's tools in one server, prefixed mail_, calendar_ and contacts_ (ICLOUD_COMBINED=false turns it off).
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 0.0.1-dev.5
v0.0.1-dev.5 (2026-10-18)
Features
- Scaffold workspace and env config reader (6d20928)
- Add PKCE verification and auth guards (247bc07)
- Add typed JWT issue and verify (81b2461)
- Add OAuth metadata and dynamic client registration (9b64f30)
- Validate OAuth authorize requests (7928b7b)
- Add OAuth login page and authorization code issuance (4cdbaee)
- Add OAuth token endpoint with PKCE and replay protection (618e9aa)
- Add bearer auth middleware and application router (3db3574)
- Add TLS serving with file, self-signed and insecure modes (482bb3d)
- Add observability setup and core configuration (fb581c3)
- Scaffold mcp-icloud-mail crate with errors and config (e21e0be)
- Parse messages into views and attachments (26cec7a)
- Build draft, reply and forward messages (9c81aa1)
- Strip Bcc and collect envelope recipients (2be1861)
- Add byte-bounded LRU message cache (cbf440a)
- Add IMAP client with lazy connection, mailbox roles and select (d3504ab)
- Add IMAP search, summaries and cached raw fetch (03e8163)
- Add IMAP flag, move, delete, create and append operations (b94f1f7)
- Add SMTP sender for iCloud with a recording test double (a3e0e1c)
- Add MCP read tools for mailboxes, search, messages, attachments and threads (ea1d7b2)
- Add MCP tools to organise messages and create drafts (1a4eae8)
- Add send_draft tool with Bcc stripping and safe partial-failure handling (98f09b9)
- Serve the mail tools over MCP Streamable HTTP with host and origin checks (18792ec)
- Add service trait and shared MCP mounting to core (60d28c4)
- Serve mail from a unified mcp-icloud binary (ac83894)
- Make each service its own OAuth protected resource (dc652be)
- calendar: Scaffold mcp-icloud-calendar library crate (d636042)
- calendar: Add error kinds and environment configuration (f9bbf7a)
- calendar: Add time zone state and local time resolution (4ef48f6)
- calendar: Add lossless iCalendar content-line layer and synthetic fixtures (3dd3033)
- calendar: Add event model and VEVENT parsing (0908938)
- calendar: Build new events and apply field patches losslessly (a0b4ceb)
- calendar: Expand recurrences and edit single occurrences or the rest of a series (92aea04)
- Parse CalDAV multistatus responses and build request bodies (698fba7)
- Add the CalDAV HTTP client with scoped auth, redirects and retries (94327b2)
- Discover iCloud calendars and validate event ids (cabb665)
- Add calendar read tools and time zone tools (c425676)
- Add create, update and delete event tools (65db480)
- calendar: Mount the calendar service at /calendar in mcp-icloud (b54f7ed)
- Reply to invitations and manage attendees when invitations are enabled (f88a489)
- Add per-service icons and a favicon (b2b73ba)
- Add the shared mcp-icloud-dav crate with the lossless content-line layer (b1ed636)
- Move multistatus parsing into mcp-icloud-dav and read CardDAV properties (5f4c850)
- Move the DAV client and home discovery into mcp-icloud-dav (8ae1df0)
- Add the contacts service crate with its configuration and errors (a1714f4)
- Read iCloud vCards and their Apple labels (226caa7)
- Build and patch vCards without touching unrelated lines (973bfbc)
- Search contacts by words or phone number (0070f01)
- Discover the iCloud address book (d7e3614)
- Keep an in-memory contacts index current with sync-collection (b10a119)
- Add the contacts read tools (b52ef8e)
- Add the contact write tools (b6a1f80)
- Add the group tools (251beed)
- Serve iCloud contacts at /contacts (b9182a6)
- Add read-only services and a write audit log around every MCP handler (bfc6b90)
- Add ICLOUD_READ_ONLY and AUDIT_LOG_PATH to mcp-icloud (1b90144)
- Add a combined MCP handler that serves several services' tools under service prefixes (019b889)
- Serve every service's tools together at /mcp (d5dfe0d)
- Work out the next birthdays and dates of contacts (08299c4)
- List upcoming birthdays and anniversaries with upcoming_dates (d4f5449)
- Find likely duplicate contacts (3c92282)
- Merge duplicate contacts (7102370)
- Copy a contact's photo onto another contact (fa94cc2)
Bug Fixes
- Drop form-action from login page CSP so redirect after login is not blocked (7891adc)
- Harden login limiter with /64 keying, global ceiling and trusted proxies (f4a0bde)
- Show redirect host and unverified client name on login page (a9a2d04)
- Compare SHA-256 digests in ct_eq so input length does not leak (b367f1b)
- Tighten authorize, token and tracing correctness (26ee90e)
- Assert concrete attachment size and label delete metric DELETE_MESSAGES (a3c8fad)
- Never log IMAP credentials by capping async_imap at info (8776fe9)
- Surface tagged NO/BAD on UID SEARCH and match completions by tag (6d1fef9)
- Bound IMAP connect and commands with timeouts (4350163)
- Back off for 60 s after a rejected IMAP login (40f54b1)
- Refresh the mailbox list once before reporting an unknown target (2ca9049)
- Never send a draft twice by serializing sends and reading drafts live (5ac20ee)
- Strip Bcc with whitespace before the colon and verify by re-parsing (abfd70a)
- Return uidvalidity from compose tools and get_thread and order threads by instant (9a40cea)
- Finish send_draft after SMTP even if the request is cancelled (cbfb241)
- Drop span-scoped log directives that bypass the async_imap cap (e094aaf)
- Do not promise raw protocol data in the unsafe log warning (5c6e3ae)
- Ignore RUSTSEC-2023-0071 in cargo-deny, rsa is unused for signing (7dc4bd7)
- Lock the shared cargo registry cache in multi-arch docker builds (08c8b6b)
- Avoid panics on multibyte addresses and extreme durations in ical parsing (a15103f)
- Keep whole days when moving an all-day event across a DST change (f6e03e6)
- Report truncated in find_free_time when series expansion is capped (6daa4af)
- Refuse series start moves over exceptions and splitting received invitations (c6fdd0c)
- Rebuild the display name only when the name or organization actually changes (bd75365)
- Accept urn:uuid remove_ids in update_group (4a7f9a6)
- Stop quoting content in parse errors and reject invalid content lines (5b8f0c0)
- Make contact searches without letters or digits match nobody (b74042c)
- Skip the write when update_group changes nothing (724e21e)
- Report unparseable groups as unreadable and log skipped multiget entries (ef702fa)
- Narrow an existing audit log file to mode 0600 (5c9e9d6)
- Keep merge_contacts answering when a PUT returns no ETag (cc8242d)
Documentation
- Add README and MIT license (70521b3)
- Rewrite README for the unified mcp-icloud server (62928f0)
- Clarify respond_to_invitation is not registered when invites are disabled (9df4ee2)
- Document the contacts service (5f70244)
- Add the contacts log target to the LOG_LEVEL example (c0c95b7)
- Add the mdBook documentation site with a CI build and link check (5626d1f)
- Write the documentation site pages (70e0f7c)
- Correct error kinds, mail mailbox defaults and phone matching rule (b231a56)
- Shorten the README and point to the documentation site (563de2b)
- Point usage, release notes and version script at the documentation site (871c41f)
- Say which fields of merged contacts are not kept (41e2f4f)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:0.0.1-dev.5Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them.
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Upgrading from mcp-icloud-mail: mail moved from /mcp to /mail; re-add the connector.
Full configuration reference: https://trozz.github.io/mcp-icloud/configuration.html
mcp-icloud 0.0.1-dev.4
v0.0.1-dev.4 (2026-10-18)
Features
- Scaffold workspace and env config reader (6d20928)
- Add PKCE verification and auth guards (247bc07)
- Add typed JWT issue and verify (81b2461)
- Add OAuth metadata and dynamic client registration (9b64f30)
- Validate OAuth authorize requests (7928b7b)
- Add OAuth login page and authorization code issuance (4cdbaee)
- Add OAuth token endpoint with PKCE and replay protection (618e9aa)
- Add bearer auth middleware and application router (3db3574)
- Add TLS serving with file, self-signed and insecure modes (482bb3d)
- Add observability setup and core configuration (fb581c3)
- Scaffold mcp-icloud-mail crate with errors and config (e21e0be)
- Parse messages into views and attachments (26cec7a)
- Build draft, reply and forward messages (9c81aa1)
- Strip Bcc and collect envelope recipients (2be1861)
- Add byte-bounded LRU message cache (cbf440a)
- Add IMAP client with lazy connection, mailbox roles and select (d3504ab)
- Add IMAP search, summaries and cached raw fetch (03e8163)
- Add IMAP flag, move, delete, create and append operations (b94f1f7)
- Add SMTP sender for iCloud with a recording test double (a3e0e1c)
- Add MCP read tools for mailboxes, search, messages, attachments and threads (ea1d7b2)
- Add MCP tools to organise messages and create drafts (1a4eae8)
- Add send_draft tool with Bcc stripping and safe partial-failure handling (98f09b9)
- Serve the mail tools over MCP Streamable HTTP with host and origin checks (18792ec)
- Add service trait and shared MCP mounting to core (60d28c4)
- Serve mail from a unified mcp-icloud binary (ac83894)
- Make each service its own OAuth protected resource (dc652be)
- calendar: Scaffold mcp-icloud-calendar library crate (d636042)
- calendar: Add error kinds and environment configuration (f9bbf7a)
- calendar: Add time zone state and local time resolution (4ef48f6)
- calendar: Add lossless iCalendar content-line layer and synthetic fixtures (3dd3033)
- calendar: Add event model and VEVENT parsing (0908938)
- calendar: Build new events and apply field patches losslessly (a0b4ceb)
- calendar: Expand recurrences and edit single occurrences or the rest of a series (92aea04)
- Parse CalDAV multistatus responses and build request bodies (698fba7)
- Add the CalDAV HTTP client with scoped auth, redirects and retries (94327b2)
- Discover iCloud calendars and validate event ids (cabb665)
- Add calendar read tools and time zone tools (c425676)
- Add create, update and delete event tools (65db480)
- calendar: Mount the calendar service at /calendar in mcp-icloud (b54f7ed)
- Reply to invitations and manage attendees when invitations are enabled (f88a489)
- Add per-service icons and a favicon (b2b73ba)
- Add the shared mcp-icloud-dav crate with the lossless content-line layer (b1ed636)
- Move multistatus parsing into mcp-icloud-dav and read CardDAV properties (5f4c850)
- Move the DAV client and home discovery into mcp-icloud-dav (8ae1df0)
- Add the contacts service crate with its configuration and errors (a1714f4)
- Read iCloud vCards and their Apple labels (226caa7)
- Build and patch vCards without touching unrelated lines (973bfbc)
- Search contacts by words or phone number (0070f01)
- Discover the iCloud address book (d7e3614)
- Keep an in-memory contacts index current with sync-collection (b10a119)
- Add the contacts read tools (b52ef8e)
- Add the contact write tools (b6a1f80)
- Add the group tools (251beed)
- Serve iCloud contacts at /contacts (b9182a6)
Bug Fixes
- Drop form-action from login page CSP so redirect after login is not blocked (7891adc)
- Harden login limiter with /64 keying, global ceiling and trusted proxies (f4a0bde)
- Show redirect host and unverified client name on login page (a9a2d04)
- Compare SHA-256 digests in ct_eq so input length does not leak (b367f1b)
- Tighten authorize, token and tracing correctness (26ee90e)
- Assert concrete attachment size and label delete metric DELETE_MESSAGES (a3c8fad)
- Never log IMAP credentials by capping async_imap at info (8776fe9)
- Surface tagged NO/BAD on UID SEARCH and match completions by tag (6d1fef9)
- Bound IMAP connect and commands with timeouts (4350163)
- Back off for 60 s after a rejected IMAP login (40f54b1)
- Refresh the mailbox list once before reporting an unknown target (2ca9049)
- Never send a draft twice by serializing sends and reading drafts live (5ac20ee)
- Strip Bcc with whitespace before the colon and verify by re-parsing (abfd70a)
- Return uidvalidity from compose tools and get_thread and order threads by instant (9a40cea)
- Finish send_draft after SMTP even if the request is cancelled (cbfb241)
- Drop span-scoped log directives that bypass the async_imap cap (e094aaf)
- Do not promise raw protocol data in the unsafe log warning (5c6e3ae)
- Ignore RUSTSEC-2023-0071 in cargo-deny, rsa is unused for signing (7dc4bd7)
- Lock the shared cargo registry cache in multi-arch docker builds (08c8b6b)
- Avoid panics on multibyte addresses and extreme durations in ical parsing (a15103f)
- Keep whole days when moving an all-day event across a DST change (f6e03e6)
- Report truncated in find_free_time when series expansion is capped (6daa4af)
- Refuse series start moves over exceptions and splitting received invitations (c6fdd0c)
- Rebuild the display name only when the name or organization actually changes (bd75365)
- Accept urn:uuid remove_ids in update_group (4a7f9a6)
- Stop quoting content in parse errors and reject invalid content lines (5b8f0c0)
- Make contact searches without letters or digits match nobody (b74042c)
- Skip the write when update_group changes nothing (724e21e)
- Report unparseable groups as unreadable and log skipped multiget entries (ef702fa)
Documentation
- Add README and MIT license (70521b3)
- Rewrite README for the unified mcp-icloud server (62928f0)
- Clarify respond_to_invitation is not registered when invites are disabled (9df4ee2)
- Document the contacts service (5f70244)
- Add the contacts log target to the LOG_LEVEL example (c0c95b7)
Install
Docker
docker run -d --name mcp-icloud -p 8443:8443 \
-e ICLOUD_EMAIL=you@icloud.com \
-e ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-e PUBLIC_URL=https://icloud.example.com \
-e OAUTH_SIGNING_KEY="$(openssl rand -hex 32)" \
-e OAUTH_ADMIN_PASSWORD=choose-a-long-password \
-e CALENDAR_TIMEZONE=Europe/London \
-v /path/to/certs:/certs:ro \
-e TLS_CERT_PATH=/certs/fullchain.pem \
-e TLS_KEY_PATH=/certs/privkey.pem \
ghcr.io/trozz/mcp-icloud:0.0.1-dev.4Binary
Download the archive for your platform below, verify it with the matching .sha256 file (shasum -a 256 -c <file>.sha256), extract it and run ./mcp-icloud with the same environment variables.
Connect
Each service is its own MCP server at https://<your PUBLIC_URL host>/<service>: mail at /mail, calendar at /calendar, contacts at /contacts. Set ICLOUD_SERVICES to run only some of them.
- claude.ai: add one custom connector per service (
https://<your PUBLIC_URL host>/mail,https://<your PUBLIC_URL host>/calendar,https://<your PUBLIC_URL host>/contacts) and sign in withOAUTH_ADMIN_PASSWORD. - Claude Code:
claude mcp add --transport http icloud-mail https://<host>/mail --header "Authorization: Bearer <MCP_AUTH_TOKEN>",claude mcp add --transport http icloud-calendar https://<host>/calendar --header "Authorization: Bearer <MCP_AUTH_TOKEN>"andclaude mcp add --transport http icloud-contacts https://<host>/contacts --header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Upgrading from mcp-icloud-mail: mail moved from /mcp to /mail; re-add the connector.
Full configuration reference: https://github.com/Trozz/mcp-icloud/blob/v0.0.1-dev.4/README.md