Skycloak
oficialServidor de Model Context Protocol para Skycloak Keycloak gestionado. Administre clústeres, reinos, aplicaciones, SSO y usuarios desde cualquier cliente MCP.
¿Qué puedes hacer con Skycloak MCP?
-
Revisión de actualización de clúster — Pregunte qué clústeres de Keycloak están atrasados en actualizaciones y obtenga la ruta recomendada a seguir mediante
list_cluster_upgradesyget_cluster_upgrade_path. -
Aprovisionamiento de reinos — Cree un reino de staging en un clúster específico con proveedores de identidad configurados, usando
create_realmycreate_identity_provider. -
Auditoría de actividad de usuarios — Encuentre quién fue agregado recientemente a un reino y revise los cambios de administración, aprovechando
list_realm_usersyquery_events. -
Configuración de integración SIEM — Configure un destino que reenvíe eventos de administración a un webhook externo, usando
create_siem_destinationytest_siem_destination. -
Reemplazo de contenido de tema — Actualice el archivo de un tema personalizado en su lugar sin perder sus asignaciones, mediante
update_theme_contentcon confirmación. -
Enrutamiento de dominio personalizado — Agregue un dominio personalizado, recupere los registros DNS a crear, verifíquelos y enrute el tráfico a un reino usando
create_domainyverify_domain.
Documentación
skycloak-mcp
Servidor oficial del Protocolo de Contexto de Modelos para Skycloak (Keycloak gestionado): gestiona tus clústeres, dominios, aplicaciones y SSO desde cualquier cliente MCP (Claude Desktop, Claude Code, Cursor).
Estado: lanzamiento temprano. La cobertura de herramientas está creciendo; consulta el registro de cambios para ver lo que está disponible.
Inicio rápido
claude mcp add --transport http skycloak https://mcp.skycloak.io
Sin clave de API, sin ID de cliente, sin configuración. Tu navegador se abre, inicias sesión en Skycloak y las herramientas aparecen. Cualquier cliente MCP que hable HTTP transmisible funciona de la misma manera: dale la URL y nada más.
Luego pide algo:
- "¿Cuáles de mis clústeres de Keycloak están atrasados en actualizaciones?"
- "Crea un dominio de staging en el clúster de la UE con inicio de sesión de Google y GitHub."
- "¿Quién fue añadido al dominio de producción en la última semana?"
- "Configura un destino SIEM que reenvíe eventos de administración a nuestro webhook de Datadog."
Autenticación y seguridad
- HTTP alojado, con OAuth (sin credenciales que configurar). Apunta tu cliente a
https://mcp.skycloak.iosin cabecera. El servidor responde401con un puntero a sus metadatos RFC 9728 en/.well-known/oauth-protected-resource, el cliente ejecuta el flujo de código de autorización del navegador contra el dominio de inicio de sesión de Skycloak, y el token de acceso que recibe se intercambia por una clave de API de corta duración y limitada al espacio de trabajo en la que se ejecuta la sesión. La clave dura una hora y se renueva automáticamente. No se almacena nada en la configuración de tu cliente. - HTTP alojado, con clave de API. Crea una clave en el panel de Skycloak y envíala como
Authorization: Bearer <key>(oAPI-Key: <key>). Cada solicitud lleva su propia credencial y actúa solo como el espacio de trabajo de esa credencial. El servidor no mantiene estado de sesión, por lo que una solicitud nunca hereda la de otro llamador. Las claves no se verifican antes de su uso: la API de Skycloak es la autoridad, por lo que una clave inválida aparece como401en la primera llamada a una herramienta en lugar de al conectar. - Las herramientas coinciden con tu rol. Con OAuth, la lista de herramientas se recorta a lo que permiten los alcances de la sesión, por lo que un miembro del espacio de trabajo de solo lectura no ve herramientas de escritura que responderían
403. Con una clave de API, toda la superficie está registrada, porque los alcances de una clave no son visibles para el servidor, y una llamada no autorizada aparece como403desde la API. - Stdio local. Ejecuta
skycloak-mcp inity aprueba en tu navegador (flujo de autorización de dispositivo OAuth 2.0). Genera una clave de API limitada al espacio de trabajo, la almacena en el llavero de tu sistema operativo y detecta tu espacio de trabajo predeterminado automáticamente (pasa--workspace <id>para elegir otro).skycloak-mcp logoutelimina la clave almacenada. - Sin interfaz / CI. Establece la variable de entorno
SKYCLOAK_API_KEY(crea una clave en el panel de Skycloak) para omitir el navegador por completo. Siempre tiene prioridad sobre el llavero. - Las escrituras están controladas por tu credencial, no por una bandera. El servidor alojado en
https://mcp.skycloak.iose ejecuta con capacidad de escritura, y lo que realmente puedes cambiar está limitado por los alcances de tu clave y tu rol en el espacio de trabajo: un miembro de solo lectura no puede mutar nada, diga lo que diga la lista de herramientas. Añade?readonly=truea la URL para forzar una superficie de herramientas de solo lectura para una sesión. El binario local es al revés y no registra herramientas de escritura a menos que se inicie con--allow-writes. - Las credenciales del clúster son opcionales.
get_cluster_credentialsdevuelve las credenciales de administrador de Keycloak de un clúster, que un asistente que tenga la clave podría ver, por lo queinitno solicita ese alcance por defecto. Usa una clave que lo tenga: créala en el panel, o con stdio inicia sesión conskycloak-mcp init --allow-credentials. Sin ella, la herramienta devuelve un 403 que explica ambas rutas. - Las herramientas destructivas requieren confirmación: eliminar un dominio, por ejemplo, necesita un argumento explícito
confirm=true. - Las solicitudes están limitadas por tasa según tu plan de Skycloak; en una respuesta
429el servidor muestraRetry-After.
Herramientas
137 herramientas: 60 de solo lectura y 77 de escritura. Las herramientas de solo lectura están siempre disponibles. En el servidor alojado, las herramientas de escritura también están registradas y controladas por los alcances de tu credencial; el binario local las registra solo cuando se inicia con --allow-writes.
Los nombres de las herramientas llevan un prefijo skycloak_ que la tabla siguiente omite, por lo que list_clusters es skycloak_list_clusters en tu cliente.
| Área | Solo lectura | Escritura (--allow-writes) |
|---|---|---|
| Clústeres | list_clusters, get_cluster, list_cluster_locations, list_cluster_types, list_cluster_features, list_cluster_versions, list_cluster_upgrades, get_cluster_upgrade_path, get_cluster_credentials, get_cluster_insights, get_cluster_maintenance_window | create_cluster, update_cluster, delete_cluster, cancel_cluster_upgrade, restart_cluster_instances, set_cluster_maintenance_window, delete_cluster_maintenance_window |
| Seguridad perimetral | get_cluster_security, list_cluster_captcha_domains | update_cluster_security, add_cluster_captcha_domain, remove_cluster_captcha_domain |
| Dominios | list_realms, get_realm | create_realm, update_realm, delete_realm |
| Aplicaciones | list_applications, get_application, list_application_roles, list_application_sessions | create_application, update_application, delete_application, assign_application_role, remove_application_role, rotate_application_secret |
| Proveedores de identidad | list_identity_providers, get_identity_provider, list_identity_provider_templates, discover_oidc | create_identity_provider (OIDC), update_identity_provider, delete_identity_provider, test_identity_provider |
| Usuarios, roles y grupos | list_realm_users, get_realm_user, list_realm_roles, get_realm_role, list_realm_groups, get_realm_group, list_realm_group_members, list_user_roles, list_user_groups | create_realm_user, update_realm_user, delete_realm_user, create_realm_role, update_realm_role, delete_realm_role, create_realm_group, update_realm_group, delete_realm_group, assign_realm_user_role, remove_realm_user_role, add_realm_user_to_group, remove_realm_user_from_group |
| Dominios personalizados | list_domains, get_domain, list_domain_routes, get_domain_route | create_domain, verify_domain, delete_domain, create_domain_route, update_domain_route, delete_domain_route |
| Marca y temas | list_themes, get_theme, get_theme_assignment, get_client_theme_assignment, get_login_branding, get_email_branding, download_theme_content, get_theme_settings | set_theme_assignment, set_client_theme_assignment, update_theme, update_theme_content, update_theme_settings, delete_theme, upsert_login_branding, delete_login_branding, upsert_email_branding, delete_email_branding |
| Extensiones | list_extensions, list_cluster_extensions | install_extension, upgrade_extension, update_extension, uninstall_extension, delete_extension |
| SMTP | get_smtp | upsert_smtp, delete_smtp, test_smtp |
| Exportaciones y registros | list_exports, get_export, get_logs, get_security_logs, query_events | create_export, delete_export, export_cluster_events |
| Importación y exportación de dominios | get_realm_export, get_realm_import | create_realm_export, create_realm_import, create_realm_import_upload_url |
| SIEM | list_siem_destinations, get_siem_destination | create_siem_destination, update_siem_destination, delete_siem_destination, test_siem_destination |
| Webhooks | list_webhook_event_types, list_webhook_subscriptions, get_webhook_subscription | create_webhook_subscription, update_webhook_subscription, delete_webhook_subscription, test_webhook_subscription |
Convenciones: las herramientas destructivas (delete_*, uninstall_extension, cancel_cluster_upgrade, update_theme_content, update_theme_settings, restart_cluster_instances) requieren confirm=true. update_theme_settings activa o desactiva exact_theme_names para el espacio de trabajo; la clave de API del llamador debe haber sido emitida para un propietario o administrador del espacio de trabajo, o recibe 403 incluso con themes:write. Activarlo mueve los temas existentes a sus nombres servidos exactos en segundo plano; un tema cuyo contenido fue reemplazado bajo su nombre exacto informa restart_required: true desde get_theme/list_themes/update_theme_content hasta que restart_cluster_instances reinicia las instancias de Keycloak de ese clúster. Un reinicio puede diferirse a la ventana de mantenimiento del clúster en lugar de aplicarse inmediatamente, informado como deferred: true y, cuando se conoce, next_window. create_cluster es asíncrono: consulta get_cluster hasta que el clúster esté available. create_domain devuelve los registros DNS que el cliente debe crear; verify_domain activa una verificación de DNS. set_theme_assignment activa un tema personalizado por tipo de tema de Keycloak (la cadena vacía restablece el valor predeterminado integrado). update_theme_content reemplaza el archivo de un tema en su lugar (ZIP base64 o JAR de Keycloakify en content_base64), manteniendo el ID, nombre y asignaciones de dominio y aplicación del tema, por lo que editar un tema ya no significa eliminarlo y volver a subirlo; necesita confirm=true porque el archivo que sobrescribe no es recuperable, y update_theme aún cambia solo el nombre, la descripción y la versión. Consulta docs/theme-content-update.md para saber cómo se realiza esa llamada. update_cluster_security deja intactos los ajustes de CAPTCHA. La importación/exportación de dominios mueve la configuración de un dominio y es independiente de create_export, que vuelca la base de datos de un clúster completo: ambas son asíncronas, y el archivo del dominio siempre está cifrado, por lo que la contraseña utilizada para exportarlo se necesita para importarlo de nuevo. Un dominio puede importarse directamente desde una exportación existente (source_export_id) o desde un archivo subido (create_realm_import_upload_url, PUT, luego upload_s3_key); importar crea un dominio y rechaza una colisión de nombres en lugar de sobrescribir, y necesita confirm=true porque trae usuarios y credenciales consigo.
Prompts
Ocho prompts te dan un punto de partida hacia esa superficie de herramientas. Los clientes los muestran como comandos de barra o acciones sugeridas; cada uno toma argumentos (dominio, clúster, ventana de tiempo) y guía al modelo a través de las herramientas correctas en el orden correcto.
| Prompt | Qué hace |
|---|---|
audit_self_registration | Encuentra todos los dominios que aún permiten auto-registro, en un clúster o en todos |
review_upgrades | Detecta clústeres atrasados en su versión de Keycloak y traza la ruta de actualización |
triage_failed_logins | Obtiene inicios de sesión fallidos recientes para un dominio y los agrupa por IP de origen |
review_identity_providers | Lista las conexiones SSO de un dominio y verifica si una específica está habilitada |
review_admin_changes | Muestra quién cambió qué en un dominio recientemente, centrado en ajustes de inicio de sesión y seguridad |
provision_environment | Crea un clúster, añade un dominio y configura un proveedor de identidad, confirmando cada paso |
set_up_custom_domain | Añade un dominio personalizado, devuelve los registros DNS exactos, verifica y lo enruta a un dominio |
rotate_client_secret | Regenera el secreto de cliente de una aplicación con el radio de impacto explicado primero |
Los prompts están controlados de la misma manera que las herramientas que nombran: los tres que mutan solo se ofrecen a sesiones que podrían llamar a las herramientas de escritura que referencian, y sus instrucciones le dicen al modelo que confirme contigo antes de cambiar nada. El requisito confirm=true en herramientas destructivas sigue aplicándose además.
Habilidades
Donde un prompt es un punto de partida, una habilidad es un manual operativo completo que el modelo carga bajo demanda. El servidor incluye cuatro, servidas a través del borrador de la extensión de Habilidades SEP-2640: declara io.modelcontextprotocol/skills en sus capacidades, responde skills/list y skills/get, y sirve cada SKILL.md como un recurso ordinario en skill://<name>/SKILL.md con un resumen sha256 en su entrada de listado. El directorio de plugins de OpenAI importa habilidades exactamente con esta forma.
| Habilidad | Qué codifica |
|---|---|
auth-incident-triage | Triage de "los usuarios no pueden iniciar sesión": separar caídas de plataforma de ataques y de cambios de configuración, usando eventos, registros WAF y salud del clúster. Solo lectura |
enterprise-sso-rollout | Conectar un IdP empresarial a un realm de extremo a extremo: validación del emisor, registro de la aplicación upstream, configuración del broker, prueba de conexión y verificación contra eventos de inicio de sesión reales |
keycloak-migration-doctor | Preflight de una exportación, importación o migración de Keycloak contra los bloqueadores que soporte realmente ve (políticas de script, la ruta legacy de /auth, expectativas de exportación parcial), y diagnosticar un trabajo fallido leyendo su error_message real en lugar del aviso genérico del dashboard |
keycloak-upgrade-readiness | Evaluar la deriva de versiones, determinar qué rompe la nueva versión de Keycloak (extensiones, temas) y secuenciar el despliegue entre entornos con una exportación como plan de reversión |
Las habilidades siguen el mismo control de acceso que las herramientas que nombran: los tres flujos de trabajo construidos alrededor de herramientas de escritura se omiten en sesiones de solo lectura, y una sesión con alcance solo recibe una habilidad cuyas herramientas realmente posee. Las fuentes viven en internal/tools/skills/, un directorio por habilidad, en el formato estándar de Agent Skills, por lo que también funcionan copiadas directamente en un directorio local de habilidades.
Conexión
Para HTTP alojado, la ruta más simple es OAuth, que no necesita credencial alguna:
claude mcp add --transport http skycloak https://mcp.skycloak.io
La primera llamada abre tu navegador, apruebas en la página de inicio de sesión de Skycloak y aparecen las herramientas. Si perteneces a más de un workspace, nombra el que quieras:
claude mcp add --transport http skycloak "https://mcp.skycloak.io?workspace=<workspace-id>"
De lo contrario, crea una clave API en el dashboard de Skycloak y configura tu cliente MCP para enviarla como token bearer:
claude mcp add --transport http skycloak https://mcp.skycloak.io --header "Authorization: Bearer sk_sc_XXX"
Esto añade lo siguiente a .claude.json:
{
"mcpServers": {
"skycloak": {
"type": "http",
"url": "https://mcp.skycloak.io",
"headers": {
"Authorization": "Bearer sk_sc_XXX"
}
}
}
}
Para stdio local, inicia sesión una vez y luego apunta tu cliente a skycloak-mcp run:
skycloak-mcp init # one-time browser sign-in; stores a key in your keychain
Claude Desktop / Cursor (local, stdio):
{
"mcpServers": {
"skycloak": {
"command": "skycloak-mcp",
"args": ["run", "--transport", "stdio"]
}
}
}
Claude Code:
claude mcp add skycloak -- skycloak-mcp run --transport stdio
Para headless / CI (sin navegador), omite init y pasa la clave en su lugar: añade "env": { "SKYCLOAK_API_KEY": "sk_sc_..." } a la configuración, o claude mcp add skycloak --env SKYCLOAK_API_KEY=sk_sc_... -- skycloak-mcp run --transport stdio.
Añade --allow-writes solo cuando tengas intención de hacer cambios (inicia sesión con skycloak-mcp init --allow-writes, o usa una clave con alcance de escritura).
Añade ?readonly=true a una URL HTTP alojada para exponer solo herramientas de solo lectura para esa sesión HTTP, o ?readonly=false para solicitar la superficie de herramientas con capacidad de escritura. El parámetro de consulta por defecto es false, pero las herramientas de escritura solo se registran cuando el servidor se inició con --allow-writes.
Añade ?workspace=<uuid> para elegir sobre qué workspace actúa una sesión OAuth. Solo es necesario cuando perteneces a más de uno; con un solo workspace el servidor lo elige por ti, y si perteneces a varios y no nombras ninguno, la conexión falla con un mensaje que los lista.
Ejecutando el transporte HTTP
skycloak-mcp run --transport http --http-addr :8080
No necesita credencial propia: los llamadores proporcionan la suya por solicitud, por lo que no se inyecta nada en el momento del despliegue. GET /healthz y GET /readyz no están autenticados y solo informan que el proceso está activo; deliberadamente no sondean la API de Skycloak, por lo que un problema upstream no puede hacer fallar la sonda de cada réplica a la vez. El servidor no mantiene estado de sesión, por lo que las réplicas no necesitan afinidad de sesión y pueden escalarse o rotarse libremente. SIGTERM detiene nuevas conexiones y drena las llamadas en curso.
La ruta OAuth está activa siempre que SKYCLOAK_ISSUER y SKYCLOAK_DASHBOARD_URL estén configuradas, que es el valor por defecto. GET /.well-known/oauth-protected-resource se sirve entonces sin autenticación, nombrando el realm como servidor de autorización. Su valor resource se toma de SKYCLOAK_PUBLIC_URL cuando está configurado, y de lo contrario de la propia Host y el esquema de la solicitud, por lo que un despliegue de un solo host detrás de un ingress no necesita configuración adicional. El esquema proviene de X-Forwarded-Proto cuando está presente, y de lo contrario por defecto es https para cualquier cosa que no sea un host de loopback, ya que TLS termina upstream y publicar un identificador http:// no coincidiría con la URL a la que se conectó el cliente. Configura SKYCLOAK_PUBLIC_URL si tu ingress reescribe Host. El documento también lista openid profile email como su scopes_supported, y el desafío WWW-Authenticate los repite como parámetro scope, por lo que un cliente que lea cualquiera de ellos le pide al realm que los proporcione: openid es obligatorio, porque el intercambio de tokens hace que el dashboard llame al endpoint userinfo de Keycloak y Keycloak rechaza un token otorgado sin él. Un token que llega sin él se rechaza en la verificación con un 401 y el desafío, en lugar de llevarse a un intercambio que no puede tener éxito, por lo que un cliente que aún tenga una concesión anterior deja de reintentar e inicia sesión de nuevo. Vaciar cualquiera de las variables de emisor o dashboard apaga OAuth por completo, y el servidor vuelve a desafiar por una clave API y nada más.
OPENAI_APPS_CHALLENGE_TOKEN sirve el token de verificación del directorio de plugins de OpenAI en /.well-known/openai-apps-challenge, como texto plano y nada más. Si no está configurado, la ruta no se registra y el path devuelve 404.
El inicio registra una línea con el cableado resuelto (oauth=, issuer=, dashboard=, public_url=, endpoint=, allow_writes=), por lo que un despliegue mal configurado se puede detectar sin un redeploy. Cada solicitud rechazada en la ruta OAuth registra una línea nombrando la etapa que falló (verify, exchange o scopes), el estado que recibió el llamador y el error subyacente. Una falla de verificación añade la comprobación que rechazó el token (expired, wrong_issuer, bad_signature, unknown_key_id, wrong_token_type, no_openid_scope, y así sucesivamente); una falla de intercambio añade el estado del dashboard y el host llamado. El llamador aparece como el sujeto del token una vez verificado, y nunca como una credencial: el token de acceso, el encabezado Authorization y la clave API acuñada nunca se registran.
Configuración
| Variable de entorno | Por defecto |
|---|---|
SKYCLOAK_API_KEY | ninguno (opcional para stdio; los clientes HTTP proporcionan encabezados API-Key en su lugar) |
SKYCLOAK_ENDPOINT | https://api.skycloak.io |
SKYCLOAK_API_VERSION | versión actual de la API |
SKYCLOAK_ISSUER | https://login.app.skycloak.io/realms/skycloak (inicio de sesión CLI, y el servidor de autorización contra el que el transporte HTTP verifica tokens) |
SKYCLOAK_CLIENT_ID | skycloak-mcp (solo flujo de dispositivo CLI) |
SKYCLOAK_DASHBOARD_URL | https://app.skycloak.io (acuña claves CLI y claves de sesión HTTP) |
SKYCLOAK_PUBLIC_URL | ninguno (derivado de cada solicitud; configúralo cuando el ingress reescribe Host) |
OPENAI_APPS_CHALLENGE_TOKEN | Sirve el token de verificación del directorio de plugins de OpenAI en /.well-known/openai-apps-challenge. Si no está configurado, ese path devuelve 404. |
Comandos: init (inicio de sesión en navegador), run (servir), logout (eliminar la clave almacenada). init acepta --workspace <id>, --allow-writes, --allow-credentials y --ttl-days (por defecto 90).
| Flag | Por defecto | Descripción |
|---|---|---|
--transport | stdio | stdio o http |
--http-addr | :8080 | dirección de escucha para el transporte HTTP |
--allow-writes | false | habilita herramientas de mutación para stdio y permite que sesiones HTTP con readonly=false registren herramientas de escritura |
Desarrollo
make build # build the server binary
make test # unit tests
make run # run on stdio for local testing
make inspector # MCP Inspector against the local binary
make lint # golangci-lint
make generate # regenerate the API client from the OpenAPI spec
El cliente API bajo internal/apiclient se genera a partir de la especificación OpenAPI de Skycloak con oapi-codegen.
Mantenerse sincronizado con la API
El cliente en internal/apiclient se genera a partir de internal/apiclient/openapi.yaml con oapi-codegen; ejecuta make generate para actualizarlo. CI falla si el código generado comprometido se desvía de la especificación. Las solicitudes se reintentan en 429/5xx con retroceso consciente de Retry-After.
Distribución
Publicado como binarios de GitHub y una imagen de contenedor ghcr.io/sky-cloak/skycloak-mcp en cada tag, y publicado en el MCP Registry como io.skycloak/skycloak-mcp. La mayoría de las personas no necesitan ninguno: el servidor alojado no requiere instalación.
Seguridad
Por favor, reporta vulnerabilidades de forma privada. Consulta SECURITY.md.
Contribuidores
Construido en Skycloak por Guilliano Molaire, Neville Omangi y Aphilas. El historial del repositorio se aplastó cuando se abrió, por lo que el registro de commits no refleja quién escribió qué.
Licencia
Apache-2.0. La descripción OpenAPI en internal/apiclient/openapi.yaml se genera a partir de la API de la plataforma Skycloak y es (c) Skycloak; se incluye aquí para que el cliente pueda generarse y verificarse. Consulta NOTICE.