Skycloak
官方用于Skycloak托管Keycloak的模型上下文协议服务器。可从任何MCP客户端管理集群、领域、应用程序、SSO和用户。
你可以用 Skycloak MCP 做什么?
-
集群升级审查 — 查询哪些 Keycloak 集群升级滞后,并通过
list_cluster_upgrades和get_cluster_upgrade_path获取推荐的升级路径。 -
Realm 配置 — 在特定集群上创建带有已配置身份提供者的暂存 realm,使用
create_realm和create_identity_provider。 -
用户活动审计 — 查找最近添加到 realm 的用户,并审查管理员变更,利用
list_realm_users和query_events。 -
SIEM 集成设置 — 配置一个将管理员事件转发到外部 webhook 的目标,使用
create_siem_destination和test_siem_destination。 -
主题内容替换 — 在不丢失分配关系的情况下就地更新自定义主题的归档文件,通过
update_theme_content并确认执行。 -
自定义域名路由 — 添加自定义域名,获取需要创建的 DNS 记录,验证这些记录,并将流量路由到 realm,使用
create_domain和verify_domain。
文档
skycloak-mcp
官方 Model Context Protocol 服务器,用于 Skycloak(托管式 Keycloak):从任何 MCP 客户端(Claude Desktop、Claude Code、Cursor)管理您的集群、领域、应用和 SSO。
状态: 早期发布。工具覆盖范围正在增长;请参阅变更日志了解可用内容。
快速开始
claude mcp add --transport http skycloak https://mcp.skycloak.io
无需 API 密钥、无需客户端 ID、无需配置。您的浏览器会打开,您登录 Skycloak,工具就会出现。任何支持流式 HTTP 的 MCP 客户端都以相同方式工作:只需给它 URL,无需其他内容。
然后提出请求,例如:
- “我的哪些 Keycloak 集群升级落后了?”
- “在欧盟集群上创建一个暂存领域,并启用 Google 和 GitHub 登录。”
- “上周谁被添加到了生产领域?”
- “设置一个 SIEM 目标,将管理员事件转发到我们的 Datadog webhook。”
认证与安全
- 托管式 HTTP,使用 OAuth(无需配置凭据)。 将您的客户端指向
https://mcp.skycloak.io,无需任何请求头。服务器以401响应,并附带指向其 RFC 9728 元数据的指针,位于/.well-known/oauth-protected-resource;客户端针对 Skycloak 登录领域运行浏览器授权码流程,获得的访问令牌会交换为会话运行的短期、工作区范围的 API 密钥。该密钥有效期为一小时,并会自动续期。您的客户端配置中不会存储任何内容。 - 托管式 HTTP,使用 API 密钥。 在 Skycloak 仪表板 中创建密钥,并将其作为
Authorization: Bearer <key>(或API-Key: <key>)发送。每个请求都携带自己的凭据,并且仅以该凭据的工作区身份运行。服务器不保留会话状态,因此请求永远不会继承其他调用者的状态。密钥在使用前不会验证:Skycloak API 是权威,因此无效密钥会在首次工具调用时以401形式出现,而不是在连接时出现。 - 工具与您的角色匹配。 通过 OAuth,工具列表会根据会话作用域允许的内容进行裁剪,因此只读工作区成员不会看到会响应
403的写入工具。使用 API 密钥时,整个工具面都会注册,因为服务器无法看到密钥的作用域,未经授权的调用会以 API 返回的403形式出现。 - 本地 stdio。 运行
skycloak-mcp init并在浏览器中批准(OAuth 2.0 设备授权流程)。它会生成工作区范围的 API 密钥,将其存储在操作系统的钥匙串中,并自动检测您的默认工作区(传递--workspace <id>以选择其他工作区)。skycloak-mcp logout会删除存储的密钥。 - 无头 / CI。 设置
SKYCLOAK_API_KEY环境变量(在 Skycloak 仪表板 中创建密钥)以完全跳过浏览器。它始终优先于钥匙串。 - 写入操作由您的凭据控制,而非标志。 位于
https://mcp.skycloak.io的托管服务器以可写模式运行,您实际能更改的内容受密钥作用域和工作区角色限制:只读成员无法修改任何内容,无论工具列表如何显示。在 URL 中添加?readonly=true可强制会话使用只读工具面。本地二进制文件则相反,除非以--allow-writes启动,否则不会注册任何写入工具。 - 集群凭据为可选加入。
get_cluster_credentials返回集群的 Keycloak 管理员凭据,持有密钥的助手随后会看到这些凭据,因此init默认不请求该作用域。使用携带该作用域的密钥:在仪表板中创建一个,或通过 stdio 使用skycloak-mcp init --allow-credentials登录。没有该作用域时,工具会返回 403,并说明两种途径。 - 破坏性工具需要确认: 例如,删除领域需要显式的
confirm=true参数。 - 请求根据您的 Skycloak 套餐进行速率限制;在
429响应时,服务器会显示Retry-After。
工具
137 个工具:60 个只读和 77 个写入。只读工具始终可用。在托管服务器上,写入工具也会注册,并由凭据的作用域控制;本地二进制文件仅在以 --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, restart_cluster_instances, 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 |
| 领域 | 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, 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 |
| 扩展 | 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 |
| 领域导入与导出 | 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 |
约定: 破坏性工具(delete_*, uninstall_extension, cancel_cluster_upgrade, update_theme_content, update_theme_settings, restart_cluster_instances)需要 confirm=true。update_theme_settings 为工作区开启或关闭 exact_theme_names;调用者的 API 密钥必须是为工作区所有者或管理员生成的,否则即使有 themes:write,也会收到 403。开启后,现有主题会在后台移动到其精确的服务名称;如果主题内容在其精确名称下被替换,则 get_theme/list_themes/update_theme_content 会报告 restart_required: true,直到 restart_cluster_instances 滚动该集群的 Keycloak 实例。重启可能会推迟到集群的维护窗口,而不是立即应用,报告为 deferred: true,并在已知时报告 next_window。create_cluster 是异步的:轮询 get_cluster,直到集群处于 available 状态。create_domain 返回客户必须创建的 DNS 记录;verify_domain 触发 DNS 检查。set_theme_assignment 按 Keycloak 主题类型激活自定义主题(空字符串重置为内置默认值)。update_theme_content 就地替换主题的归档(content_base64 中的 base64 ZIP 或 Keycloakify JAR),保留主题的 ID、名称以及领域和应用分配,因此编辑主题不再意味着删除并重新上传;它需要 confirm=true,因为被覆盖的归档无法恢复,而 update_theme 仍然只更改名称、描述和版本。有关该调用的方式,请参阅 docs/theme-content-update.md。update_cluster_security 不触碰 CAPTCHA 设置。领域导入/导出移动一个领域的配置,与 create_export 分开,后者转储整个集群的数据库:两者都是异步的,领域归档始终加密,因此导出时使用的密码在再次导入时需要。领域可以直接从现有导出导入(source_export_id)或从上传的归档导入(create_realm_import_upload_url,PUT,然后 upload_s3_key);导入会创建领域,并在名称冲突时拒绝而不是覆盖,并且需要 confirm=true,因为它会带来用户和凭据。
提示词
八个提示词为您提供进入该工具面的起点。客户端将它们显示为斜杠命令或建议操作;每个提示词都接受参数(领域、集群、时间窗口),并引导模型按正确顺序使用正确的工具。
| 提示词 | 功能 |
|---|---|
audit_self_registration | 查找仍允许自助注册的每个领域,跨一个集群或所有集群 |
review_upgrades | 发现 Keycloak 版本落后的集群,并规划升级路径 |
triage_failed_logins | 拉取领域最近的失败登录,并按源 IP 分组 |
review_identity_providers | 列出领域的 SSO 连接,并检查特定连接是否已启用 |
review_admin_changes | 显示最近谁在领域中更改了什么,重点关注登录和安全设置 |
provision_environment | 创建集群、添加领域并配置身份提供商,逐步确认 |
set_up_custom_domain | 添加自定义域名,返回精确的 DNS 记录,验证,并将其路由到领域 |
rotate_client_secret | 重新生成应用的客户端密钥,并先说明影响范围 |
提示词与其命名的工具一样受到控制:三个会更改状态的提示词仅提供给可以调用其引用的写入工具的会话,并且其指令告诉模型在更改任何内容之前与您确认。破坏性工具的 confirm=true 要求仍然适用。
技能
提示词是起点,而技能是模型按需加载的完整操作手册。服务器附带四个技能,通过草案 SEP-2640 技能扩展 提供:它在能力中声明 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 | 针对支持团队实际遇到的阻塞项(脚本策略、旧版 /auth 路径、部分导出预期),对 Keycloak 导出、导入或迁移进行预检;并通过读取真实的 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>"
否则,请在 Skycloak 仪表盘中创建 API 密钥,并将您的 MCP 客户端配置为以 bearer token 形式发送该密钥:
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
对于无头 / 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 添加到托管 HTTP URL 中,以仅暴露该 HTTP 会话的只读工具;或添加 ?readonly=false 以请求支持写入的工具面。查询参数默认为 false,但仅当服务器以 --allow-writes 启动时,才会注册写入工具。
添加 ?workspace=<uuid> 以选择 OAuth 会话作用于哪个工作区。仅当您属于多个工作区时才需要此参数;如果只有一个工作区,服务器会为您选择;如果您属于多个工作区但未指定任何名称,连接将失败并显示列出这些工作区的消息。
运行 HTTP 传输
skycloak-mcp run --transport http --http-addr :8080
它本身不需要凭据:调用方在每次请求中提供自己的凭据,因此部署时不会注入任何内容。GET /healthz 和 GET /readyz 无需认证,仅报告进程是否正常运行;它们有意不探测 Skycloak API,因此上游故障不会导致所有副本的探针同时失败。服务器不持有会话状态,因此副本无需会话亲和性,可以自由扩展或滚动更新。SIGTERM 会停止新连接并排空正在进行的调用。
只要设置了 SKYCLOAK_ISSUER 和 SKYCLOAK_DASHBOARD_URL(默认情况下均已设置),OAuth 路径即处于启用状态。此时 GET /.well-known/oauth-protected-resource 以未认证方式提供,将 realm 命名为授权服务器。其 resource 值在设置 SKYCLOAK_PUBLIC_URL 时取自该变量,否则取自请求自身的 Host 和协议方案,因此位于入口后面的单主机部署无需额外配置。协议方案在存在 X-Forwarded-Proto 时取自该变量,否则对于非回环主机默认为 https,因为 TLS 在上游终止,发布 http:// 标识符将与客户端连接的 URL 不匹配。如果您的入口重写 Host,请设置 SKYCLOAK_PUBLIC_URL。该文档还将 openid profile email 列为其 scopes_supported,并且 WWW-Authenticate 质询将其作为 scope 参数重复,因此读取其中任一内容的客户端都会向 realm 请求这些参数:openid 是必需的,因为令牌交换会使仪表盘调用 Keycloak 的 userinfo 端点,而 Keycloak 会拒绝未授予该范围的令牌。未携带该范围的令牌在验证时会被拒绝并返回 401 和质询,而不会进入无法成功的交换流程,因此仍持有旧授权的客户端会停止重试并重新登录。将颁发者或仪表盘变量中的任一值清空会完全关闭 OAuth,服务器将恢复为仅质询 API 密钥。
OPENAI_APPS_CHALLENGE_TOKEN 在 /.well-known/openai-apps-challenge 提供 OpenAI 插件目录域名验证令牌,仅以纯文本形式返回。未设置时,该路由不会注册,路径返回 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(仅 CLI 设备流) |
SKYCLOAK_DASHBOARD_URL | https://app.skycloak.io(铸造 CLI 密钥和 HTTP 会话密钥) |
SKYCLOAK_PUBLIC_URL | 无(从每个请求派生;当入口重写 Host 时设置) |
OPENAI_APPS_CHALLENGE_TOKEN | 在 /.well-known/openai-apps-challenge 提供 OpenAI 插件目录验证令牌。未设置时,该路径返回 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 启用变更工具,并允许带有 readonly=false 的 HTTP 会话注册写入工具 |
开发
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
internal/apiclient 下的 API 客户端是根据 Skycloak OpenAPI 规范使用 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 容器镜像形式发布,并作为 io.skycloak/skycloak-mcp 发布到 MCP Registry。大多数人两者都不需要:托管服务器无需安装。
安全
请私下报告漏洞。请参阅 SECURITY.md。
贡献者
由 Guilliano Molaire、Neville Omangi 和 Aphilas 在 Skycloak 构建。仓库历史在开放时被压缩,因此提交日志不能反映谁写了什么。
许可证
Apache-2.0。internal/apiclient/openapi.yaml 中的 OpenAPI 描述是从 Skycloak 平台 API 生成的,版权归 Skycloak 所有;将其包含在此处是为了能够生成和验证客户端。请参阅 NOTICE。