Skip to main content

mcpAD

A FastMCP server that exposes the msad Active Directory / LDAP library as MCP tools.

Built with Python 3.14 and uv. It reuses the typed, public msad API (search users/groups, memberships, account status). All tools are read-only.

Tools

Tool Description
find_users Find users by name/surname/mail/sam/department (ANDed, * wildcards)
get_user Get a single user (exact match)
find_groups Find groups (* wildcards)
get_group Get a single group (exact match)
find_computers Find computers by name/dns/os (* wildcards)
get_computer Get a single computer (sAMAccountName/cn/dNSHostName)
find_ous Find organizational units by name (* wildcards)
get_ou Get a single OU by its ou name or full DN (exact match)
get_ou_contents List objects under an OU (optionally filtered by object_class)
find_inactive_users Find users whose last logon is older than days (default 90)
find_stale_computers Find computers whose last logon is older than days (default 90)
get_domain_info Domain object: security-relevant settings and metadata (audit)
get_password_policy Default domain password policy (audit)
get_password_policy_violations Users whose password violates the policy (audit)
get_privileged_groups Well-known privileged groups with member counts (audit)
get_by_dn Fetch any entry directly by its DN (resolve manager / managedBy)
group_members List group members (direct or nested)
user_groups List a user's groups (nested by default)
is_member Is a user a (nested) member of a group?
is_disabled Is an account disabled?
is_locked Is an account locked?
test_connection Test AD connectivity and bind (returns ok/target/auth/error)
health Server health check (server name, msad version, connectivity)

The find_users, find_groups, find_computers and find_ous tools accept an optional base (a DN, e.g. an OU) to restrict the search to that subtree instead of the whole domain.

Returned attributes

By default get_user / find_users return a useful attribute set: identity fields plus manager — the distinguished name (DN) of the user's manager, e.g. CN=Anna Bianchi,OU=Staff,DC=group,DC=example,DC=com — as well as memberOf (direct group DNs), userAccountControl, accountExpires, lastLogonTimestamp and whenCreated. Group lookups include managedBy (the DN of the group's owner), member, groupType and whenCreated.

To expand a manager (or any DN-valued field) into a full record, call get_by_dn with that DN. This is a direct, efficient lookup (the DN is used as the search base), so an agent can do: get_user("mrossi") → read manager → get_by_dn("<that DN>").

Authentication & connection

The server has no connection settings of its own: it reuses the msad configuration file, ~/.msad.toml by default (create it with msad init). Each tool call opens a short-lived connection through msad.connect().

Domain parameters (~/.msad.toml)

[defaults]
domain = "group"              # used when a tool call omits `domain`

[domains.group]
host = "dc.example.com"       # hostname only (no scheme, no :port)
base = "dc=group,dc=example,dc=com"
port = 636                    # default: 389
use_ssl = true                # default: false  (true = LDAPS)
# user = "svc_account"        # optional (see auth below)
# password = "..."            # optional

# A second domain (here using user/password auth):
[domains.lab]
host = "dc.lab.example.com"
base = "dc=lab,dc=example,dc=com"
port = 636
use_ssl = true
user = "svc_reader"
password = "s3cr3t"

You can declare several [domains.<name>] blocks and pick one per call with the tool's domain argument, or globally via MSAD_DOMAIN. For example, an agent can call find_users(surname="Rossi", domain="lab") to target the lab domain while [defaults].domain stays group.

Overrides via environment

  • MSAD_DOMAIN — default domain when a tool call omits domain
  • MSAD_CONFIG_FILE — path to an alternative TOML config

Authentication modes

The mode is chosen automatically from the domain block:

  • Kerberos (SASL) — when user/password are not both set (the default). Obtain a ticket first:

    kinit                # or: kinit <user>@REALM
    

    The server relies on the system Kerberos ticket cache (or a keytab via KRB5_CLIENT_KTNAME). If the ticket is missing or expired, tools fail with a clean MsadConnectionError message. When running as a background/remote service, make sure that process can see a valid ticket or keytab.

  • User / password — when both user and password are set. Simple LDAP bind. The password is stored in clear text in the TOML, so restrict the file permissions (chmod 600 ~/.msad.toml).

    Note: setting only one of user/password silently falls back to Kerberos. Set both, or neither.

Use LDAPS (port = 636, use_ssl = true) whenever possible.

Running

Using uvx:

uvx --from git+https://github.com/matteoredaelli/mcpAD mcpAD

The Makefile wraps the common cases. Transport, host and port are configurable:

make start-stdio                        # stdio (for local MCP clients)
make start-http                         # streamable-http on 127.0.0.1:8000
make start-http HOST=0.0.0.0 PORT=9000  # bind elsewhere
make start-sse                          # sse transport
make start TRANSPORT=streamable-http PORT=9000   # generic form

Equivalent raw commands (the server reads MCP_TRANSPORT / MCP_HOST / MCP_PORT from the environment):

uv run mcpad                                        # stdio (default)
MCP_TRANSPORT=streamable-http MCP_PORT=9000 uv run mcpad

Registering the server with an MCP client / agent

MCP clients (Claude Desktop, IDE agents, custom agents, ...) usually accept a JSON config with a mcpServers map. Two deployment styles:

Local (stdio) — the client launches the server

The client spawns the process and talks to it over stdio. This is the simplest setup and keeps everything on your machine (including your Kerberos ticket).

{
  "mcpServers": {
    "mcpAD": {
      "command": "uv",
      "args": [
        "run",
        "--directory", "/path/to/mcpAD",
        "mcpad"
      ],
      "env": {
        "MSAD_DOMAIN": "group"
      }
    }
  }
}

Notes:

  • --directory makes uv use this project's environment regardless of the client's working directory.
  • Kerberos: the spawned process inherits your environment, so a ticket obtained with kinit in the same user session is used automatically. For an unattended client, point it at a keytab (e.g. add "KRB5_CLIENT_KTNAME": "/path/to.keytab" to env).

Remote (streamable-http) — the server runs as a service

Start the server as a long-running HTTP service, then point the client at its URL. Useful when the server runs on a host that has AD/Kerberos access while the client runs elsewhere.

Start the service:

make start-http HOST=0.0.0.0 PORT=9000
# serves the MCP endpoint at http://<host>:9000/mcp

Client config referencing the URL:

{
  "mcpServers": {
    "mcpAD": {
      "transport": "http",
      "url": "http://mcp-host.example.com:9000/mcp"
    }
  }
}

Notes:

  • The default streamable-http path is /mcp.
  • The server itself performs no client authentication; if you expose it beyond localhost, put it behind a reverse proxy / network controls and treat the AD credentials on that host accordingly.
  • Kerberos runs where the server runs: that host needs a valid ticket or a keytab, not the client.

Development

uv sync
uv run python -c "import asyncio; from mcpad import mcp; print(asyncio.run(mcp.list_tools()))"

The msad dependency can be installed from its Git repository, or as an editable local path during development so that library changes are picked up immediately.

Metadata

Release files for mcpad 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcpad 0.1.0
File Size Uploaded
mcpad-0.1.0.tar.gz 9.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcpad 0.1.0
File Interpreter ABI Platform
mcpad-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.8 kB

Release files / mcpad-0.1.0.tar.gz

Download URL mcpad-0.1.0.tar.gz
Size 9.2 kB
Tags Source
SHA-256 checksum
How to use checksums
74da492a5ad57b3003482221220bdb8e04d071cb58151126d9a5c30ff7642e4a
BLAKE2b-256 checksum
How to use checksums
0f728d037ef4be50a872f84297e9cfb223969d637c85f523740f6c3b2576a0e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mcpad-0.1.0-py3-none-any.whl

Download URL mcpad-0.1.0-py3-none-any.whl
Size 9.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d198401b62b0d5fcbb5270adbd75c35bf07a3310e8520b4246a4c29632c3686
BLAKE2b-256 checksum
How to use checksums
7941a871e84ce78d15eb4845afd5010896d02201063ea9b62f4a89072f16bd2b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page