search_usersLABSCO SUMMARY
A tenant admin's read surface, with real write tools sitting next to it.
Reading is the safe majority: who holds privilege, who has no MFA, who signed in and from where. But password reset and application delete are in the same server, so the app registration you point it at decides how much a bad prompt can do — which is exactly what the permissions helper exists to keep small.
What it is
A Python FastMCP server over the Microsoft Graph API, organised as one module per resource: users, groups, applications and service principals, sign-in logs, MFA and password operations.
What you get
- search_users by name or email, get_user_by_id for one account
- get_user_groups and get_user_roles for a user's memberships and directory roles
- get_privileged_users for the members of directory roles across the tenant
- Group lifecycle and membership: create, read, update and delete, plus adding and removing members and owners
- Applications and service principals: list, create, update and delete, with app role assignments and delegated permissions for both
- Sign-in logs for a user over the last X days
- MFA status for one user or for every member of a group
- Password reset with a custom or generated password, optionally requiring a change at next sign-in
- A permissions helper that suggests the Graph permissions a task needs, so a grant can stay narrow
Requirements
Credentials for a Microsoft Graph app registration, kept in a .env file the repository excludes from version control. Which Graph permissions you must grant depends on which modules you use — the built-in permissions helper names them per task.
Setup effort
Follow the published steps — Clone the repo.
USE CASES
Finding out who actually holds admin rights
List the members of directory roles across the tenant rather than checking roles one at a time.
Working out why someone cannot reach something
Find the account, then read its groups and its directory roles side by side.
Checking MFA coverage before an audit
Read MFA status for every member of a group in one call instead of per user.
Investigating a suspicious sign-in
Pull the user's sign-in logs for the last few days and see where the attempts came from.
Granting only the permissions a task needs
Ask the permissions helper which Graph permissions the operation requires, then grant those and no more.
39 tools
Listed in project docs. Your client may show a different list.
get_user_by_idget_privileged_usersget_user_rolesget_user_groupsget_all_groupsget_group_by_idsearch_groups_by_nameget_group_memberscreate_groupupdate_groupdelete_groupadd_group_memberremove_group_memberadd_group_ownerremove_group_ownerget_user_sign_insget_user_mfa_statusget_group_mfa_statusget_all_managed_devicesget_managed_devices_by_userget_conditional_access_policiesget_conditional_access_policy_by_idget_user_audit_logsreset_user_password_directsuggest_permissions_for_tasklist_permission_categories_and_tasksget_all_graph_permissionssearch_permissionslist_applicationsget_application_by_idcreate_applicationupdate_applicationdelete_applicationlist_service_principalsget_service_principal_by_idcreate_service_principalupdate_service_principaldelete_service_principalBEFORE YOU INSTALL
What to know first
Tools you get
39 tools named in the project's documentation. Many tools write to your tenant, such as create_group, delete_group and reset_user_password_direct. All register regardless of permissions; writes fail unless the app has permissions such as Group.ReadWrite.All.
Requires
- TENANT_ID in your environment
- CLIENT_ID in your environment
- CLIENT_SECRET in your environment
INSTALLATION
Connect your client
Server setup
Clone the repo.
Create a config/.env file with TENANT_ID, CLIENT_ID, CLIENT_SECRET
Grant the app registration the Microsoft Graph application permissions listed in the README table (Directory.Read.All, User.Read.All, Group.ReadWrite.All, …)
For Claude:
fastmcp install '<YOUR_PATH_TO_SRC>/msgraph_mcp_server/server.py' --with msgraph-sdk --with azure-identity --with azure-core --with msgraph-core -f <YOUR_PATH_TO_ENV>For Cursor: add the entry shown in the Cursor tab to your .cursor/mcp.json
MCP Clients
Claude Desktop
fastmcp install '<YOUR_PATH_TO_SRC>/msgraph_mcp_server/server.py' \
--with msgraph-sdk --with azure-identity --with azure-core --with msgraph-core \
-f <YOUR_PATH_TO_ENV>Cursor
{
"mcpServers": {
"EntraID MCP Server": {
"command": "uv",
"args": [
"run",
"--with",
"azure-core",
"--with",
"azure-identity",
"--with",
"fastmcp",
"--with",
"msgraph-core",
"--with",
"msgraph-sdk",
"fastmcp",
"run",
"<YOUR_PATH_TO_SRC>/msgraph_mcp_server/server.py"
],
"env": {
"TENANT_ID": "<YOUR_TENANT_ID>",
"CLIENT_ID": "<YOUR_CLIENT_ID>",
"CLIENT_SECRET": "<YOUR_CLIENT_SECRET>"
}
}
}
}