MCP (Model Context Protocol) server for iCloud integration, providing tools for managing calendars (CalDAV), contacts (CardDAV), and email (IMAP/SMTP).
- Stateless Architecture: No state stored between requests
- Full CRUD Operations: Complete management of calendars, contacts, and email
- Flexible Authentication: Via headers or environment variables
- Multiple Transports: stdio (local) or Streamable HTTP (server)
- Docker Support: Easy deployment with Docker and Docker Compose
calendar_list_calendars- List all calendarscalendar_list_events- List events with date filteringcalendar_create_event- Create new eventcalendar_update_event- Update existing eventcalendar_delete_event- Delete eventcalendar_search_events- Search events by text
contacts_list- List all contactscontacts_get- Get specific contactcontacts_create- Create new contact (name, phones, emails, addresses, organization, title)contacts_update- Update existing contactcontacts_delete- Delete contactcontacts_search- Search contacts by text
email_list_folders- List mail foldersemail_list_messages- List messages in folderemail_get_message- Get full message detailsemail_get_messages- Get multiple messages at once (bulk fetch)email_search- Search messages by textemail_send- Send email via SMTPemail_save_draft- Save an email to Drafts without sendingemail_move- Move message to folderemail_delete- Delete or trash messageemail_mark_read- Mark message as reademail_mark_unread- Mark message as unread
- Python 3.10 - 3.12 (Python 3.13+ not yet supported due to dependency compatibility)
- iCloud account with App-Specific Password (Generate here)
# Clone repository
git clone <repository-url>
cd icloud-mcp
# Create virtual environment with Python 3.10-3.12
python3.12 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install package in editable mode
pip install -e .
# Configure environment
cp .env.example .env
# Edit .env with your credentials# Clone repository
git clone <repository-url>
cd icloud-mcp
# Configure environment
cp .env.example .env
# Edit .env with your credentials
# Build and run with Docker Compose
docker-compose up -dCreate a .env file with the following variables:
# iCloud Credentials (fallback if not in headers)
ICLOUD_EMAIL=your-email@icloud.com
ICLOUD_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx
# iCloud Servers (optional, defaults to standard iCloud servers)
CALDAV_SERVER=https://caldav.icloud.com
CARDDAV_SERVER=https://contacts.icloud.com
IMAP_SERVER=imap.mail.me.com
SMTP_SERVER=smtp.mail.me.com
# Server Configuration
MCP_SERVER_PORT=8000
IMAP_PORT=993
SMTP_PORT=587
# HTTP transport access control (see Security Considerations)
MCP_AUTH_TOKEN=
HOST=127.0.0.1
HTTP_TIMEOUT=30
EMAIL_SEND_ALLOWLIST=
# Email folders
SENT_FOLDER=Sent Messages
DRAFTS_FOLDER=Drafts| Variable | Description |
|---|---|
MCP_AUTH_TOKEN |
Bearer token required on the HTTP transport. Unset by default, which leaves the HTTP transport unauthenticated. |
HOST |
Bind address for the HTTP transport. Defaults to 127.0.0.1 (local only). |
HTTP_TIMEOUT |
Timeout in seconds for outbound IMAP/SMTP/CalDAV/CardDAV calls. Defaults to 30. |
EMAIL_SEND_ALLOWLIST |
Comma-separated recipient addresses email_send and email_save_draft are permitted to use. Empty (default) allows any recipient. Drafts are checked too, since a draft to a blocked address only needs a click in the mail client to become a send. |
SENT_FOLDER |
IMAP folder for the copy of a sent message. Defaults to Sent Messages; Sent and Sent Items are tried as fallbacks. |
DRAFTS_FOLDER |
IMAP folder email_save_draft writes to. Defaults to Drafts. |
iCloud credentials - the server supports two methods, checked in order:
-
Request Headers (recommended for multi-user scenarios):
X-Apple-Email: iCloud email addressX-Apple-App-Specific-Password: App-specific password
-
Environment Variables (fallback):
ICLOUD_EMAILICLOUD_APP_SPECIFIC_PASSWORD
If credentials are not found in either location, the server returns a 401 error. Credentials are held only for the duration of the request that uses them - they are not cached or persisted server-side.
MCP client access (HTTP transport) - by default the HTTP transport accepts requests from anyone who can reach it, with no login of any kind. Set MCP_AUTH_TOKEN to require a Bearer <token> header on every request; without it, any client that can open a TCP connection to the server can call every tool, including email_send. See Security Considerations.
# Using Python directly
python run.py
# Or using the module
python -m icloud_mcp.server# Using Python
python run.py --http --port 8000
# Using Docker Compose
docker-compose upThe server will be available at http://localhost:8000/mcp.
By default it binds to 127.0.0.1 and accepts unauthenticated requests. Read Security Considerations before binding it to anything other than localhost.
This method allows Claude Desktop to directly launch the MCP server as a subprocess.
Step 1: Install dependencies locally:
pip install -e .Step 2: Create a .env file with your credentials:
cp .env.example .env
# Edit .env and add your iCloud credentialsStep 3: Find your Claude Desktop configuration file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Step 4: Add this configuration (replace the path):
{
"mcpServers": {
"icloud": {
"command": "python",
"args": ["/absolute/path/to/icloud-mcp/run.py"],
"network": {
"enabled": true,
"allowedDomains": [
"caldav.icloud.com",
"contacts.icloud.com",
"*.contacts.icloud.com",
"imap.mail.me.com",
"smtp.mail.me.com"
]
}
}
}
}Important: Replace /absolute/path/to/icloud-mcp/ with the actual full path to your project directory.
Example on macOS:
{
"mcpServers": {
"icloud": {
"command": "python",
"args": ["/Users/username/Projects/icloud-mcp/run.py"],
"network": {
"enabled": true,
"allowedDomains": [
"caldav.icloud.com",
"contacts.icloud.com",
"*.contacts.icloud.com",
"imap.mail.me.com",
"smtp.mail.me.com"
]
}
}
}
}Note: The network.allowedDomains configuration is required for contacts to work properly, as the server needs to access iCloud's CardDAV servers.
Step 5: Restart Claude Desktop completely (Quit and reopen)
After restarting Claude Desktop:
- Open Claude Desktop application
- Look for the π¨ (tools/hammer) icon in the bottom-right corner
- You should see "icloud" server listed with green status
- Try commands like:
- "List my calendars"
- "Show my contacts"
- "Get my unread emails"
Server doesn't appear:
- Check JSON syntax in config file (use a JSON validator)
- View logs: Help β Show Logs in Claude Desktop
- Verify the path to
run.pyis absolute (not relative) - Ensure Python is in your PATH
- Check that you're using Python 3.10-3.12 (not 3.13+)
401 Authentication errors:
- Ensure you're using an App-Specific Password, not your regular Apple password
- Generate one at: https://appleid.apple.com/account/manage
- Check
.envfile has correct credentials
Contacts not working (empty results or errors):
- Ensure you've added the
network.allowedDomainsconfiguration to Claude Desktop config - The domains
contacts.icloud.comand*.contacts.icloud.commust be in the allowed list - Restart Claude Desktop after updating the config
Tools fail with 500 errors:
- Check server logs for details
- Verify iCloud credentials are valid
- Ensure network connectivity to iCloud servers
The server is fully stateless:
- No sessions or state stored between requests
- Each request contains all necessary authentication information
- Connections to iCloud services are created per-request and closed immediately
- Perfect for horizontal scaling and serverless deployments
- Transport: Streamable HTTP protocol with
/mcpendpoint - Calendar (CalDAV): Uses
caldavlibrary for standard CalDAV operations - Contacts (CardDAV): Direct HTTP/WebDAV implementation using
requestswith proper RFC 6352 CardDAV protocol - Email (IMAP/SMTP): Uses
imapclientfor IMAP and standardsmtplibfor SMTP - Authentication: Headers via
get_http_headers()with environment variable fallback
network.allowedDomainsapplies only to the stdio subprocess Claude Desktop launches, and is enforced by Claude Desktop itself (see Claude Desktop integration). The Streamable HTTP transport has no equivalent: a running HTTP server can reach any host the machine can reach.- The HTTP transport is unauthenticated unless you set
MCP_AUTH_TOKEN. With it set, every request must carry a matchingBearer <token>header; without it, anyone who can reach the port can call every tool, includingemail_send. - By default the server binds to
127.0.0.1only (setHOSTto change this).docker-compose.ymlpublishes the port on127.0.0.1only, so the container is not reachable from other machines out of the box. - If you need to expose the server beyond localhost, you must set
MCP_AUTH_TOKEN, and you should put it behind a reverse proxy with TLS - the server itself does not terminate TLS. - iCloud credentials (email and app-specific password) are held only for the duration of each request; they are not cached, logged, or persisted server-side.
- Store App-Specific Passwords securely (use secret management tools) and never commit the
.envfile to version control. - Consider header-based iCloud credentials (
X-Apple-Email/X-Apple-App-Specific-Password) for multi-user scenarios instead of a single shared.env.
icloud-mcp/
βββ src/
β βββ icloud_mcp/
β βββ __init__.py
β βββ config.py # Configuration management
β βββ auth.py # Authentication handling
β βββ calendar.py # CalDAV tools
β βββ contacts.py # CardDAV tools (direct HTTP/WebDAV)
β βββ email.py # IMAP/SMTP tools
β βββ server.py # FastMCP server and tool registration
βββ .env.example # Example environment configuration
βββ .gitignore
βββ Dockerfile
βββ docker-compose.yml
βββ pyproject.toml # Python project configuration and dependencies
βββ run.py # Entry point script
βββ README.md
# Install development dependencies
pip install -e ".[dev]"
# Run tests (when added)
pytest# Format code
black src/
# Lint code
ruff check src/MIT License - See LICENSE file for details
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
For issues and questions:
- Open an issue on GitHub
- Check existing issues for solutions
- Review iCloud API documentation
Built with:
- FastMCP - MCP server framework
- caldav - CalDAV library for calendar operations
- requests - HTTP library for CardDAV operations
- IMAPClient - IMAP library
- vobject - vCard/iCalendar parsing