All checks were successful
Build And Test / publish (push) Successful in 48s
211 lines
5.4 KiB
Markdown
211 lines
5.4 KiB
Markdown
# DAV/IMAP MCP Server
|
|
|
|
A self-hosted MCP server that connects IMAP/SMTP, CalDAV, and CardDAV to MCP-compatible clients. It exposes email, calendar, and contacts tools and can optionally send new email notifications to a Poke webhook.
|
|
|
|
## Features
|
|
|
|
- Email tools over IMAP/SMTP (list, read, search, drafts, send drafts, flags, unsubscribe)
|
|
- Calendar tools over CalDAV (list, create, update, delete)
|
|
- Contacts tools over CardDAV (list, create, update, delete)
|
|
- Optional email notifications via webhook with IMAP IDLE or polling
|
|
- SQLite cache with Alembic migrations
|
|
- API key auth for the MCP endpoint
|
|
|
|
## Quickstart (Docker Compose)
|
|
|
|
1. Copy the environment template:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
2. Edit `.env` with your credentials.
|
|
|
|
3. Start the server:
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
4. Verify it is running:
|
|
```bash
|
|
curl http://localhost:8000/mcp
|
|
```
|
|
|
|
## Local Run (Python)
|
|
|
|
```bash
|
|
python -m venv venv
|
|
source venv/bin/activate # Windows: venv\Scripts\activate
|
|
pip install -r requirements.txt
|
|
cp .env.example .env
|
|
# Edit .env
|
|
python src/server.py
|
|
```
|
|
|
|
## Configuration
|
|
|
|
All settings are read from `.env`. Configure only the services you want to enable.
|
|
|
|
### Minimal email-only setup
|
|
|
|
```bash
|
|
MCP_API_KEY=your-secret-key
|
|
PORT=8000
|
|
|
|
IMAP_HOST=imap.example.com
|
|
IMAP_USERNAME=you@example.com
|
|
IMAP_PASSWORD=your-password
|
|
SMTP_HOST=smtp.example.com
|
|
SMTP_USERNAME=you@example.com
|
|
SMTP_PASSWORD=your-password
|
|
SMTP_FROM_EMAIL=you@example.com
|
|
|
|
ENABLE_CALENDAR=false
|
|
ENABLE_CONTACTS=false
|
|
```
|
|
|
|
### Full setup (email + calendar + contacts)
|
|
|
|
```bash
|
|
MCP_API_KEY=your-secret-key
|
|
PORT=8000
|
|
|
|
IMAP_HOST=imap.example.com
|
|
IMAP_PORT=993
|
|
IMAP_USERNAME=you@example.com
|
|
IMAP_PASSWORD=your-password
|
|
IMAP_USE_SSL=true
|
|
|
|
SMTP_HOST=smtp.example.com
|
|
SMTP_PORT=587
|
|
SMTP_USERNAME=you@example.com
|
|
SMTP_PASSWORD=your-password
|
|
SMTP_USE_TLS=true
|
|
SMTP_FROM_EMAIL=you@example.com
|
|
SMTP_FROM_NAME=Your Name
|
|
|
|
CALDAV_URL=https://caldav.example.com/dav
|
|
CALDAV_USERNAME=you@example.com
|
|
CALDAV_PASSWORD=your-password
|
|
ICS_CALENDARS=Team|https://example.com/team.ics,Family|https://example.com/family.ics
|
|
ICS_CALENDAR_TIMEOUT=20
|
|
ICS_CALENDARS=Team|https://example.com/team.ics,Family|https://example.com/family.ics
|
|
ICS_CALENDAR_TIMEOUT=20
|
|
|
|
CARDDAV_URL=https://carddav.example.com/dav
|
|
CARDDAV_USERNAME=you@example.com
|
|
CARDDAV_PASSWORD=your-password
|
|
CONTACTS_ADDRESSBOOK_ID=/dav/addressbooks/users/you@example.com/contacts/
|
|
```
|
|
|
|
Contacts tools always use `CONTACTS_ADDRESSBOOK_ID`. Listing address books is not exposed via MCP.
|
|
|
|
ICS calendars are optional and read-only. Set `ICS_CALENDARS` to a comma-separated list of entries, each as `name|url` or just `url` if you want the name inferred.
|
|
|
|
### Email notifications (Poke webhook)
|
|
|
|
Enable notifications to send new-email alerts to Poke. The server will use IMAP IDLE when available and fall back to polling.
|
|
|
|
```bash
|
|
ENABLE_EMAIL_NOTIFICATIONS=true
|
|
NOTIFICATION_MAILBOXES=INBOX,Updates
|
|
NOTIFICATION_POLL_INTERVAL=60
|
|
NOTIFICATION_IDLE_TIMEOUT=1680
|
|
|
|
POKE_WEBHOOK_URL=https://poke.com/api/v1/inbound-sms/webhook
|
|
POKE_API_KEY=your-poke-api-key
|
|
POKE_WEBHOOK_TIMEOUT=30
|
|
POKE_WEBHOOK_MAX_RETRIES=3
|
|
```
|
|
|
|
## MCP Client Setup
|
|
|
|
### MCP Inspector
|
|
|
|
```bash
|
|
npx @modelcontextprotocol/inspector
|
|
```
|
|
- Transport: Streamable HTTP
|
|
- URL: `http://localhost:8000/mcp`
|
|
|
|
### Claude Desktop
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"pim": {
|
|
"transport": "http",
|
|
"url": "http://localhost:8000/mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Poke
|
|
|
|
Add your MCP endpoint at https://poke.com/settings/connections.
|
|
|
|
## Available Tools
|
|
|
|
| Category | Tools |
|
|
| --- | --- |
|
|
| Email | `list_mailboxes`, `list_emails`, `list_drafts`, `read_email`, `search_emails`, `move_email`, `delete_email`, `delete_draft`, `save_draft`, `edit_draft`, `send_draft`, `set_email_flags`, `unsubscribe_maillist` |
|
|
| Calendar | `list_calendars`, `list_events`, `get_event`, `create_event`, `update_event`, `delete_event` |
|
|
| Contacts | `list_contacts`, `get_contact`, `create_contact`, `update_contact`, `delete_contact` |
|
|
| System | `get_server_info` |
|
|
|
|
### Sending email
|
|
|
|
Emails are sent only from drafts. Create or edit a draft with `save_draft`/`edit_draft`, then send it with `send_draft` using the returned draft ID.
|
|
|
|
### Replying to an email
|
|
|
|
Use `in_reply_to_email_id` on `save_draft` or `edit_draft` to create a reply without a separate tool. Then send it with `send_draft`.
|
|
|
|
- Provide `in_reply_to_email_id` (and optionally `in_reply_to_mailbox`, default `INBOX`).
|
|
- `reply_all=true` includes original recipients; otherwise it replies to the sender/Reply-To.
|
|
- If `to`/`subject` are omitted, they are derived from the original email; `body` is still required.
|
|
- `in_reply_to_email_id` is the email UID from `list_emails`/`read_email`, not the RFC Message-ID header.
|
|
|
|
Example (send a reply):
|
|
```json
|
|
{
|
|
"tool": "save_draft",
|
|
"args": {
|
|
"in_reply_to_email_id": "12345",
|
|
"in_reply_to_mailbox": "INBOX",
|
|
"reply_all": true,
|
|
"body": "Thanks — sounds good to me."
|
|
}
|
|
}
|
|
```
|
|
|
|
Then send the draft by its returned ID:
|
|
```json
|
|
{
|
|
"tool": "send_draft",
|
|
"args": {
|
|
"email_id": "67890"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Database and Migrations
|
|
|
|
The server uses SQLite (default: `/data/cache.db`) and Alembic.
|
|
|
|
```bash
|
|
alembic revision --autogenerate -m "Describe change"
|
|
alembic upgrade head
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
- Connection refused: check `docker compose ps` or `curl http://localhost:8000/mcp`
|
|
- Auth errors: confirm `MCP_API_KEY` and client config
|
|
- IMAP/SMTP failures: verify credentials and app-specific passwords
|
|
- CalDAV/CardDAV failures: confirm base URL and username
|
|
|
|
## License
|
|
|
|
MIT
|