Skip to content

πŸ” Behind Cloud-IAM

See Cloud-IAM’s managed Keycloak in action.

Visit Official Site

Keycloak MCP technical reference ​

The Keycloak MCP server is a read-only Model Context Protocol server that fronts the Keycloak Admin REST API of your managed Keycloak. Once enabled, an MCP-aware client like Claude or Cursor can list realms, users, clients, roles and groups straight from an AI assistant, authenticated with the end user's own Keycloak account.

This page documents the technical side of the feature. It explains how the stack is built, how Cloud-IAM deploys it on your Keycloak cluster, and how identity is propagated from the client all the way to the Admin API.

Not to be confused with the Cloud-IAM MCP

The Cloud-IAM MCP server at mcp.cloud-iam.com targets the Cloud-IAM control plane: organizations, deployments, billing, audit trail. The Keycloak MCP documented here targets your Keycloak Admin API and runs inside your Cloud-IAM managed Keycloak cluster. The two servers can be enabled independently and coexist without conflict.

Architecture ​

The Keycloak MCP is a three-service Docker Compose stack co-located with the Keycloak nodes of your cluster. Only the OAuth and MCP surface of the gateway is exposed to the outside world, and it shares the same public hostname that fronts Keycloak.

                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚                Cloud-IAM Keycloak cluster             β”‚
Claude / MCP client    β”‚                                                       β”‚
      β”‚                β”‚   nginx  ──▢  gateway ──OBO──▢  keycloak-mcp ──▢ KC   β”‚
      β”‚  HTTPS         β”‚              (:9292)            (:9192)     Admin API β”‚
      └───────────────▢│                β”‚                                      β”‚
        <host>/mcp     β”‚                └──▢ Cerbos (:3592)                    β”‚
                       β”‚                                                       β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The three services play these roles:

  • gateway is the only component reachable from outside the cluster. It validates the caller's user JWT against your Keycloak realm, performs an RFC 8693 token exchange to mint an on-behalf-of (OBO) token, pre-authorizes the tool call with Cerbos, and forwards the request to the MCP server.
  • keycloak-mcp is the MCP server itself. It receives the OBO token and calls the Keycloak Admin REST API with it, so every read runs under the identity of the caller.
  • cerbos is a local policy engine. It applies a coarse pre-filter on the caller's realm roles before the tool call reaches the Admin API.

Keycloak itself stays the final authority. The Admin API rejects any read the caller's realm-management roles do not permit, regardless of what Cerbos allows.

Available tools ​

All tools are GET-only calls on the Keycloak Admin REST API. The target realm is passed as a tool parameter rather than baked into the URL, so a single MCP endpoint can serve every realm the caller has admin rights on.

ToolAdmin endpointRequired realm-management role
keycloak_list_realmsGET /admin/realmsview-realm
keycloak_get_realmGET /admin/realms/{realm}view-realm
keycloak_list_users / keycloak_get_user…/usersview-users (or query-users)
keycloak_list_clients / keycloak_get_client…/clientsview-clients (or query-clients)
keycloak_list_roles…/rolesview-realm
keycloak_list_groups…/groupsquery-groups (or view-users)

Cross-realm listing

A token issued from realm X only administers X. To see every realm on a deployment, the caller must sign in on the master realm with the admin role. Otherwise keycloak_list_realms only returns the caller's own realm.

Identity model (OAuth 2.1 + RFC 8693) ​

The MCP client connects with the end user's Keycloak account. There is no shared API key and no service account. The identity of the caller flows all the way to the Admin API, so every action is attributable and auditable.

Three OAuth clients live in your Keycloak realm:

ClientTypeRole
sa_cloud-iam-mcp-loginPublic (PKCE)Used by the MCP client to sign in the end user.
sa_cloud-iam-mcp-gatewayConfidentialRequester of the RFC 8693 token exchange. The OBO token is minted for this client.
sa_cloud-iam-mcp-serverConfidentialService-account fallback for the MCP server. Unused when the gateway forwards an OBO token, which is the default.

The exchanged token is audienced on realm-management, so resource_access.realm-management is present in the OBO. This is what the Admin API reads when it authorizes view-users, view-clients, and the other read roles.

Cerbos runs before the tool call as a lightweight pre-filter. The caller must hold one of mcp-keycloak-reader, realm-admin or admin as a realm role for any Keycloak tool to be dispatched. Cerbos does not replace Keycloak's authorization: it just fails fast on requests that are clearly not eligible.

Keycloak 26.2 or later is required, since the exchange relies on Standard Token Exchange v2. Cloud-IAM configures Standard Token Exchange on the confidential exchange client, and the audience mapper that makes the exchange client sit inside the aud of the user token. Both are prerequisites for the RFC 8693 exchange to succeed.

Security posture ​

  • Read-only. No tool mutates state, and every action maps to a GET on the Admin API.
  • No shared credentials. The caller signs in with their personal Keycloak account, and the assistant never sees a static token.
  • User-scoped tokens. The OBO token carries the end user's identity, so Keycloak audit logs attribute every read to the actual user.
  • Least privilege by default. Users need both a realm role for the Cerbos pre-filter and the matching realm-management roles for the Admin API check. Neither alone unlocks the tools.
  • Internal by design. Only the gateway is exposed, and only through the same nginx that fronts Keycloak.
  • Isolated stack. The Compose project runs on a dedicated network, has no persistent volume, and is torn down cleanly when the feature is disabled.