email-insights
email-insights
MCP-сервер, предоставляющий аналитику сигналов электронной почты для Claude Desktop, с фоновым рабочим процессом для запланированных асинхронных задач извлечения и структурированным логированием.
Структура проекта
email-insights/
├── data/
│ └── emails.csv # Raw email data (id, from, subject, body, date)
├── database/
│ └── signals.db # SQLite database (created after running ingestion)
├── db/
│ ├── connection.py # Single source of truth for SQLite connections
│ ├── schema.py # DDL for all tables (idempotent CREATE IF NOT EXISTS)
│ ├── signals.py # Read/write for signals table
│ ├── raw_emails.py # Read/write for raw_emails table
│ └── jobs.py # Read/write for jobs and failed_extractions tables
├── ingestion/
│ ├── fetch_emails_imap.py # Fetch emails via IMAP → store raw in SQLite
│ ├── parse_csv.py # Step 1: Load emails from CSV
│ ├── extract_signals.py # Step 2: Call local LLM to extract signals
│ └── store_signals.py # Step 3: Write signals to SQLite (run this)
├── logs/
│ └── worker.log # Rotating log file (auto-created, 5 MB max, 3 backups)
├── mcp_server/
│ ├── server.py # MCP server: registers tools and starts listening
│ └── tools.py # SQLite query functions + job scheduling tools
├── utils/
│ └── logger.py # Shared structured logger (stderr + rotating file)
├── worker/
│ └── job_runner.py # Background worker: polls SQLite and runs extraction jobs
├── requirements.txt
└── README.mdRelated MCP server: io.github.p-w-4-z/inbox-mcp
Настройка
1. Установка зависимостей
pip install -r requirements.txt2. Настройка учетных данных IMAP
Скопируйте .env.example в .env и введите свои учетные данные:
IMAP_HOST=imap.gmail.com
IMAP_USER=you@gmail.com
IMAP_PASSWORD=your-app-specific-password
IMAP_PORT=993 # optional, default 993
IMAP_MAILBOX=INBOX # optional, default INBOXДля Gmail создайте пароль приложения на странице myaccount.google.com/apppasswords.
3. Загрузка писем в SQLite
Получите все письма из вашего почтового ящика и сохраните их в таблице raw_emails:
python ingestion/fetch_emails_imap.pyИндикатор выполнения показывает статус получения и сохранения в реальном времени. Опции:
# Fetch only the 50 most recent emails
python ingestion/fetch_emails_imap.py --limit 50
# Also export a CSV backup
python ingestion/fetch_emails_imap.py --output data/backup.csv
# Count emails in a date range (no fetch)
python ingestion/fetch_emails_imap.py --count --start-date 2025-01-01 --end-date 2025-03-014. Запуск LM Studio
Откройте LM Studio и загрузите любую модель, следующую инструкциям (Llama 3, Mistral и т. д.)
Запустите локальный сервер: Local Server → Start Server
URL по умолчанию:
http://127.0.0.1:10101Скопируйте строку идентификатора модели и вставьте ее в
ingestion/extract_signals.pyкакLOCAL_MODEL
5. Запуск извлечения сигналов
python ingestion/store_signals.pyЭтот скрипт считывает data/emails.csv, отправляет каждое письмо в вашу локальную LLM для извлечения сигналов и сохраняет результаты в database/signals.db.
6. Запуск фонового рабочего процесса
Рабочий процесс — это отдельный процесс, который опрашивает систему на наличие запланированных задач извлечения. Запустите его в отдельном терминале:
python worker/job_runner.pyРабочий процесс записывает всю активность в logs/worker.log и в stderr. Он опрашивает SQLite каждые 10 секунд и автоматически подхватывает любые ожидающие или запланированные задачи.
7. Подключение Claude Desktop
Добавьте этот сервер в конфигурацию Claude Desktop:
Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"email-insights": {
"command": "python",
"args": ["/absolute/path/to/email-insights/mcp_server/server.py"]
}
}
}Перезапустите Claude Desktop. Вы должны увидеть email-insights в списке инструментов.
Инструменты MCP
Инструменты запросов
Инструмент | Описание |
| Запрос сигналов с дополнительными фильтрами по дате/теме/тону |
| Количество писем по категориям тем |
| Разбивка по типу отправителя со статистикой срочности |
| Поиск сигналов по ключевым словам |
Инструменты планирования задач
Инструмент | Описание |
| Создание задачи извлечения — выполняется сейчас, в запланированное время или в полночь |
| Получение прогресса задачи в реальном времени (обновляется после каждого письма) |
| Повторная постановка в очередь только тех писем, которые не удалось обработать в предыдущей задаче |
Все инструменты планирования возвращают результат немедленно. Извлечение выполняется асинхронно в рабочем процессе.
Режимы работы schedule_extraction_tool
| Поведение |
|
| Рабочий процесс подхватывает задачу при следующем опросе (по умолчанию) | не используется |
| Выполняется в определенное время |
|
| Выполняется сегодня в 00:00:00 | не используется |
Архитектура
Claude Desktop ──stdio──▶ mcp_server/server.py
│
mcp_server/tools.py
│
SQLite signals.db
│
worker/job_runner.py ◀── runs separately
│
LM Studio (local LLM)MCP-сервер и рабочий процесс — это два полностью независимых процесса, которые совместно используют только базу данных SQLite. MCP-сервер никогда не ждет завершения извлечения — он создает запись о задаче и немедленно возвращает результат. Рабочий процесс отвечает за все записи в таблицах jobs и failed_extractions (обновления статуса, прогресс, ошибки); MCP-сервер только считывает статус задачи.
Схема SQLite
CREATE TABLE raw_emails (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email_id TEXT UNIQUE, -- SHA-256(date|sender_name|sender_email)[:16]
date TEXT, -- ISO format from email Date header
sender_name TEXT,
sender_email TEXT,
subject TEXT,
body TEXT,
fetched_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE signals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email_id TEXT UNIQUE,
topic TEXT, -- job application | recruiter outreach | rejection | interview | networking | other
tone TEXT, -- positive | neutral | negative
sender_type TEXT, -- recruiter | company HR | networking contact | university | other
urgency TEXT, -- high | medium | low
requires_action INTEGER, -- 0 or 1
date TEXT -- ISO format: YYYY-MM-DD
);
CREATE TABLE jobs (
job_id INTEGER PRIMARY KEY AUTOINCREMENT,
schema_id INTEGER,
status TEXT NOT NULL DEFAULT 'pending', -- pending | scheduled | running | completed | failed
run_at TEXT, -- ISO datetime; NULL means run immediately
total_emails INTEGER DEFAULT 0,
processed_emails INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now')),
completed_at TEXT,
error_message TEXT,
retry_of_job_id INTEGER -- set for retry jobs; links back to source job
);
CREATE TABLE failed_extractions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
email_id TEXT NOT NULL,
error_message TEXT,
created_at TEXT DEFAULT (datetime('now'))
);Таблицы jobs и failed_extractions создаются автоматически при первом использовании — ручная миграция не требуется.
Структурированное логирование
Вся активность рабочего процесса записывается в logs/worker.log (создается автоматически) и в stderr.
Формат лога:
[2026-03-05 14:22:01] [INFO] Worker started, polling every 10 seconds
[2026-03-05 14:22:11] [INFO] Job 1 picked up: schema_id=None, 10 emails to process
[2026-03-05 14:22:13] [INFO] [1/10] email_id=e001 extracted: topic=recruiter outreach, tone=positive
[2026-03-05 14:22:14] [WARNING] [2/10] email_id=e002 retrying after error: JSONDecodeError
[2026-03-05 14:22:16] [ERROR] [2/10] email_id=e002 failed after retry, saved to failed_extractions
[2026-03-05 14:22:45] [INFO] Job 1 completed in 34.2s: 9 success, 1 failedФайл лога ротируется при достижении 5 МБ, сохраняются последние 3 файла (worker.log, worker.log.1, worker.log.2).
Что можно узнать из кода
mcp_server/server.py
FastMCP("email-insights")— создает экземпляр сервера с отображаемым именем@mcp.tool()— регистрирует декорированную функцию как вызываемый инструмент MCPDocstrings имеют значение — Claude читает их, чтобы решить, когда и как вызывать каждый инструмент
Подсказки типов (Type hints) — FastMCP использует их для построения схемы входных данных JSON, которую получает Claude
mcp.run()— запускает цикл stdio; Claude Desktop взаимодействует через stdin/stdout
mcp_server/tools.py
Полностью отделены от MCP — обычные функции Python, возвращающие строки JSON
Параметризованные SQL-запросы предотвращают инъекции:
WHERE topic LIKE ?сparamsФабрика
sqlite3.Rowпозволяет обращаться к столбцам по имени:row["topic"]_ensure_jobs_tables()используетCREATE TABLE IF NOT EXISTS— безопасно вызывать при каждом вызове инструмента
worker/job_runner.py
Опрашивает SQLite каждые 10 секунд — брокер сообщений не нужен, достаточно общей БД
PRAGMA journal_mode=WALпозволяет MCP-серверу читать данные, пока рабочий процесс их записываетЛогика повторных попыток: одна попытка при тайм-ауте или неверном JSON, затем запись в
failed_extractionsprocessed_emailsобновляется после каждого письма, поэтомуcheck_job_status_toolвсегда отражает текущий прогресс
utils/logger.py
get_logger(name)идемпотентен — безопасно вызывать из любого модуля, без дублирования обработчиковRotatingFileHandlerпредотвращает бесконечный рост размера файла на дискеИспользует
sys.stderrдля обработчика потока —sys.stdoutзарезервирован для протокола JSON-RPC MCP
ingestion/fetch_emails_imap.py
imaplib.IMAP4_SSL— подключается к любому IMAP-серверу; учетные данные загружаются из.envmail.search(None, "ALL")возвращает все ID сообщений; порядок обратный (сначала самые новые)Индикаторы выполнения
tqdmпоказывают статус получения и сохранения в SQLite в реальном времени с текущей темой в качестве суффиксаСохраняет в таблицу
raw_emailsчерезdb.raw_emails— идемпотентно (INSERT OR REPLACE)--outputявляется необязательным: CSV записывается только при явном указании
ingestion/extract_signals.py
OpenAI(base_url="http://127.0.0.1:10101/v1")— направляет клиент на LM StudioНизкий
temperature=0.1— более детерминированный вывод, лучше подходит для структурированного JSONУдаляет маркеры кода Markdown, в которые LLM может обернуть свой JSON-ответ
Возвращается к безопасным значениям по умолчанию, если парсинг не удался — конвейер никогда не падает из-за одного плохого письма
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityDmaintenanceA local MCP server that provides LLM clients with read/write access to email and calendar data from Gmail, iCloud, and generic IMAP providers. It runs entirely on your machine, keeping data private while enabling email management, calendar operations, and task handling through natural language.39MIT
- AlicenseAqualityDmaintenanceProvider-agnostic email MCP server that connects any IMAP mailbox to AI assistants, enabling email management through natural language.8AGPL 3.0
- Alicense-qualityBmaintenanceAn MCP server that receives emails on your domain and allows AI assistants to search, read, and manage them via natural language queries.1,276MIT
- AlicenseAqualityDmaintenanceMCP server for parsing .eml email files, extracting metadata, content, and attachments with smart organization into folders. Enables AI to read and handle email files offline without triggering trackers.22AGPL 3.0
Related MCP Connectors
Shipmail MCP server for AI agent custom-domain email inboxes with REST API and webhooks.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Hosted email MCP for AI agents with inboxes, send/receive, memory, recovery, and credits.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Shubby98/email-insights'
If you have feedback or need assistance with the MCP directory API, please join our Discord server