MP

microsoft/purview-dlm-mcp

Security testing
9 stars 7 forks Quality 84 Trend 37MIT

An MCP (Model Context Protocol) server for diagnosing Microsoft Purview Data Lifecycle Management issues via Exchange Online PowerShell.

Overview

An MCP (Model Context Protocol) server for diagnosing Microsoft Purview Data Lifecycle Management issues via Exchange Online PowerShell. - — run_powershell for executing read-only Exchange Online commands, get_execution_log for retrieving a full audit trail, ask_learn for Microsoft Learn documentation lookup, create_issue for reporting issues with the MCP server to GitHub, and submit_feedback for collecting structured diagnostic session feedback - — step-by-step diagnostic workflows aligned to common DLM symptoms - — automated evaluation engine that parses PowerShell output and produces structured findings with remediation - — only pre-approved read-only cmdlets can be executed; mutating commands are blocked - Node.js 18+ - PowerShell 7 — 7.4.22, 7.5.13, 7.6.9 or later. PowerShell bundles its own .NET runtime, and earlier builds are exposed to CVE-2026-111497; updating the system .NET does not patch pwsh. - ExchangeOnlineManagement PowerShell module (v3.

README

Microsoft Purview DLM Diagnostics MCP

An MCP (Model Context Protocol) server for diagnosing Microsoft Purview Data Lifecycle Management issues via Exchange Online PowerShell.

Features

  • 5 MCP tools — run_powershell for executing read-only Exchange Online commands, get_execution_log for retrieving a full audit trail, ask_learn for Microsoft Learn documentation lookup, create_issue for reporting issues with the MCP server to GitHub, and submit_feedback for collecting structured diagnostic session feedback
  • 11 TSG reference guides — step-by-step diagnostic workflows aligned to common DLM symptoms
  • 72 diagnostic checks — automated evaluation engine that parses PowerShell output and produces structured findings with remediation
  • Cmdlet allowlist — only pre-approved read-only cmdlets can be executed; mutating commands are blocked

Prerequisites

Required Permissions

The authenticating user (DLM_UPN) needs read access to both Exchange Online and Security & Compliance PowerShell sessions.

Option Roles Notes
Least-privilege Global Reader + Compliance Administrator Recommended — covers both EXO and S&C read access
Single role group Organization Management Covers both workloads but broader than necessary
Full admin Global Administrator Works but overly broad — not recommended

Why Both Workloads?

The server connects to two PowerShell sessions:

  • Exchange Online (Connect-ExchangeOnline) — cmdlets like Get-Mailbox, Get-MailboxStatistics, Export-MailboxDiagnosticLogs, Get-OrganizationConfig
  • Security & Compliance (Connect-IPPSSession) — cmdlets like Get-RetentionCompliancePolicy, Get-RetentionComplianceRule, Get-AdaptiveScope, Get-ComplianceTag

Exchange cmdlets require EXO roles; compliance cmdlets require S&C roles. Without both, some diagnostics will fail with permission errors.

Authentication

The server uses MSAL interactive browser sign-in — a browser window opens for the user to authenticate. No credentials are stored or passed via environment variables.

Licensing Requirements

Some diagnostics require specific licensing on target mailboxes:

Feature Required License
Archive diagnostics Exchange Online Archiving or E3/E5
Adaptive scopes E5 Compliance or E5 Information Protection & Governance
Teams retention Microsoft 365 E3+

Quick Start

npx -y @microsoft/purview-dlm-mcp

Set DLM_UPN and DLM_ORGANIZATION in your MCP client config (see below).

MCP Client Configuration

Claude Desktop

Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "dlm-diagnostics": {
      "command": "npx",
      "args": ["-y", "@microsoft/purview-dlm-mcp"],
      "env": {
        "DLM_UPN": "[email protected]",
        "DLM_ORGANIZATION": "yourtenant.onmicrosoft.com",
        "DLM_COMMAND_TIMEOUT_MS": "180000"
      }
    }
  }
}

VS Code

Add this to your .vscode/settings.json or user settings:

{
  "mcp": {
    "servers": {
      "dlm-diagnostics": {
        "command": "npx",
        "args": ["-y", "@microsoft/purview-dlm-mcp"],
        "env": {
          "DLM_UPN": "[email protected]",
          "DLM_ORGANIZATION": "yourtenant.onmicrosoft.com",
          "DLM_COMMAND_TIMEOUT_MS": "180000"
        }
      }
    }
  }
}

Available Tools

Tool Description
run_powershell Execute a read-only Exchange Online PowerShell command against the allowlist
get_execution_log Retrieve the log of all commands executed during the current session
ask_learn Look up Microsoft Purview documentation on Microsoft Learn (fallback when no TSG matches)
create_issue Report an issue with the MCP server to GitHub, attaching session diagnostic context
submit_feedback Submit structured feedback about a diagnostic session (emits telemetry, no PII)

Tool Examples

run_powershell

User: “Archiving is not working on [email protected]”

The AI uses run_powershell to investigate step by step:

✅ Step 1 — Check mailbox archive status
   Command: Get-Mailbox -Identity [email protected] | FL ArchiveStatus, ArchiveState, RetentionPolicy
   Finding: ArchiveStatus = Active, ArchiveState = Local

✅ Step 2 — Check archive mailbox size
   Command: Get-MailboxStatistics -Identity [email protected] -Archive | FL DisplayName, TotalItemSize, ItemCount
   Finding: TotalItemSize = 98.5 GB (4,231 items)

⚠️ Step 3 — Check auto-expanding archive
   Command: Get-Mailbox -Identity [email protected] | FL AutoExpandingArchiveEnabled
   Finding: AutoExpandingArchiveEnabled = False — archive is near 100 GB limit

Root Cause: Archive is near quota and auto-expanding archive is not enabled.
Recommended Action: Enable auto-expanding archive at the org level.

get_execution_log

User: “Show me all the commands that were run during this investigation”

Returns a Markdown-formatted audit trail:

## Execution Log (3 entries)

| # | Time | Command | Duration | Status |
|---|------|---------|----------|--------|
| 1 | 14:23:01 | Get-Mailbox -Identity [email protected] | 2.1s | ✅ |
| 2 | 14:23:04 | Get-MailboxStatistics -Identity [email protected] -Archive | 1.8s | ✅ |
| 3 | 14:23:06 | Get-Mailbox -Identity [email protected] \| FL AutoExpandingArchiveEnabled | 1.5s | ✅ |

ask_learn

User: “How do I create a retention policy in Purview?”

The AI uses ask_learn to find relevant documentation:

## Retention Policies

Create and configure retention policies to automatically retain or delete content.

### Key Steps
1. Go to Microsoft Purview compliance portal → Data lifecycle management → Retention policies
2. Select "New retention policy" and configure locations (Exchange, SharePoint, OneDrive, Teams, etc.)
3. Choose whether to retain content, delete it, or both
4. Set the retention period and what triggers it (creation date or last modified date)

### Learn More
- [Create and configure retention policies](https://learn.microsoft.com/purview/create-retention-policies)
- [Retention policies for Exchange Online](https://learn.microsoft.com/purview/retention-policies-exchange)

create_issue

User: “The allowlist is rejecting Get-ComplianceTag even though it should be allowed — file a bug”

The AI uses create_issue to report the bug to the MCP server’s GitHub repo:

✅ Created GitHub issue #42
   Title: Allowlist incorrectly blocks Get-ComplianceTag cmdlet
   Category: bug
   Labels: bug
   URL: https://github.com/microsoft/purview-dlm-mcp/issues/42

   Session context included: 3 commands executed, 1 failure

Environment Variables

Variable Required Description
DLM_UPN Yes Admin UPN for Exchange Online (e.g., [email protected])
DLM_ORGANIZATION Yes Tenant organization (e.g., contoso.onmicrosoft.com)
DLM_COMMAND_TIMEOUT_MS No Command execution timeout in ms (default: 180000)
DLM_COLLECT_TELEMETRY No Set to false to disable all telemetry (default: true)
DLM_COLLECT_TELEMETRY_MICROSOFT No Set to false to disable Microsoft 1P telemetry (default: true)

Supported TSGs

Symptom Reference Guide
Policy shows Success but content is not retained/deleted on target workloads retention-policy-not-applying.md
Policy status shows Error, PolicySyncTimeout, or PendingDeletion policy-stuck-error.md
Archive mailbox exists but items stay in the primary mailbox items-not-moving-to-archive.md
Archive is near 100 GB but no auxiliary archive is being created auto-expanding-archive.md
User was deleted but mailbox was purged instead of becoming inactive inactive-mailbox.md
Recoverable Items folder growing uncontrollably or SubstrateHolds is large substrateholds-quota.md
Teams retention policy exists but messages remain visible past retention period teams-messages-not-deleting.md
Both MRM and Purview retention on a mailbox causing unexpected behavior mrm-purview-conflict.md
Adaptive scope includes wrong members or scope query not targeting correct users/sites adaptive-scope.md
Auto-apply retention label policy not labeling content or shows “Off (Error)” auto-apply-labels.md
SharePoint site cannot be deleted due to retention policy or hold sharepoint-site-deletion-blocked.md

Architecture

The server is a TypeScript/Node.js application built with the @modelcontextprotocol/sdk. The server runs a persistent PowerShell 7 session that authenticates to Exchange Online using MSAL interactive auth. Commands flow through:

  1. MCP Server (src/index.ts) — entry point, receives tool calls from the MCP client
  2. Configuration (src/config.ts) — exports COMMAND_TIMEOUT_MS
  3. PowerShell Executor (src/powershell/executor.ts) — manages the PowerShell child process lifecycle and auth
  4. Cmdlet Allowlist (src/powershell/allowlist.ts) — validates every command against the approved cmdlet list before execution
  5. TSG Diagnostics Engine (src/tsg-diagnostics.ts) — evaluates command output against reference guide checklists
  6. GitHub Integration (src/github/auth.ts, src/github/issues.ts) — authenticates via DLM_GITHUB_TOKEN or gh auth token and creates structured GitHub issues
  7. Telemetry (src/telemetry.ts) — optional Application Insights telemetry for tool invocations, session lifecycle, and errors (1P only, no PII, opt-out via env var)

Security Model

  • Read-only allowlist — every command is parsed with the PowerShell parser and must use only a fixed allowlist of read-only Exchange Online / Security & Compliance cmdlets plus formatting cmdlets. Native executables, scripts, redirection, dynamic invocation, .NET method calls, and unmapped aliases are rejected before execution
  • Hardened session (defense in depth) — the session no longer resolves native executables or script files by name or path, removes aliases outside a small formatting set, and shadows high-risk cmdlets. This raises the bar for a validation bypass but is not a sandbox; the allowlist above is the security boundary
  • No stored credentials — authentication uses MSAL interactive flow; no passwords or tokens are persisted
  • Session isolation — each server instance runs its own PowerShell process with independent session state
  • Telemetry — 1P Application Insights only, no PII collected, opt-out via DLM_COLLECT_TELEMETRY=false

Skills

Diagnostic skills are self-contained reference guides used by AI assistants. Each skill has a SKILL.md and a references/ directory with per-symptom troubleshooting guides.

Skill Description Location
dlm-diagnostics 11 troubleshooting guides for DLM issues .github/skills/dlm-diagnostics/
asklearn Fallback: Microsoft Learn docs for Purview topics .github/skills/asklearn/
skill-creator Meta-skill for authoring new diagnostic skills .github/skills/skill-creator/

Skills are mirrored in both .github/skills/ (GitHub Copilot) and .claude/skills/ (Claude Code).

Contributing

See CONTRIBUTING.md for development setup, testing instructions, and pull request guidelines.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft’s Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party’s policies.

License

MIT

View the full README on GitHub

Install

npx -y @microsoft/purview-dlm-mcp
New to MCP? Start with the mcpskill.org guide →

Configuration

{ "mcpServers": { "dlm-diagnostics": { "command": "npx", "args": ["-y", "@microsoft/purview-dlm-mcp"], "env": { "DLM_UPN": "[email protected]", "DLM_ORGANIZATION": "yourtenant.onmicrosoft.com", "DLM_COMMAND_TIMEOUT_MS": "180000" } } } }