Skip to main content
Glama
Shubby98

email-insights

by Shubby98

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.md

Related MCP server: io.github.p-w-4-z/inbox-mcp

Einrichtung

1. Abhängigkeiten installieren

pip install -r requirements.txt

2. 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 INBOX

Fü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.py

Ein 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-01

4. 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:10101

  • Kopieren Sie die Modell-ID-Zeichenfolge und fügen Sie sie in ingestion/extract_signals.py als LOCAL_MODEL ein

5. Signalextraktion ausführen

python ingestion/store_signals.py

Dies 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.py

Der 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

get_email_signals_tool

Signale mit optionalen Datums-/Themen-/Tonfall-Filtern abfragen

get_topic_distribution_tool

Anzahl der E-Mails pro Themenkategorie

get_sender_patterns_tool

Aufschlüsselung nach Absendertyp mit Dringlichkeitsstatistiken

search_signals_tool

Signale nach Schlüsselwörtern durchsuchen

Auftragsplanungs-Tools

Tool

Beschreibung

schedule_extraction_tool

Einen Extraktionsauftrag erstellen – wird sofort, zu einer geplanten Zeit oder um Mitternacht ausgeführt

check_job_status_tool

Echtzeit-Fortschritt für einen Auftrag abrufen (aktualisiert nach jeder E-Mail)

retry_failed_emails_tool

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

run_mode

Verhalten

scheduled_time

"now"

Worker übernimmt beim nächsten Abruf (Standard)

nicht verwendet

"scheduled"

Wird zu einer bestimmten Zeit ausgeführt

"HH:MM" oder "YYYY-MM-DD HH:MM"

"midnight"

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 failed

Die 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-Tool

  • Docstrings 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 ? mit params

  • Die sqlite3.Row-Factory ermöglicht den Zugriff auf Spalten per Name: row["topic"]

  • _ensure_jobs_tables() verwendet CREATE 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=WAL ermöglicht dem MCP-Server das Lesen, während der Worker schreibt

  • Wiederholungslogik: ein erneuter Versuch bei Timeout oder fehlerhaftem JSON, danach failed_extractions

  • processed_emails wird nach jeder E-Mail aktualisiert, sodass check_job_status_tool immer den Live-Fortschritt widerspiegelt

utils/logger.py

  • get_logger(name) ist idempotent — sicher aus jedem Modul aufrufbar, keine doppelten Handler

  • RotatingFileHandler verhindert unbegrenztes Festplattenwachstum

  • Verwendet sys.stderr für den Stream-Handler — sys.stdout ist 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 .env geladen

  • mail.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 an

  • Speichert in der Tabelle raw_emails via db.raw_emails — idempotent (INSERT OR REPLACE)

  • --output ist 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 Studio

  • Niedrige temperature=0.1 — deterministischere Ausgabe, besser für strukturiertes JSON

  • Entfernt 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

F
license - not found
-
quality - not tested
D
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    B
    quality
    D
    maintenance
    A 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.
    39
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provider-agnostic email MCP server that connects any IMAP mailbox to AI assistants, enabling email management through natural language.
    8
    AGPL 3.0
  • A
    license
    -
    quality
    B
    maintenance
    An MCP server that receives emails on your domain and allows AI assistants to search, read, and manage them via natural language queries.
    1,276
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    MCP 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.
    2
    2
    AGPL 3.0

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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