# Outlook Semantic MCP - Architecture

The Outlook Semantic MCP Server is a NestJS-based microservice that connects Microsoft Outlook email with the Unique platform through the Model Context Protocol (MCP). It syncs emails from connected mailboxes into the Unique knowledge base and exposes MCP tools for AI-assisted email search, draft creation, and contact lookup.

## High-Level Architecture

## System Components

### Authentication

The server manages two separate authentication layers:

- **MCP OAuth** — Authenticates MCP clients (e.g. Claude Desktop) using OAuth 2.1 with PKCE. Issues short-lived MCP tokens that clients use for all subsequent tool calls.

- **Microsoft OAuth** — Authenticates with Microsoft Entra ID using delegated permissions to obtain Graph API tokens on behalf of the signed-in user. These tokens are encrypted and stored server-side — they are never exposed to MCP clients.

The user authenticates once through a browser-based flow. The server exchanges the authorization code for Microsoft tokens (using a confidential client secret), stores them encrypted, and issues a separate MCP token to the client. From that point on, the MCP client authenticates with its MCP token, and the server uses the stored Microsoft tokens internally.

**Token Lifetimes:** MCP tokens (60-second access, 30-day refresh) are configurable. Microsoft tokens (~1-hour access, ~90-day refresh) are set by Microsoft. The server automatically refreshes expired Microsoft access tokens. If the refresh token itself expires (~90 days of inactivity), the user must reconnect. See [Security — Token TTLs](https://docs.unique.ai/it-operators/integrations-connectors/outlook-semantic-mcp/outlook-semantic-mcp-technical-reference/outlook-semantic-mcp-security) for the full reference.

### MCP Tools

The tools layer exposes capabilities to AI clients over the Model Context Protocol. Each tool call is authenticated via MCP OAuth and, where needed, delegates to Microsoft Graph using the stored Microsoft token.

Tools fall into these categories:

- **Email search** — Queries the Unique knowledge base (no live Graph API call per search)
- **Draft creation** — Creates drafts in the user's Outlook Drafts folder via Graph API
- **Contact lookup** — Searches the user's Microsoft contacts directory via Graph API
- **Mailbox utilities** — Lists folders and categories via Graph API for search filtering
- **Connection management** — Checks webhook status, reconnects, or removes the mailbox connection

See [Tools Reference](https://docs.unique.ai/it-operators/integrations-connectors/outlook-semantic-mcp/outlook-semantic-mcp-technical-reference/outlook-semantic-mcp-tools) for the full list and behavior details.

### Sync Pipeline

After a user connects, the following pipelines keep the knowledge base in sync with the user's mailbox. See [Flows](https://docs.unique.ai/it-operators/integrations-connectors/outlook-semantic-mcp/outlook-semantic-mcp-technical-reference/outlook-semantic-mcp-flows) for sequence diagrams.

**Full Sync** — triggers automatically after connection; fetches historical emails in paginated batches (newest first); applies `INGESTION_DEFAULT_MAIL_FILTERS`; resumable via persisted Graph cursor; initializes the watermark that live catch-up depends on.

**Live Catch-Up** — webhook-driven; acknowledged immediately via RabbitMQ, processed async in the consumer; queries Graph for messages since the watermark; watermark defaults to `now()` on inbox creation so notifications are never buffered.

**Directory Sync** — runs on a 5-minute delta query schedule (configurable via `DIRECTORY_SYNC_CRON_SCHEDULE`); keeps local folder tree in sync with Outlook; powers `list_mailboxes_and_directories` and folder-based search filtering; detects email deletion by tracking moves to excluded folders (e.g. Deleted Items).

**Subscription Management** — Graph webhook subscription created automatically on connect; renewed via Microsoft lifecycle notifications (`reauthorizationRequired`). If `subscriptionRemoved`, user calls `reconnect_inbox`; `verify_inbox_connection` reports status (`active`, `expiring_soon`, `expired`, `not_configured`).

**Delegated Access Discovery (optional, `DELEGATED_ACCESS_SCAN`)** — when not `disabled`, two background jobs keep delegated access state current. The **discovery job** (both `full_access_only` and `granular_access` modes) tests each connected user's access to other connected users' mailboxes via Microsoft Graph on a configurable schedule (default: every 12 hours; for `full_access_only` consider 4× per day since discovery is the sole revocation mechanism). The **verification job** (`granular_access` mode only, default: every 4 hours) confirms which individual folders within each delegated mailbox are still readable. Neither job triggers email ingestion — they write permission records that `search_emails` reads at query time to include the owner's scope alongside the delegate's own scope. A recovery scheduler (configurable via `DELEGATED_ACCESS_RECOVERY_CRON_SCHEDULE`) automatically restarts either job if it stalls. See [Delegated Access Discovery Flow](https://docs.unique.ai/it-operators/integrations-connectors/outlook-semantic-mcp/outlook-semantic-mcp-technical-reference/outlook-semantic-mcp-flows).

### Data Storage (PostgreSQL)

PostgreSQL stores all persistent state:

- **User profiles** — Identity, encrypted Microsoft OAuth tokens
- **MCP OAuth state** — Client registrations, sessions, authorization codes, access/refresh tokens with family-based revocation
- **Webhook subscriptions** — Active Microsoft Graph subscriptions per user
- **Sync state** — Full sync progress, live catch-up state, mail filters per user
- **Folder structure** — Outlook directory tree synced from Graph API for folder-based filtering
- **Delegated access state** — `delegatedAccessAccounts` (delegate/owner pairs with access type) and `delegatedAccessDirectories` (folder-level access grants for `granular_access` mode)

Microsoft tokens are encrypted at rest using AES-256-GCM. MCP tokens use 512-bit cryptographically random values with TTL-based expiration.

### Message Queue (RabbitMQ)

RabbitMQ decouples webhook receipt from email processing to meet Microsoft's strict webhook response deadline (< 10 seconds). When a webhook notification arrives, it is acknowledged immediately and enqueued for asynchronous processing.

Failed messages are routed to a Dead Letter Exchange for inspection and retry.

### Unique Integration

The server integrates with the Unique platform to:

- **Ingest emails** — Uploads email content to the Unique knowledge base during both full sync and live catch-up
- **Search emails** — Queries the knowledge base for semantic email search (the `search_emails` tool)
- **Manage scopes** — Creates and manages the knowledge base scope to which emails are synced
