Skip to main content
Glama
markizano

ldap-mcp-server

by markizano

LDAP MCP Server

A Python-based Model Context Protocol (MCP) server that exposes LDAP directory operations to AI agents and coding assistants like Claude, Cursor, and OpenCode.

This is a Python port of the original trxo/ldap-mcp implementation written in Go by @trxo. Full credit to the original author for the design and concept.

Features

  • Full LDAP CRUD operations - Search, read, add, modify, and delete directory entries

  • Dual transport modes - stdio (local) and SSE (networked)

  • LDIF and JSON output - RFC 2849 compliant LDIF formatting or structured JSON

  • API key authentication - Secure Bearer token or X-API-Key header validation (SSE mode)

  • Read-only or read-write - Control write access via --read-write flag

  • TLS support - LDAPS and StartTLS with certificate validation

  • MCP resources - Expose Root DSE and individual entries as resources

  • Comprehensive tests - 50+ unit tests with full coverage

Related MCP server: Agent Identity MCP Server

Installation

From PyPI (when published)

pip install kizano-ldap-mcp-server

From Source

git clone https://github.com/markizano/ldap-mcp-server.git
cd ldap-mcp-server
pip install -e .
git clone https://github.com/markizano/ldap-mcp-server.git
cd ldap-mcp-server
uv pip install -e .

Quick Start

1. Configuration

Create a .env file (copy from .env.example):

# LDAP connection
LDAP_URI=ldap://localhost:389
LDAP_BIND_DN=cn=admin,dc=example,dc=com
LDAP_BIND_PASSWORD=your_password_here

# MCP server (SSE mode)
MCP_HOST=0.0.0.0
MCP_PORT=9090
LDAP_MCP_SERVER_API_KEY=your-secure-api-key-here

# Logging
LOG_LEVEL=INFO

2. Start the Server

stdio mode (local development, no API key needed):

ldap-mcp-server --transport stdio --read-write

SSE mode (network server with authentication):

ldap-mcp-server --transport sse --host 0.0.0.0 --port 9090

3. Configure Your MCP Client

For stdio mode (Claude Desktop, Cursor, OpenCode):

Add to your MCP client configuration (e.g., ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json):

{
  "mcpServers": {
    "ldap": {
      "command": "ldap-mcp-server",
      "args": ["--transport", "stdio", "--read-write"],
      "env": {
        "LDAP_URI": "ldap://localhost:389",
        "LDAP_BIND_DN": "cn=admin,dc=example,dc=com",
        "LDAP_BIND_PASSWORD": "your_password_here"
      }
    }
  }
}

For SSE mode (remote server):

{
  "mcpServers": {
    "ldap": {
      "url": "http://your-server:9090/sse",
      "headers": {
        "Authorization": "Bearer YOUR_LDAP_MCP_SERVER_API_KEY"
      }
    }
  }
}

Usage

Available Tools

The server exposes the following MCP tools:

search_entries

Search for LDAP entries matching a filter.

search_entries(
    base_dn="ou=users,dc=example,dc=com",
    filter="(objectClass=inetOrgPerson)",
    scope="sub",  # base, one, or sub
    attributes=["cn", "mail", "uid"],  # None for all attributes
    output_format="ldif"  # ldif or json
)

get_entry

Retrieve a single entry by DN.

get_entry(
    dn="uid=jsmith,ou=users,dc=example,dc=com",
    attributes=["cn", "mail"],
    output_format="ldif"
)

add_entry (requires --read-write)

Create a new LDAP entry.

add_entry(
    dn="uid=newuser,ou=users,dc=example,dc=com",
    attributes={
        "objectClass": ["inetOrgPerson", "organizationalPerson"],
        "cn": ["New User"],
        "sn": ["User"],
        "mail": ["newuser@example.com"]
    }
)

modify_entry (requires --read-write)

Modify an existing entry.

modify_entry(
    dn="uid=jsmith,ou=users,dc=example,dc=com",
    changes=[
        {
            "operation": "replace",
            "attribute": "mail",
            "values": ["newemail@example.com"]
        }
    ]
)

delete_entry (requires --read-write)

Delete an entry.

delete_entry(dn="uid=olduser,ou=users,dc=example,dc=com")

Available Resources

ldap://root-dse

Server metadata and capabilities (JSON format).

ldap://entry/{url-encoded-dn}

Individual entry by DN (LDIF format).

Example: ldap://entry/uid%3Djsmith%2Cou%3Dusers%2Cdc%3Dexample%2Cdc%3Dcom

Command-Line Options

usage: ldap-mcp-server [-h] [--transport {stdio,sse}] [--host HOST]
                       [--port PORT] [--url URL] [--bind-dn BIND_DN]
                       [--bind-password BIND_PASSWORD] [--starttls]
                       [--insecure] [--read-write] [--timeout TIMEOUT]
                       [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]

options:
  --transport {stdio,sse}    Transport mode (default: sse)
  --host HOST                Host to bind to (default: 0.0.0.0)
  --port PORT                Port to listen on (default: 9090)
  --url URL                  LDAP server URL
  --bind-dn BIND_DN          Bind DN for service account
  --bind-password BIND_PASSWORD
                             Bind password
  --starttls                 Use StartTLS (cannot be used with ldaps://)
  --insecure                 Skip TLS certificate verification (INSECURE)
  --read-write               Enable write operations
  --timeout TIMEOUT          LDAP operation timeout in seconds (default: 30)
  --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
                             Logging level (default: INFO)

CLI flags override environment variables.

Development

Running Tests

# Install test dependencies
pip install -e ".[test]"

# Run all tests
pytest tests/

# Run with coverage
pytest tests/ --cov=ldap_mcp_server --cov-report=html

Project Structure

ldap-mcp.py/
├── lib/ldap_mcp_server/
│   ├── __init__.py         # Entry point with dotenv loading
│   ├── __main__.py         # python -m support
│   ├── cli.py              # Argument parsing
│   ├── config.py           # Configuration dataclass
│   ├── ldap_client.py      # LDAP connection wrapper
│   ├── ldif.py             # LDIF formatter (RFC 2849)
│   ├── middleware.py       # API key authentication
│   ├── resources.py        # MCP resource registrations
│   ├── server.py           # Main serve() function
│   └── tools.py            # MCP tool registrations
├── tests/
│   ├── test_config.py      # Configuration tests
│   ├── test_ldif.py        # LDIF formatting tests
│   └── test_middleware.py  # Authentication tests
├── pyproject.toml          # Package metadata
└── pytest.ini              # Test configuration

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository and create a feature branch

  2. Write tests for new functionality (maintain >90% coverage)

  3. Follow the coding style:

    • Use type hints for all function signatures

    • All imports at the top of the module (no JIT imports)

    • Follow DRY principles (no copy-paste code)

    • Docstrings for all public functions

  4. Run the test suite before submitting:

    pytest tests/ -v
  5. Update documentation if adding features

  6. Submit a pull request with a clear description

Development Setup

# Clone the repo
git clone https://github.com/markizano/ldap-mcp-server.git
cd ldap-mcp-server

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # or `.venv\Scripts\activate` on Windows

# Install in editable mode with test dependencies
pip install -e ".[test]"

# Run tests
pytest tests/ -v

Security

  • API keys are read from environment variables only, never from CLI or config files

  • TLS certificate validation is enabled by default (use --insecure to disable for testing)

  • Write operations are disabled by default (requires explicit --read-write flag)

  • Bind credentials should use service accounts with minimal required privileges

Warning: Never commit .env files or hardcode credentials in code.

License

MIT License - see LICENSE file for details

Credits

Troubleshooting

"Failed to connect to LDAP"

  • Verify LDAP_URI is correct (ldap:// or ldaps://)

  • Check firewall rules allow connections to LDAP port (389 or 636)

  • Test with ldapsearch to verify credentials

"401 Unauthorized" (SSE mode)

  • Ensure LDAP_MCP_SERVER_API_KEY is set in environment

  • Verify client is sending Authorization: Bearer <key> or X-API-Key: <key> header

  • Check server logs for auth attempts

"405 Method Not Allowed"

  • Client may be POSTing to /sse instead of /messages

  • Client URL should be http://host:port/sse (not /messages)

Write operations fail

  • Ensure server started with --read-write flag

  • Verify bind DN has write permissions in LDAP directory

  • Check LDAP server logs for permission errors

Support

Roadmap

  • Connection pooling for high-traffic deployments

  • Schema introspection and validation

  • LDAP server discovery (DNS SRV records)

  • Prometheus metrics endpoint

  • Docker image and Kubernetes manifests

  • Interactive schema browser MCP resource


Made with ❤️ for the MCP community

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A production-ready MCP server that enables AI assistants to manage enterprise Active Directory environments through 45 specialized tools for users, groups, and GPOs. Its multi-client architecture allows for the secure management of multiple AD domains from a single codebase using natural language commands.
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that enables AI-powered assessment of Active Directory on-premises environments by exposing AD data as queryable tools for LLMs like Claude.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for read-only LDAP directory operations, enabling search, entry retrieval, schema browsing, and comparison via natural language.
    MIT