Skycloak
官方適用於Skycloak託管Keycloak的Model Context Protocol伺服器。可從任何MCP客戶端管理叢集、領域、應用程式、SSO與使用者。
你可以用 Skycloak MCP 做什麼?
從任何 MCP 用戶端管理您的 Skycloak(受管 Keycloak)叢集、領域與 SSO。
- 叢集升級審查 — 詢問哪些叢集在 Keycloak 升級上落後,並透過
list_cluster_upgrades和get_cluster_upgrade_path取得升級路徑。 - 領域佈建 — 使用
create_realm和create_identity_provider建立支援 Google 與 GitHub 登入的領域。 - SIEM 轉發 — 透過
create_siem_destination設定 SIEM 目的地,將管理事件轉發至 Datadog webhook。 - 自訂網域設定 — 使用
create_domain和verify_domain新增自訂網域、取得 DNS 記錄並進行驗證。
文件
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 後工具就會出現。任何支援 streamable HTTP 的 MCP 用戶端都以相同方式運作:只要提供 URL,其他什麼都不用。
然後就可以提出要求:
- 「我的哪些 Keycloak 叢集升級進度落後?」
- 「在 EU 叢集上建立一個 staging 領域,並啟用 Google 與 GitHub 登入。」
- 「上週有哪些人被加入 production 領域?」
- 「設定一個 SIEM 目的地,將管理事件轉發到我們的 Datadog webhook。」
驗證與安全
- 託管 HTTP,使用 OAuth(無需設定任何憑證)。 將您的用戶端指向
https://mcp.skycloak.io,不需任何標頭。伺服器以401回應,並指向位於/.well-known/oauth-protected-resource的 RFC 9728 中繼資料;用戶端會針對 Skycloak 登入領域執行瀏覽器授權碼流程,取得的存取權杖會換成短期、限定工作區的 API 金鑰供工作階段使用。金鑰有效期為一小時,並會自動續期。您的用戶端設定中不會儲存任何內容。 - 託管 HTTP,使用 API 金鑰。 在 Skycloak 儀表板 建立金鑰,並以
Authorization: Bearer <key>(或API-Key: <key>)傳送。每個請求都攜帶自己的憑證,且只以該憑證的工作區身分運作。伺服器不保留工作階段狀態,因此請求絕不會繼承其他呼叫者的狀態。金鑰在使用前不會被驗證:Skycloak API 才是權威來源,因此無效的金鑰會在第一次工具呼叫時以401呈現,而非在連線時。 - 工具與您的角色相符。 透過 OAuth 時,工具清單會依工作階段的 scopes 允許範圍裁減,因此唯讀工作區成員不會看到會回應
403的寫入工具。使用 API 金鑰時會註冊完整工具面,因為伺服器看不到金鑰的 scopes,未經授權的呼叫會以 API 回傳的403呈現。 - 本機 stdio。 執行
skycloak-mcp init並在瀏覽器中核准(OAuth 2.0 裝置授權流程)。它會產生一個限定工作區的 API 金鑰,儲存在您作業系統的金鑰圈中,並自動偵測您的預設工作區(傳入--workspace <id>可選擇其他工作區)。skycloak-mcp logout會移除已儲存的金鑰。 - 無頭模式 / CI。 設定
SKYCLOAK_API_KEY環境變數(在 Skycloak 儀表板 建立金鑰)即可完全略過瀏覽器。它永遠優先於金鑰圈。 - 寫入操作由您的憑證把關,而非旗標。 位於
https://mcp.skycloak.io的託管伺服器具備寫入能力,而您實際能變更的範圍受限於金鑰的 scopes 與工作區角色:唯讀成員無法變更任何內容,無論工具清單怎麼顯示。在 URL 加上?readonly=true可強制工作階段使用唯讀工具面。本機二進位檔則相反,除非以--allow-writes啟動,否則不會註冊任何寫入工具。 - 叢集憑證為選擇性啟用。
get_cluster_credentials會回傳叢集的 Keycloak 管理員憑證,持有金鑰的助理隨後就會看到這些憑證,因此init預設不會要求該 scope。請使用帶有此 scope 的金鑰:在儀表板建立一個,或透過 stdio 以skycloak-mcp init --allow-credentials登入。若無此 scope,工具會回傳 403,並說明這兩種途徑。 - 破壞性工具需要確認: 例如刪除領域需要明確的
confirm=true參數。 - 請求會依您的 Skycloak 方案進行速率限制;收到
429回應時,伺服器會呈現Retry-After。
工具
共 129 個工具:58 個唯讀、71 個寫入。唯讀工具永遠可用。在託管伺服器上,寫入工具也會註冊,並由您憑證的 scopes 把關;本機二進位檔僅在以 --allow-writes 啟動時才會註冊它們。
工具名稱帶有 skycloak_ 前綴,下表已省略,因此 list_clusters 在您的用戶端中即為 skycloak_list_clusters。
| 領域 | 唯讀 | 寫入 (--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 |
| Edge security | 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 |
| Applications | 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 |
| Identity providers | 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 |
| Users, roles & groups | 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 |
| Custom domains | 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 |
| Branding & themes | 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 |
| Extensions | list_extensions, list_cluster_extensions | install_extension, upgrade_extension, update_extension, uninstall_extension, delete_extension |
| SMTP | get_smtp | upsert_smtp, delete_smtp, test_smtp |
| Exports & logs | list_exports, get_export, get_logs, get_security_logs, query_events | create_export, delete_export, export_cluster_events |
| Realm import & export | 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)需要 confirm=true。create_cluster 是非同步的:輪詢 get_cluster 直到叢集狀態為 available。create_domain 回傳客戶必須建立的 DNS 記錄;verify_domain 觸發 DNS 檢查。set_theme_assignment 依 Keycloak 主題類型啟用自訂主題(空字串會重設為內建預設值)。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 Skills 擴充 提供:它在 capabilities 中宣告 io.modelcontextprotocol/skills,回應 skills/list 和 skills/get,並將每個 SKILL.md 作為一般資源提供於 skill://<name>/SKILL.md,其清單條目帶有 sha256 摘要。OpenAI 的外掛目錄正是以這種格式匯入技能。
| 技能 | 內容 |
|---|---|
auth-incident-triage | 分流「使用者無法登入」問題:使用事件、WAF 日誌與叢集健康狀態,區分平台故障、攻擊與設定變更。唯讀 |
enterprise-sso-rollout | 將企業 IdP 端到端接入領域:issuer 驗證、上游應用程式註冊、broker 設定、連線測試,以及對照真實登入事件進行驗證 |
keycloak-migration-doctor | 針對支援團隊實際會遇到的阻礙(script 政策、舊版 /auth 路徑、部分匯出預期)預檢 Keycloak 匯出、匯入或遷移,並透過閱讀真實的 error_message 而非一般儀表板通知來診斷失敗的工作 |
keycloak-upgrade-readiness | 評估版本漂移、釐清新版 Keycloak 會破壞什麼(擴充、主題),並以匯出檔作為復原計畫,依序安排跨環境的部署 |
技能的控管方式與它們所指名的工具相同:三個圍繞寫入工具建構的工作流程不會提供給唯讀工作階段,而受限工作階段只會獲得其實際擁有工具的技能。原始碼位於 internal/tools/skills/,每個技能一個目錄,採用標準 Agent Skills 格式,因此直接複製到本機 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 登入,或使用具寫入權限的金鑰)。
在託管的 HTTP URL 中加入 ?readonly=true,可僅為該 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 和 scheme,因此位於 ingress 後方的單主機部署無需額外設定。scheme 在存在 X-Forwarded-Proto 時取自該變數,否則對非 loopback 主機預設為 https,因為 TLS 在上游終止,發布 http:// 識別碼將無法與用戶端連線的 URL 相符。若您的 ingress 改寫 Host,請設定 SKYCLOAK_PUBLIC_URL。該文件也將 openid profile email 列為其 scopes_supported,而 WWW-Authenticate 挑戰會將它們重複為 scope 參數,因此讀取任一方的用戶端都會向 realm 請求它們:openid 為必填,因為 token 交換會使 dashboard 呼叫 Keycloak 的 userinfo 端點,而 Keycloak 會拒絕未經其授權的 token。缺少該授權的 token 會在驗證時以 401 和挑戰被拒絕,而不是被帶入無法成功的交換中,因此仍持有先前授權的用戶端會停止重試並重新登入。將 issuer 或 dashboard 變數任一設為空白會完全關閉 OAuth,伺服器將恢復僅要求 API 金鑰,不再要求其他內容。
OPENAI_APPS_CHALLENGE_TOKEN 在 /.well-known/openai-apps-challenge 提供 OpenAI 外掛目錄的網域驗證 token,僅以純文字形式提供,不含其他內容。若未設定,該路由不會註冊,路徑將回傳 404。
啟動時會記錄一行,顯示其解析出的設定(oauth=、issuer=、dashboard=、public_url=、endpoint=、allow_writes=),因此無需重新部署即可發現設定錯誤的部署。每個在 OAuth 路徑上被拒絕的請求都會記錄一行,標明失敗的階段(verify、exchange 或 scopes)、呼叫端收到的狀態碼,以及底層錯誤。驗證失敗會加上拒絕該 token 的檢查項目(expired、wrong_issuer、bad_signature、unknown_key_id、wrong_token_type、no_openid_scope 等);交換失敗則會加上 dashboard 的狀態和所呼叫的主機。呼叫端在 token 驗證通過後以 token 的 subject 身分出現,絕不會以憑證身分出現:存取 token、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 傳輸驗證 token 所依據的授權伺服器) |
SKYCLOAK_CLIENT_ID | skycloak-mcp(僅 CLI 裝置流程) |
SKYCLOAK_DASHBOARD_URL | https://app.skycloak.io(鑄造 CLI 金鑰和 HTTP 工作階段金鑰) |
SKYCLOAK_PUBLIC_URL | 無(從每個請求推導;當 ingress 改寫 Host 時設定) |
OPENAI_APPS_CHALLENGE_TOKEN | 在 /.well-known/openai-apps-challenge 提供 OpenAI 外掛目錄的驗證 token。未設定時,該路徑回傳 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 用戶端是使用 oapi-codegen 從 Skycloak OpenAPI 規格產生的。
與 API 保持同步
位於 internal/apiclient 的用戶端是使用 oapi-codegen 從 internal/apiclient/openapi.yaml 產生的;執行 make generate 即可重新整理。若提交的生成程式碼與規格有差異,CI 將失敗。請求會在 429/5xx 時重試,並採用具 Retry-After 感知的退避策略。
發布
以 GitHub 二進位檔和每個 tag 上的 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。