Microsoft Entra MCP Server
A FastMCP server that provides AI assistants with access to Microsoft Entra (Azure AD) directory services. It enables LLMs to search for users, groups, and check memberships using the Microsoft Graph API.
README
Microsoft Entra MCP Server
A FastMCP server that provides AI assistants with access to Microsoft Entra (Azure AD) directory services. This server enables LLMs to search for users, groups, and check memberships using the Microsoft Graph API.
Features
- 🔍 4 Tools: Search users, search groups, get user membership, get group members
- 🧠 Full-text Search: Uses Microsoft Graph
$searchwith AND tokenization for order-agnostic matches (e.g., "Arun AND Singh" matches "Singh, Arun" and "Arun Kumar Singh") - 📈 Accurate Counts: Uses
ConsistencyLevel: eventualwith$count=trueand pagination across@odata.nextLink - 🔁 Pagination: Users, groups, and group members are paginated to return complete results up to limits
- 🆔 Robust Identifier Resolution: Membership lookup resolves user ID from email/UPN before querying
- 🎨 7 Prompts: Pre-built prompt templates for common Entra queries
- 🔐 Secure Authentication: Uses Azure AD app registration with client credentials
- 🌐 Health Endpoint: Built-in health check for monitoring
- ✅ Fully Tested: Comprehensive test suite with pytest
Prerequisites
Azure AD App Registration
- Go to Azure Portal → Microsoft Entra ID → App registrations
- Create a new app registration
- Note down:
- Application (client) ID
- Directory (tenant) ID
- Create a client secret under Certificates & secrets
- Grant the following Microsoft Graph API permissions:
User.Read.AllGroup.Read.AllGroupMember.Read.All
Environment Variables
Set these environment variables before running. You can either:
Option 1: Direct environment variables
export ENTRA_TENANT_ID="your-tenant-id-here"
export ENTRA_CLIENT_ID="your-client-id-here"
export ENTRA_CLIENT_SECRET="your-client-secret-here"
Option 2: Use .env file
cp env.template .env
# Edit .env with your actual values
The server will automatically load variables from a .env file if it exists.
Quick Start
Installation
pip install -r requirements.txt
Running Locally
# Create virtual environment
python3 -m venv .venv
# Activate virtual environment
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Set environment variables
export ENTRA_TENANT_ID="..."
export ENTRA_CLIENT_ID="..."
export ENTRA_CLIENT_SECRET="..."
# Run the server
python main.py
Server will start on http://0.0.0.0:8001
Using Docker
# Build the image
docker build -t entra-mcp .
# Run the container with environment variables
docker run -p 8001:8001 \
-e ENTRA_TENANT_ID="..." \
-e ENTRA_CLIENT_ID="..." \
-e ENTRA_CLIENT_SECRET="..." \
entra-mcp
API Reference
Tools
1. search_entra_users
Search for users by display name, email, or user principal name.
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | Yes | - | Search term for user name, email, or UPN (full-text $search with AND-tokenized terms) |
max_results |
integer | No | 10 | Maximum number of results to return |
Search Behavior:
- Full-text across
displayName,mail, anduserPrincipalNameusing Graph$search - Tokens are ANDed for better relevance (e.g., "Arun Singh" →
"Arun" AND "Singh"), matching order-agnostic names and middle names - Uses
ConsistencyLevel: eventualand$count=truefor accurate totals - Paginates across
@odata.nextLinkand returns up tomax_results
Example Usage:
# Order-agnostic and middle-name tolerant
search_entra_users(query="Arun Singh", max_results=25)
# Also matches comma-separated and compound names
search_entra_users(query="Singh, Arun", max_results=25)
# Email or UPN fragments are also matched by `$search`
search_entra_users(query="arun.singh@company.com")
2. search_entra_groups
Search for groups by display name or description.
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | Yes | - | Search term for group name or description (full-text $search with AND-tokenized terms) |
max_results |
integer | No | 10 | Maximum number of results to return |
Search Behavior:
- Full-text across
displayNameanddescriptionwith Graph$searchand AND-tokenized terms - Uses
ConsistencyLevel: eventualand$count=truefor accurate totals - Paginates across
@odata.nextLinkand returns up tomax_results
3. get_user_group_membership
Get all groups a user belongs to.
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
user_identifier |
string | Yes | - | User ID, UPN, or email address |
Behavior:
- Resolves the user ID from email/UPN automatically when needed
- Uses
ConsistencyLevel: eventual,$count=true, and paginates across@odata.nextLink
4. get_group_members
Get all members of a group.
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
group_identifier |
string | Yes | - | Group ID or display name |
max_results |
integer | No | 50 | Maximum number of members to return |
Behavior:
- Uses
ConsistencyLevel: eventualand paginates across@odata.nextLink - Returns up to
max_resultsmembers
Available Prompts
1. find_user_by_name
Find a user by their display name.
Default now suggests a broader search and higher limit to take advantage of $search:
# Suggests: Call search_entra_users with: query='{name}', max_results=25
2. find_user_by_email
Find a user by their email address.
3. find_group_by_name
Find a group by name.
4. check_user_groups
Check what groups a user belongs to.
5. list_group_members
List all members of a specific group.
6. user_access_audit
Perform an access audit for a user.
7. group_membership_audit
Audit the membership of a security-sensitive group.
Testing
Health Check
curl http://localhost:8001/health
Run Test Suite
# Run all tests
python -m pytest tests/ -v
Project Structure
streamable-HTTP-Entra-MCP/
├── main.py # Main server with tools and authentication
├── promptz.py # Prompt templates for LLMs (7 prompts)
├── requirements.txt # Python dependencies
├── README.md # This file
└── tests/
├── __init__.py
└── test_main.py # Tests for main functionality
Security Notes
- The server requires Azure AD application permissions to read user and group data
- All API calls are authenticated using client credentials flow
- No user data is stored locally - all queries go directly to Microsoft Graph API
- Ensure your Azure AD app has minimal required permissions
Graph Query Semantics Used
ConsistencyLevel: eventualis required for$searchand$count$searchvalues are AND-tokenized to improve relevance and handle name order variations$count=trueis requested to return accurate totals- Results are paginated via
@odata.nextLinkuntil limits are reached
Use Cases
- 🔍 User Lookup: Find user information by name or email
- 👥 Group Discovery: Search for available groups
- 🔐 Access Control: Check user group memberships for permissions
- 📊 Audit & Compliance: Review group memberships and user access
- 🤖 AI Assistants: Enable LLMs to answer questions about Entra directory
Dependencies
Core:
fastmcp==2.13.0.1- FastMCP framework for MCP serverhttpx==0.28.1- Async HTTP clientazure-identity==1.19.0- Azure authenticationmsal==1.31.0- Microsoft Authentication Library
Development:
pytest==8.3.4- Testing frameworkpytest-asyncio==0.24.0- Async test support
API Data Source
This server uses the Microsoft Graph API:
- Base URL:
https://graph.microsoft.com/v1.0 - Authentication: Client Credentials Flow
- Scopes:
https://graph.microsoft.com/.default
Troubleshooting
Authentication Errors
# Check environment variables are set
echo $ENTRA_TENANT_ID $ENTRA_CLIENT_ID $ENTRA_CLIENT_SECRET
# Verify Azure AD app permissions in Azure Portal
# Ensure client secret is not expired
Import Errors
# Install dependencies
pip install -r requirements.txt
# Verify Azure packages
pip list | grep azure
License
See LICENSE file for details.
Built with ❤️ using FastMCP and Microsoft Graph API
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。