Skycloak
официальныйСервер Model Context Protocol для управляемого Skycloak Keycloak. Управляйте кластерами, realm'ами, приложениями, SSO и пользователями из любого MCP-клиента.
Что можно делать с Skycloak MCP?
Управляйте своими кластерами Skycloak (управляемый Keycloak), realm'ами и SSO из любого MCP-клиента.
- Проверка обновлений кластера — Узнайте, какие кластеры отстают от обновлений Keycloak, и получите путь обновления через
list_cluster_upgradesиget_cluster_upgrade_path. - Создание realm'ов — Создайте realm с входом через Google и GitHub с помощью
create_realmиcreate_identity_provider. - Пересылка в SIEM — Настройте назначение SIEM, которое пересылает события администратора в вебхук Datadog через
create_siem_destination. - Настройка пользовательского домена — Добавьте пользовательский домен, получите DNS-записи и проверьте их с помощью
create_domainиverify_domain.
Документация
skycloak-mcp
Официальный сервер Model Context Protocol для Skycloak (управляемый Keycloak): управляйте своими кластерами, realm'ами, приложениями и SSO из любого MCP-клиента (Claude Desktop, Claude Code, Cursor).
Статус: ранний релиз. Покрытие инструментами растёт; см. журнал изменений, чтобы узнать, что доступно.
Быстрый старт
claude mcp add --transport http skycloak https://mcp.skycloak.io
Никакого API-ключа, никакого client ID, никакой настройки. Открывается ваш браузер, вы входите в Skycloak, и инструменты появляются. Любой MCP-клиент, поддерживающий streamable HTTP, работает так же: дайте ему URL и больше ничего.
Затем попросите что-нибудь:
- «Какие из моих кластеров Keycloak отстают по обновлениям?»
- «Создай staging realm на кластере в ЕС со входом через Google и GitHub.»
- «Кто был добавлен в production realm за последнюю неделю?»
- «Настрой назначение SIEM, которое пересылает события администратора на наш вебхук Datadog.»
Аутентификация и безопасность
- Размещённый HTTP, с OAuth (без настройки учётных данных). Укажите вашему клиенту
https://mcp.skycloak.ioбез заголовка. Сервер отвечает401со ссылкой на свои метаданные RFC 9728 по адресу/.well-known/oauth-protected-resource, клиент выполняет браузерный поток авторизационного кода против login realm Skycloak, и полученный токен доступа обменивается на кратковременный API-ключ с областью действия рабочего пространства, на котором работает сессия. Ключ действует час и автоматически продлевается. Ничего не хранится в конфигурации вашего клиента. - Размещённый HTTP, с API-ключом. Создайте ключ в панели управления Skycloak и отправляйте его как
Authorization: Bearer <key>(илиAPI-Key: <key>). Каждый запрос несёт собственные учётные данные и действует только от имени рабочего пространства этих учётных данных. Сервер не хранит состояние сессии, поэтому запрос никогда не наследует состояние другого вызывающего. Ключи не проверяются перед использованием: API Skycloak является источником истины, поэтому недействительный ключ проявляется как401при первом вызове инструмента, а не при подключении. - Инструменты соответствуют вашей роли. При OAuth список инструментов сокращается до того, что разрешают области сессии, поэтому участнику рабочего пространства с доступом только на чтение не показываются инструменты записи, которые ответили бы
403. С API-ключом регистрируется вся поверхность, потому что области ключа не видны серверу, и несанкционированный вызов проявляется как403от API. - Локальный stdio. Запустите
skycloak-mcp initи подтвердите в браузере (поток авторизации устройства OAuth 2.0). Он создаёт API-ключ с областью действия рабочего пространства, сохраняет его в связке ключей вашей операционной системы и автоматически определяет ваше рабочее пространство по умолчанию (передайте--workspace <id>, чтобы выбрать другое).skycloak-mcp logoutудаляет сохранённый ключ. - Безголовый режим / CI. Установите переменную окружения
SKYCLOAK_API_KEY(создайте ключ в панели управления Skycloak), чтобы полностью пропустить браузер. Она всегда имеет приоритет над связкой ключей. - Запись ограничена вашими учётными данными, а не флагом. Размещённый сервер по адресу
https://mcp.skycloak.ioработает с поддержкой записи, и то, что вы реально можете изменить, ограничено областями вашего ключа и вашей ролью в рабочем пространстве: участник с доступом только на чтение не может ничего изменить, что бы ни говорил список инструментов. Добавьте?readonly=trueк URL, чтобы принудительно включить поверхность инструментов только для чтения для сессии. Локальный бинарный файл устроен наоборот и не регистрирует инструменты записи, если не запущен с--allow-writes. - Учётные данные кластера — по желанию.
get_cluster_credentialsвозвращает учётные данные администратора Keycloak кластера, которые ассистент, владеющий ключом, затем увидит, поэтомуinitне запрашивает эту область по умолчанию. Используйте ключ, который её несёт: создайте его в панели управления или при stdio войдите сskycloak-mcp init --allow-credentials. Без него инструмент возвращает 403, объясняющий оба пути. - Деструктивные инструменты требуют подтверждения: удаление realm, например, требует явного аргумента
confirm=true. - Запросы ограничиваются по скорости в соответствии с вашим планом Skycloak; при ответе
429сервер показываетRetry-After.
Инструменты
129 инструментов: 58 только для чтения и 71 для записи. Инструменты только для чтения доступны всегда. На размещённом сервере инструменты записи также зарегистрированы и ограничены областями ваших учётных данных; локальный бинарный файл регистрирует их только при запуске с --allow-writes.
Имена инструментов несут префикс skycloak_, который опущен в таблице ниже, поэтому list_clusters — это skycloak_list_clusters в вашем клиенте.
| Область | Только чтение | Запись (--allow-writes) |
|---|---|---|
| Кластеры | 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 |
| Периметровая безопасность | get_cluster_security, list_cluster_captcha_domains | update_cluster_security, add_cluster_captcha_domain, remove_cluster_captcha_domain |
| Realm'ы | list_realms, get_realm | create_realm, update_realm, delete_realm |
| Приложения | 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 |
| Провайдеры удостоверений | 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 |
| Пользователи, роли и группы | 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 |
| Пользовательские домены | 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 |
| Брендинг и темы | 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 |
| Расширения | list_extensions, list_cluster_extensions | install_extension, upgrade_extension, update_extension, uninstall_extension, delete_extension |
| SMTP | get_smtp | upsert_smtp, delete_smtp, test_smtp |
| Экспорт и журналы | list_exports, get_export, get_logs, get_security_logs, query_events | create_export, delete_export, export_cluster_events |
| Импорт и экспорт 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 |
| Вебхуки | list_webhook_event_types, list_webhook_subscriptions, get_webhook_subscription | create_webhook_subscription, update_webhook_subscription, delete_webhook_subscription, test_webhook_subscription |
Соглашения: деструктивные инструменты (delete_*, uninstall_extension, cancel_cluster_upgrade) требуют confirm=true. create_cluster асинхронен: опрашивайте get_cluster, пока кластер не станет available. create_domain возвращает DNS-записи, которые должен создать клиент; verify_domain запускает проверку DNS. set_theme_assignment активирует пользовательскую тему для каждого типа темы Keycloak (пустая строка сбрасывает к встроенной по умолчанию). update_cluster_security не трогает настройки CAPTCHA. Импорт/экспорт realm переносит конфигурацию одного realm и отделён от create_export, который выгружает базу данных всего кластера: оба асинхронны, и архив realm всегда зашифрован, поэтому пароль, использованный для экспорта, нужен для повторного импорта. Realm можно импортировать прямо из существующего экспорта (source_export_id) или из загруженного архива (create_realm_import_upload_url, PUT, затем upload_s3_key); импорт создаёт realm и отказывает при совпадении имени, а не перезаписывает, и требует confirm=true, потому что переносит пользователей и учётные данные.
Промпты
Восемь промптов дают вам отправную точку в этой поверхности инструментов. Клиенты показывают их как слэш-команды или предлагаемые действия; каждый принимает аргументы (realm, кластер, временное окно) и проводит модель через нужные инструменты в нужном порядке.
| Промпт | Что он делает |
|---|---|
audit_self_registration | Найти каждый realm, который всё ещё разрешает самостоятельную регистрацию, в одном кластере или во всех |
review_upgrades | Выявить кластеры, отстающие по версии Keycloak, и выстроить путь обновления |
triage_failed_logins | Получить недавние неудачные входы для realm и сгруппировать их по исходному IP |
review_identity_providers | Перечислить SSO-подключения realm и проверить, включено ли конкретное |
review_admin_changes | Показать, кто и что менял в realm недавно, с фокусом на настройках входа и безопасности |
provision_environment | Создать кластер, добавить realm и подключить провайдера удостоверений, подтверждая каждый шаг |
set_up_custom_domain | Добавить пользовательский домен, вернуть точные DNS-записи, проверить и направить его на realm |
rotate_client_secret | Перегенерировать секрет клиента приложения с заранее описанным радиусом поражения |
Промпты ограничены так же, как и инструменты, которые они называют: три изменяющих предлагаются только сессиям, которые могли бы вызвать упомянутые инструменты записи, и их инструкции говорят модели подтвердить с вами перед любыми изменениями. Требование confirm=true для деструктивных инструментов всё равно применяется поверх.
Навыки
Если промпт — это отправная точка, то навык — это полный операционный сценарий, который модель загружает по требованию. Сервер поставляет четыре навыка, обслуживаемых через черновое расширение SEP-2640 Skills: он объявляет io.modelcontextprotocol/skills в своих возможностях, отвечает на skills/list и skills/get и обслуживает каждый SKILL.md как обычный ресурс по адресу skill://<name>/SKILL.md с дайджестом sha256 в записи списка. Каталог плагинов OpenAI импортирует навыки именно в такой форме.
| Навык | Что он кодирует |
|---|---|
auth-incident-triage | Разбор «пользователи не могут войти»: отделить сбои платформы от атак и от изменений конфигурации, используя события, журналы WAF и здоровье кластера. Только чтение |
enterprise-sso-rollout | Подключить корпоративный IdP к realm от начала до конца: проверка издателя, регистрация вышестоящего приложения, конфигурация брокера, тестирование подключения и проверка по реальным событиям входа |
keycloak-migration-doctor | Предварительная проверка экспорта, импорта или миграции Keycloak на предмет блокировщиков, которые реально видит поддержка (скриптовые политики, устаревший путь /auth, ожидания частичного экспорта), и диагностика неудачного задания по чтению реального error_message вместо общего уведомления на панели |
keycloak-upgrade-readiness | Оценить расхождение версий, выяснить, что ломает новая версия Keycloak (расширения, темы), и выстроить последовательность развёртывания по средам с экспортом как планом отката |
Навыки следуют той же схеме ограничения, что и инструменты, которые они называют: три сценария, построенные вокруг инструментов записи, скрыты от сессий только для чтения, а сессии с ограниченными областями предлагается только тот навык, инструменты которого у неё реально есть. Исходники находятся в internal/tools/skills/, по одному каталогу на навык, в стандартном формате Agent Skills, поэтому они также работают при прямом копировании в локальный каталог навыков.
Подключение
Для размещённого HTTP самый простой путь — OAuth, которому вообще не нужны учётные данные:
claude mcp add --transport http skycloak https://mcp.skycloak.io
Первый вызов открывает ваш браузер, вы подтверждаете на странице входа Skycloak, и инструменты появляются. Если вы принадлежите более чем к одному рабочему пространству, укажите нужное:
claude mcp add --transport http skycloak "https://mcp.skycloak.io?workspace=<workspace-id>"
В противном случае создайте API-ключ в панели управления Skycloak и настройте ваш MCP-клиент отправлять его как bearer-токен:
claude mcp add --transport http skycloak https://mcp.skycloak.io --header "Authorization: Bearer sk_sc_XXX"
Это добавляет следующее в .claude.json:
{
"mcpServers": {
"skycloak": {
"type": "http",
"url": "https://mcp.skycloak.io",
"headers": {
"Authorization": "Bearer sk_sc_XXX"
}
}
}
}
Для локального stdio войдите один раз, затем укажите вашему клиенту skycloak-mcp run:
skycloak-mcp init # one-time browser sign-in; stores a key in your keychain
Claude Desktop / Cursor (локально, stdio):
{
"mcpServers": {
"skycloak": {
"command": "skycloak-mcp",
"args": ["run", "--transport", "stdio"]
}
}
}
Claude Code:
claude mcp add skycloak -- skycloak-mcp run --transport stdio
Для headless / CI (без браузера) пропустите init и передайте ключ вместо этого: добавьте "env": { "SKYCLOAK_API_KEY": "sk_sc_..." } в конфигурацию или claude mcp add skycloak --env SKYCLOAK_API_KEY=sk_sc_... -- skycloak-mcp run --transport stdio.
Добавляйте --allow-writes только когда планируете вносить изменения (войдите через skycloak-mcp init --allow-writes или используйте ключ с правами на запись).
Добавьте ?readonly=true к hosted HTTP URL, чтобы открыть только read-only инструменты для этой HTTP-сессии, или ?readonly=false для запроса поверхности инструментов с правами записи. Параметр запроса по умолчанию — false, но инструменты записи регистрируются только если сервер был запущен с --allow-writes.
Добавьте ?workspace=<uuid>, чтобы выбрать, над каким workspace действует OAuth-сессия. Это нужно только если вы принадлежите более чем к одному; при одном workspace сервер выбирает его сам, а если вы принадлежите к нескольким и не указали ни одного, соединение завершится ошибкой со списком этих workspace.
Запуск HTTP-транспорта
skycloak-mcp run --transport http --http-addr :8080
Ему не нужны собственные учётные данные: вызывающие стороны предоставляют свои в каждом запросе, поэтому при развёртывании ничего не внедряется. GET /healthz и GET /readyz не требуют аутентификации и сообщают только о том, что процесс работает; они намеренно не обращаются к Skycloak API, поэтому сбой на стороне вышестоящего сервиса не может одновременно уронить проверки всех реплик. Сервер не хранит состояние сессии, поэтому репликам не нужна привязка сессий, и их можно свободно масштабировать или обновлять. SIGTERM останавливает новые подключения и завершает выполняющиеся вызовы.
OAuth-путь активен, когда заданы SKYCLOAK_ISSUER и SKYCLOAK_DASHBOARD_URL, что происходит по умолчанию. Тогда GET /.well-known/oauth-protected-resource обслуживается без аутентификации и указывает realm как сервер авторизации. Его значение resource берётся из SKYCLOAK_PUBLIC_URL, если оно задано, а в противном случае — из собственных Host и схемы запроса, так что развёртывание на одном хосте за ingress не требует дополнительной настройки. Схема берётся из X-Forwarded-Proto, если она присутствует, и в противном случае по умолчанию используется https для всего, кроме loopback-хоста, поскольку TLS завершается вышестоящим сервером, и публикация идентификатора http:// не соответствовала бы URL, к которому подключился клиент. Установите SKYCLOAK_PUBLIC_URL, если ваш ingress переписывает Host. Документ также перечисляет openid profile email как свой scopes_supported, а вызов WWW-Authenticate повторяет их как параметр scope, поэтому клиент, читающий любой из них, запрашивает их у realm: openid обязателен, потому что при обмене токенами панель вызывает userinfo-эндпоинт Keycloak, а Keycloak отказывает токену, выданному без него. Токен, прибывший без него, отклоняется при проверке с 401 и вызовом, а не передаётся в обмен, который не может завершиться успешно, поэтому клиент, всё ещё имеющий грант из прошлого, перестаёт повторять попытки и входит снова. Если очистить любую из переменных issuer или dashboard, OAuth полностью отключается, и сервер снова запрашивает только API-ключ.
OPENAI_APPS_CHALLENGE_TOKEN обслуживает токен проверки домена каталога плагинов OpenAI по адресу /.well-known/openai-apps-challenge как обычный текст и ничего больше. Если не задано, маршрут не регистрируется, и путь возвращает 404.
При запуске выводится одна строка с разрешённой конфигурацией (oauth=, issuer=, dashboard=, public_url=, endpoint=, allow_writes=), поэтому неправильно настроенное развёртывание можно заметить без повторного развёртывания. Каждый запрос, отклонённый на OAuth-пути, записывает одну строку с названием этапа, на котором произошёл сбой (verify, exchange или scopes), статусом, полученным вызывающей стороной, и базовой ошибкой. Сбой проверки добавляет проверку, отклонившую токен (expired, wrong_issuer, bad_signature, unknown_key_id, wrong_token_type, no_openid_scope и так далее); сбой обмена добавляет статус панели и вызванный хост. Вызывающая сторона отображается как субъект токена после его проверки и никогда как учётные данные: токен доступа, заголовок Authorization и выпущенный API-ключ никогда не записываются в журнал.
Конфигурация
| Переменная окружения | По умолчанию |
|---|---|
SKYCLOAK_API_KEY | нет (необязательно для stdio; HTTP-клиенты предоставляют заголовки API-Key вместо этого) |
SKYCLOAK_ENDPOINT | https://api.skycloak.io |
SKYCLOAK_API_VERSION | текущая версия API |
SKYCLOAK_ISSUER | https://login.app.skycloak.io/realms/skycloak (вход через CLI и сервер авторизации, против которого HTTP-транспорт проверяет токены) |
SKYCLOAK_CLIENT_ID | skycloak-mcp (только device flow в CLI) |
SKYCLOAK_DASHBOARD_URL | https://app.skycloak.io (выпускает ключи CLI и ключи HTTP-сессий) |
SKYCLOAK_PUBLIC_URL | нет (выводится из каждого запроса; задайте, если ingress переписывает Host) |
OPENAI_APPS_CHALLENGE_TOKEN | Обслуживает токен проверки домена каталога плагинов OpenAI по адресу /.well-known/openai-apps-challenge. Если не задано, этот путь возвращает 404. |
Команды: init (вход через браузер), run (запуск сервера), logout (удаление сохранённого ключа). init принимает --workspace <id>, --allow-writes, --allow-credentials и --ttl-days (по умолчанию 90).
| Флаг | По умолчанию | Описание |
|---|---|---|
--transport | stdio | stdio или http |
--http-addr | :8080 | адрес прослушивания для HTTP-транспорта |
--allow-writes | false | включает изменяющие инструменты для stdio и разрешает HTTP-сессиям с readonly=false регистрировать инструменты записи |
Разработка
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
API-клиент в internal/apiclient генерируется из спецификации OpenAPI Skycloak с помощью oapi-codegen.
Поддержание синхронизации с API
Клиент в internal/apiclient генерируется из internal/apiclient/openapi.yaml с помощью oapi-codegen; запустите make generate, чтобы обновить его. CI завершается ошибкой, если зафиксированный сгенерированный код расходится со спецификацией. Запросы повторяются при 429/5xx с задержкой с учётом Retry-After.
Распространение
Выпускается как бинарные файлы GitHub и образ контейнера ghcr.io/sky-cloak/skycloak-mcp на каждом теге, а также публикуется в MCP Registry как io.skycloak/skycloak-mcp. Большинству людей не нужно ни то, ни другое: hosted-сервер не требует установки.
Безопасность
Пожалуйста, сообщайте об уязвимостях конфиденциально. См. SECURITY.md.
Авторы
Создано в Skycloak Гиллиано Молером, Невиллом Оманги и Афиласом. История репозитория была сжата при открытии, поэтому журнал коммитов не отражает, кто что написал.
Лицензия
Apache-2.0. Описание OpenAPI в internal/apiclient/openapi.yaml генерируется из платформенного API Skycloak и принадлежит (c) Skycloak; оно включено сюда, чтобы клиент можно было генерировать и проверять. См. NOTICE.