Skip to main content
Glama
fredriksknese

mcp-activedirectory

README.md
# mcp-activedirectory

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for **Microsoft Active Directory**, providing AI assistants with access to on-prem AD (via LDAP) and Azure AD / Entra ID (via Microsoft Graph API).

## Features

Supports two modes simultaneously:

- **On-prem Active Directory** — connects to a domain controller via LDAP/LDAPS using the `ldapts` library
- **Azure AD / Entra ID** — connects via the Microsoft Graph API using OAuth2 Client Credentials

**18 tools** across five categories:

### User Management
| Tool | Description |
|------|-------------|
| `list_users` | List users with optional name, email, or department filter |
| `get_user` | Get full user details including decoded UAC flags (on-prem) or full profile (Azure AD) |
| `get_user_groups` | List all groups a user is a member of |
| `search_users` | Advanced search by name, email, department, title, phone, or UPN |

### Group Management
| Tool | Description |
|------|-------------|
| `list_groups` | List groups with optional name filter |
| `get_group` | Get group details including member count and decoded group type |
| `get_group_members` | List all group members; supports recursive nested group expansion (on-prem) |
| `search_groups` | Search groups by name or description |

### Computer Accounts (On-prem AD only)
| Tool | Description |
|------|-------------|
| `list_computers` | List computer accounts with OS, last logon (human-readable), and OU |
| `get_computer` | Get full computer account details |
| `search_computers` | Search by name, OS, OU path, DNS hostname, or description |

### Organizational Units (On-prem AD only)
| Tool | Description |
|------|-------------|
| `list_ous` | List OUs with full path, sorted by depth |
| `get_ou` | Get OU details |
| `search_ous` | Search OUs by name, description, or parent path |

### Azure AD / Entra ID (Azure AD only)
| Tool | Description |
|------|-------------|
| `list_devices` | List Entra ID registered/joined devices with OS and compliance status |
| `get_device` | Get full device details by object ID |
| `list_service_principals` | List app registrations and service principals |
| `get_user_sign_in_activity` | Get last sign-in information for a user |

## Installation

```bash
git clone git@github.com:fredriksknese/mcp-activedirectory.git
cd mcp-activedirectory
npm install
npm run build
```

## Configuration

The server is configured via environment variables. At least one of `AD_HOST` or `AZURE_TENANT_ID` must be set.

### On-prem Active Directory (LDAP)

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `AD_HOST` | Yes | — | Domain controller hostname or IP address |
| `AD_PORT` | No | `389` | LDAP port (`636` for LDAPS) |
| `AD_USE_SSL` | No | `false` | Use LDAPS (`true`/`false`) |
| `AD_BIND_DN` | Yes | — | Bind DN, e.g. `CN=svc-mcp,OU=Service Accounts,DC=corp,DC=example,DC=com` |
| `AD_BIND_PASSWORD` | Yes | — | Bind account password |
| `AD_BASE_DN` | Yes | — | Base DN for all searches, e.g. `DC=corp,DC=example,DC=com` |
| `AD_ALLOW_SELF_SIGNED` | No | `true` | Accept self-signed TLS certificates |

### Azure AD / Entra ID (Microsoft Graph API)

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `AZURE_TENANT_ID` | Yes | — | Azure AD tenant ID (GUID) |
| `AZURE_CLIENT_ID` | Yes | — | App registration (client) ID |
| `AZURE_CLIENT_SECRET` | Yes | — | App registration client secret |

## Required Permissions

### On-prem Active Directory

The service account (`AD_BIND_DN`) needs **read access** to the directory. The minimum required permissions are:

- **Read** on User objects (all attributes listed below)
- **Read** on Group objects
- **Read** on Computer objects
- **Read** on OrganizationalUnit objects

Recommended: add the service account to the built-in **Domain Users** group and grant **Read** delegated permissions on the domain root, or use the built-in **Read-only Domain Controllers** access pattern.

Attributes read for users: `cn`, `sAMAccountName`, `displayName`, `mail`, `userPrincipalName`, `department`, `title`, `telephoneNumber`, `mobile`, `manager`, `memberOf`, `userAccountControl`, `lastLogon`, `whenCreated`, `whenChanged`, `description`, `distinguishedName`, `objectGUID`

### Azure AD / Entra ID (Microsoft Graph)

Create an **App Registration** in Azure AD and grant the following **Application permissions** (not Delegated):

| Permission | Scope | Required for |
|------------|-------|--------------|
| `User.Read.All` | Microsoft Graph | Reading user profiles and group memberships |
| `Group.Read.All` | Microsoft Graph | Reading groups and group members |
| `Device.Read.All` | Microsoft Graph | Reading Entra ID registered/joined devices |
| `AuditLog.Read.All` | Microsoft Graph | Reading sign-in activity (`signInActivity` field) |

Grant **Admin Consent** for all permissions in the Azure portal.

## Usage with Claude Desktop

Add to your `claude_desktop_config.json`:

### On-prem AD only

```json
{
  "mcpServers": {
    "activedirectory": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-activedirectory/dist/index.js"],
      "env": {
        "AD_HOST": "dc01.corp.example.com",
        "AD_BIND_DN": "CN=svc-mcp,OU=Service Accounts,DC=corp,DC=example,DC=com",
        "AD_BIND_PASSWORD": "your-service-account-password",
        "AD_BASE_DN": "DC=corp,DC=example,DC=com"
      }
    }
  }
}
```

### Azure AD / Entra ID only

```json
{
  "mcpServers": {
    "activedirectory": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-activedirectory/dist/index.js"],
      "env": {
        "AZURE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

### Both simultaneously

```json
{
  "mcpServers": {
    "activedirectory": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-activedirectory/dist/index.js"],
      "env": {
        "AD_HOST": "dc01.corp.example.com",
        "AD_BIND_DN": "CN=svc-mcp,OU=Service Accounts,DC=corp,DC=example,DC=com",
        "AD_BIND_PASSWORD": "your-service-account-password",
        "AD_BASE_DN": "DC=corp,DC=example,DC=com",
        "AZURE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

## Usage with Claude Code

```bash
claude mcp add activedirectory -- node /absolute/path/to/mcp-activedirectory/dist/index.js
```

## LDAPS / SSL Configuration

To use LDAPS (port 636):

```json
"env": {
  "AD_HOST": "dc01.corp.example.com",
  "AD_PORT": "636",
  "AD_USE_SSL": "true",
  "AD_ALLOW_SELF_SIGNED": "true"
}
```

Set `AD_ALLOW_SELF_SIGNED` to `"false"` if your domain controller uses a certificate from a trusted CA.

## Example Prompts

Once connected, you can ask your AI assistant things like:

- *"List all users in the IT department"*
- *"Get details for user jdoe including their group memberships"*
- *"Which groups does john.doe@company.com belong to?"*
- *"Show me all members of the Domain Admins group"*
- *"List all Windows Server 2022 computers in the Servers OU"*
- *"Which computer accounts haven't logged in since 2024?"*
- *"Show me the top-level OUs in the domain"*
- *"List all Azure AD joined devices"*
- *"When did user@company.com last sign in?"*
- *"List all service principals of type ManagedIdentity"*

## Architecture

```
src/
├── index.ts              # Entry point — creates MCP server + STDIO transport
├── ad-client.ts          # LDAP client wrapping ldapts for on-prem AD
├── graph-client.ts       # Microsoft Graph API client with OAuth2 token caching
└── tools/
    ├── users.ts          # User tools (list, get, search, groups) — AD + Azure
    ├── groups.ts         # Group tools (list, get, members, search) — AD + Azure
    ├── computers.ts      # Computer account tools — on-prem AD only
    ├── ous.ts            # Organizational unit tools — on-prem AD only
    └── azure.ts          # Azure-specific tools (devices, service principals, sign-in)
```

## Development

```bash
npm run dev      # Run with tsx (no compilation needed)
npm run build    # Compile TypeScript to dist/
npm start        # Run compiled output
```

## Requirements

- Node.js 18+
- For on-prem AD: network access to a domain controller on port 389 (LDAP) or 636 (LDAPS)
- For Azure AD: an App Registration with the required Graph API permissions

## License

SEE LICENSE IN LICENSE

TDQS

A3.5/5.0

Scored across 18 tools

Disambiguation5/5

Each tool targets a distinct resource type or operation (e.g., get vs list vs search, computer vs device, group vs group members). There is no ambiguity between tools.

Naming Consistency5/5

All tool names follow the verb_noun pattern consistently (e.g., get_computer, list_users, search_groups). No mixing of naming conventions.

Tool Count5/5

18 tools cover both on-prem AD and Azure AD resources (users, groups, computers, devices, OUs, service principals) without being excessive. The scope is appropriate for a directory server.

Completeness2/5

The tool set is entirely read-only; there are no create, update, or delete operations. For an Active Directory server, this is a significant gap that prevents full lifecycle management.

Maintenance

ActivityInactive
ResponsivenessNo issues