An MCP server for LLM agents to interact with email via IMAP/SMTP
Project description
clerk
A thin CLI for LLM agents to interact with email via IMAP/SMTP.
Philosophy
Clerk is intentionally dumb. It's a bridge, not a brain.
┌─────────────────────────────────────┐
│ Claude Code (LLM) │
│ • Decides what's important │
│ • Summarizes conversations │
│ • Drafts replies │
│ • Orchestrates workflows │
└─────────────────────────────────────┘
│ uses
▼
┌─────────────────────────────────────┐
│ clerk │
│ • Fetches email (IMAP) │
│ • Sends email (SMTP) │
│ • Returns structured JSON │
│ • Knows nothing about content │
└─────────────────────────────────────┘
Installation
pip install clerk
Or install from source:
git clone https://github.com/spinoza/clerk.git
cd clerk
pip install -e .
Quick Start
1. Add an account
# Interactive setup for IMAP/SMTP
clerk accounts add --name personal
# Or for Gmail with OAuth
clerk accounts add-gmail work
2. Check your inbox
clerk inbox
clerk inbox --unread --json
3. Read a conversation
clerk show <conv-id>
clerk show <conv-id> --json
4. Search
clerk search "from:alice project deadline"
clerk search "has:attachment after:2025-01-01"
5. Compose and send
# Create a draft
clerk draft new --to bob@example.com --subject "Hello" --body "Hi there!"
# Review it
clerk draft show <draft-id>
# Send it (requires confirmation)
clerk send <draft-id>
CLI Reference
Inbox & Messages
clerk inbox # List conversations
clerk inbox --limit 50 # More results
clerk inbox --unread # Only unread
clerk inbox --fresh # Bypass cache
clerk inbox --json # JSON output
clerk show <conv-id> # Show conversation
clerk show <message-id> # Show single message
clerk show abc123 # Prefix matching (if unambiguous)
clerk unread # Unread counts by folder
Conversation IDs are 12-character SHA256 prefixes. Shorter prefixes work if unambiguous — if multiple conversations match, clerk shows them for disambiguation.
Search
# Basic search (FTS on cached messages)
clerk search "quarterly report"
# Advanced search with operators
clerk search "from:alice subject:meeting has:attachment"
# Raw SQL for power users
clerk search-sql "SELECT * FROM messages WHERE from_addr LIKE '%@example.com'"
Search Operators
| Operator | Example | Description |
|---|---|---|
from: |
from:alice |
Sender contains |
to: |
to:bob@example.com |
Recipient contains |
subject: |
subject:meeting |
Subject contains |
body: |
body:quarterly |
Body contains |
has:attachment |
has:attachment |
Has attachments |
is:unread |
is:unread |
Unread messages |
is:read |
is:read |
Read messages |
is:flagged |
is:flagged |
Starred/flagged |
after: |
after:2025-01-01 |
After date |
before: |
before:2025-01-15 |
Before date |
date: |
date:2025-01-10 |
On specific date |
Drafts & Sending
clerk draft new --to bob@example.com --subject "Hi" --body "Hello!"
clerk draft new --reply-to <conv-id> --body "Thanks!"
clerk draft list
clerk draft show <draft-id>
clerk draft delete <draft-id>
clerk send <draft-id> # Preview and confirm
Attachments
clerk attachment <message-id> --list
clerk attachment <message-id> document.pdf --save ./downloads/
Folders
clerk folders # List folders
clerk move <message-id> Archive
clerk archive <message-id> # Move to Archive
Interactive Shell
clerk shell
The shell provides all CLI commands with tab completion and history:
clerk> inbox --limit 5
clerk> search from:alice
clerk> sql SELECT * FROM messages LIMIT 10
clerk> exit
Account Management
clerk accounts list
clerk accounts add --name work
clerk accounts add-gmail personal
clerk accounts test work
clerk accounts remove work
Cache
clerk cache status
clerk cache clear
clerk cache refresh
Configuration
Config file: ~/.config/clerk/config.yaml
default_account: personal
accounts:
personal:
protocol: imap
imap:
host: imap.fastmail.com
port: 993
username: user@fastmail.com
smtp:
host: smtp.fastmail.com
port: 587
username: user@fastmail.com
from:
address: user@fastmail.com
name: "User Name"
work:
protocol: gmail
oauth:
client_id_file: ~/.config/clerk/gmail_client.json
cache:
window_days: 7
inbox_freshness_min: 5
body_freshness_min: 60
send:
require_confirmation: true
rate_limit: 20
Credential Storage
Passwords are stored in your system keyring (libsecret, macOS Keychain, Windows Credential Manager).
Alternative methods:
password_cmd: "pass email/fastmail"- command that outputs passwordpassword_file: ~/.secrets/email.txt- file containing password
MCP Server
Clerk includes an MCP (Model Context Protocol) server for LLM integration:
clerk mcp-server
Add to Claude Code's MCP configuration:
{
"mcpServers": {
"clerk": {
"command": "clerk",
"args": ["mcp-server"]
}
}
}
Available Tools
| Tool | Description |
|---|---|
clerk_inbox |
List conversations |
clerk_show |
Get conversation/message details (prefix matching) |
clerk_search |
Search messages (FTS + operators) |
clerk_sql |
Readonly SQL queries on message database |
clerk_search_sql |
SQL search returning Message objects |
clerk_draft |
Create draft |
clerk_drafts |
List drafts |
clerk_send |
Send draft (two-step confirmation) |
clerk_delete_draft |
Delete draft |
clerk_mark_read |
Mark message as read |
clerk_mark_unread |
Mark message as unread |
clerk_archive |
Archive message |
clerk_move |
Move message to folder |
clerk_flag |
Flag/unflag message |
clerk_attachments |
List attachments |
clerk_status |
Connection status |
Claude Code Skill
Install the clerk skill for Claude Code:
clerk skill install # Install globally (~/.claude/skills/clerk/)
clerk skill install --local # Install for current project only
clerk skill status # Check installation status
clerk skill uninstall # Remove
The skill teaches Claude Code how to use clerk commands effectively.
Data Locations
~/.config/clerk/
config.yaml # Configuration
gmail_client.json # Gmail OAuth client (optional)
~/.local/share/clerk/
cache.db # Message cache (ephemeral)
drafts/ # Pending drafts
sent.log # Audit log
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run integration tests (requires Docker)
docker-compose -f docker-compose.test.yml up -d
pytest tests/integration/
docker-compose -f docker-compose.test.yml down
# Lint and type check
ruff check src tests
mypy src
Demo Environment
A Docker-based demo with a mock email server (Greenmail):
cd demo
make start # Start Greenmail mail server
make setup # Configure clerk for demo
make send-test # Populate with 18 test emails
make stop # Tear down
Then use clerk normally: clerk inbox --fresh
See demo/README.md for details on test accounts and email content.
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file email_clerk-0.7.0.tar.gz.
File metadata
- Download URL: email_clerk-0.7.0.tar.gz
- Upload date:
- Size: 118.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea18d9ceda78ae1cfd5050cecf2905caa8380e744091db5e972c12308df8732d
|
|
| MD5 |
cb315b088da3837f0d77e67b56085962
|
|
| BLAKE2b-256 |
fc26cecfabef109a290ba678441d0639e21f79e314e545a0f17b0a91ac4359d7
|
File details
Details for the file email_clerk-0.7.0-py3-none-any.whl.
File metadata
- Download URL: email_clerk-0.7.0-py3-none-any.whl
- Upload date:
- Size: 47.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7da3a3c21b7174c81995eb43c8a7733e70f2aadf40eaf8c360f1b0a1f9a0828b
|
|
| MD5 |
e2aa380a2c6fb444991beaefae4efcae
|
|
| BLAKE2b-256 |
ee25bb1f4512c376d9bcd0407c3f118af7e9bf00a23b9a4d942dcbd471fafcb4
|