MCP server for querying an email corpus using vector search, full-text search, and hybrid retrieval with Gemini embeddings and LanceDB indexing
Email_RAG demonstrates solid tool design with clear naming (verb_noun pattern), comprehensive parameter schemas, and well-structured descriptions. All four tools follow action-verb conventions (list_, search, get_, get_). Descriptions are detailed (150-250 chars) and include usage guidance. However, output schemas are not explicitly documented in the source, and error handling lacks recovery guidance. The search tool's hybrid approach and recipient filter show thoughtful API design. Missing: explicit output schema documentation, error classification, and confirmation patterns for sensitive operations.
Retrieve the full email message by result ID: headers (From/To/Cc/Subject/Date), complete body text, and attachment list. Enables in-conversation quoting and analysis without requiring the user to follow a link.
Generate fresh signed URLs (15-minute expiry) for email and attachment access by result ID. Use this to mint links for search winners without re-running the full search.
List the mailbox folders in the indexed email corpus, plus the most frequent sender domains. Call this first when the user refers to a folder loosely ("my sent mail") or asks "who emails me the most" — use the exact folder names returned here in subsequent queries.
Search the email corpus using vector search, full-text search (BM25), or hybrid (vector + FTS fused via reciprocal-rank fusion). Returns ranked results with email metadata, text previews, and optional signed URLs for full message/attachment access.
Output schemas not documented. Tool descriptions explain what is returned (e.g., 'ranked results with email metadata, text previews'), but formal output schema definitions are absent from the source. LLMs cannot reliably extract fields or plan downstream calls without explicit response structure.
Error handling lacks recovery guidance. No evidence of error classification (retryable vs. user-fixable vs. fatal) or actionable error messages. E.g., if search fails due to invalid modality, the LLM receives no hint to validate against VALID_MODALITIES.
No confirmation or dry-run pattern for sensitive operations. get_links generates signed URLs (15-min expiry) and search returns URLs by default. No mechanism to preview or confirm before exposing access links.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 67 | <=2025-11-25 | v2 |
Parameter 'modalities' accepts free-form array but VALID_MODALITIES is hardcoded server-side. LLMs cannot discover valid values from the schema; they must infer from description or hallucinate. Should declare as enum: ['email', 'pdf', 'image', 'docx', 'xlsx', 'text'].
Pagination not explicitly documented. search accepts 'limit' but no offset/cursor or total_count guidance. Large result sets could exhaust context; LLMs need clear pagination semantics.