email-insights
email-insights
Ein MCP-Server, der E-Mail-Signalanalysen für Claude Desktop bereitstellt, inklusive eines Hintergrund-Workers für geplante asynchrone Extraktionsaufträge und strukturiertes Logging.
Projektstruktur
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
Einrichtung
1. Abhängigkeiten installieren
pip install -r requirements.txt2. IMAP-Zugangsdaten konfigurieren
Kopieren Sie .env.example nach .env und tragen Sie Ihre Zugangsdaten ein:
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 INBOXFür Gmail generieren Sie ein App-spezifisches Passwort unter myaccount.google.com/apppasswords.
3. E-Mails in SQLite abrufen
Abrufen aller E-Mails aus Ihrem Posteingang und Speichern in der Tabelle raw_emails:
python ingestion/fetch_emails_imap.pyEin Fortschrittsbalken zeigt den Live-Status des Abrufs und Speichervorgangs an. Optionen:
# 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 starten
Öffnen Sie LM Studio und laden Sie ein beliebiges instruktionsfolgendes Modell (Llama 3, Mistral usw.)
Starten Sie den lokalen Server: Local Server → Start Server
Standard-URL:
http://127.0.0.1:10101Kopieren Sie die Modell-ID-Zeichenfolge und fügen Sie sie in
ingestion/extract_signals.pyalsLOCAL_MODELein
5. Signalextraktion ausführen
python ingestion/store_signals.pyDies liest data/emails.csv, sendet jede E-Mail zur Signalextraktion an Ihr lokales LLM
und speichert die Ergebnisse in database/signals.db.
6. Hintergrund-Worker starten
Der Worker ist ein separater Prozess, der auf geplante Extraktionsaufträge wartet. Führen Sie ihn in einem eigenen Terminal aus:
python worker/job_runner.pyDer Worker protokolliert alle Aktivitäten in logs/worker.log und nach stderr. Er fragt SQLite alle 10 Sekunden ab und übernimmt automatisch alle anstehenden oder fälligen geplanten Aufträge.
7. Claude Desktop verbinden
Fügen Sie diesen Server zu Ihrer Claude Desktop-Konfiguration hinzu:
Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"email-insights": {
"command": "python",
"args": ["/absolute/path/to/email-insights/mcp_server/server.py"]
}
}
}Starten Sie Claude Desktop neu. Sie sollten email-insights in der Tool-Liste sehen.
MCP-Tools
Abfrage-Tools
Tool | Beschreibung |
| Signale mit optionalen Datums-/Themen-/Tonfall-Filtern abfragen |
| Anzahl der E-Mails pro Themenkategorie |
| Aufschlüsselung nach Absendertyp mit Dringlichkeitsstatistiken |
| Signale nach Schlüsselwörtern durchsuchen |
Auftragsplanungs-Tools
Tool | Beschreibung |
| Einen Extraktionsauftrag erstellen – wird sofort, zu einer geplanten Zeit oder um Mitternacht ausgeführt |
| Echtzeit-Fortschritt für einen Auftrag abrufen (aktualisiert nach jeder E-Mail) |
| Nur die E-Mails erneut in die Warteschlange stellen, die bei einem vorherigen Auftrag fehlgeschlagen sind |
Alle Planungstools kehren sofort zurück. Die Extraktion erfolgt asynchron im Worker-Prozess.
schedule_extraction_tool Ausführungsmodi
| Verhalten |
|
| Worker übernimmt beim nächsten Abruf (Standard) | nicht verwendet |
| Wird zu einer bestimmten Zeit ausgeführt |
|
| Wird heute Nacht um 00:00:00 ausgeführt | nicht verwendet |
Architektur
Claude Desktop ──stdio──▶ mcp_server/server.py
│
mcp_server/tools.py
│
SQLite signals.db
│
worker/job_runner.py ◀── runs separately
│
LM Studio (local LLM)Der MCP-Server und der Worker sind zwei völlig getrennte Prozesse, die sich nur die SQLite-Datenbank teilen. Der MCP-Server wartet niemals auf den Abschluss der Extraktion – er erstellt einen Auftragsdatensatz und kehrt sofort zurück. Der Worker ist für alle Schreibvorgänge in die Tabellen jobs und failed_extractions verantwortlich (Statusaktualisierungen, Fortschritt, Fehler); der MCP-Server liest nur den Auftragsstatus.
SQLite-Schema
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'))
);Sowohl jobs als auch failed_extractions werden bei der ersten Verwendung automatisch erstellt – keine manuelle Migration erforderlich.
Strukturiertes Logging
Alle Worker-Aktivitäten werden in logs/worker.log (automatisch erstellt) und nach stderr geschrieben.
Log-Format:
[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 failedDie Log-Datei rotiert bei 5 MB und behält die letzten 3 Dateien (worker.log, worker.log.1, worker.log.2).
Was man aus dem Code lernen kann
mcp_server/server.py
FastMCP("email-insights")— erstellt die Serverinstanz mit einem Anzeigenamen@mcp.tool()— registriert die dekorierte Funktion als aufrufbares MCP-ToolDocstrings sind wichtig — Claude liest sie, um zu entscheiden, wann und wie jedes Tool aufgerufen werden soll
Typ-Hinweise — FastMCP verwendet sie, um das JSON-Eingabeschema zu erstellen, das Claude erhält
mcp.run()— startet die stdio-Schleife; Claude Desktop kommuniziert über stdin/stdout
mcp_server/tools.py
Völlig getrennt von MCP — einfache Python-Funktionen, die JSON-Strings zurückgeben
Parametrisierte SQL-Abfragen verhindern Injektionen:
WHERE topic LIKE ?mitparamsDie
sqlite3.Row-Factory ermöglicht den Zugriff auf Spalten per Name:row["topic"]_ensure_jobs_tables()verwendetCREATE TABLE IF NOT EXISTS— sicher bei jedem Tool-Aufruf
worker/job_runner.py
Fragt SQLite alle 10 Sekunden ab — kein Message Broker erforderlich, nur eine gemeinsame DB
PRAGMA journal_mode=WALermöglicht dem MCP-Server das Lesen, während der Worker schreibtWiederholungslogik: ein erneuter Versuch bei Timeout oder fehlerhaftem JSON, danach
failed_extractionsprocessed_emailswird nach jeder E-Mail aktualisiert, sodasscheck_job_status_toolimmer den Live-Fortschritt widerspiegelt
utils/logger.py
get_logger(name)ist idempotent — sicher aus jedem Modul aufrufbar, keine doppelten HandlerRotatingFileHandlerverhindert unbegrenztes FestplattenwachstumVerwendet
sys.stderrfür den Stream-Handler —sys.stdoutist für das JSON-RPC-Protokoll von MCP reserviert
ingestion/fetch_emails_imap.py
imaplib.IMAP4_SSL— verbindet sich mit jedem IMAP-Server; Zugangsdaten werden aus.envgeladenmail.search(None, "ALL")gibt alle Nachrichten-IDs zurück; umgekehrt für die Reihenfolge "neueste zuerst"tqdm-Fortschrittsbalken zeigen den Live-Abruf- und SQLite-Speicherstatus mit dem aktuellen Betreff als Suffix anSpeichert in der Tabelle
raw_emailsviadb.raw_emails— idempotent (INSERT OR REPLACE)--outputist optional: CSV wird nur geschrieben, wenn es explizit übergeben wird
ingestion/extract_signals.py
OpenAI(base_url="http://127.0.0.1:10101/v1")— richtet den Client auf LM StudioNiedrige
temperature=0.1— deterministischere Ausgabe, besser für strukturiertes JSONEntfernt Markdown-Code-Blöcke, die das LLM möglicherweise um seine JSON-Antwort legt
Greift auf sichere Standardwerte zurück, falls das Parsen fehlschlägt — die Pipeline stürzt bei einer fehlerhaften E-Mail nie ab
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