Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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

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 .

Using uv (recommended)

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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kizano_ldap_mcp_server-1.0.1.dev0.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kizano_ldap_mcp_server-1.0.1.dev0-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file kizano_ldap_mcp_server-1.0.1.dev0.tar.gz.

File metadata

File hashes

Hashes for kizano_ldap_mcp_server-1.0.1.dev0.tar.gz
Algorithm Hash digest
SHA256 8ad661516f46e25c06f45dc5465c3b1494d732ad95141e939227878a1f5b3fc4
MD5 2e02682910f60df0eba5e76381f9a798
BLAKE2b-256 bd008123f04a3d32f934c656e033361848e8ea3ba029a0c31f772da7b0673dd1

See more details on using hashes here.

File details

Details for the file kizano_ldap_mcp_server-1.0.1.dev0-py3-none-any.whl.

File metadata

File hashes

Hashes for kizano_ldap_mcp_server-1.0.1.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce8b7d1269f8556efc7f766c51dd3040205e9b67a9be8abb688134bb33148222
MD5 19bb75f21c1336a6deda2bad59886268
BLAKE2b-256 470fc791fe1bc30a102408b582c91f5dc3a1d885b0be1bc5a970b057662fad3a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.1.dev0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page