Skycloak
oficialServidor do Model Context Protocol para o Keycloak gerenciado pela Skycloak. Gerencie clusters, realms, aplicativos, SSO e usuários a partir de qualquer cliente MCP.
O que você pode fazer com Skycloak MCP?
Gerencie seus clusters Skycloak (Keycloak gerenciado), realms e SSO a partir de qualquer cliente MCP.
- Revisão de upgrade de cluster — Pergunte quais clusters estão atrasados nos upgrades do Keycloak e obtenha o caminho de upgrade via
list_cluster_upgradeseget_cluster_upgrade_path. - Provisionamento de realm — Crie um realm com login do Google e GitHub usando
create_realmecreate_identity_provider. - Encaminhamento SIEM — Configure um destino SIEM que encaminhe eventos de administrador para um webhook do Datadog via
create_siem_destination. - Configuração de domínio personalizado — Adicione um domínio personalizado, obtenha os registros DNS e verifique com
create_domaineverify_domain.
Documentação
skycloak-mcp
Servidor oficial do Model Context Protocol para Skycloak (Keycloak gerenciado): gerencie seus clusters, realms, aplicativos e SSO a partir de qualquer cliente MCP (Claude Desktop, Claude Code, Cursor).
Status: lançamento inicial. A cobertura de ferramentas está crescendo; consulte o changelog para saber o que está disponível.
Início rápido
claude mcp add --transport http skycloak https://mcp.skycloak.io
Sem chave de API, sem client ID, sem configuração. Seu navegador abre, você faz login no Skycloak e as ferramentas aparecem. Qualquer cliente MCP que fale HTTP com streaming funciona da mesma forma: forneça a URL e nada mais.
Depois, peça algo:
- "Quais dos meus clusters Keycloak estão atrasados nas atualizações?"
- "Crie um realm de staging no cluster da UE com login do Google e GitHub."
- "Quem foi adicionado ao realm de produção na última semana?"
- "Configure um destino SIEM que encaminhe eventos de administrador para nosso webhook do Datadog."
Autenticação e segurança
- HTTP hospedado, com OAuth (sem credencial para configurar). Aponte seu cliente para
https://mcp.skycloak.iosem cabeçalho. O servidor responde401com um ponteiro para seus metadados RFC 9728 em/.well-known/oauth-protected-resource, o cliente executa o fluxo de código de autorização no navegador contra o realm de login do Skycloak, e o token de acesso retornado é trocado por uma chave de API de curta duração, com escopo do workspace, na qual a sessão é executada. A chave dura uma hora e é renovada automaticamente. Nada é armazenado na configuração do seu cliente. - HTTP hospedado, com chave de API. Crie uma chave no painel do Skycloak e envie-a como
Authorization: Bearer <key>(ouAPI-Key: <key>). Cada requisição carrega sua própria credencial e age apenas como o workspace dessa credencial. O servidor não mantém estado de sessão, então uma requisição nunca herda a de outro chamador. As chaves não são verificadas antes do uso: a API do Skycloak é a autoridade, então uma chave inválida aparece como401na primeira chamada de ferramenta, em vez de no momento da conexão. - As ferramentas correspondem ao seu papel. Via OAuth, a lista de ferramentas é reduzida ao que os escopos da sessão permitem, então um membro de workspace somente leitura não vê ferramentas de escrita que responderiam
403. Com chave de API, toda a superfície é registrada, porque os escopos de uma chave não são visíveis ao servidor, e uma chamada não autorizada aparece como403da API. - Stdio local. Execute
skycloak-mcp inite aprove no seu navegador (fluxo de autorização de dispositivo OAuth 2.0). Ele gera uma chave de API com escopo do workspace, armazena-a no chaveiro do seu sistema operacional e detecta seu workspace padrão automaticamente (passe--workspace <id>para escolher outro).skycloak-mcp logoutremove a chave armazenada. - Headless / CI. Defina a variável de ambiente
SKYCLOAK_API_KEY(crie uma chave no painel do Skycloak) para pular o navegador completamente. Ela sempre tem precedência sobre o chaveiro. - Escritas são controladas pela sua credencial, não por uma flag. O servidor hospedado em
https://mcp.skycloak.ioexecuta com capacidade de escrita, e o que você pode realmente alterar é limitado pelos escopos da sua chave e pelo seu papel no workspace: um membro somente leitura não pode modificar nada, independentemente da lista de ferramentas. Adicione?readonly=trueà URL para forçar uma superfície de ferramentas somente leitura em uma sessão. O binário local é o oposto e não registra ferramentas de escrita a menos que seja iniciado com--allow-writes. - Credenciais de cluster são opcionais.
get_cluster_credentialsretorna as credenciais de administrador do Keycloak de um cluster, que um assistente com a chave veria, entãoinitnão solicita esse escopo por padrão. Use uma chave que o contenha: crie uma no painel, ou via stdio faça login comskycloak-mcp init --allow-credentials. Sem isso, a ferramenta retorna um 403 que explica ambas as rotas. - Ferramentas destrutivas exigem confirmação: excluir um realm, por exemplo, requer um argumento explícito
confirm=true. - As requisições são limitadas por taxa de acordo com seu plano Skycloak; em uma resposta
429, o servidor expõeRetry-After.
Ferramentas
129 ferramentas: 58 somente leitura e 71 de escrita. Ferramentas somente leitura estão sempre disponíveis. No servidor hospedado, as ferramentas de escrita também são registradas e controladas pelos escopos da sua credencial; o binário local as registra apenas quando iniciado com --allow-writes.
Os nomes das ferramentas carregam um prefixo skycloak_ que a tabela abaixo omite, então list_clusters é skycloak_list_clusters no seu cliente.
| Área | Somente leitura | Escrita (--allow-writes) |
|---|---|---|
| Clusters | 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, set_cluster_maintenance_window, delete_cluster_maintenance_window |
| Segurança de borda | get_cluster_security, list_cluster_captcha_domains | update_cluster_security, add_cluster_captcha_domain, remove_cluster_captcha_domain |
| Realms | list_realms, get_realm | create_realm, update_realm, delete_realm |
| Aplicativos | 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 |
| Provedores de identidade | 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 |
| Usuários, papéis e 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 |
| Domínios 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 e temas | list_themes, get_theme, get_theme_assignment, get_client_theme_assignment, get_login_branding, get_email_branding, download_theme_content | set_theme_assignment, set_client_theme_assignment, update_theme, delete_theme, upsert_login_branding, delete_login_branding, upsert_email_branding, delete_email_branding |
| Extensões | list_extensions, list_cluster_extensions | install_extension, upgrade_extension, update_extension, uninstall_extension, delete_extension |
| SMTP | get_smtp | upsert_smtp, delete_smtp, test_smtp |
| Exportações e logs | list_exports, get_export, get_logs, get_security_logs, query_events | create_export, delete_export, export_cluster_events |
| Importação e exportação de realm | 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 |
Convenções: ferramentas destrutivas (delete_*, uninstall_extension, cancel_cluster_upgrade) exigem confirm=true. create_cluster é assíncrona: consulte get_cluster até que o cluster esteja available. create_domain retorna os registros DNS que o cliente deve criar; verify_domain aciona uma verificação de DNS. set_theme_assignment ativa um tema personalizado por tipo de tema do Keycloak (string vazia redefine para o padrão integrado). update_cluster_security não altera as configurações de CAPTCHA. A importação/exportação de realm move a configuração de um realm e é separada de create_export, que despeja o banco de dados de um cluster inteiro: ambas são assíncronas, e o arquivo do realm é sempre criptografado, então a senha usada para exportá-lo é necessária para importá-lo novamente. Um realm pode ser importado diretamente de uma exportação existente (source_export_id) ou de um arquivo enviado (create_realm_import_upload_url, PUT, depois upload_s3_key); a importação cria um realm e recusa uma colisão de nome em vez de sobrescrever, e exige confirm=true porque traz usuários e credenciais junto.
Prompts
Oito prompts dão a você um ponto de partida para essa superfície de ferramentas. Os clientes os exibem como comandos de barra ou ações sugeridas; cada um aceita argumentos (realm, cluster, janela de tempo) e conduz o modelo pelas ferramentas certas na ordem certa.
| Prompt | O que faz |
|---|---|
audit_self_registration | Encontra todo realm que ainda permite auto-registro, em um cluster ou em todos |
review_upgrades | Identifica clusters atrasados na versão do Keycloak e traça o caminho de atualização |
triage_failed_logins | Obtém logins recentes com falha para um realm e os agrupa por IP de origem |
review_identity_providers | Lista as conexões SSO de um realm e verifica se uma específica está habilitada |
review_admin_changes | Mostra quem alterou o quê em um realm recentemente, com foco em configurações de login e segurança |
provision_environment | Cria um cluster, adiciona um realm e configura um provedor de identidade, confirmando cada etapa |
set_up_custom_domain | Adiciona um domínio personalizado, devolve os registros DNS exatos, verifica e o roteia para um realm |
rotate_client_secret | Regenera o client secret de um aplicativo com o raio de impacto explicado antes |
Os prompts são controlados da mesma forma que as ferramentas que nomeiam: os três que alteram são oferecidos apenas a sessões que poderiam chamar as ferramentas de escrita que referenciam, e suas instruções dizem ao modelo para confirmar com você antes de mudar qualquer coisa. O requisito confirm=true em ferramentas destrutivas ainda se aplica por cima.
Skills
Onde um prompt é um ponto de partida, uma skill é um playbook operacional completo que o modelo carrega sob demanda. O servidor inclui quatro, servidas pela extensão de rascunho SEP-2640 Skills: ele declara io.modelcontextprotocol/skills em suas capacidades, responde skills/list e skills/get, e serve cada SKILL.md como um recurso comum em skill://<name>/SKILL.md com um digest sha256 em sua entrada de listagem. O diretório de plugins da OpenAI importa skills exatamente nesse formato.
| Skill | O que codifica |
|---|---|
auth-incident-triage | Triagem de "usuários não conseguem fazer login": separa indisponibilidades de plataforma de ataques e de mudanças de configuração, usando eventos, logs de WAF e saúde do cluster. Somente leitura |
enterprise-sso-rollout | Conecta um IdP empresarial a um realm de ponta a ponta: validação do emissor, registro do aplicativo upstream, configuração do broker, teste de conexão e verificação contra eventos reais de login |
keycloak-migration-doctor | Pré-valida uma exportação, importação ou migração do Keycloak contra os bloqueadores que o suporte realmente vê (políticas de script, o caminho legado /auth, expectativas de exportação parcial) e diagnostica um trabalho com falha lendo seu error_message real em vez do aviso genérico do painel |
keycloak-upgrade-readiness | Avalia desvio de versão, descobre o que a nova versão do Keycloak quebra (extensões, temas) e sequencia a implantação entre ambientes com uma exportação como plano de reversão |
As skills seguem o mesmo controle que as ferramentas que nomeiam: os três fluxos construídos em torno de ferramentas de escrita são retidos de sessões somente leitura, e uma sessão com escopo só recebe uma skill cujas ferramentas ela realmente possui. As fontes estão em internal/tools/skills/, um diretório por skill, no formato padrão Agent Skills, então também funcionam copiadas diretamente para um diretório local de skills.
Conectando
Para HTTP hospedado, a rota mais simples é OAuth, que não exige nenhuma credencial:
claude mcp add --transport http skycloak https://mcp.skycloak.io
A primeira chamada abre seu navegador, você aprova na página de login do Skycloak e as ferramentas aparecem. Se você pertence a mais de um workspace, nomeie o que deseja:
claude mcp add --transport http skycloak "https://mcp.skycloak.io?workspace=<workspace-id>"
Caso contrário, crie uma chave de API no painel do Skycloak e configure seu cliente MCP para enviá-la como bearer token:
claude mcp add --transport http skycloak https://mcp.skycloak.io --header "Authorization: Bearer sk_sc_XXX"
Isso adiciona o seguinte a .claude.json:
{
"mcpServers": {
"skycloak": {
"type": "http",
"url": "https://mcp.skycloak.io",
"headers": {
"Authorization": "Bearer sk_sc_XXX"
}
}
}
}
Para stdio local, faça login uma vez e aponte seu cliente para 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 (sem navegador), pule init e passe a chave: adicione "env": { "SKYCLOAK_API_KEY": "sk_sc_..." } à configuração, ou claude mcp add skycloak --env SKYCLOAK_API_KEY=sk_sc_... -- skycloak-mcp run --transport stdio.
Adicione --allow-writes apenas quando pretender fazer alterações (entre com skycloak-mcp init --allow-writes, ou use uma chave com escopo de escrita).
Adicione ?readonly=true a uma URL HTTP hospedada para expor apenas ferramentas somente-leitura para essa sessão HTTP, ou ?readonly=false para solicitar a superfície de ferramentas com capacidade de escrita. O parâmetro de consulta tem como padrão false, mas as ferramentas de escrita são registradas apenas quando o servidor foi iniciado com --allow-writes.
Adicione ?workspace=<uuid> para escolher em qual workspace uma sessão OAuth atua. Só é necessário quando você pertence a mais de um; com um único workspace o servidor escolhe por você, e se você pertencer a vários e não nomear nenhum, a conexão falha com uma mensagem listando-os.
Executando o transporte HTTP
skycloak-mcp run --transport http --http-addr :8080
Ele não precisa de credencial própria: os chamadores fornecem as suas por requisição, então nada é injetado no momento do deploy. GET /healthz e GET /readyz não são autenticados e relatam apenas que o processo está ativo; eles deliberadamente não consultam a API do Skycloak, então uma falha upstream não pode derrubar a sonda de todas as réplicas de uma vez. O servidor não mantém estado de sessão, então as réplicas não precisam de afinidade de sessão e podem ser escaladas ou atualizadas livremente. SIGTERM interrompe novas conexões e drena chamadas em andamento.
O caminho OAuth está ativo sempre que SKYCLOAK_ISSUER e SKYCLOAK_DASHBOARD_URL estão definidos, o que é o padrão. GET /.well-known/oauth-protected-resource é então servido sem autenticação, nomeando o realm como servidor de autorização. Seu valor de resource é obtido de SKYCLOAK_PUBLIC_URL quando definido, e caso contrário do próprio Host e esquema da requisição, então uma implantação de host único atrás de um ingress não precisa de configuração extra. O esquema vem de X-Forwarded-Proto quando presente, e caso contrário tem como padrão https para qualquer coisa exceto um host de loopback, já que o TLS termina upstream e publicar um identificador http:// não corresponderia à URL na qual o cliente se conectou. Defina SKYCLOAK_PUBLIC_URL se o seu ingress reescreve Host. O documento também lista openid profile email como seu scopes_supported, e o desafio WWW-Authenticate os repete como um parâmetro scope, então um cliente que lê qualquer um deles pede ao realm: openid é obrigatório, porque a troca de token faz o dashboard chamar o endpoint userinfo do Keycloak e o Keycloak recusa um token concedido sem ele. Um token que chega sem ele é recusado na verificação com um 401 e o desafio, em vez de ser levado a uma troca que não pode ter sucesso, então um cliente que ainda possui uma concessão anterior para de tentar e faz login novamente. Apagar qualquer uma das variáveis de issuer ou dashboard desativa o OAuth completamente, e o servidor volta a exigir uma chave de API e nada mais.
OPENAI_APPS_CHALLENGE_TOKEN serve o token de verificação de domínio do diretório de plugins da OpenAI em /.well-known/openai-apps-challenge, como texto simples e nada mais. Se não definido, a rota não é registrada e o caminho retorna 404.
A inicialização registra uma linha com a configuração resolvida (oauth=, issuer=, dashboard=, public_url=, endpoint=, allow_writes=), para que uma implantação mal configurada possa ser detectada sem um novo deploy. Cada requisição recusada no caminho OAuth registra uma linha nomeando o estágio que falhou (verify, exchange ou scopes), o status que o chamador recebeu e o erro subjacente. Uma falha de verificação adiciona a checagem que rejeitou o token (expired, wrong_issuer, bad_signature, unknown_key_id, wrong_token_type, no_openid_scope, e assim por diante); uma falha de troca adiciona o status do dashboard e o host chamado. O chamador aparece como o sujeito do token uma vez verificado, e nunca como uma credencial: o token de acesso, o cabeçalho Authorization e a chave de API cunhada nunca são registrados.
Configuração
| Env var | Padrão |
|---|---|
SKYCLOAK_API_KEY | nenhum (opcional para stdio; clientes HTTP fornecem cabeçalhos API-Key em vez disso) |
SKYCLOAK_ENDPOINT | https://api.skycloak.io |
SKYCLOAK_API_VERSION | versão atual da API |
SKYCLOAK_ISSUER | https://login.app.skycloak.io/realms/skycloak (login via CLI, e o servidor de autorização contra o qual o transporte HTTP verifica tokens) |
SKYCLOAK_CLIENT_ID | skycloak-mcp (fluxo de dispositivo CLI apenas) |
SKYCLOAK_DASHBOARD_URL | https://app.skycloak.io (cunha chaves CLI e chaves de sessão HTTP) |
SKYCLOAK_PUBLIC_URL | nenhum (derivado de cada requisição; defina quando o ingress reescreve Host) |
OPENAI_APPS_CHALLENGE_TOKEN | Serve o token de verificação do diretório de plugins da OpenAI em /.well-known/openai-apps-challenge. Se não definido, esse caminho retorna 404. |
Comandos: init (login no navegador), run (servir), logout (remover a chave armazenada). init aceita --workspace <id>, --allow-writes, --allow-credentials e --ttl-days (padrão 90).
| Flag | Padrão | Descrição |
|---|---|---|
--transport | stdio | stdio ou http |
--http-addr | :8080 | endereço de escuta para o transporte HTTP |
--allow-writes | false | habilita ferramentas de mutação para stdio e permite que sessões HTTP com readonly=false registrem ferramentas de escrita |
Desenvolvimento
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
O cliente de API em internal/apiclient é gerado a partir da especificação OpenAPI do Skycloak com oapi-codegen.
Mantendo-se em sincronia com a API
O cliente em internal/apiclient é gerado a partir de internal/apiclient/openapi.yaml com oapi-codegen; execute make generate para atualizá-lo. O CI falha se o código gerado commitado divergir da especificação. Requisições são repetidas em 429/5xx com backoff ciente de Retry-After.
Distribuição
Lançado como binários do GitHub e uma imagem de contêiner ghcr.io/sky-cloak/skycloak-mcp em cada tag, e publicado no MCP Registry como io.skycloak/skycloak-mcp. A maioria das pessoas não precisa de nenhum dos dois: o servidor hospedado não requer instalação.
Segurança
Por favor, relate vulnerabilidades de forma privada. Veja SECURITY.md.
Contribuidores
Construído na Skycloak por Guilliano Molaire, Neville Omangi e Aphilas. O histórico do repositório foi compactado quando foi aberto, então o log de commits não reflete quem escreveu o quê.
Licença
Apache-2.0. A descrição OpenAPI em internal/apiclient/openapi.yaml é gerada a partir da API da plataforma Skycloak e é (c) Skycloak; está incluída aqui para que o cliente possa ser gerado e verificado. Veja NOTICE.