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

Smithery

Официальный сервер 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_windowcreate_cluster, update_cluster, delete_cluster, cancel_cluster_upgrade, set_cluster_maintenance_window, delete_cluster_maintenance_window
Периметровая безопасностьget_cluster_security, list_cluster_captcha_domainsupdate_cluster_security, add_cluster_captcha_domain, remove_cluster_captcha_domain
Realm'ыlist_realms, get_realmcreate_realm, update_realm, delete_realm
Приложенияlist_applications, get_application, list_application_roles, list_application_sessionscreate_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_oidccreate_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_groupscreate_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_routecreate_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_contentset_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_extensionsinstall_extension, upgrade_extension, update_extension, uninstall_extension, delete_extension
SMTPget_smtpupsert_smtp, delete_smtp, test_smtp
Экспорт и журналыlist_exports, get_export, get_logs, get_security_logs, query_eventscreate_export, delete_export, export_cluster_events
Импорт и экспорт realmget_realm_export, get_realm_importcreate_realm_export, create_realm_import, create_realm_import_upload_url
SIEMlist_siem_destinations, get_siem_destinationcreate_siem_destination, update_siem_destination, delete_siem_destination, test_siem_destination
Вебхукиlist_webhook_event_types, list_webhook_subscriptions, get_webhook_subscriptioncreate_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_ENDPOINThttps://api.skycloak.io
SKYCLOAK_API_VERSIONтекущая версия API
SKYCLOAK_ISSUERhttps://login.app.skycloak.io/realms/skycloak (вход через CLI и сервер авторизации, против которого HTTP-транспорт проверяет токены)
SKYCLOAK_CLIENT_IDskycloak-mcp (только device flow в CLI)
SKYCLOAK_DASHBOARD_URLhttps://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).

ФлагПо умолчаниюОписание
--transportstdiostdio или http
--http-addr:8080адрес прослушивания для HTTP-транспорта
--allow-writesfalseвключает изменяющие инструменты для 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.