Metadata-Version: 2.5
Name: entraid-mcp-server
Version: 0.3.1
Summary: FastMCP server for Microsoft Graph / Entra ID, using Azure DefaultAzureCredential by default.
Project-URL: Homepage, https://github.com/baoduy/entraid-mcp-server
Project-URL: Repository, https://github.com/baoduy/entraid-mcp-server
Project-URL: Issues, https://github.com/baoduy/entraid-mcp-server/issues
Author: baoduy
License: MIT License
        
        Copyright (c) 2024 baoduy
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: azure,azure-identity,entra-id,fastmcp,mcp,microsoft-graph
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
Requires-Python: >=3.10
Requires-Dist: azure-core<2,>=1.41.0
Requires-Dist: azure-identity<2,>=1.26.0
Requires-Dist: fastmcp<5,>=4.1.3
Requires-Dist: msgraph-beta-sdk<2,>=1.66.0
Requires-Dist: msgraph-core<2,>=1.5.2
Requires-Dist: msgraph-sdk<2,>=1.65.0
Requires-Dist: python-dotenv<2,>=1.2.4
Description-Content-Type: text/markdown

# EntraID MCP Server

An MCP server that lets an AI client such as Claude Desktop or Cursor read and manage your Microsoft Entra ID tenant — users, groups, MFA, devices, policies, logs and app registrations — through 48 Microsoft Graph tools.

## 📖 Overview

- [Users](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/users/index.md) — search users, read a profile, list privileged users and a user's groups and roles (`resources/users.py`).
- [Groups](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/groups/index.md) — find, create, change and delete groups; add and remove members and owners (`resources/groups.py`).
- [Sign-in logs](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/sign-in-logs/index.md) — a user's sign-ins over the last days (`resources/signin_logs.py`).
- [MFA](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/mfa/index.md) — registered authentication methods for a user or every user in a group (`resources/mfa.py`).
- [Devices (Intune)](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/devices/index.md) — managed devices, detected apps, compliance and configuration, on the Graph beta endpoint (`resources/managed_devices.py`).
- [Conditional access](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/conditional-access/index.md) — the tenant's policies as flat rows (`resources/conditional_access.py`).
- [Audit logs](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/audit-logs/index.md) — the directory changes a user made (`resources/audit_logs.py`).
- [Password management](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/password-management/index.md) — reset a password to a given or generated value; read password methods (`resources/password_auth.py`).
- [Permissions helper](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/permissions-helper/index.md) — suggest and search Microsoft Graph permissions (`resources/permissions_helper.py`).
- [Applications](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/applications/index.md) — list, read, create, change and delete app registrations (`resources/applications.py`).
- [Service principals](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/service-principals/index.md) — list, read, create, change and delete service principals (`resources/service_principals.py`).

Every tool carries an MCP mark, so a client can let lookups run and ask before a change: 34 tools are read-only; 5 change the tenant without destroying anything (the 3 creates, add member, add owner); 9 are destructive (the 3 deletes, remove member, remove owner, the password reset and the 3 updates).

The server publishes tools only — no MCP resources or prompts. It is started and called by an AI client on behalf of an Entra ID admin. It runs on the admin's machine, talks to the client over standard input and output, and signs in to Microsoft Graph as the admin (or as an app you configure).

## 🏗️ Runtime architecture

![An AI client sends tools/call over stdio to the FastMCP server, which dispatches to a tool function in server.py, then to a resource module, which uses GraphClient to call Microsoft Graph v1.0 (or beta for devices); on the first call GraphAuthManager gets a token from Microsoft Entra ID; main() starts the server after loading the first .env file found.](https://raw.githubusercontent.com/baoduy/entraid-mcp-server/main/docs/diagrams/runtime.svg)

## 🌐 Downstream systems

| System | What for | How | When it is down |
|---|---|---|---|
| Microsoft Graph v1.0 | Every tool except the 9 device tools and the 2 permission-suggestion tools | HTTPS through msgraph-sdk | The tool call ends in an error result; the server sets no timeout or retry of its own |
| Microsoft Graph beta | The 9 device (Intune) tools | HTTPS through msgraph-beta-sdk | As above |
| Microsoft Entra ID | A token for Graph, on the first Graph call | The azure-identity credential the [configuration](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/configuration.md) selects | The tool call ends in an error result |

The identity the server signs in as needs Graph permissions for the tools you use. Microsoft Graph checks them; the server checks none. This list is carried over from the previous README (application permissions):

| Permission | For |
|---|---|
| `User.Read.All` | Users |
| `Directory.Read.All` | Directory data: users, groups, roles |
| `RoleManagement.Read.Directory` | Directory roles |
| `Group.Read.All`, `GroupMember.Read.All` | Reading groups and members |
| `Group.ReadWrite.All` | Creating, changing and deleting groups; adding and removing members and owners |
| `AuditLog.Read.All` | Sign-in logs and audit logs |
| `UserAuthenticationMethod.Read.All` | MFA and password methods |
| `User-PasswordProfile.ReadWrite.All` | Password reset (see ❓ Open questions) |
| `Policy.Read.All`, `AuthenticationContext.Read.All` | Conditional access policies |
| `DeviceManagementManagedDevices.Read.All`, `DeviceManagementConfiguration.Read.All`, `DeviceManagementApps.Read.All` | Device tools |
| `Application.ReadWrite.All` | Creating, changing and deleting applications and service principals |

## 🚀 Quick Start

You need [`uv`](https://docs.astral.sh/uv/) and Python 3.10 or later. The package pulls in fastmcp on its 4.x line (`fastmcp>=4.1.3,<5`), msgraph-sdk, msgraph-beta-sdk, msgraph-core, azure-identity, azure-core and python-dotenv, each pinned below its next major version in `pyproject.toml`.

1. Sign in to Azure with an account that has the permissions above. The server uses this login by default:

   ```bash
   az login
   ```

2. Add the server to the `mcpServers` object of your AI client's MCP settings — Claude Desktop: `claude_desktop_config.json`; Cursor: `.cursor/mcp.json`:

   ```json
   {
     "mcpServers": {
       "entraid": {
         "command": "uvx",
         "args": ["entraid-mcp-server"]
       }
     }
   }
   ```

   `uvx` downloads the latest release from PyPI and starts it; add `@<version>` to the package name to pin one.

3. To sign in as an app instead of your Azure login (no interactive login available, for example), add an `env` block to the same entry. Never commit real values:

   ```json
   "env": {
     "TENANT_ID": "<your-tenant-id>",
     "CLIENT_ID": "<your-client-id>",
     "CLIENT_SECRET": "<your-client-secret>"
   }
   ```

   Certificate sign-in, `.env` files and the order the server tries credentials in: [configuration](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/configuration.md).

4. Restart the client so it starts the server.

To run from a clone instead (from the repo root, with `uv` installed):

```bash
uv sync
uv run entraid-mcp-server          # or: uv run python -m msgraph_mcp_server
```

With the package installed in an environment (`pip install entraid-mcp-server`), the `entraid-mcp-server` command starts the same server.

## ✅ Verify it works

In your AI client, list the server's tools: you should see **48**. Then call `list_permission_categories_and_tasks` — it needs no Graph access, so it works before any permission is granted. The result starts:

```json
{"status": "success", "categories": {"users": {"tasks": [{"name": "read_user_profile", "description": "Read user profile information"}, ...
```

with the categories `users`, `groups`, `mail`, `calendar`, `files`, `devices`, `audit_logs` and `directory`. The server signs in only on the first tool that calls Microsoft Graph, so a sign-in problem shows up there, as the tool's error result.

The client also sees the server's name, `EntraID MCP Server`, and its version: the installed release number (from a clone, the version in `pyproject.toml`).

## 🛠️ Common commands

All from the repo root:

| Command | What it does |
|---|---|
| `uv sync --locked` | Install the locked dependencies, dev tools included |
| `uv build` | Build the wheel and source archive into `dist/` |
| `uv run pytest` | Run the unit tests (an in-memory Microsoft Graph; no tenant needed) |
| `uv run ruff check` | Lint |
| `uv run ruff format --check` | Check formatting |
| `uv run entraid-mcp-server` | Start the server on stdio |

Releases are automatic: there is no publish command to run. A pull request to `dev`, and a push to `dev`, run the check workflow (build, tests, lint, format). When `dev` is merged into `main` and the push touches `src/msgraph_mcp_server/`, `pyproject.toml`, `README.md`, `LICENSE` or the publish workflow, the publish workflow (which can also be started by hand on `main`) computes the next version from the git tags, builds the package, publishes it to PyPI and creates the GitHub release.

## ⚠️ Known limitations

- The device tools use the Microsoft Graph **beta** endpoint, which Microsoft can change without notice.
- The server sets no timeout or retry of its own; a slow or failing Graph call ends the tool call with an error result.
- `search_groups_by_name` matches the start of the display name, not any part of it.
- `create_group` is several Graph calls with no rollback: if an owner or member add fails, the group stays created.
- `reset_user_password_direct` returns a generated password in its result, so it reaches the AI client's conversation.
- Membership checks and searches read Graph with eventual consistency: a change made moments earlier may not be seen yet.

## 📚 Documentation

| Page | Answers |
|---|---|
| [Users](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/users/index.md) | How to find users and read their groups and roles |
| [Groups](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/groups/index.md) | How groups, members and owners are managed, and what each result means |
| [Sign-in logs](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/sign-in-logs/index.md) | How to read a user's sign-ins |
| [MFA](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/mfa/index.md) | How MFA status is worked out for a user or a group |
| [Devices (Intune)](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/devices/index.md) | Which device, compliance and configuration data you can read |
| [Conditional access](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/conditional-access/index.md) | How policies are flattened into rows |
| [Audit logs](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/audit-logs/index.md) | How to read the changes a user made |
| [Password management](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/password-management/index.md) | How a reset works and how the password is protected |
| [Permissions helper](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/permissions-helper/index.md) | How to find the Graph permissions a task needs |
| [Applications](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/applications/index.md) | How app registrations are managed |
| [Service principals](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/features/service-principals/index.md) | How service principals are managed |
| [Configuration](https://github.com/baoduy/entraid-mcp-server/blob/main/docs/configuration.md) | Which settings choose how the server signs in, and where it reads them |
| [LICENSE](https://github.com/baoduy/entraid-mcp-server/blob/main/LICENSE) | MIT licence |

## ❓ Open questions

| Question | Why it matters | Checked | Who can answer |
|---|---|---|---|
| Is the permissions table above complete and least-privilege for the current 48 tools? | Admins grant exactly what this table says. | The code checks no permission; the table is carried over from the previous README. Only `get_user_sign_ins` names a permission in code (`AuditLog.Read.All`). | Maintainer (baoduy) |
| Does the password reset need `User-PasswordProfile.ReadWrite.All` (this table) or `User.ReadWrite.All` (the permissions helper's suggestion)? | A wrong grant makes the reset fail, or grants more than needed. | `reset_user_password_direct` sends `PATCH /users/{id}` with `passwordProfile`; `COMMON_PERMISSION_MAPPINGS` lists `User.ReadWrite.All`. | Maintainer (baoduy) |
| Where should users report problems or ask for support? | The README names no support route. | `pyproject.toml` lists the GitHub issues page as `Issues`; no support policy is in the repo. | Maintainer (baoduy) |
