v0.1.0 · first usable release

A real directory.
A small control plane.

LabLDAP stands up 389 Directory Server, applies a declarative scenario, then hands you REST, MCP, and a browser UI that share one authorization policy. Directory Manager is bootstrap-only.

LabLDAP directory console on a laptop
Engine389-ds 2.4.6
Control planeGo 1.26
Agent surfaceMCP 2026-07-28
ImagesLocal only
Why it exists

Not a fake. Not a naked 389 DS container.

In-memory mocks lie about the protocol. Raw directory containers leave Directory Manager in an environment variable for the rest of the afternoon. LabLDAP splits the job the way an operator would.

directory Long-running 389 DS

Owns /data. Source of truth for users, groups, memberships, and passwords.

bootstrap One-shot labldap-bootstrap

Uses Directory Manager from a secret file, applies the scenario, then exits.

control Long-running labldap

Restricted service account. No DM secret. No Docker socket. Serves UI, REST, and MCP.

Surfaces

One policy. Four ways in.

Create a user in the browser, fetch it over REST, bind with ldapsearch, and an agent can read it through MCP.

Browser UI

Users, groups, search, bind test, schema, audit, LDIF export, and a gated soft reset. Session cookie, not a token in localStorage.

REST

Versioned OpenAPI at /api/v1. Revisions, problem documents, the same scopes as every other transport.

MCP

Streamable HTTP POST /mcp or labldap mcp-stdio. Reads on by default. Writes stay off until you enable them.

Ninety seconds

Compose up. Sign in. Search.

Docker Engine 24+ and Compose v2.24+. First run builds local images. Later runs reuse them.

  1. make compose-up — secrets, lab CA, 389 DS, bootstrap, control.
  2. https://127.0.0.1:8443/ — trust the lab cert, paste secrets/token-admin.
  3. ldap://127.0.0.1:3389 — bind as a directory user, not as Directory Manager.
git clone https://github.com/hilather/go-lab-ldap-mcp.git
cd go-lab-ldap-mcp
make compose-up

TOKEN=$(tr -d '\n' < secrets/token-admin)
curl -sk -H "Authorization: Bearer $TOKEN" \
  https://127.0.0.1:8443/api/v1/users
On the host

Loopback only. Lab certificates.

SurfaceAddressNotes
UI / REST / MCP127.0.0.1:8443Lab TLS. Bearer or session cookie.
LDAP / StartTLS127.0.0.1:3389Simple bind as a directory user.
LDAPS127.0.0.1:3636Trust the generated lab CA.
Health/health · /health/readyLiveness never talks to LDAP.
Safety

Laboratory on purpose.

This is not a production identity system. The constraints are the product.

  • LDAP bind hits 389 DS, not Go. ldap://127.0.0.1:3389 is a real directory. The Go process is HTTPS only.
  • No Docker socket in the control plane.
  • Directory Manager is bootstrap-only.
  • Static tokens are an explicit lab mode.
  • Ephemeral tmpfs is not a wipe — host swap can persist pages.
  • Active Directory emulation is out of scope.
Guides

Read these first.