{
  "markdown": "# mcp-keycloak\n\n[![CI](https://github.com/dockndevai/mcp-keycloak/actions/workflows/ci.yml/badge.svg)](https://github.com/dockndevai/mcp-keycloak/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![npm](https://img.shields.io/npm/v/@dockndevai/mcp-keycloak)](https://www.npmjs.com/package/@dockndevai/mcp-keycloak)\n\nA [Model Context Protocol](https://modelcontextprotocol.io) server for **Keycloak**. It lets an MCP-capable client (Claude Desktop, Claude Code, etc.) inspect and manage Keycloak realms, users, clients, roles, and groups — with security controlled entirely by flags.\n\nThe design goal is **safe by default**: it starts read-only, scopes to an allowlist of realms, protects sensitive realms from mutation, and gates destructive operations behind an explicit opt-in.\n\n## Features\n\n- **Multi-realm** — every tool takes a `realm` argument; scope it with an allowlist.\n- **Access modes** — `read-only` → `read-write` → `admin`, layered so a mode never exposes tools above its level.\n- **Security flags** — realm allowlist, protected realms, delete gating, dry-run, and JSON audit logging (see below).\n- **Two auth strategies** — confidential-client service account (recommended) or admin username/password.\n- **Zero heavy dependencies** — a thin fetch-based Admin REST client, plus the MCP SDK and zod.\n\n## Security model\n\n| Concern | Flag | Default | Effect |\n| --- | --- | --- | --- |\n| What can the server do at all? | `KEYCLOAK_MODE` | `read-only` | `read-only` exposes only read tools; `read-write` adds mutations; `admin` adds destructive tools. Tools above the mode are **never registered**. |\n| Which realms are in scope? | `KEYCLOAK_REALM_ALLOWLIST` | *(all)* | Comma-separated. When set, any operation on a realm outside the list is refused. |\n| Which realms are read-only forever? | `KEYCLOAK_PROTECTED_REALMS` | `master` | Protected realms can be read but never mutated or deleted, regardless of mode. |\n| Can it delete? | `KEYCLOAK_ALLOW_DELETE` | `false` | `delete_*` tools require this **and** admin mode. |\n| Preview without touching Keycloak | `KEYCLOAK_DRY_RUN` | `false` | Write/admin tools validate + log intent, then return without calling Keycloak. |\n| Audit trail | `KEYCLOAK_AUDIT_LOG` | `true` | Emits a JSON line to stderr per guarded operation (`ALLOW` / `DENY` / `DRY_RUN`). |\n\nThese layers are independent — for example `admin` mode with `KEYCLOAK_ALLOW_DELETE=false` can create and update users but cannot delete them.\n\n## Tools\n\n**Read** (`read-only`+): `list_realms`, `get_realm`, `list_users`, `get_user`, `count_users`, `list_clients`, `list_realm_roles`, `list_groups`\n\n**Write** (`read-write`+): `create_user`, `update_user`, `reset_password`, `logout_user`\n\n**Admin** (`admin`): `delete_user`\n\n## Quickstart — add to your agent\n\nPublished on npm as [`@dockndevai/mcp-keycloak`](https://www.npmjs.com/package/@dockndevai/mcp-keycloak). No clone or build needed — your MCP client runs it on demand with `npx`. **Start in `read-only` mode**; see [`.env.example`](.env.example) for every variable and [docs/CLIENTS.md](docs/CLIENTS.md) for the full per-client guide.\n\n**Claude Code** (CLI)\n\n```bash\nclaude mcp add keycloak -e KEYCLOAK_URL=\"https://keycloak.example.com\" -e KEYCLOAK_CLIENT_ID=\"admin-cli\" -e KEYCLOAK_CLIENT_SECRET=\"your-secret\" -e KEYCLOAK_MODE=\"read-only\" -- npx -y @dockndevai/mcp-keycloak\n```\n\n**Claude Desktop · Cursor · Windsurf** — same block in `claude_desktop_config.json`, `.cursor/mcp.json`, or `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"keycloak\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@dockndevai/mcp-keycloak\"\n      ],\n      \"env\": {\n        \"KEYCLOAK_URL\": \"https://keycloak.example.com\",\n        \"KEYCLOAK_CLIENT_ID\": \"admin-cli\",\n        \"KEYCLOAK_CLIENT_SECRET\": \"your-secret\",\n        \"KEYCLOAK_MODE\": \"read-only\"\n      }\n    }\n  }\n}\n```\n\n**OpenAI Codex CLI** — in `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.keycloak]\ncommand = \"npx\"\nargs = [\"-y\", \"@dockndevai/mcp-keycloak\"]\nenv = { KEYCLOAK_URL = \"https://keycloak.example.com\", KEYCLOAK_CLIENT_ID = \"admin-cli\", KEYCLOAK_CLIENT_SECRET = \"your-secret\", KEYCLOAK_MODE = \"read-only\" }\n```\n\n**VS Code (GitHub Copilot, Agent mode)** — in `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"keycloak\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@dockndevai/mcp-keycloak\"\n      ],\n      \"env\": {\n        \"KEYCLOAK_URL\": \"https://keycloak.example.com\",\n        \"KEYCLOAK_CLIENT_ID\": \"admin-cli\",\n        \"KEYCLOAK_CLIENT_SECRET\": \"your-secret\",\n        \"KEYCLOAK_MODE\": \"read-only\"\n      }\n    }\n  }\n}\n```\n\n## Configure\n\nCopy `.env.example` and fill it in, or set the variables directly in your MCP client config. A confidential client with the `realm-management` roles you need is the recommended credential.\n\n## Run from source (development)\n\nPrefer the published package above. To run from a clone:\n\n```bash\nnpm install\nnpm run build\nnode dist/index.js   # with the environment variables set\n```\n\n## Develop\n\n```bash\nnpm run dev        # watch mode\nnpm test           # unit tests for the security policy\nnpm run typecheck\n```\n\n## Publishing\n\nThis server ships a [`server.json`](server.json) for the official MCP registry and an [`mcpName`](package.json) for npm ownership validation. See **[PUBLISHING.md](PUBLISHING.md)** for publishing to npm and listing on the MCP registry, Smithery, Glama, Cursor, and PulseMCP.\n\n## License\n\nMIT\n",
  "bytes": 5523,
  "sha": "6ea52a9a963951135b61c13eeda4d6e88901cbd14e1a97b05756e7809dfdb7fb",
  "repo_slug": "dockndevai/mcp-keycloak",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_dockndevai_mcp_keycloak_530385b5/readme"
}