Outlook Semantic MCP - Security — Unique AI Documentation

Outlook Semantic MCP - Security

This document describes the security architecture, cryptographic decisions, and threat model for the Outlook Semantic MCP Server.

Security at a Glance:

Data Classification and Flow

What Is Stored Where

The Outlook Semantic MCP Server stores no email content in its own database. It acts as a secure pass-through: emails are fetched from Microsoft Graph into memory and uploaded directly to the Unique knowledge base. Nothing from the email body, subject, or attachments is written to the MCP server's PostgreSQL database.

Data Stored In Protection Contains Email Content?
Microsoft OAuth tokens (access + refresh) PostgreSQL user_profiles AES-256-GCM encrypted No
MCP bearer tokens PostgreSQL tokens Opaque 512-bit random values No
Sync state and progress counters PostgreSQL inbox_configurations Plaintext metadata No
Outlook folder structure (names + IDs) PostgreSQL directories Plaintext metadata No
Microsoft Graph subscription IDs PostgreSQL subscriptions Plaintext metadata No
Email subject, body, sender, recipients Unique Knowledge Base Ingested for semantic search Yes

Data Flow

Connection and Sync — The user authenticates once. The server obtains Microsoft tokens (kept server-side, encrypted), issues an opaque MCP token to the client, and begins syncing emails into the Unique knowledge base. No email content is stored in the MCP server's database.

Tool Usage — The MCP client uses its opaque token to call tools. The server handles all Microsoft Graph interaction internally — the client never sees Microsoft tokens.

Data Removal

Action What Is Removed
User calls delete_inbox_data Microsoft Graph subscription, per-user root scopes and all ingested email content in Unique KB, inbox configuration, folder sync data
MCP tokens Expire naturally (access: 60 seconds, refresh: 30 days); not automatically removed from KB

When a user calls delete_inbox_data, the per-user root scopes are removed from the Unique knowledge base, which also removes all ingested email content for that user.

Knowledge Base Data Isolation

Each connected user's emails are stored in a dedicated root scope (a top-level isolation boundary in the Unique knowledge base that logically separates one user's data from another's) within the Unique knowledge base. Scopes are created automatically when the user connects (by DirectoriesSyncModule) and are removed when delete_inbox_data is called.

Logical isolation:

Unique platform-level access:

Principal Access Level
Authenticated MCP user Can search their own emails via search_emails tool
MCP server service account Write access to ingestion and scope management APIs (used during sync)
Unique platform administrators Can access email scopes via the Unique API (e.g. scopesByCompany) — scopes are not surfaced in the Unique UI and require direct API or database access
Direct PostgreSQL access (MCP DB) Encrypted tokens and sync state only — no email content

Email scopes created by the MCP server are not visible in the Unique Knowledge Base UI. Accessing them requires direct Unique API calls or database access. Organizations with strict email privacy requirements should control who has API and database access to the Unique platform.

Security Layers

Webhook Requests

Webhook requests pass through each layer from top to bottom. Each layer must pass before the next is reached.

Layer Mechanism Protects Against
Transport TLS 1.2+ via Kong Gateway Eavesdropping, man-in-the-middle
Rate Limiting IP-based throttling at ingress layer (e.g., Kong) Brute-force, abuse
Webhook Integrity clientState validation Forged webhook notifications

MCP Requests

MCP requests pass through each layer from top to bottom. Each layer must pass before the next is reached.

Layer Mechanism Protects Against
Transport TLS 1.2+ via Kong Gateway Eavesdropping, man-in-the-middle
Rate Limiting IP-based throttling at ingress layer (e.g., Kong) Brute-force, abuse
Authentication OAuth 2.1 + PKCE Unauthorized access, authorization code interception
Session Integrity HMAC-SHA256 on OAuth session state Session hijacking via forged callbacks
Token Design 512-bit cryptographically random opaque values Token guessing
Data at Rest AES-256-GCM encryption for Microsoft tokens Token theft from database

Token Security

Microsoft Tokens (Encrypted at Rest)

Microsoft access and refresh tokens are stored encrypted using AES-256-GCM:

Aspect Implementation
Algorithm AES-256-GCM (authenticated encryption)
Key Size 256 bits (32 bytes, provided as 64 hex characters)
IV Random 12 bytes generated per encryption operation
Stored Format {iv}.{tag}.{data} — all components base64 encoded (handled by the @unique-ag/mcp-oauth package)
Key Storage ENCRYPTION_KEY environment variable

Why AES-GCM:

Token lifecycle:

  1. Microsoft issues tokens during OAuth flow
  2. Tokens encrypted immediately before database write into user_profiles
  3. Tokens decrypted only when needed for Graph API calls
  4. Re-encrypted after a successful refresh

MCP Tokens (Opaque Random Values)

MCP access and refresh tokens are cryptographically random opaque values:

Aspect Implementation
Generation randomBytes(64) encoded as base64url (512-bit)
Storage Stored directly in tokens table with TTL-based expiration
Validation Cache-first lookup, then database check
Security property Unguessability (512-bit random) — not hashing

Token TTLs:

Token Type Default TTL Source Configurable Via
MCP Access Token 60 seconds Service limit AUTH_ACCESS_TOKEN_EXPIRES_IN_SECONDS
MCP Refresh Token 30 days Service limit AUTH_REFRESH_TOKEN_EXPIRES_IN_SECONDS
Microsoft Access Token ~1 hour Microsoft limit Not configurable — issued by Microsoft
Microsoft Refresh Token ~90 days Microsoft limit Not configurable — issued by Microsoft

Session State Integrity (AUTH_HMAC_SECRET)

During the OAuth callback, the server validates session state using HMAC-SHA256:

HMAC-SHA256(AUTH_HMAC_SECRET, "{sessionId}:{sessionNonce}") → base64url

This prevents an attacker from injecting a forged OAuth callback that could hijack another user's session.

OAuth 2.1 with PKCE

The MCP OAuth implementation follows OAuth 2.1 with mandatory PKCE. The tokens issued to the client are opaque MCP tokens — Microsoft tokens remain on the server and are never sent to any client.

PKCE protection:

Token separation:

Token Stays On Used For
Microsoft access token Server only Graph API calls
Microsoft refresh token Server only Renewing Graph access
MCP access token Client Authenticating tool calls
MCP refresh token Client Renewing MCP access

Refresh Token Rotation

MCP refresh tokens are rotated on every use with family-based revocation:

How family revocation works:

Each token pair shares a familyId (format: tkfam_...) and a generation counter. On every refresh:

  1. Server checks usedAt — if already set, the token was reused
  2. If reused → entire family revoked immediately (all tokens with same familyId deleted)
  3. If valid → token marked used, new token issued with incremented generation

This detects scenarios where an attacker obtains a refresh token and uses it while the legitimate client still holds the original. Whichever uses it second triggers the revocation.

Webhook Validation

Microsoft Graph webhook notifications are validated using the clientState field:

Validation details:

Rate Limiting

Rate limiting is expected to be handled at the infrastructure/ingress layer (e.g., Kong ingress controller), not within the application itself. The following limits are recommended:

Scope Recommended Limit Layer Purpose
Global (all endpoints) 10 requests / 60 seconds Ingress (Kong) General brute-force protection
Authorization endpoint 3 requests / 60 seconds Ingress (Kong) Tighter protection for auth initiation

Secret Management

Required Secrets

Secret Rotation Impact
ENCRYPTION_KEY All users must reconnect
AUTH_HMAC_SECRET Only mid-OAuth-flow sessions invalidated
MICROSOFT_CLIENT_SECRET Update + restart only (zero-downtime)
MICROSOFT_WEBHOOK_SECRET All subscriptions must be recreated

Rotation Procedures

Key security considerations for rotation:

Security Checklist for Operators

See [Operator Manual — Self-Hosted] for the full pre-production checklist.