Skip to main content
Glama
atulram

Keycloak Realm Inspector

by atulram

Keycloak Realm Inspector

Un servidor MCP que es puramente un recurso protegido OAuth 2.0, para una charla de KeyConf 2026 sobre Client ID Metadata Documents (draft-ietf-oauth-client-id-metadata-document-02).

No emite nada — ni /authorize, ni /token, ni secreto de cliente. Keycloak emite los tokens; este servidor los valida contra el JWKS de Keycloak, sirve el descubrimiento de la RFC 9728 y expone tres herramientas que hacen visible CIMD desde dentro del servidor de recursos.

Tres partes, deliberadamente separadas

Keycloak

el servidor de autorización. --features=cimd, KC_HTTP_RELATIVE_PATH=/auth, puerto 8080

El cliente MCP

publica su documento de metadatos en una URL que controla. Esa URL es su client_id. Se sirve en el puerto 9000

Este servidor

el recurso protegido. Puerto 9001

Este servidor no aloja, lee ni obtiene el documento de metadatos del cliente. No hay ninguna ruta /client-metadata.json ni copia local. Keycloak obtiene esa URL a través de la red durante /authorize. En este repositorio, la URL solo aparece como una cadena opaca que llega en el claim azp — que es el punto central de la demo, y por eso el documento lo sirve un proceso separado en un puerto separado.

Related MCP server: mcpauth

Ejecución

Se asume que Keycloak está en marcha, con el realm creado y la política de cliente CIMD ya aplicada. El cliente, su documento de metadatos y el asistente de tokens se encuentran junto a este repositorio en ../cimd-demo/auth-server/.

# terminal 1 — the client's document. Its own party, its own port.
cd ../cimd-demo/auth-server && python -m http.server 9000

# terminal 2 — the resource server
pip install -r requirements.txt
python server.py                     # http://localhost:9001

# terminal 3 — get a token, then point an MCP client at :9001/mcp
cd ../cimd-demo/auth-server && python get-token.py

El flujo

  1. El cliente llama a /mcp sin token y recibe un 401 con WWW-Authenticate: Bearer ..., resource_metadata="…".

  2. El cliente sigue esa referencia hasta /.well-known/oauth-protected-resource/mcp y descubre qué servidor de autorización emite tokens válidos.

  3. El cliente se autentica directamente contra Keycloak, usando la URL de su documento de metadatos como client_id. Keycloak obtiene esa URL y materializa al cliente.

  4. El cliente reintenta /mcp con el token de portador.

La RFC 9728 §3.1 sitúa el segmento well-known entre el host y la ruta del recurso, por lo que el documento de descubrimiento se encuentra en /.well-known/oauth-protected-resource/mcp. La ruta a secas devuelve un 404.

Herramientas

  • whoami()sub, preferred_username, azp, scope, exp, iss del token del llamante, además de registered_via_cimd. Solo lee el token; no realiza ninguna llamada a Keycloak, por lo que funciona incluso si las credenciales de administrador son incorrectas.

  • list_clients(only_cimd=False) — clientes del realm, con los client_id con forma de URL ordenados al principio para que el cliente llamante termine en la primera línea.

  • get_client_metadata(client_id) — la representación propia de Keycloak de un cliente. Esta es la vista derivada de Keycloak, no el documento publicado.

CIMD se detecta porque el client_id empieza por http:// o https://. Un client_id con forma de URL es la pista.

get_client_metadata elimina secret y registrationAccessToken antes de devolverlos. Ambos son credenciales de portador activas, y esta salida va a un proyector y a una grabación.

Dos carencias conocidas

Indicadores de recurso RFC 8707. audience= está presente pero comentado en JWTVerifier. Restringir el token por audiencia requeriría que el cliente enviara resource en /authorize, y la ruta CIMD de Keycloak 26.7 aún no lo respeta (keycloak#45106, keycloak#45284). Por lo tanto, el token lleva la audiencia account habitual de Keycloak y este servidor no puede restringir por audiencia. Visible a propósito.

Sin aplicación de scopes. required_scopes no está definido, por lo que se acepta cualquier token del realm con firma válida y no caducado — incluido uno de una concesión de contraseña de admin-cli. Eso es útil en el escenario: ejecuta whoami() con un token de administrador (azp es una cadena opaca) y de nuevo con el token CIMD (azp es una URL), la misma herramienta, el mismo servidor, la diferencia en un solo campo. También significa que debes estar seguro de qué token tienes en la mano.

Configuración

Todos son os.getenv con valores predeterminados de localhost.

Variable

Valor predeterminado

KEYCLOAK_BASE_URL

http://localhost:8080/auth

KEYCLOAK_REALM

cimd-demo

KEYCLOAK_ISSUER

{base}/realms/{realm}

KEYCLOAK_JWKS_URI

{issuer}/protocol/openid-connect/certs

MCP_BASE_URL

http://localhost:9001

PORT

9001

KEYCLOAK_ADMIN

admin

KEYCLOAK_ADMIN_PASSWORD

admin

KEYCLOAK_ISSUER y KEYCLOAK_JWKS_URI son configurables por separado en lugar de derivarse el uno del otro: en Kubernetes el emisor es la URL pública, por lo que iss coincide con lo que ven los clientes, mientras que la obtención de JWKS debe dirigirse al Service dentro del clúster.

fastmcp está fijado a una versión exacta. La superficie de autenticación cambia — resource_server_url pasó a ser base_url, AccessToken.claims llegó en la 2.11.3 — y allowed_client_redirect_uris no es un parámetro de RemoteAuthProvider en ninguna versión, a pesar de lo que muestra la documentación. Pertenece a OAuthProxy, que este servidor no usa.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Drop-in OAuth 2.1 + Dynamic Client Registration for MCP servers, providing authentication middleware and token verification.
    20
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables secure MCP tool calls (add and multiply numbers) by validating OAuth2 tokens via Keycloak token introspection.
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/atulram/keycloak-realm-inspector'

If you have feedback or need assistance with the MCP directory API, please join our Discord server