ldap-mcp-server
Read-only MCP server for querying and auditing an LDAP directory.
Search users by uid, name, or email with partial matching and a result limit.
List the groups a given user belongs to.
Detect expired accounts or passwords unchanged for more than N days.
Reconcile a CSV of
usuario,aplicacion,rolaccess entries against the directory to find nonexistent users, expired accounts, and users with multiple roles in the same application.Safely query LDAP with read-only access, escaped filters, and restricted CSV file reads.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ldap-mcp-serverwhich groups does ana.garcia belong to?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ldap-mcp-server
Servidor MCP (Model Context Protocol) de solo lectura que permite a un agente de IA (Claude, u otro cliente MCP) consultar y auditar un directorio LDAP: buscar usuarios, ver sus grupos, detectar cuentas inactivas y cruzar listados de accesos para encontrar hallazgos de IAM.
Proyecto demostrativo basado en mi experiencia automatizando la depuración de accesos en entornos regulados. Todos los datos son ficticios (
dc=example,dc=org).
English summary: a read-only MCP server that lets AI agents query and audit an LDAP directory (user search, group membership, inactive accounts, access-list reconciliation). Ships with a Dockerized OpenLDAP and fake data.
Herramientas MCP
Herramienta | Qué hace |
| Busca por uid, nombre o correo (coincidencia parcial). |
| Devuelve los grupos ( |
| Cuentas expiradas ( |
| Cruza un CSV |
Related MCP server: LDAP Assistant MCP
Arquitectura
flowchart LR
A[Claude / agente IA] -- MCP stdio --> B[ldap-mcp-server<br/>MCP Python SDK]
B --> C[audit.py<br/>reglas de auditoría]
B --> D[directory.py<br/>ldap3 solo lectura]
D -- LDAP --> E[(OpenLDAP<br/>Docker)]
F[accesos.csv] --> BSolo lectura: la conexión se abre con
read_only=True; el servidor no expone ninguna operación de escritura.Filtros LDAP escapados para evitar inyección LDAP.
Lectura de CSV acotada:
cruzar_accesossolo lee archivos.csvdentro deLDAP_MCP_CSV_DIR(por defecto./data); rechaza rutas absolutas,.., rutas UNC y enlaces simbólicos.Lógica separada del acceso a datos: las reglas de auditoría se prueban sin servidor LDAP.
Inicio rápido
Requisitos: Python 3.10+, uv y Docker.
# 1. Levantar OpenLDAP con datos ficticios
docker compose up -d
# 2. Instalar dependencias y correr pruebas
uv sync
uv run pytest
# 3. Pruebas de integración contra el OpenLDAP local
cp .env.example .env
LDAP_INTEGRATION=1 uv run --env-file .env pytestConectarlo a Claude Desktop
Agrega esto a claude_desktop_config.json (ajusta la ruta):
{
"mcpServers": {
"ldap": {
"command": "uv",
"args": ["--directory", "C:/ruta/a/ldap-mcp-server", "run", "ldap-mcp-server"],
"env": {
"LDAP_URL": "ldap://localhost:389",
"LDAP_BIND_DN": "cn=admin,dc=example,dc=org",
"LDAP_BIND_PASSWORD": "admin_demo_local",
"LDAP_BASE_DN": "dc=example,dc=org",
"LDAP_MCP_CSV_DIR": "C:/ruta/a/ldap-mcp-server/data"
}
}
}
}Ejemplos de preguntas para el agente:
"¿Qué cuentas llevan más de 90 días sin cambiar la clave?"
"¿A qué grupos pertenece ana.garcia?"
"Cruza
accesos_ejemplo.csvcontra el directorio y dime qué accesos hay que revocar."
Estructura
src/ldap_mcp/
server.py # herramientas MCP (MCPServer, SDK oficial de Python)
directory.py # acceso LDAP de solo lectura (ldap3)
audit.py # reglas de auditoría (puras, testeables)
models.py # modelo Usuario
data/
seed.ldif # directorio ficticio
accesos_ejemplo.csv # listado de accesos de ejemplo
tests/ # unitarias + integración opcionalSeguridad
Usa una cuenta de servicio con permisos solo de lectura sobre el directorio.
No guardes credenciales en el repositorio: usa variables de entorno o
.env(ignorado por git).Para producción usa
ldaps://o StartTLS.
Autor
Kevin Stiven Naranjo González — AI-Ops & Agentic AI Engineer · LinkedIn · CV
Licencia MIT.
Available Tools
4 toolsbuscar_usuarioA
Busca usuarios por uid, nombre o correo (coincidencia parcial).
Args: texto: Texto a buscar, por ejemplo "garcia" o "ana.". limite: Máximo de resultados (1-100).
| Name | Required | Description | Default |
|---|---|---|---|
| texto | Yes | ||
| limite | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and it does disclose two useful traits: matching is partial/substring rather than exact, and results are capped (1-100). It does not say whether the search is case/accent-insensitive, what ordering results come in, or what an empty result looks like, so mutation/permission-risk context is limited but not contradictory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence carries the purpose and match mode, followed by a tight Args block. Slightly redundant with the parameter titles in the schema, but nothing wasted for a two-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the core matching semantics are covered. Still missing for a lookup tool: which field takes precedence when the text could be a uid, name, or email, and whether partial matching applies to all three — an agent could mis-assume behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description has to compensate, and it largely does: 'texto' is illustrated with concrete examples ('garcia', 'ana.'), and 'limite' is given the 1-100 bound that the schema omits (schema only shows default 20). It stops short of saying what happens if limite is out of range or if texto is blank.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Busca usuarios') plus the searchable fields (uid, nombre, correo) and match semantics (coincidencia parcial). The three siblings are unrelated operations (grupos, cuentas inactivas, cruzar accesos), so no explicit differentiation is needed, but the description never names an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the name and verb: an agent can infer 'search for a user when you have a partial identifier'. There is no statement of when this is preferable to the siblings, no prerequisites (auth scope needed to see other users), and no guidance on behavior when the text matches nothing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cruzar_accesosB
Cruza un listado de accesos contra el directorio y marca hallazgos.
El CSV debe tener las columnas: usuario, aplicacion, rol. Devuelve usuarios inexistentes, cuentas expiradas y usuarios con varios roles en la misma aplicación.
Args: csv_texto: Contenido del CSV. ruta_csv: Alternativa: ruta local a un archivo .csv.
| Name | Required | Description | Default |
|---|---|---|---|
| ruta_csv | No | ||
| csv_texto | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden. It does disclose the analysis output (three categories of findings), which implies a non-mutating read operation, but says nothing about precedence when both csv_texto and ruta_csv are supplied, nothing about size or encoding limits, and nothing about error behavior for malformed CSVs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and the return categories, then the CSV contract, then the Args block. The Args section is slightly redundant with the schema titles, but given zero schema descriptions it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does supply the return-value shape at a summary level, which is the main thing needed. It falls short on input-mode conflict resolution and failure modes, which matter for a two-source-input tool with no annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate and it partially does: it explains that csv_texto is raw CSV content and ruta_csv is a 'Alternativa' local file path, plus the required column shape. However, both parameters are optional with empty-string defaults, and the description never resolves what happens if both are provided or if neither is.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('cruza un listado de accesos contra el directorio') and enumerates the exact findings it produces (usuarios inexistentes, cuentas expiradas, roles duplicados). It does not explicitly contrast itself with the sibling detectar_cuentas_inactivas, which overlaps on the expired-accounts check, but the batch-CSV framing is distinct enough to be actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the caller must already have a CSV with usuario/aplicacion/rol columns to reach for this tool. There is no statement of when to prefer it over detectar_cuentas_inactivas or buscar_usuario, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
detectar_cuentas_inactivasB
Lista cuentas expiradas o con la clave sin cambiar en más de N días.
Args: dias_sin_cambio_clave: Umbral en días (por defecto 90).
| Name | Required | Description | Default |
|---|---|---|---|
| dias_sin_cambio_clave | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral-disclosure burden. It implies a read-only listing operation, but does not state permissions, whether it is safe, how results are formatted, or whether there are rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded, stating the purpose before the parameter details. The Args section is somewhat redundant for a single parameter but does not add verbosity or bury the key information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-parameter query tool, the description gives enough to invoke it correctly. However, with no annotations and no output schema, it leaves open the read-only nature, return format, and any operational constraints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must explain the sole parameter, and it does: dias_sin_cambio_clave is the threshold in days with a default of 90. This fully compensates for the otherwise undocumented schema property.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it lists accounts that are expired or whose password has not changed in more than N days. This is clear enough to distinguish it from siblings like buscar_usuario or listar_grupos_de_usuario, although it does not explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool returns but gives no explicit guidance on when to choose it over alternatives such as buscar_usuario or cruzar_accesos. There are no stated prerequisites, exclusions, or contextual cues beyond the basic criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listar_grupos_de_usuarioB
Devuelve los grupos a los que pertenece un usuario.
Args: uid: Identificador exacto del usuario, por ejemplo "ana.garcia".
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Devuelve' implies a read-only lookup, but it says nothing about permissions needed, whether a nonexistent uid errors or returns an empty list, or what the returned group entries look like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in one clear sentence and the Args block is compact. The docstring formatting is slightly verbose for a single parameter but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description covers purpose and the identifier format adequately. It does not describe the shape of the returned groups (names vs. objects) or edge-case behavior, leaving a clear gap an agent would want filled.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: it explains that uid is the 'Identificador exacto del usuario' and supplies a concrete example format ('ana.garcia'). This adds real meaning beyond the bare string type in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource in Spanish: returns the groups a user belongs to. This is clearly distinguishable from siblings like buscar_usuario (finds users) or cruzar_accesos (crosses accesses). It lacks an explicit contrast with those siblings, so a 4 rather than a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus buscar_usuario or cruzar_accesos, nor any mention of prerequisites such as the user needing to exist. The usage is only implicit in the verb 'Devuelve'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
buscar_usuario - First observed
cruzar_accesos - First observed
detectar_cuentas_inactivas - First observed
listar_grupos_de_usuario
TDQS
Scored across 4 tools
The tools are highly distinct: one searches by various criteria, one lists groups for a specific user, one detects inactivity, and one performs complex CSV cross-validation. Each serves a very clear and non-overlapping purpose.
The tools consistently follow a clear action_subject pattern using Spanish verbs and nouns (e.g., 'buscar_usuario', 'listar_grupos_de_usuario'). The naming conventions are predictable and highly readable across the entire set.
For a directory server, four tools cover essential management and auditing functions effectively. While a few more granular retrieval tools might be useful, the current count is well-scoped to the functions presented.
The current set is almost entirely focused on read-only operations and auditing. There is a critical absence of basic user lifecycle management functions, such as creating, deleting, or modifying user attributes/passwords.
Maintenance
Related MCP Connectors
Free open dataset of compliance, security and risk AI agents and audit firms. Read-only search.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Read-only finance and operations controls for AI agents with evidence and safe next actions.
Read-only local AI advice, shared reports and website audits. No PC scan or local actions.
Related MCP Servers
- FlicenseAqualityCmaintenanceProvides AI assistants with unified access to on-prem Active Directory via LDAP and Azure AD / Entra ID through the Microsoft Graph API. It enables comprehensive management and search of users, groups, computers, and cloud devices using 18 specialized tools.18-
- AlicenseNot gradedqualityCmaintenanceEnables troubleshooting of LDAP directory services through natural language queries, providing health diagnostics, replication status, performance metrics, log analysis, and configuration comparisons across multiple servers.1GPL 3.0
- AlicenseBqualityDmaintenanceProvides read-only access to corporate LDAP directories, enabling AI assistants to search for people, navigate organizational hierarchies, and export contact information.125MIT
- FlicenseNot gradedqualityCmaintenanceProvides read-only tools for monitoring and investigating Active Directory Domain Services, including users, groups, OUs, computers, GPOs, and domain metadata via LDAPS.-