Skip to main content
Glama
TigerToker

MDI MCP Server

by TigerToker
README.md
# MDI MCP Server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that integrates with **Microsoft Defender for Identity (MDI)** via the Microsoft Graph API. Use it with VS Code + GitHub Copilot to query MDI data and generate styled HTML reports — all from natural language.

## Features

| Category | Tools |
|----------|-------|
| **Alerts & Incidents** | Query MDI alerts by severity, fetch security incidents |
| **Secure Score** | Get latest score, identity-related control recommendations |
| **Risky Users** | List risky users, view risk detections from Identity Protection |
| **Sensor Health** | Check MDI sensor status, surface health issues |
| **Activity Timeline** | Suspicious logon events, directory changes (password resets, group changes) |
| **Advanced Hunting** | Run arbitrary KQL queries against Defender tables |
| **HTML Reports** | Generate dark-themed, print-friendly reports for any of the above |

## Prerequisites

1. **Python 3.10+**
2. **Azure AD App Registration** with the following **Application** permissions:
   - `SecurityAlert.Read.All`
   - `SecurityIncident.Read.All`
   - `SecurityEvents.Read.All`
   - `IdentityRiskyUser.Read.All`
   - `IdentityRiskEvent.Read.All`
   - `ThreatHunting.Read.All`
   
   > Grant admin consent after adding the permissions.

3. **VS Code** with [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) extension installed.

## Quick Start

### 1. Clone and install

```bash
git clone https://github.com/TigerToker/mdi-mcp-server.git
cd mdi-mcp-server
pip install -e .
```

### 2. Configure credentials

Copy `.env.example` to `.env` and fill in your Azure AD app registration details:

```bash
cp .env.example .env
# Edit .env with your AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
```

### 3. Connect to VS Code + Copilot

The repo includes `.vscode/mcp.json` which auto-registers the server. Open the project folder in VS Code and Copilot will detect the MCP server.

Alternatively, add this to your **User** `settings.json` for global access:

```json
"mcp": {
    "servers": {
        "mdi-mcp-server": {
            "type": "stdio",
            "command": "python",
            "args": ["-m", "mdi_mcp_server.server"],
            "cwd": "/path/to/mdi-mcp-server/src",
            "env": {
                "AZURE_TENANT_ID": "your-tenant-id",
                "AZURE_CLIENT_ID": "your-client-id",
                "AZURE_CLIENT_SECRET": "your-client-secret"
            }
        }
    }
}
```

### 4. Start asking questions

In Copilot Chat, try:
- *"Show me all high-severity MDI alerts from the last week"*
- *"Generate a comprehensive MDI report for the past 30 days"*
- *"Are there any risky users in my tenant?"*
- *"What's the health status of our MDI sensors?"*
- *"Run an Advanced Hunting query for failed logon attempts"*

## Project Structure

```
mdi-mcp-server/
├── src/mdi_mcp_server/
│   ├── server.py              # MCP server entry point & tool definitions
│   ├── graph_client.py        # Microsoft Graph API client
│   ├── report_generator.py    # Jinja2-based HTML report builder
│   └── templates/
│       └── report.html        # Dark-themed HTML report template
├── .vscode/mcp.json           # VS Code MCP server configuration
├── .github/copilot-instructions.md
├── pyproject.toml
├── requirements.txt
└── .env.example
```

## Available MCP Tools

### Query Tools
| Tool | Description |
|------|-------------|
| `get_mdi_alerts` | Fetch MDI alerts with optional severity filter |
| `get_mdi_incidents` | Fetch security incidents |
| `get_secure_score` | Latest Secure Score snapshots |
| `get_secure_score_controls` | All Secure Score control profiles |
| `get_risky_users` | Risky users from Identity Protection |
| `get_risk_detections` | Individual risk detection events |
| `get_mdi_sensor_info` | MDI sensor & domain controller status |
| `get_mdi_health_issues` | MDI health alerts |
| `get_suspicious_activity_timeline` | Suspicious logon events |
| `get_identity_directory_events` | Directory change events |
| `run_custom_hunting_query` | Ad-hoc KQL via Advanced Hunting |

### Report Generation Tools
| Tool | Description |
|------|-------------|
| `generate_alerts_report` | HTML report of MDI alerts |
| `generate_incidents_report` | HTML report of security incidents |
| `generate_risky_users_report` | HTML report of risky users |
| `generate_secure_score_report` | HTML report of Secure Score |
| `generate_sensor_health_report` | HTML report of sensor health |
| `generate_full_mdi_report` | Comprehensive report with all data |

## Required Graph API Permissions

| Permission | Type | Purpose |
|------------|------|---------|
| `SecurityAlert.Read.All` | Application | Read security alerts (MDI alerts) |
| `SecurityIncident.Read.All` | Application | Read security incidents |
| `SecurityEvents.Read.All` | Application | Read security events |
| `IdentityRiskyUser.Read.All` | Application | Read risky user data |
| `IdentityRiskEvent.Read.All` | Application | Read risk detection events |
| `ThreatHunting.Read.All` | Application | Run Advanced Hunting queries |

## GitHub Copilot Extension

This project also ships as a **GitHub Copilot Extension** — a standalone agent that responds to natural-language queries about MDI directly inside GitHub Copilot Chat.

### How It Works

The extension runs a FastAPI server that implements the [GitHub Copilot Extensions agent protocol](https://docs.github.com/en/copilot/building-copilot-extensions). When you `@mention` the extension in Copilot Chat, your message is routed to the `/agent` endpoint, which parses your intent, queries the Graph API, and streams back a markdown response.

### Running Locally

```bash
# Install dependencies
pip install -e .

# Set environment variables
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
export GITHUB_WEBHOOK_SECRET="your-webhook-secret"

# Start the server
uvicorn mdi_mcp_server.copilot_extension:app --host 0.0.0.0 --port 8080 --app-dir src
```

### Docker

```bash
docker build -t mdi-copilot-extension .
docker run -p 8080:8080 \
  -e AZURE_TENANT_ID="..." \
  -e AZURE_CLIENT_ID="..." \
  -e AZURE_CLIENT_SECRET="..." \
  -e GITHUB_WEBHOOK_SECRET="..." \
  mdi-copilot-extension
```

### Deploy to Azure Container Apps

Use the provided deployment script:

```powershell
.\deploy.ps1 -ResourceGroup "mdi-copilot-rg" -AcrName "myacr"
```

Or deploy manually via Bicep:

```bash
az deployment group create \
  --resource-group mdi-copilot-rg \
  --template-file infra/main.bicep \
  --parameters containerImage="myacr.azurecr.io/mdi-copilot-extension:latest" \
               azureTenantId="..." azureClientId="..." \
               azureClientSecret="..." githubWebhookSecret="..."
```

### Register the Extension

1. Go to **GitHub Settings → Developer Settings → GitHub Apps → Copilot Extensions**
2. Create a new Copilot Extension (or GitHub App with Copilot agent)
3. Set the **Agent URL** to your deployed endpoint: `https://<your-app>.azurecontainerapps.io/agent`
4. Set the **Webhook Secret** to match `GITHUB_WEBHOOK_SECRET`
5. Install the app on your organization or account

### Extension Commands

Once installed, use `@mdi` (or your extension name) in Copilot Chat:

- `@mdi show me high severity alerts from the last 7 days`
- `@mdi generate a full MDI report for the past 30 days`
- `@mdi are there any risky users?`
- `@mdi what's our secure score?`
- `@mdi check MDI sensor health`

## License

MIT