email-insights
email-insights
Claude Desktop에 이메일 신호 분석 기능을 제공하는 MCP 서버로, 예약된 비동기 추출 작업을 위한 백그라운드 워커와 구조화된 로깅 기능을 포함합니다.
프로젝트 구조
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 INBOXGmail의 경우, 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에 기록합니다. 10초마다 SQLite를 폴링하며 보류 중이거나 예정된 작업을 자동으로 가져옵니다.
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로그 파일은 5MB 단위로 순환되며 최근 3개의 파일(worker.log, worker.log.1, worker.log.2)을 유지합니다.
코드에서 배울 점
mcp_server/server.py
FastMCP("email-insights")— 표시 이름으로 서버 인스턴스 생성@mcp.tool()— 데코레이트된 함수를 호출 가능한 MCP 도구로 등록Docstring의 중요성 — Claude는 이를 읽고 도구를 언제 어떻게 호출할지 결정함
타입 힌트 — FastMCP는 이를 사용하여 Claude가 수신하는 JSON 입력 스키마를 구축함
mcp.run()— stdio 루프 시작; Claude Desktop은 stdin/stdout을 통해 통신함
mcp_server/tools.py
MCP와 완전히 분리됨 — JSON 문자열을 반환하는 일반 Python 함수
매개변수화된 SQL 쿼리로 인젝션 방지:
params와 함께WHERE topic LIKE ?사용sqlite3.Row팩토리를 사용하면 이름으로 열에 액세스 가능:row["topic"]_ensure_jobs_tables()는CREATE TABLE IF NOT EXISTS를 사용하여 모든 도구 호출 시 안전하게 실행 가능
worker/job_runner.py
10초마다 SQLite 폴링 — 메시지 브로커 필요 없음, 공유 DB만 사용
PRAGMA journal_mode=WAL을 통해 워커가 쓰는 동안 MCP 서버가 읽기 가능재시도 로직: 타임아웃 또는 잘못된 JSON 발생 시 1회 재시도 후
failed_extractions로 이동processed_emails는 이메일마다 업데이트되어check_job_status_tool이 항상 실시간 진행 상황을 반영함
utils/logger.py
get_logger(name)은 멱등성을 가짐 — 어떤 모듈에서든 안전하게 호출 가능, 중복 핸들러 없음RotatingFileHandler는 디스크 공간의 무한한 증가를 방지함스트림 핸들러에
sys.stderr사용 —sys.stdout은 MCP의 JSON-RPC 프로토콜을 위해 예약됨
ingestion/fetch_emails_imap.py
imaplib.IMAP4_SSL— 모든 IMAP 서버에 연결;.env에서 자격 증명 로드mail.search(None, "ALL")은 모든 메시지 ID를 반환; 최신순으로 정렬하려면 역순 사용tqdm진행률 표시줄은 현재 제목을 접미사로 표시하며 실시간 가져오기 및 SQLite 저장 상태를 보여줌db.raw_emails를 통해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에 적합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