Outlook Semantic MCP - Tools
11 min read
Outlook Semantic MCP - Tools
The Outlook Semantic MCP Server exposes tools whose availability depends on the deployment mode (MCP_BACKEND) and debug settings.
Mode A (
verify_inbox_connection, reconnect_inbox, delete_inbox_data, and sync_progress are only available when MCP_BACKEND=MicrosoftGraphAndUniqueApi. They are not registered in MicrosoftGraph mode.
Debug-Mode Tools
run_full_sync, pause_full_sync, resume_full_sync, and restart_full_sync are only available when MCP_BACKEND=MicrosoftGraphAndUniqueApi AND MCP_DEBUG_MODE=enabled. They do not appear for standard deployments or in MicrosoftGraph mode. Note: Debug mode exposes these tools to all connected MCP users, not just operators. Do not leave enabled in production.
Tool Overview
Tool | Category | Mutating | Mode |
|---|---|---|---|
Email Search | No | Both | |
Email Search | No | Both | |
Draft Creation | Yes | Both | |
Contact Lookup | No | Both | |
Mailbox Utilities | No | Both | |
Mailbox Utilities | Yes | Both | |
Subscription Management | No | Mode A only | |
Subscription Management | Yes | Mode A only | |
Subscription Management | Yes | Mode A only | |
Sync Monitoring | No | Mode A only | |
Full Sync Control (debug only) | Yes | Mode A only | |
Full Sync Control (debug only) | Yes | Mode A only | |
Full Sync Control (debug only) | Yes | Mode A only | |
Full Sync Control (debug only) | Yes | Mode A only |
Mutating means the tool writes data to at least one of the following:
Outlook mailbox — creates or modifies data in Microsoft Graph (e.g. a draft email or a webhook subscription)
Internal database — persists or removes state managed by this server (e.g. subscription records, sync state, folder cache)
Unique knowledge base — indexes or removes email content from the knowledge base used for search
Tool | What it mutates |
|---|---|
| Creates a draft message in the user's Outlook mailbox via Microsoft Graph |
| Refreshes the folder cache in the internal database by re-fetching the folder tree from Microsoft Graph |
| Creates or renews the Microsoft Graph webhook subscription and writes the subscription record to the internal database |
| Cancels the Microsoft Graph webhook subscription and deletes the subscription record, folder cache, root scope, and all ingested email content from the Unique knowledge base |
| Triggers ingestion of all mailbox emails into the Unique knowledge base and updates sync state in the internal database |
| Updates the sync state to |
| Updates the sync state to resume ingestion in the internal database |
| Resets sync state in the internal database and re-triggers full ingestion into the Unique knowledge base |
Email Search
search_emails
Search emails and return matched passages. The tool behaviour and input schema differ by deployment mode.
Available in: Both modes
Mode A: MicrosoftGraphAndUniqueApi
Runs two searches in parallel — semantic search against the Unique knowledge base and a KQL keyword search against Microsoft Graph — then merges and deduplicates the results. Both query arrays are required and must address the same user question.
Input parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
| array (1–10) | Yes | Semantic searches. Compose 2–4 parallel entries that approach the question from different angles. |
| array (1–10) | Yes | KQL keyword searches addressing the same question. |
Each entry in uniqueSemanticSearchQueries:
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Natural-language search query |
| No | Scope to one mailbox. When omitted all accessible mailboxes are searched. | |
| array | No | Structured filters. Multiple condition objects are OR-combined; fields within one object are AND-combined. |
| integer (100–200) | No | Maximum results for this query. Default: 100. Use 200 for broad queries. |
Each entry in msGraphKeywordSearchQueries:
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | KQL query string. See KQL reference below. |
| No | Scope to one mailbox. | |
| integer (1–100) | No | Maximum results for this query. Default: 100. |
Each object in conditions (applies to uniqueSemanticSearchQueries entries only) may include:
Field | Type | Description |
|---|---|---|
|
| ISO 8601 UTC — emails received on or after this date |
|
| ISO 8601 UTC — emails received on or before this date |
|
| Filter by sender. Use |
|
| Filter by To recipient |
|
| Filter by CC recipient |
|
| Folder IDs from |
|
| Filter by attachment presence. Value is a string, not a boolean. |
|
| Category labels from |
Available operators:
Singular:
equals,notEquals,greaterThan,greaterThanOrEqual,lessThan,lessThanOrEqual,contains,notContains,isNull,isNotNull,isEmpty,isNotEmptyArray:
in,notIn,containsAny(email fields only — expands to OR ofcontainsfilters)
Example (Mode A):
{
"uniqueSemanticSearchQueries": [
{
"search": "quarterly report from Alice",
"conditions": [
{
"fromSenders": { "value": "alice@example.com", "operator": "equals" },
"dateFrom": { "value": "2024-01-01T00:00:00Z", "operator": "greaterThanOrEqual" }
}
],
"limit": 100
},
{
"search": "Q1 budget summary",
"conditions": [
{
"fromSenders": { "value": "alice@example.com", "operator": "equals" }
}
],
"limit": 100
}
],
"msGraphKeywordSearchQueries": [
{
"kqlQuery": "from:alice@example.com subject:\"quarterly report\" received>=2024-01-01",
"limit": 100
}
]
}Mode B: MicrosoftGraph
Calls the Microsoft Graph Search API directly with KQL queries. No semantic search is performed. Only msGraphKeywordSearchQueries is accepted.
Input parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
| array (1–10) | Yes | KQL keyword searches. |
Each entry uses the same kqlQuery, mailbox, and limit fields as described in Mode A above.
Note: Folder filtering via directories conditions is not supported in Mode B. The Microsoft Graph Search API does not expose a folder-scoped KQL predicate.
Example (Mode B):
{
"msGraphKeywordSearchQueries": [
{
"kqlQuery": "from:alice@example.com subject:\"quarterly report\" received>=2024-01-01",
"limit": 100
}
]
}KQL reference
Supported KQL property filters for kqlQuery:
Filter | Example | Notes |
|---|---|---|
|
| Sender SMTP, display name, or domain |
|
| To recipient |
|
| CC recipient |
|
| Any of from/to/cc/bcc |
|
| Words in subject |
|
| Words in body |
|
| Received on or after |
|
| Received on or before |
|
| Has attachments |
|
| Outlook category |
|
| Message type |
Syntax rules: - No space between property and value: from:alice@example.com not from: alice@example.com - Boolean operators must be uppercase: AND, OR, NOT - Suffix wildcards only: report*, not *report - Phrases in double quotes: subject:"quarterly report" - Do NOT use folder: — it is not supported and causes a request error
Return shape (both modes)
{
success: boolean;
message?: string; // error description when success is false
status?: string; // informational subscription/backend status
syncWarning?: string; // Mode A only — present when ingestion is incomplete or in error state. Always display to the user before showing results.
searchNotes?: string; // informational notes about the search run (e.g. unrecognised folders excluded). Display to the user after results.
results?: Array<{
uniqueContentId?: string; // Unique KB content ID. Present for semantic-backend results only.
msGraphMessageId?: string; // Microsoft Graph message ID. Present for Graph-backend results; also present for semantic results when both backends matched the same email.
backend: "Unique" | "MsGraph"; // which backend returned this result
folderId: string; // internal folder ID — do not display to users
title: string; // email subject
from: string; // sender email address
receivedDateTime?: string | null; // ISO 8601
text: string; // matched passage or excerpt — not the full body
outlookWebLink: string; // direct URL to open in Outlook Web — use as link target when non-empty
sourceMailbox?: string | null; // mailbox this email belongs to
openEmailParams: { // pass directly to open_email_by_id without modification
id: string;
idType: "Unique" | "MsGraph";
mailbox?: string;
parentFolderId?: string;
idIsImmutable?: boolean;
};
}>;
}Usage notes:
Pass the
openEmailParamsobject from a result directly toopen_email_by_idto retrieve the full email body.If
syncWarningis present (Mode A only), display it to the user and callsync_progressto check ingestion status — results may be incomplete.If
searchNotesis present, display it to the user after showing results.Folder filtering via
conditions[].directoriesis supported in Mode A only.Well-known system folder names (
"Inbox","Sent Items","Drafts") can be used directly indirectories— no need to calllist_mailboxes_and_directoriesfor those.For custom folders, call
list_mailboxes_and_directoriesfirst to obtain folder IDs.
open_email_by_id
Retrieve the full content of an email by its ID returned from search_emails.
Input parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Email identifier. Use |
|
| Yes | Backend type. Use |
| No | Use | |
| string | No | Use |
| boolean | No | Use |
Return shape:
{
success: boolean;
status?: string;
message?: string;
emailData?: {
id: string;
title: string | null;
metadata: unknown | null;
text: string; // full email body or the matched chunks depending on which search returned the results
};
}Usage notes:
Always pass the
openEmailParamsobject from asearch_emailsresult directly as the tool input — do not construct these parameters manually.The
textfield inemailDatacontains the full email body. This is distinct from thetextfield insearch_emailsresults, which contains only a matched passage or excerpt.
Draft Creation
create_draft_email
Create a draft email in the connected Outlook mailbox. The draft is saved to the Drafts folder but not sent — the user must open it in Outlook and send manually.
Input parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Subject line |
| string | Yes | Email body. Must match the format declared in |
|
| Yes | Body format — |
| array | Yes | Primary recipients |
| string (email) | Yes | Recipient email address |
| string | No | Recipient display name |
| array | No | CC recipients (same shape as |
| array | No | Files to attach |
| string | Yes | File name including extension (e.g. |
| string | Yes | File content URI. Two schemes supported (see below) |
Attachment data URI schemes:
Scheme | Format | Description |
|---|---|---|
Unique KB |
| File from the Unique knowledge base |
Inline base64 |
| Base64-encoded content with explicit MIME type |
Attachment scheme availability
The unique://content/{contentId} scheme only works when UNIQUE_SERVICE_AUTH_MODE=cluster_local. In external auth mode the Unique ingestion service cannot resolve internal content URIs — use the data:[mediatype];base64,<data> scheme instead.
Return shape:
{
success: boolean;
message: string;
draftId?: string; // Microsoft message ID
webLink?: string; // link to open draft in Outlook
attachmentsFailed?: Array<{
fileName: string;
reason: string;
}>;
}Usage notes:
Use
lookup_contactsto resolve recipient email addresses before calling this tool.If attachments partially fail, the draft is still created and
draftIdis returned alongside theattachmentsFailedlist.The
webLinkin the response opens the draft directly in Outlook Web.
Contact Lookup
lookup_contacts
Search for contacts by name across the Microsoft People API and the connected inbox. Use this to resolve recipient addresses before creating a draft.
Input parameters:
Parameter | Type | Required | Description |
|---|---|---|---|
| string (min 2 chars) | Yes | Name or partial name to search for |
Return shape:
{
contacts: Array<{
name: string;
email: string;
source: "people_api" | "inbox";
similarityScore: number;
}>;
message?: string;
}Usage notes:
Results come from two sources: the Microsoft People API (colleagues, frequent contacts) and emails found in the synced inbox.
similarityScoreranks results by name similarity — use this to surface the best match.
Mailbox Utilities
These tools return metadata needed to build filters for search_emails. They do not manage or modify mailbox data.
list_categories
List all Outlook mail categories available for the user.
Input parameters: None
Return shape:
{
success: boolean;
message: string;
status?: string;
categories?: string[]; // category display names
count?: number;
}Usage notes:
Category names returned here can be passed to the
categoriesfilter insearch_emails.
list_mailboxes_and_directories
List all Outlook mailboxes and their folder trees available to the user.
Available in: Both modes
Input parameters: None
Return shape:
{
success: boolean;
message: string;
status?: string;
mailboxes?: Array<{
email: string | null;
displayName: string | null;
isOwn: boolean; // true for the user's own primary mailbox
folders: Array<{
id: string; // pass to directories filter in search_emails
displayName: string;
children: Array<...>; // recursive — same shape
}>;
}>;
}Usage notes:
Folder
idvalues can be passed to thedirectoriesfilter insearch_emailsto narrow results to a specific folder.In Mode A, the folder tree is synced from Microsoft Graph and reflects the user's current mailbox structure. Calling this tool triggers a fresh sync of the folder tree.
Folder filtering via
directoriesis only effective in Mode A (MicrosoftGraphAndUniqueApi). In Mode B, the Microsoft Graph Search API does not support folder-scoped filtering — thedirectoriescondition is ignored.Well-known system folder names (
"Inbox","Sent Items","Drafts", etc.) can be used directly insearch_emailswithout calling this tool first.When
DELEGATED_ACCESS_SCANis enabled, themailboxesarray includes delegated mailboxes alongside the user's own mailbox. TheisOwnfield istruefor the user's primary mailbox andfalsefor delegated ones. Folder IDs from delegated mailboxes can be passed to thedirectoriescondition insearch_emailsto narrow results to a specific folder in a delegated mailbox (folder filtering viadirectoriesis only effective in Mode A).
Subscription Management
Mode A (
verify_inbox_connection, reconnect_inbox, and delete_inbox_data are only available when MCP_BACKEND=MicrosoftGraphAndUniqueApi. These tools are not registered in MicrosoftGraph mode because no webhook subscriptions are created.
verify_inbox_connection
Check the status of the inbox connection and Microsoft Graph webhook subscription.
Input parameters: None
Return shape:
{
status: "active" | "expiring_soon" | "expired" | "not_configured";
message: string;
subscription: {
id: string;
expiresAt: string;
minutesUntilExpiration: number;
createdAt: string;
updatedAt: string;
} | null;
}Status | Meaning | Action |
|---|---|---|
| Subscription is valid | None required |
| Expires within 15 minutes | Renewal is automatic; no action needed |
| Subscription has lapsed | Call |
| No subscription exists | Call |
reconnect_inbox
Re-establish the Microsoft Outlook inbox subscription when expired or not configured.
Input parameters: None
Return shape:
{
success: boolean;
message: string;
subscription: {
id: string;
expiresAt: string;
minutesUntilExpiration: number;
status: "created" | "already_active" | "expiring_soon";
} | null;
}Usage notes:
Safe to call even if a subscription already exists — it will return
already_activewithout creating a duplicate.When a new subscription is created (status:
created), a full sync is triggered automatically. If the subscription isalready_activeorexpiring_soon, no full sync is triggered.
delete_inbox_data
Permanently delete all synced email data from Unique and cancel the Microsoft Graph subscription. This stops future email ingestion and removes all previously ingested email content for your inbox from the Unique knowledge base.
Input parameters: None
Return shape:
{
success: boolean;
message: string;
subscription: {
id: string;
status: "removed" | "not_found";
} | null;
}Usage notes:
This is a destructive operation: all previously ingested email content for the user is permanently removed from the Unique knowledge base, and no new emails will be ingested.
To resume ingestion after deletion, call
reconnect_inbox.
Sync Monitoring
Mode A (
sync_progress is only available when MCP_BACKEND=MicrosoftGraphAndUniqueApi. There is no sync pipeline in MicrosoftGraph mode.
sync_progress
Check the current state of the full email sync and live catch-up pipeline. Call this after a syncWarning is returned by search_emails, or to monitor initial sync progress after connecting.
Input parameters: None
Return shape:
{
state: "error" | "running" | "finished";
message: string;
userEmail: string;
syncStats?: {
fullSyncState: "ready" | "running" | "waiting-for-ingestion" | "paused" | "failed";
liveCatchUpState: "ready" | "running" | "failed";
runAt: string | null; // last completion time
startedAt: string | null; // last start time
expectedTotal: number | null; // total emails at sync start
skippedMessages: number; // filtered out by inbox filters
scheduledForIngestion: number; // successfully uploaded
failedToUploadForIngestion: number;
filters: {
retentionWindowInDays: number;
ignoredBefore: string; // ISO 8601 UTC cutoff — emails before this date are excluded
ignoredSenders: string[];
ignoredContents: string[];
};
dateWindow: {
newestReceivedEmailDateTime: string | null;
oldestReceivedEmailDateTime: string | null;
newestLastModifiedDateTime: string | null;
};
} | null;
ingestionStats?: {
failed: number;
finished: number;
inProgress: number;
} | { state: "error" } | null;
debugData?: { // only present when MCP_DEBUG_MODE=enabled
providerUserId: string;
userProfileId: string;
subscriptionId: string;
} | null;
}Usage notes:
state: "running"means the full sync is actively fetching and uploading. Search results will be partial untilstate: "finished".scheduledForIngestioncounts emails uploaded to Unique;ingestionStats.finishedcounts those confirmed processed by the knowledge base.failedToUploadForIngestionemails were skipped after retries — check operator logs for details.syncStats.liveCatchUpState: "failed"indicates the live catch-up pipeline stalled. Recovery is automatic — theINGESTION_LIVE_CATCHUP_RECOVERY_CRONscheduler resets it within 5 minutes. No user-callable tool exists for this outsideMCP_DEBUG_MODE; users should wait and operators can monitor pod logs.
Debug-Mode Tools
The following four tools are only available when MCP_DEBUG_MODE=enabled is set in the server configuration. They are intended for operators diagnosing sync issues, not for end users.
Mode A (
These tools are only available when MCP_BACKEND=MicrosoftGraphAndUniqueApi AND MCP_DEBUG_MODE=enabled.
run_full_sync
Trigger a full re-sync of the Outlook mailbox into the knowledge base. Skips if a sync was run recently.
Input parameters: None
Return shape:{ success: boolean; message: string }
Usage notes: Use sync_progress to monitor progress after triggering.
pause_full_sync
Pause an in-progress full sync. The current batch finishes before the sync stops.
Input parameters: None
Return shape:{ success: boolean; message: string }
Usage notes: Use resume_full_sync to continue from where the sync paused.
resume_full_sync
Resume a paused full sync from the point it was paused.
Input parameters: None
Return shape:{ success: boolean; message: string }
restart_full_sync
Restart the full sync from scratch, discarding all previous progress.
Input parameters: None
Return shape:{ success: boolean; message: string; version?: string }
Usage notes: This is destructive — all sync progress counters and the next-page cursor are reset. Use only when recovering from a corrupted sync state.
Related Documentation
Full Sync - Full sync mechanics and states
Live Catch-Up - Webhook-driven real-time ingestion
Flows - Sequence diagrams for OAuth, sync, and draft creation flows
Permissions - Microsoft Graph permissions required by these tools