keycloak-mcp
Provides a standalone Keycloak Admin REST interface, allowing agents to search and describe API operations, perform read-only administration calls, and run compensated workflows to manage Keycloak resources using OAuth 2.0 client credentials.
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., "@keycloak-mcplist all users in the realm"
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.
keycloak-mcp
A standalone Keycloak Admin REST interface for Claude Code, Codex, OpenClaw, and JavaScript callers. It uses OAuth 2.0 client credentials only. No user password, browser login, or operator token is accepted by the runtime.
The runtime serves one pinned catalog of Keycloak Admin REST operations, generated from an official OpenAPI definition. Search and describe tools make the selected surface usable without placing hundreds of tools in an LLM context. Set KEYCLOAK_MCP_CATALOG_VERSION to the catalog that matches your server:
Version | Generated from | Use for |
| the current release's definition, downloaded on 2026-09-26 (26.7.x) | a server on that release |
| a 26.3.5 server | |
| the Keycloak HEAD definition, plus the operations only the Java admin client reaches | a server built from Keycloak's main branch, such as |
The Java admin client (org.keycloak:keycloak-admin-client) reaches operations that Keycloak's OpenAPI definition leaves out, such as typed authorization policies and permissions, user-storage synchronization, cache clearing, LDAP connection tests, verifiable-credential grants and server information. When data/admin-client-supplement-nightly.json is bundled, the nightly catalog adds them; the Java equivalence module generates that file from the admin client's HEAD snapshot (mvn -f equivalence/pom.xml -Psupplement). keycloak_describe_operation gives each operation an origin, openapi or admin-client. An admin-client operation also names the admin-client methods that reach it (adminClient), and the schemas it references resolve through keycloak_describe_schema like the definition's own. nightly is the catalog that the equivalence suite checks against a live Keycloak HEAD server; Verification says what that covers.
Each catalog records the SHA-256 of the definition it was built from, and keycloak_search_operations reports it. npm run catalog:update regenerates all three from upstream; review their diffs and rerun checks before release (TESTING.md lists the steps). The nightly catalog moves with Keycloak HEAD, so regenerate it before relying on it against a newer build. Where a definition disagrees with Keycloak's handlers, keycloak-mcp corrects its description without changing the pinned definition. The 26.3.5 definition omits the JSON body of federated-identity creation and names two different clients {client-uuid} on one path. All three omit the multipart body of certificate uploads and list the authorization-resource search filters on operations that do not read them. src/catalog/corrections.js lists each correction with the Keycloak source behind it. Installed SPI routes can be added through a private, deployment-specific catalog; they are not part of Keycloak's official Admin REST specification.
Install and configure
Requires Node.js 22 or newer. In a clone of this repository:
npm ci
npm run checkCreate a confidential Keycloak client with service accounts enabled. Grant its service-account user only the realm-management roles needed for the target realm. Keep the secret in a private JSON file outside the repository, for example /Users/you/.config/keycloak-mcp/service-account.json:
{
"KEYCLOAK_BASE_URL": "https://keycloak.example.com",
"KEYCLOAK_REALM": "example",
"KEYCLOAK_AUTH_REALM": "master",
"KEYCLOAK_CLIENT_ID": "keycloak-mcp-service",
"KEYCLOAK_CLIENT_SECRET": "replace-me",
"KEYCLOAK_MCP_CATALOG_VERSION": "26.3.5",
"KEYCLOAK_MCP_ALLOW_WRITE": "false"
}Set file mode 0600. The runtime rejects group-readable or world-readable configuration files. KEYCLOAK_AUTH_REALM names the realm that issues the service-account token; KEYCLOAK_REALM is the administered realm. The base URL must use HTTPS, except for loopback development. When KEYCLOAK_MCP_CONFIG names this file, it is authoritative for every setting it defines: environment variables only supply settings the file leaves out, and an empty environment value counts as unset. Switches such as KEYCLOAK_MCP_ALLOW_WRITE accept true or "true" and false or "false"; any other value stops startup with an error.
Claude Code
claude mcp add -s user keycloak -e KEYCLOAK_MCP_CONFIG=/absolute/path/service-account.json -- node /absolute/path/keycloak-mcp/src/index.jsCodex
codex mcp add keycloak --env KEYCLOAK_MCP_CONFIG=/absolute/path/service-account.json -- node /absolute/path/keycloak-mcp/src/index.jsOpenClaw
The package is a native OpenClaw plugin. The root openclaw.plugin.json declares the five tools in contracts.tools, and package.json points openclaw.extensions at ./openclaw/index.js. The npm name keycloak-mcp belongs to an unrelated package, so install from a tarball packed from this repository, not a bare npm spec:
npm pack
openclaw plugins install npm-pack:./keycloak-mcp-0.1.1.tgz --force --accept-capabilities
openclaw config set plugins.entries.keycloak-mcp.config.configPath /absolute/path/service-account.json
openclaw plugins inspect keycloak-mcp --runtime--force confirms a source outside ClawHub, and --accept-capabilities accepts the declared tool surface; review both before passing them. The config file must be private (0600) and visible inside the OpenClaw process or container. When configPath is set, the file is authoritative and ambient KEYCLOAK_* variables cannot override it. Without configPath, it reads KEYCLOAK_MCP_CONFIG or the KEYCLOAK_* variables from its process environment; with no configuration at all, registration fails and plugins inspect --runtime reports the error. It registers the same five tools individually. To upgrade, pack the new version and reinstall it with --force: openclaw plugins update keycloak-mcp resolves the name on npm. If OpenClaw runs in a rootless container, ensure the mounted package appears owned by the container user or root; its loader can block an otherwise readable plugin with untrusted ownership. The workflow lock database must be reachable from that container before enabling writes. npm run live:openclaw (TESTING.md) exercises the packed plugin through a real OpenClaw Gateway; the archived run used OpenClaw 2026.9.6. Validate the extension against your OpenClaw release before enabling it.
Related MCP server: mcp-keycloak-admin
Tools
Tool | Effect |
| Find operations by path, summary, tag, or method; paginated. |
| Show full parameters, request bodies, and response schemas for one exact operation key. |
| Expand a Keycloak representation referenced by an operation. |
| Call a read-only catalog operation with the configured service account and realm: GET, and the POSTs that change nothing (client-description and identity-provider certificate conversion, authorization policy and permission evaluation, client certificate download, partial realm export). |
| Preflight by default. Execute up to 20 steps only with |
An operation key is METHOD /admin/realms/{realm}/... or, for a configured SPI route, METHOD /realms/{realm}/.... The caller supplies named path parameters in args.path, query values in args.query, and request data in args.body or args.bodyBase64. Content types must appear in the pinned specification or extension catalog. Without args.contentType, a string body is sent as the operation's declared text/* type, else its XML or YAML type, and any other body as JSON when the operation accepts JSON; failing those, the first declared type is used. Responses are requested as JSON whenever the operation offers JSON; args.accept selects another declared response type. A read returns { status, contentType, value }, where contentType is the response's media type; an empty body has neither contentType nor value, so it is never confused with a JSON null. JSON numbers are returned exactly as Keycloak wrote them, including integers beyond 2^53; tool arguments, however, are parsed by the MCP SDK, which rounds such integers before keycloak-mcp sees them. Binary responses are returned as base64. Requests and responses default to a 1 MiB limit; KEYCLOAK_MCP_MAX_BODY_BYTES can raise it to at most 64 MiB in a private deployment config. Response streams stop when they cross that limit. Over stdio, one MCP message carries at most 10 MiB (the MCP SDK's default at both ends), so the stdio server refuses to start with a limit above 7,815,168 bytes, the largest body whose base64 form fits one message; OpenClaw and JavaScript callers keep the 64 MiB ceiling. An incoming stdio message over 10 MiB is dropped with a JSON-RPC error that names no request, since its id was in the dropped bytes, and a result that would need more than 10 MiB becomes a tool error; the session continues either way. Larger responses can overwhelm an LLM context, so use Keycloak pagination where available.
Installed SPI routes
Put a deployment-specific JSON catalog outside the repository, set its mode to 0600, and set KEYCLOAK_MCP_EXTENSION_CATALOG to its absolute path in the private service-account config. Each route must declare whether it is read-only and whether a service-account token can call it:
{
"source": "deployed provider inventory and route review",
"operations": [
{
"method": "GET",
"path": "/realms/{realm}/example/info",
"summary": "Example provider information",
"tags": ["example"],
"readOnly": true,
"serviceAccountSupported": true,
"responseTypes": ["application/json"]
}
]
}The loader rejects duplicate official routes, URLs outside the configured realm, unsafe paths, and extension operations without an explicit service-account assessment. User-token routes can be listed with serviceAccountSupported: false for discovery, but the runtime refuses to call them. Extension mutations default to irreversible and require the explicit irreversible override, even when a compensation is supplied. Pin the catalog to the running image and provider hashes, then recheck it after every provider deployment. Authentication flows, mappers, custom grants, and introspection providers may have no new REST path; record those separately in the deployment inventory.
Example dry run:
{
"steps": [
{
"operation": "PUT /admin/realms/{realm}",
"args": { "body": { "displayName": "New name" } },
"compensate": {
"operation": "PUT /admin/realms/{realm}",
"args": { "body": { "displayName": "Previous name" } }
}
}
]
}For a POST that returns a Location ending in its new resource ID, a compensation path parameter can use "$step.locationId". Some Keycloak creates, including authorization resources and scopes, return a JSON id or _id without Location; use "$step.responseId" for a generated UUID in that response. Keycloak answers those two creates with an existing scope or resource instead of refusing a name that is taken, so when a compensation is bound to the created ID, keycloak-mcp names the new object itself with a random UUID in the body (id for a scope, _id for a resource): Keycloak then creates exactly that object or refuses the step with 409, and a response that names any other object is not compensated. Such a body must not carry its own id or _id. A resource create that names scopes which do not exist creates them as well, and deleting the resource leaves them. The runtime accepts one binding only for a DELETE of that collection's direct child, checks any Location against the configured Keycloak origin and response ID, and records the resolved path in the private workflow receipt. Where keycloak-mcp withholds the create's response, as for client initial-access tokens, $step.responseId is refused unless sensitive reads are enabled; use $step.locationId there. A missing or conflicting ID stops the run IN_DOUBT for manual reconciliation, and because Keycloak accepted that step, the result's failedStepResponse gives its status, location and (redacted) value so the object it created can be found; the receipt records the status and Location. Each entry of a workflow result's completed list gives the step's operation and HTTP status, Keycloak's location when it sent one, and the id of the resource the step created when a compensation was bound to it; later steps can use that ID. The receipt records the same, except that it withholds a Location whose path carries a withheld parameter.
Global POST /admin/realms is allowed only when the request body names the configured KEYCLOAK_REALM and its compensation is DELETE /admin/realms/{realm}. Before compensating a successful realm creation, the client obtains a fresh service-account token: Keycloak may add the new realm's admin roles only after the earlier token was issued. Global administration still requires the explicit KEYCLOAK_MCP_ALLOW_REALM_ADMIN=true setting and appropriate service-account roles.
The public JavaScript API exports KeycloakAdmin, WorkflowBuilder, runWorkflow, listOperations, and describeOperation from keycloak-mcp. For example:
import { KeycloakAdmin, WorkflowBuilder, configFromEnv } from 'keycloak-mcp';
const admin = new KeycloakAdmin(configFromEnv());
const workflow = new WorkflowBuilder(admin)
.step('PUT /admin/realms/{realm}', { body: { displayName: 'New name' } }, {
operation: 'PUT /admin/realms/{realm}',
args: { body: { displayName: 'Previous name' } },
});
await workflow.plan(); // no network write
await workflow.run();step(operation, args, compensation, { irreversible: true }) marks a step irreversible, like irreversible: true on a runWorkflow step; pass null as the compensation for a step that has none.
Certificate uploads accept contentType: 'multipart/form-data' with a body object. Text fields are strings; a file field is { filename, contentType, base64 }. The client builds the boundary and checks the decoded-size budget before allocating a file. For example, use keystoreFormat: 'Certificate PEM' and a file object for either certificate upload route. State-changing certificate uploads require a workflow with an explicit compensation or irreversible override; the identity-provider upload-certificate converter is read-only, and the private key it reads from an uploaded keystore is redacted like every privateKey field.
Write safety and actual guarantees
Reads are enabled by default. To execute mutations, set KEYCLOAK_MCP_ALLOW_WRITE=true, supply an explicit compensating operation for every mutation, and use one of:
KEYCLOAK_MCP_SINGLE_WRITER=truefor a deployment that truly has one process writing this realm; orKEYCLOAK_MCP_LOCK_DATABASE_URLfor a shared PostgreSQL advisory lock across cooperating instances.
The lock is per Keycloak base URL and realm. It does not fence external Keycloak administrators or unrelated clients. The PostgreSQL lock is a session-level advisory lock, so connect directly or through session pooling; PgBouncer transaction pooling cannot hold it. The connection is checked before each step and before each compensation. If it drops (an idle_session_timeout, a failover), the server has released the lock, so the run stops with lost the PostgreSQL lock connection and ends IN_DOUBT without compensating, because another workflow may already hold the realm. A local file receipt is written before and after each step under KEYCLOAK_MCP_JOURNAL_DIR (default ~/.local/state/keycloak-mcp). The receipt includes operation keys and path parameters, but omits request bodies and query values; restrict access to it because path parameters can identify users or clients. A step is sent only after its receipt is written, so a journal that cannot be written stops the run before the next request. Once Keycloak has changed, a receipt write that fails never stops the compensation that follows: the run finishes and its result lists the failed writes in journalErrors. A lock that cannot be released after the run is reported in lockReleaseError; once a request has been sent, the result, with its runId, is always returned rather than an error. A crash, timeout, lost lock, or 5xx can leave the current step in doubt even when prior steps were compensated. On an operation error, the result is IN_DOUBT; failedStepMayHaveCommitted is false for a read-only failed step and for a step whose request was never sent (its lock check, its in-flight receipt or the token grant failed first), and priorStepsCompensated reports only whether earlier compensation calls succeeded. Read back affected resources and reconcile using the receipt's runId.
Irreversible operations, listed under "How operations are classified" below, require the explicit irreversible override. Preflight permits an otherwise irreversible compensation when it deletes the realm just created by the matching global create step, deletes a direct child using that create response's generated ID, or deletes a newly created realm role, client role or identity-provider instance using the exact nonblank name or alias in the create body. The named exception is limited to those three create routes. Names can change, so right after such a create keycloak-mcp reads the new object by its name for its immutable ID: a role is then compensated through DELETE .../roles-by-id/{role-id}, whatever it is called by then, and an identity provider, which Keycloak addresses only by alias, is deleted by alias only if that alias still has the created internalId. A POST mutation can compensate only with a DELETE of its created direct child, keeping the same parent path; an ID or UUID path parameter must use $step.locationId or $step.responseId, not a caller-supplied ID. A representation update compensation must use PUT or PATCH on the same route, path parameters, and query. Repeating an association PUT cannot undo the association; a DELETE may remove a pre-existing association, so these operations require the irreversible override until prior state can be proved. Other compensation bodies remain caller-declared, so preflight cannot establish that they restore prior state. Role-mapping additions require an explicit irreversible override because deleting the mapping could remove a role that was already assigned before the workflow. A successful create and compensating DELETE still require readback to establish the final state, and the lock does not fence other Keycloak writers.
Read-only operations retry HTTP 502, 503, and 504 at most twice with short delays and return an attempts count when a retry occurs. A safe GET also refreshes an invalidated service-account token and retries once after HTTP 401. A successful logout-all clears the cached token. Mutations, including side-effecting GET operations, are never retried automatically because a failed response may follow a committed change. A failed call reports the HTTP status, the number of attempts and Keycloak's own error text (error, errorMessage or error_description), cut to 300 characters and redacted like a response. A redirect is reported with its status and never followed.
Operations outside the configured realm, including reads such as GET /admin/realms that return every realm the service account can see, are blocked unless KEYCLOAK_MCP_ALLOW_REALM_ADMIN=true. The runtime rejects arbitrary URLs, unknown operation keys, undeclared query and content types, path traversal, redirects, and direct mutation calls through keycloak_read. Secret fields of Keycloak representations, private JSON Web Key members (as in a client's jwks.string) and private keys in any string, whether PEM or the base64 DER without a header that Keycloak writes, client initial-access tokens, detailed admin-event representations, client certificate info and keystore downloads, installation exports, generated examples, and known secret endpoints are redacted unless KEYCLOAK_MCP_ALLOW_SENSITIVE_READS=true. The secret fields are listed, with the Keycloak source that makes each one secret, in src/policy/table.js: client secrets, rotated secrets, private-key attributes and registration access tokens, which Keycloak returns in clear to a client manager, the private key of an uploaded keystore, and the SMTP, identity-provider, LDAP, key-provider, reCAPTCHA and credential secrets that Keycloak masks as **********. Every other field, and Keycloak's own mask, is returned as sent. Keycloak cannot know which custom attribute holds a secret and returns them all in clear; list such keys in KEYCLOAK_MCP_SECRET_ATTRIBUTES (comma-separated, or a JSON list in the config file) to redact them in every attributes and config map and in the userAttributes snapshot of a user's verifiable-credential grants. A redacted value reads [REDACTED by keycloak-mcp] (or [REDACTED by keycloak-mcp: sensitive endpoint] for a withheld response). Keycloak would store such text as the real value, so any request whose path, query or body contains it is refused before it is sent: leave redacted fields out of an update, which keeps the stored secret.
How operations are classified
Every operation-specific rule is in src/policy/table.js, each with its reason and the Keycloak source behind it, and the resulting classification of every operation in each bundled catalog is pinned in test/unit/fixtures/classification-<version>.json (mutation, irreversible, sensitive, bodyRules), so a change to either is a reviewed diff. Without a rule, GET and HEAD read, every other method mutates, and DELETE is irreversible.
Reads that are POSTs: client-description and identity-provider certificate conversion, authorization policy and permission evaluation, client certificate download (still withheld as a sensitive response) and partial realm export change nothing and run through
keycloak_read.Irreversible whatever the body: existing-resource
DELETEoperations; bodyless associationPUToperations with a matchingDELETEroute; logouts, session removal and impersonation; password resets, credential changes other than a label, and clearing brute-force lockouts; sent email (test email included) and organization invitations; client-secret and registration-access-token regeneration; client certificate and key generation and upload, which drop the stored private key;partialImportand authorization-settings import; cache eviction; not-before pushes; triggering or migrating Keycloak workflows; fetching identity-provider metadata from a supplied URL; and the GET endpoints that reload identity-provider keys or make Keycloak contact a client's registered cluster nodes (test-nodes-available).Irreversible because of the body: preflight judges the JSON a step sends (its
body, or itsbodyBase64decoded as Keycloak decodes JSON: UTF-8, UTF-16 or UTF-32, with or without a byte-order mark) against the body rules, and a step that triggers one needs the override like any irreversible step; the refusal names each rule, for example[sets-credentials]. A body is judged alone, without reading Keycloak's current state, so a field that could change something counts as changing it: send only the fields an update changes. Values count as Keycloak's JSON reader coerces them:"false","FALSE"or0turns a flag off likefalse,"true"or1turns it on liketrue, a numeric string sets a number, and a value Keycloak would reject counts as the one a rule guards against. The rules are:sets-secret: anyPUTorPATCHthat sets a secret field (a client secret, a registration access token, a private-key or rotated-secret attribute, a key inKEYCLOAK_MCP_SECRET_ATTRIBUTES, private JSON Web Key members, an LDAP, identity-provider, key-provider or reCAPTCHA secret, or a private key anywhere). Keycloak's own mask**********sets nothing in aconfigmap, which keeps the stored value for it; a clientsecretsent as the mask is stored as the mask.sets-credentials,links-federation,unlocks-user: a user update withcredentials, with afederationLink(a user whose link a provider does not validate can be deleted on its next read), or withenabled: true(which clears a brute-force lockout; leaveenabledout unless you mean to unlock).drops-authorization,disables-service-account: a client update that does not setauthorizationServicesEnabled: true, leaving it out included, or that makes the client public or bearer-only, deletes the client's authorization settings;serviceAccountsEnabled: falsedeletes the service-account user. A client update is therefore reversible only when it carriesauthorizationServicesEnabled: true, so updating a client without authorization services needs the override.renames-realm,renames-role,renames-required-action: a new realm name, role name or required-action alias (a required-action body without its alias clears it).moves-not-before,replaces-smtp,stops-realm-events: a realm update that setsnotBefore, sendssmtpServer(the stored SMTP password is dropped unless masked with an unchanged destination), or turns off or narrows event recording (eventsEnabled,adminEventsEnabledoradminEventsDetailsEnabledfalse,eventsListeners,enabledEventTypes) or sets a positiveeventsExpirationorattributes.adminEventsExpiration, which makes Keycloak delete older events or admin events.stops-events: the same forPUT .../events/config, where a missingeventsEnabledturns user events off; sendeventsEnabled: trueto keep them.repoints-federation,regenerates-keys: a component config withconnectionUrl,bindDn,scimurlorloginusername(the stored bind credential goes to the new address on the next user search), or with a key size or curve (a generated key provider makes a new key).drops-idp-secret,repoints-idp-secret: an identity-provider update whoseconfigleaves outclientSecret, or sends it null or empty, deletes the stored secret, whatever the body'sproviderId: Keycloak keeps the stored provider type and applies the body's config to it. SendingclientSecret: "**********"keeps the stored secret, and Keycloak accepts it for a SAML or other provider that has none. An update that namestokenUrlortokenIntrospectionUrlwhile its maskedclientSecretkeeps the stored secret sends that secret there. Since the config map is replaced whole, an OAuth 2.0 or OpenID Connect provider update that keeps its token endpoint triggers one rule or the other and needs the override.disables-admin-permissions: a fine-grained admin-permissions (version 1)PUTwithoutenabled: true, which deletes the permissions.moves-group: a group create whose body names an existingid, which Keycloak moves instead of creating a group.unreadable-body: for any operation above, abodyBase64body sent as JSON that is not valid text in its encoding or not exactly one JSON document. Keycloak may still read it, since it decodes overlong UTF-8 and ignores what follows the first document, so the other rules cannot vouch for it.
Operations only the Java admin client reaches (
nightly): each route has its own rule inADMIN_CLIENT_ROUTES. Typed authorization policy and permission reads, verifiable-credential listings and server information are reads. Typed policy and permission creates and updates and verifiable-credential grants are reversible mutations. Their deletes, verifiable-credential refreshes, offers and revocations, cache clears, LDAP connection and capability tests (Keycloak connects and binds to the host the body names) and user-storage synchronization, unlinking and removal of imported users are irreversible. An admin-client operation that no rule covers counts as an irreversible mutation with a withheld response.Extension routes declare
readOnlyandirreversiblethemselves; an extension mutation by GET or HEAD cannot declare a compensation, because no rule could check it, and runs only as an irreversible step.
Some effects keep their classification and are documented instead. A read of users in a realm with user federation contacts the directory, can import users into Keycloak, and can delete a user whose federation link no longer validates. Creating a Keycloak workflow schedules actions on existing resources, which the compensating delete does not undo once they have run. An authorization resource create that names scopes which do not exist creates them, and deleting the resource leaves them. An authenticator-config update replaces the whole config map, so a secret left out of it is removed; its body does not say which authenticator it configures, so no rule can tell whether it drops one: send the secret back as the ********** Keycloak returned.
Keycloak Admin REST does not expose a transaction spanning multiple HTTP requests. Compensations are best effort and cannot recreate deleted sessions, sent mail, rotated secrets, external side effects, or every prior representation. Known irreversible operations and bodies are blocked by default. An operator can also classify any mutation as irreversible. To run either case, set KEYCLOAK_MCP_ALLOW_IRREVERSIBLE=true and mark that step irreversible=true; a later failure returns IN_DOUBT even if other steps compensate. The catalog still describes every operation. The Keycloak guide explains service-account roles and permissions.
Verification
npm run check runs a syntax check of every module and script, then the unit tests (with golden masters of catalog, request-building, preflight and workflow behaviour) and the mock-integration tests, which drive the real stdio server against a mock Keycloak whose default responses were recorded from Keycloak HEAD. CI runs it on Node.js 22 and 24. The equivalence suite, npm run test:equivalence (Java 21, Maven and Docker), checks keycloak-mcp against a live Keycloak HEAD server, the Java admin client and HEAD's OpenAPI definition, and writes a verdict for every operation to a ledger. TESTING.md describes each tier, what it proves and what it does not, and how to run it.
What equivalence with Keycloak HEAD means here: for the nightly catalog, a run of the equivalence suite shows that the catalog lists exactly HEAD's documented operations plus those only the Java admin client reaches, and gives each one a verdict. The result holds for the Keycloak image, feature profile, admin-client snapshot and definition that the run's ledger records. A functional comparison stands behind an operation only where the ledger says EQUIVALENT; a ROUTED_ONLY operation was reached but not compared, and a DIVERGENT_DOCUMENTED one differs in a documented way. A newer Keycloak build is not covered until the suite runs against it. No live suite checks the latest and 26.3.5 catalogs; they rely on the unit and mock-integration tiers and on the upstream definitions.
Evidence from live runs in September 2026, including route ledgers for 26.3.5 and 26.7.4 and an OpenClaw integration, is archived in docs/validation-history/2026-09. It predates the current source and is not verified again.
This server cannot be deployed
Maintenance
Related MCP Connectors
Keycloak identity management expert with semantic search, protocol guides, and config analysis
- SkycloakOAuthio.skycloak
Managed Keycloak from any MCP client: clusters, realms, apps, SSO, users, domains, audit events.
The bridge from K2 agents through Wrangler to your master AI - safe, approval-gated Cloudflare ops.
OAuth 2.1 short-link tools for AI agents with scoped tokens, approvals, audit logs, and revocation.
Related MCP Servers
- AlicenseCqualityCmaintenanceEnables management of Keycloak identity and access management through the Keycloak Admin REST API, providing 299 tools for operations like user management, client configuration, and realm administration via natural language.1003MIT
- AlicenseAqualityBmaintenanceEnables administrators to manage Keycloak realms, users, roles, clients, groups, and more through its Admin REST API, with safe-by-default configuration and destructive operation confirmation.5663 npm3MIT
- AlicenseNot gradedqualityDmaintenanceExposes Keycloak admin operations as tools via the Model Context Protocol, allowing management of users, clients, groups, roles, and more through natural language.78 npmMIT
- AlicenseCqualityDmaintenanceA comprehensive MCP server for Keycloak administration, offering 80+ tools to manage users, realms, clients, roles, groups, sessions, events, organizations, and more directly from AI assistants.8640 npmMIT