An MCP (Model Context Protocol) server that provides secure access to Microsoft Entra ID (Azure AD) resources via Microsoft Graph API.
- Users: Read user profiles, groups, licenses, and department information
- Devices: Access device inventory with OS and sign-in information
- Applications: Query application registrations and their properties
- Azure Integration: Logs all activities to Azure Blob Storage for audit purposes
- Security: Uses application permissions with client credentials flow
- Azure tenant with admin access
- Python 3.8+
- Azure Storage account for logging
- Go to Azure Portal → Microsoft Entra ID → App registrations → New registration
- Configure:
- Name:
MCP-MSGraph-Server
- Account types:
Single tenant
- No redirect URI needed
- Name:
- Note the Application (client) ID and Directory (tenant) ID
Add these Application permissions in API permissions:
User.Read.All
Group.Read.All
Directory.Read.All
Device.Read.All
Application.Read.All
Important: Click "Grant admin consent" after adding permissions.
- Go to Certificates & secrets → New client secret
- Set expiration to 24 months (recommended)
- Copy the secret value immediately
Create a storage account for logging:
- Create storage account in Azure Portal
- Get the connection string from Access keys
- Container
mcp-logs
will be created automatically
pip install -r requirements.txt
- Copy
.env.example
to.env
:
cp .env.example .env
- Update
.env
with your values:
AZURE_TENANT_ID=your-tenant-id-here
AZURE_CLIENT_ID=your-client-id-here
AZURE_CLIENT_SECRET=your-client-secret-here
AZURE_STORAGE_CONNECTION_STRING=your-storage-connection-string-here
AZURE_LOG_CONTAINER_NAME=mcp-logs
python mcp_msgraph_server.py
Get Microsoft Entra ID users with profile information.
{
"tool": "get_entra_users",
"arguments": {
"filter": "startswith(displayName,'John')",
"fields": ["displayName", "mail", "department"]
}
}
Response includes:
- Display name and email
- Department information
- Group memberships
- Assigned licenses
Get registered devices in your tenant.
{
"tool": "get_entra_devices",
"arguments": {
"filter": "operatingSystem eq 'Windows'"
}
}
Response includes:
- Device name and OS
- Last sign-in timestamp
- Device ID
Get application registrations.
{
"tool": "get_entra_applications",
"arguments": {
"filter": "startswith(displayName,'MyApp')"
}
}
Response includes:
- Application name and ID
- Creation date
- Sign-in audience
All tools support OData filter queries:
startswith(displayName,'John')
- Name starts with "John"mail eq 'user@domain.com'
- Exact email matchoperatingSystem eq 'Windows'
- Windows devices onlycreatedDateTime ge 2024-01-01T00:00:00Z
- Created after date
All API calls and operations are logged to Azure Blob Storage:
- Location:
logs/YYYY/MM/DD/timestamp.json
- Format: Structured JSON with timestamp, level, message, and metadata
- Levels: INFO, ERROR
- Includes: Request details, response counts, error information
✅ Implemented:
- Application permissions (no user context required)
- Client credentials flow
- Token caching with expiration
- Secure environment variable configuration
- Comprehensive audit logging
- Request timeout protection
🔄 Recommended:
- Rotate client secrets every 24 months
- Monitor blob storage logs regularly
- Use Azure Key Vault for secrets in production
- Implement IP restrictions if needed
- Set up alerting on failed authentication attempts
-
"Insufficient privileges"
- Verify admin consent was granted for API permissions
- Check that application permissions (not delegated) were added
-
"Authentication failed"
- Verify tenant ID, client ID, and client secret
- Check that client secret hasn't expired
-
"Blob storage errors"
- Verify storage connection string
- Ensure storage account is accessible
Enable verbose logging by checking blob storage logs:
- Authentication attempts
- API request details
- Error messages with context
This project follows security best practices for enterprise deployments.