KeyCloak MCP について
KeyCloak MCPは、MCPクライアントをKeyCloak Admin REST APIに接続し、ID管理とセキュリティ調査を行うサーバーです。ユーザー、セッション、イベント、クライアント、Realm設定を扱い、人のログインではなくサービスアカウントで認証します。
主な機能
- 01ユーザーと認証情報の検索・確認
- 02パスワードのリセットとユーザー状態の管理
- 03ログインイベント、失敗、IP活動の調査
- 04グループ、クライアント、アクティブセッションの確認
- 05セキュリティと設定変更の要約
活用シーン
- 01パスワードスプレーとログイン失敗の調査
- 02Realm設定と管理者による変更の確認
- 03グループメンバーとユーザーセッションの確認
MCP 対応
Admin REST API経由で、KeyCloakの管理・セキュリティツールをMCPクライアントに提供します。サービスアカウントでClient Credentials Grant認証を行い、ユーザーセッションは作成しません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
33掲載時のツール一覧 · 1 週間前に更新
このツールにパラメーターはありません。
詳細
keycloak-mcp
English | 日本語
KeyCloak Admin REST API 用の MCP(Model Context Protocol)サーバーです。
ドキュメント:https://shigechika.github.io/keycloak-mcp/
サービスアカウント(Client Credentials Grant)で認証するため、人間のパスワードや TOTP は関与しません。また、Infinispan に安全です。ユーザーセッションを作成せず、userinfo エンドポイントにもアクセスしません。
機能
ユーザー
| ツール | 説明 |
|---|---|
count_users | レルム内のユーザー総数 |
search_users | 部分一致検索(ユーザー名/メールアドレス/氏名) |
get_user | 完全一致するユーザー名の詳細情報 |
reset_password | 1 人のユーザーのパスワードをリセット |
reset_passwords_batch | CSV から一括リセット(1 行につき username,password。パスワードが空欄の場合は生成) |
get_user_sessions | 1 人のユーザーのアクティブなセッション。タイムスタンプは現地時間 |
logout_user | 1 人のユーザーのアクティブなセッションをすべて終了 |
set_user_enabled | 1 人のユーザーを有効または無効にする。無効にするとすべてのログインがブロックされます(カスタム属性は保持) |
MFA/認証情報
| ツール | 説明 |
|---|---|
get_user_credentials | 1 人のユーザーに設定された認証情報の種類。otp エントリがある場合、TOTP/HOTP が設定されています |
get_totp_users | レルム全体の TOTP 導入状況:otp 認証情報を持つユーザー数と割合、および(任意で)ユーザー一覧。ユーザーを列挙して各ユーザーの認証情報を読み取ります(N+1。max_users で上限を設定) |
グループ
| ツール | 説明 |
|---|---|
list_user_groups | ユーザーが所属するグループ |
list_users_by_group | グループのメンバー |
セキュリティ
| ツール | 説明 |
|---|---|
get_brute_force_status | ユーザーが現在、ブルートフォース検知によってロックされているかどうか |
get_realm_security_defenses | レルムレベルのセキュリティポリシー:ブルートフォース検知の有効/無効としきい値、パスワードポリシー、ブラウザーのセキュリティヘッダー |
get_config_changes | 保存済みの日次スナップショット以降にレルム設定で変更された内容(Configuration snapshots を参照)。読み取り専用です。baseline_date で古いスナップショットを指定します。 |
get_login_failures_by_ip | 送信元 IP ごとの失敗内訳(KEYCLOAK_SITES_INI が設定されている場合はサイト名を表示) |
get_ip_activity | 1 つの送信元 IP を徹底的に調査:成功/失敗件数、影響を受けたユーザー/クライアント、タイムライン。構造化 JSON を返します。 |
spray_check | 漏えい候補一覧を組み込んだパスワードスプレー検知:異なるユーザーが 10 人以上でログイン成功率が 20%未満の外部 IP をすべてスプレー元とし、そのログイン成功(証拠タプル time / ip / username / user_id / client_id)を漏えい候補とします。各行には confidence が含まれます。high は漏えいの判定です。low は、共有の出口(学校の NAT、自宅回線、VDI)で件数ルールに該当したことを意味します。これは user_success_rate(ログインした異なるユーザー数 ÷ 異なるユーザー数、0.2 以上)、failure_concentration(単一のユーザー名に集中した失敗の割合、0.5 以上)、または KEYCLOAK_KNOWN_EGRESS との一致で示されます。この場合、ログインは公開せず、所有者に確認してください。top_failed_users と not_found_domains には、失敗が続いたユーザーと、user_not_found を引き起こした入力ミスのあるドメインが表示されます。JSON の形は固定で、対象期間が途中で切り詰められた場合は complete: false になります。 |
detect_login_loops | 短時間にログインを繰り返しすぎたユーザー(リダイレクトループ)を検出 |
イベント
| ツール | 説明 |
|---|---|
get_events | 種類、ユーザー名、クライアント、IP、期間で絞り込みます。ユーザー名は内部でユーザー ID に解決されます。失敗イベントには KeyCloak の error フィールド(例:invalid_user_credentials)が含まれます。 |
get_login_stats | ログイン成功/失敗の合計。全結果をページ分割して取得 |
get_login_stats_by_hour | 時刻別のログイン数(現地時間) |
get_login_stats_by_client | クライアント/SP 別のログイン数 |
get_password_update_events | UPDATE_PASSWORD の履歴 |
管理イベント
get_eventsで確認できるのはユーザーイベントのみです。管理者が実行したアクションや、サービスアカウントがカスタム属性を書き込んだ場合、そのイベントは表示されません。管理イベントエンドポイントがこのギャップを埋めます。
| ツール | 説明 |
|---|---|
get_admin_events | 操作(CREATE / UPDATE / DELETE / ACTION)、リソースタイプ(USER / CLIENT / ROLE / GROUP / …)、リソースパス、日付範囲で絞り込みます |
get_user_attribute_history | 1人のユーザーに絞り込んだUPDATE/ACTIONイベントです。自動化パイプラインによってカスタム属性(例:provisioning_flag)がいつ書き込まれたかを追跡するのに便利です |
どちらのツールも、表現ペイロードを制御するmax_reprを受け付けます。正の値はN文字に切り詰め(デフォルトは500)、0は省略、負の値は全体を含めます。
セッションとクライアント
| ツール | 説明 |
|---|---|
get_session_stats | クライアントごとのアクティブセッション数 |
get_client_sessions | 1つのクライアント(SP)のアクティブセッション |
list_clients | レルム内のSAMLおよびOIDCクライアント |
get_client | 1つのクライアントの設定(認証フローのオーバーライド(SPごとのMFA切り替え)を含む)。attributesとprotocolMappersは省略されるため、クライアントシークレットやSAML署名情報がツール出力に含まれることはありません。 |
get_realm_roles | レルムレベルのロール |
朝の巡回
| ツール | 説明 |
|---|---|
health_check | 実行中のサーバーバージョンを報告し、KeyCloakバックエンドに到達できること、およびサービスアカウントが認証できることを確認します。軽量です(トークンリクエスト1回のみ。ユーザー/イベント/セッションのスキャンは行いません)。status、auth、設定済みのURL/レルムを含む、固定形式の辞書を返します。これらのフィールドで取り得る値を列挙しているのは、このツール自身の説明のみです。 |
daily_brief | 朝のワンショットヘルスチェックです。ログイン統計、ブルートフォース攻撃のIP、スプレーチェック(spray_checkと同じルールで、侵害されたアカウントと証拠を含む)、アクティブセッション、パスワード更新、管理イベント、設定変更(ロール、ロールマッピング、フロー、クライアントスコープ、プロトコルマッパー、コンポーネント、レルムに関する管理イベント、およびKEYCLOAK_STATE_DIRが設定されている場合のスナップショット比較。どちらも[CONFIG]と表示されます)、さらにロールを持つグループへのメンバー追加(グループが読み取り専用のquery-*/view-*以外のrealm-managementロールを付与する場合は[PRIVILEGE]と表示されます)を、1つのMarkdownサマリーにまとめます。ip_failure_thresholdの失敗回数を超えるIP(デフォルトは50)とスプレーの送信元はWARNINGとして表示されます。APIエラーはCRITICALとして表示されます。since_hoursで遡る時間枠を制御します(デフォルトは18時間)。 |
セットアップ
# uv
uv pip install keycloak-mcp
# pip
pip install keycloak-mcp
ソースから:
git clone https://github.com/shigechika/keycloak-mcp.git
cd keycloak-mcp
# uv
uv sync
# pip
pip install -e .
設定
| 変数 | 説明 | デフォルト |
|---|---|---|
KEYCLOAK_URL | ベース URL。例:https://keycloak.example.com | 必須 |
KEYCLOAK_REALM | レルム名 | master |
KEYCLOAK_CLIENT_ID | サービスアカウントのクライアント ID | 必須 |
KEYCLOAK_CLIENT_SECRET | クライアントシークレット | 必須 |
KEYCLOAK_SITES_INI | IP をサイト名に対応付ける INI ファイル(以下を参照) | 未設定 |
KEYCLOAK_KNOWN_EGRESS | 共有エグレスポイント(VDI、VPN コンセントレーター、パートナープロキシなど)の CIDR をカンマ区切りで指定します。spray_check は一致する IP に known_egress: true のラベルを付け、confidence: low としてマークします。これらが除外されることはありません。 | 未設定 |
KEYCLOAK_DEFAULT_DATE_FROM_HOURS | date_from を省略した場合にイベントツールが使用するデフォルトの遡及期間です。0 に設定すると全履歴をスキャンします(大規模なレルムではハングする可能性があります)。 | 24 |
KEYCLOAK_DEADLINE | 高負荷のイベント/TOTP ツールの呼び出しごとの実時間予算(秒)です。広い期間や大規模なレルムで予算を超える場合、ツールはクライアントの約 60 秒のゲートウェイタイムアウトを超えて KeyCloak に過剰な負荷をかけるのではなく、一部結果であることを明示して(⚠️ 警告)処理を停止し、結果を返します。各リクエストのタイムアウトも残り時間以内に制限され、期限を過ぎて再試行することはないため、遅いページが 1 つあっても呼び出しが期限を超えることはありません。0 以下の場合は無効になります。 | 45 |
KEYCLOAK_MAX_EVENTS | イベントツールが取得するイベントのページネーションごとの上限です(低速な高オフセットページネーションの深さも制限します)。上限を超える場合、結果は一部結果であることが明示されます。0 以下の場合は無効になります。 | 200000 |
KEYCLOAK_MAX_USERS | max_users 引数が 0 の場合に get_totp_users がスキャンするユーザーのデフォルト上限です(ユーザーごとに認証情報の呼び出しが 1 回必要です)。0 以下の場合は無効になります(レルム全体が対象となり、KEYCLOAK_DEADLINE のみで制限されます)。 | 5000 |
KEYCLOAK_USER_ATTRIBUTE_WHITELIST | get_user が表示できるカスタムユーザー属性キーをカンマ区切りで指定します。デフォルトでは未設定です。ユーザー名の解決に使用する検索エンドポイントは属性を含まない簡易表現を返すため、get_user が返すのはユーザー名/名前/メールアドレス/有効状態/作成日時のみです。キーを許可リストに追加すると、get_user は ID を指定した追加の検索を 1 回行い、その属性に値がある場合は追加します。それ以外の情報がツール出力に含まれることはありません。安全策として、許可リストにあるキー名が認証情報を示すように見える場合(password、secret、token などを含む場合)、値を表示せずブロックされたものとして報告します。ただし、こうしたパターンに該当しない名前の認証情報属性は表示されるため、完全な保証ではありません。 | 未設定 |
KEYCLOAK_GROUP_WRITE_ROOT | オプトイン方式のグループ変更ツール(plan_group_changes、apply_group_changes)を有効にし、指定した絶対パスの配下にあるグループに対象を限定します(例:/Staff)。未設定、空、または形式が不正な場合、2 つのツールは登録されません。サーバーの前に人間による承認手順を設けたデプロイ環境でのみ設定してください。 | 未設定 |
KEYCLOAK_PROTECTED_GROUPS | グループ変更ツールが追加または削除を拒否するグループの完全パスを ; 区切りで指定します(子孫グループも含みます)。形式が不正な項目がある場合、保護設定を黙って破棄するのではなく、グループ変更ツールを無効にします。 | 未設定 |
KEYCLOAK_GROUP_BATCH_MAX | グループ変更の呼び出しごとの最大行数です。 | 30 |
KEYCLOAK_GROUP_MODE | multi(KeyCloak のデフォルト。ユーザーは複数のグループに所属できます)または single(グループを追加すると他のすべての所属が置き換えられるデプロイ環境向け。たとえば、ユーザーごとに 1 つのグループだけを維持するイベントリスナーを使用する場合)を指定します。それ以外の値ではグループツールが無効になります。グループの変更を参照してください。 | multi |
KEYCLOAK_STATE_DIR | 日次設定スナップショットの保存先ディレクトリです(<dir>/config-snapshots。ディレクトリは 0700、ファイルは 0600 で作成されます)。未設定の場合、スナップショットは作成されません。daily_brief は引き続き設定管理者のイベントを報告します。設定スナップショットを参照してください。 | 未設定 |
KEYCLOAK_GROUP_DEADLINE | グループ変更ツールの時間予算(秒)です。ユーザー 30 人のバッチにはデフォルトの 45 秒より長い時間が必要です。サーバーの前に約 60 秒のタイムアウトが設定されたものがない環境(たとえば、クライアントがサーバーを直接起動する場合)では、値を増やしてください。未設定の場合は KEYCLOAK_DEADLINE が使用されます。 | 未設定 |
KEYCLOAK_SESSION_PROBES | get_user_sessions(および set_user_enabled の残りセッション数)がセッション一覧を統合する個別の接続数です。ロードバランサーの背後にあり、KeyCloak ノード間でユーザーセッションを共有していない場合(分散 Infinispan キャッシュがない場合)、各ノードが一覧表示するのは自身のセッションのみです。 | 8 |
KEYCLOAK_LOGOUT_CLEAN_PROBES | logout_user は、連続してこの回数のプローブでセッションが見つからなくなるまでプローブを続けます。各プローブは個別の接続でセッションを一覧表示し、到達したノードにセッションがあればそのノードでユーザーをログアウトさせます。最初のプローブはセッションが一覧にない場合でもログアウトを実行します。データベース内のユーザーの notBefore も設定され、すべてのノードで確認されるためです。ツールはこの処理についても報告します。新しい接続がどのノードに到達するかはロードバランサー次第です。送信元 IP によるアフィニティが設定されている場合、プローブが一部のノードに一度も到達しないことがあるため、すべてのノードで効果が維持されるのは notBefore の設定です。セッションが共有されている場合は、この値と KEYCLOAK_SESSION_PROBES を 1 に設定してください。 | 10 |
KEYCLOAK_LOGOUT_MAX_PROBES | logout_user のプローブ回数の上限です。上限に達してもセッションが見つかる場合、ツールは成功と報告せず、その旨を(⚠️)示します。プローブは、get_user_sessions と set_user_enabled のセッション一覧表示と同様に、KEYCLOAK_DEADLINE の制限を受けます。時間切れまたはリクエストの失敗時には、ツールは検証が不完全であること(⚠️)を示し、それまでに実行した内容を報告します。 | 40 |
KeyCloak クライアントの設定
- KeyCloak 管理コンソールで新しいクライアントを作成します。
- クライアント認証 と サービスアカウントのロール をオンにします。
view-users、view-events、view-clientsを付与します。パスワードのリセットが必要な場合に限り、manage-usersも付与します。
書き込み操作
デフォルトでは、4 つのツールが状態を変更します。それ以外のツールは読み取り専用です。グループ変更を有効にすると(以下を参照)、apply_group_changes が 5 つ目のツールになります。
| ツール | Admin API 呼び出し |
|---|---|
reset_password | PUT /users/{id}/reset-password |
reset_passwords_batch | 同じ呼び出しを CSV の各行に対して実行 |
set_user_enabled | enabled を切り替えて PUT /users/{id} |
logout_user | GET /users/{id}/sessions + POST /users/{id}/logout。新しい接続で繰り返します(KEYCLOAK_LOGOUT_CLEAN_PROBES を参照) |
4 つすべてに、サービスアカウントの manage-users が必要です。このロールを付与しなければ、サーバーは読み取り専用になります。この 4 つのツールは 403 で失敗し、ほかのすべてのツールは引き続き動作するため、変更権限を付与せずに、調査のために AI アシスタントにレルムを渡せます。アカウント復旧や封じ込めが必要な場合に限り、manage-users を付与してください。
グループ変更(オプトイン)
plan_group_changes と apply_group_changes は、ユーザーをグループ間で移動します(たとえば、スタッフの異動)。これらのツールは KEYCLOAK_GROUP_WRITE_ROOT が設定されている場合にのみ有効になるため、承認手順なしでバイナリを共有するデプロイでは、これらのツールが公開されることはありません。
| ツール | Admin API 呼び出し |
|---|---|
plan_group_changes | 読み取り専用:GET /users?username=...&exact=true、GET /group-by-path/...、GET /groups/{id}/role-mappings、GET /roles-by-id/{id}/composites、GET /clients/{id}、GET /users/{id}/groups |
apply_group_changes | PUT /users/{id}/groups/{groupId} の後に DELETE /users/{id}/groups/{groupId} |
plan_group_changesはすべてのユーザーとグループを完全一致する名前/パスで解決し、各行について現在の直接の所属グループ、実行される操作、ステータスを返します。そのdigestには、解決された ID、各ユーザーの現在の所属グループ、ポリシーが含まれます。apply_group_changesは再度プランを作成し、すべての行が引き続き実行可能で、digestが承認済みのものと一致しない限り、何も変更しません。そのため、プラン作成後に誰かがメンバーシップを変更すると、バッチ全体が中止されます。追加してから削除し、追加の直前に移動先を再検査し、書き込みの前にメンバーシップを再取得し、書き込み後に読み戻します。不一致、エラー、または時間予算の超過(KEYCLOAK_GROUP_DEADLINE)が発生した時点で停止します。残り時間内にすべての操作を完了できないユーザーの処理は開始しないため、追加と削除の間で停止することはありません。appliedの値はyes、no、partial、unknown(書き込みを読み戻せなかった場合)のいずれかです。KEYCLOAK_GROUP_MODE=singleの場合、移動は追加操作1回で行います。サーバーが古いグループを自動的に削除するため、DELETE は送信されず、読み戻し結果には移動先だけが含まれている必要があります。行には追加するグループを指定する必要があります(削除のみの行では、ユーザーの所属グループがなくなります)。removeが省略されている場合は、ユーザーの現在のグループが補完され、承認者は何が残るかを確認できます。そのグループはプラン作成時と追加の直前に、removeの場合と同様に検査されます。ユーザーが複数のグループに所属しているとサーバーのルールに反するため、処理は拒否されます(手動で修正してください)。以前の状態をプランで復元できないユーザー(グループに所属していなかった場合、またはサーバーが置き換えを行わなかった場合)は、reverseではなくmanual_restoreに記載されます。KeyCloak がこの動作をする場合は設定してください。multiモードでは、そのようなサーバーではすべての移動が同時変更として停止し、singleモードでは、古いグループを残すサーバーの場合、モードが一致しないというメッセージとともに移動が停止します。- 拒否される移動先:ルート外のグループ、ルート自体、保護されたグループとその子孫。
- ロールを持つグループは拒否されません。承認者が管理コンソールで同じ操作を実行できる場合、部署の管理者グループへの移動は通常の異動です。各プラン行には
gained_rolesとlost_rolesが記載されます。これは、すべてのグループメンバーシップを通じてユーザーが持つロールに対する、移動による差分です(共通の祖先または別のグループを通じて保持されるロールは、追加にも削除にも含まれません。ユーザーに直接割り当てられたロールは読み取られません)。add_rolesとremove_rolesは、それぞれ指定されたグループへの所属によって付与されるロールです。レルムロールは名前で、クライアントロールはclient:role形式で表示されます。祖先グループから継承されるロールと、複合ロールの内容(深さを問わず)も含まれます。承認者には追加・削除されるロールを提示してください。これらはdigestの一部であり、追加の前に移動先のロールを再度読み取ります(1回の呼び出しにつき、グループごとに最大5秒に1回)。そのため、承認後にロールが割り当てられた(または複合ロールに追加された)場合、処理は停止します。ロール変更を表示できない行(パスで解決できない現在のグループ。たとえば、名前に/が含まれるグループ)は拒否されます。 1.3.0 で変更:以前のバージョンでは、ロールマッピングを持つグループはすべて拒否されていました。この動作を前提としていた場合は、アップグレード前に該当するグループをKEYCLOAK_PROTECTED_GROUPSに登録してください。 - メンバーシップはロールがなくてもアクセスを付与する場合があります(サービスプロバイダーが確認する SAML/OIDC グループマッパー、認可サービスのグループポリシーなど)。ロールの有無にかかわらず、これらのツールで決して変更してはならないグループを
KEYCLOAK_PROTECTED_GROUPSに登録してください。保護されたパスはすべて KeyCloak に存在する必要があります。解決できないパスが1つでもある場合(名前変更、移動、大文字と小文字の違いなど)、設定が修正されるまで、すべてのプランが拒否されます。 digestは、プラン作成後に何も変更されていないことを示します。誰かがプランを承認したことを証明するものではありません。plan_group_changesを呼び出す任意の呼び出し元が、有効な digest を取得できます。たとえば、クライアント側で digest を保持し、呼び出しのたびに担当者に確認を求めるなど、apply_group_changesの前に承認の仕組みを設けてください。承認は1回限りとして扱ってください。たとえばreverseの実行後など、メンバーシップがプラン作成時の状態に戻ると、古い digest が再び一致します。- 結果には、適用された変更を取り消すための変更を示す
reverseが含まれます。これは新たなプランと承認のための提案であり、自動的には適用されません。メンバーシップを復元しても、誤った状態だった期間中に発生したアクセスは取り消されません。 書き込みにはmanage-usersが必要です。KeyCloak のバージョンによっては、グループとそのロールマッピングの読み取りにもquery-groupsが必要な場合があります。複合ロールを展開するにはレルムロールの読み取り(view-realm)が必要で、クライアントロールの名前を取得するにはクライアントの読み取り(view-clients)が必要です。確認のため、plan_group_changesを一度実行してください。
設定スナップショット(任意)
KEYCLOAK_STATE_DIR を設定すると、毎日の最初の daily_brief でレルム設定のスナップショットが保存され、各 daily_brief で現在の設定と前日以前の最新スナップショットが比較されます。変更があると、変更されたフィールドとともに [CONFIG] 警告が表示されます。get_config_changes では変更の一覧を取得できます。
- 対象:レルム設定(ブルートフォース検知、パスワードおよび OTP ポリシー、セッションとトークンの有効期間、フローバインディング)、イベント設定、レルムロールと各複合ロールの内容、認証フローとその実行、必須アクション、クライアント(リダイレクト URI、許可されたフロー、フローのオーバーライド、属性、プロトコルマッパー)、クライアントスコープ、デフォルトのクライアントスコープ、コンポーネント、およびサービスアカウントが読み取り可能な場合の ID プロバイダー。グループのロールマッピングとクライアントロールはスナップショットに含まれません。代わりに、管理イベントとして報告されます。
- グループメンバーシップは設定ではないため、スナップショットに含まれません。代わりに、概要では、振り返り期間内にロールを持つグループ(グループ自身または複合ロールを通じた祖先のロール)に追加されたユーザーと、そのユーザーを追加した人を、ロールとともに一覧表示します。グループが
realm-managementロールのうちquery-*/view-*以外(realm-admin、manage-usersなど)を付与する場合、その追加は[PRIVILEGE]になります。master レルムでは、<realm>-realm管理クライアントロールまたはadminレルムロールも対象です。グループは現在の ID で読み取られ、ロールはparentIdをたどって確認されるため、イベント発生後に名前が変更されたり移動されたりしても見落としません。グループを読み取れない場合、その追加は個別の[CONFIG]警告として報告されます。この確認に使える時間は、Configuration セクションの予算のうち最大 8 秒です。 - シークレットは保存されません。
secret、password、privateKey、apiKey、credential、tokenなどを含むキーの文字列値(get_userでも使われるマーカー)は<redacted>に置き換えられるため、シークレットの変更は変更として表示されません。このようなキーのtrue/falseと数値は設定値として表示されます。ただし、フィールド自体がシークレット(...password、...secret)の場合は除きます。これは一般的な名前に対する安全策であり、保証するものではありません。長い値(証明書や公開鍵など)はハッシュとして保存されます。 - 完全な読み取りができた場合に限り、保存されます。時間予算が切れた場合、概要には比較をスキップしたことが表示され、以前のベースラインが保持されます。
- スナップショットを書き込むのは
daily_briefのみで、1 日に最初の 1 回だけです。そのため、日中に行われた変更は翌朝に再度報告されます。直近の 30 件が保持されます。 - 設定の読み取りには
view-realmとview-clientsが必要です。ID プロバイダーの読み取りにはview-identity-providersも必要です。この権限がない場合、そのセクションは比較対象から除外され、その旨が概要に表示されます。
セットアップを確認する
環境変数を設定したら、MCP クライアントに接続する前に --check を実行し、認証が機能することを確認してください。
export KEYCLOAK_URL=https://keycloak.example.com
export KEYCLOAK_REALM=my-realm
export KEYCLOAK_CLIENT_ID=keycloak-mcp
export KEYCLOAK_CLIENT_SECRET=your-secret
keycloak-mcp --check
# HTTP Request: POST https://keycloak.example.com/realms/my-realm/protocol/openid-connect/token "HTTP/1.1 200 OK"
# OK: authenticated to https://keycloak.example.com/admin/realms/my-realm
終了コード:0 は成功、1 は設定エラー(変数が不足)、2 は認証エラーです。
IP アドレスのサイト名表示(任意)
ツールの出力に含まれる IP アドレスにサイト名を付けるには、KEYCLOAK_SITES_INI に INI ファイルを指定してください。get_user_sessions、get_events、get_login_failures_by_ip などのツールが自動的に読み込みます。定義した範囲外のアドレスには external と表示されます。変数を設定しない場合、IP アドレスはそのまま表示されます。
sites.ini.example を参照してください。最小限のファイルは次のとおりです。
[hq]
name = HQ (Tokyo)
ipv4 = 192.0.2.0/24, 198.51.100.0/24
ipv6 = 2001:db8:1::/48
[vpn]
name = VPN
ipv4 = 10.0.0.0/8, 172.16.0.0/12
[section] ごとに 1 つのサイトを指定します。name は表示名です(省略するとセクション名が使われます)。ipv4/ipv6 には、カンマ区切りで CIDR を指定します。単一のホストには /32 または /128 を指定します。照合はファイル内の順序で行われるため、範囲の広い指定よりも具体的な範囲を先に記述してください。
使い方
Claude Code(プラグイン)
このリポジトリは単一プラグインのマーケットプレイスも兼ねているため、Claude Code からサーバーをインストールできます。
/plugin marketplace add shigechika/keycloak-mcp
/plugin install keycloak-mcp@keycloak-mcp
プラグインは uvx keycloak-mcp を起動し、設定で説明されているものと同じ環境変数を読み込みます。Claude Code を起動する前に、それらをエクスポートしてください。KEYCLOAK_REALM の既定値は master で、KEYCLOAK_SITES_INI は未設定のままでもかまいません。
Claude Code を実行するプロセスの PATH に uvx が含まれている必要があります。通常、ログインシェルには含まれていますが、GUI から起動したアプリには含まれていない場合があります。プラグインが起動しない場合は、uvをシステム全体にインストールしてください。
Claude Code(手動)
.mcp.json に記述します。
{
"mcpServers": {
"keycloak-mcp": {
"type": "stdio",
"command": "keycloak-mcp",
"env": {
"KEYCLOAK_URL": "https://keycloak.example.com",
"KEYCLOAK_REALM": "my-realm",
"KEYCLOAK_CLIENT_ID": "keycloak-mcp",
"KEYCLOAK_CLIENT_SECRET": ""
}
}
}
}
Claude Desktop
claude_desktop_config.json に記述します。
{
"mcpServers": {
"keycloak-mcp": {
"command": "keycloak-mcp",
"env": {
"KEYCLOAK_URL": "https://keycloak.example.com",
"KEYCLOAK_REALM": "my-realm",
"KEYCLOAK_CLIENT_ID": "keycloak-mcp",
"KEYCLOAK_CLIENT_SECRET": ""
}
}
}
}
Codex
codex mcp add keycloak-mcp \
--env KEYCLOAK_URL=https://keycloak.example.com \
--env KEYCLOAK_REALM=my-realm \
--env KEYCLOAK_CLIENT_ID=keycloak-mcp \
--env KEYCLOAK_CLIENT_SECRET=your-secret \
-- keycloak-mcp
stdio サーバーを起動するその他の MCP クライアントも同様です。コマンドに keycloak-mcp を指定し、クライアントの環境に KEYCLOAK_* 変数を設定してください。
シェルから
export KEYCLOAK_URL=https://keycloak.example.com
export KEYCLOAK_REALM=my-realm
export KEYCLOAK_CLIENT_ID=keycloak-mcp
export KEYCLOAK_CLIENT_SECRET=your-secret
keycloak-mcp
CLI
keycloak-mcp --version # Print version and exit
keycloak-mcp --help # Show usage and required environment variables
keycloak-mcp --check # Verify env vars and authentication, then exit
keycloak-mcp # Run the MCP STDIO server (default)
引数なしモードが通常のモードです。MCP クライアントはこのモードで起動します。
日次スプレーレポート(バッチ)
spray_check は現在時刻を終点とするローリングウィンドウを調べます。巡回には適していますが、日ごとにアーカイブすることはできません。その場合は、スケジュールされたジョブから、同じ分析を暦日の 1 日分に対して実行してください。
keycloak-mcp spray-report --date 2026-09-17 --tz Asia/Tokyo > 2026-09-17.json
- ウィンドウは
--tz(既定値:ホストのタイムゾーン)における[DATE 00:00, DATE+1 00:00)です。dateFrom/dateToは KeyCloak サーバーのタイムゾーンで解釈されるため、サーバーのログに使用されているタイムゾーンを指定してください。イベントは両端のタイムスタンプに基づいてウィンドウ内に絞り込まれます。 - 1 つの JSON ドキュメントが標準出力に出力されます。エラーは標準エラー出力に出力され、終了コードはゼロ以外になります(2 = 設定、1 = 取得/認証)。その場合、標準出力には何も出力されません。
- 出力は
spray_checkの形式で、external_ipsには、ユーザー名を含むイベントが少なくとも 1 件あるすべての外部 IP が含まれます(min_report_users=1)。また、すべての外部 IP の LOGIN / LOGIN_ERROR を数えるexternal_totals(失敗イベントにユーザー名がなく、そのため行がない IP も含みます)、fetch_complete、resolve_complete、coverage(first_event、last_event、head_gap_seconds、tail_gap_seconds)、schema、keycloak_mcp_version、sites_ini_sha256も含まれます。*_completeの両方のフラグが true で、どちらのギャップも大きくない場合にのみ、その日を確定済みとして扱ってください。片端にギャップがある場合、通常は--tzが KeyCloak サーバーのタイムゾーンと異なっています。 KEYCLOAK_SITES_INIによって範囲が得られない場合(すべての IP が外部として数えられます)、--allow-no-sitesが指定されていない限り実行を拒否します。また、KEYCLOAK_KNOWN_EGRESSに CIDR ではないエントリがある場合も実行を拒否します。- このコマンド固有の上限が適用されます(
--deadline 900、--max-events 1000000、--max-resolves 2000)。HTTP ゲートウェイ経由のツール呼び出し向けに設定されたKEYCLOAK_DEADLINE/KEYCLOAK_MAX_EVENTSは適用されません。 - 出力には送信元 IP とユーザー名が含まれます。公開される場所には保存しないでください。
開発
git clone https://github.com/shigechika/keycloak-mcp.git
cd keycloak-mcp
# uv
uv sync --dev
uv run pytest -v
uv run ruff check .
# pip
python3 -m venv .venv
.venv/bin/pip install -e . && .venv/bin/pip install pytest pytest-cov respx ruff
.venv/bin/pytest -v
.venv/bin/ruff check .
ライブスモークテスト
pytest はフィクスチャに対してロジックをチェックしますが、ツールが実際のデータを返さなくなったことまでは検出できません。scripts/smoke_test.py は、設定されたレルムに対して登録済みのすべてのツールを実行し、空の応答、不正な形式の応答、エラー応答があれば失敗します。
# needs KEYCLOAK_URL / KEYCLOAK_CLIENT_ID / KEYCLOAK_CLIENT_SECRET
uv run python scripts/smoke_test.py
uv run python scripts/smoke_test.py --only login_stats --traceback
- 読み取り専用です。 状態を変更するすべてのツール(
reset_password、logout_user、set_user_enabled、reset_passwords_batch)は名前でスキップされ、テストでそれが保証されています。レポートにはツール名とステータスのみが出力され、ペイロードは出力されません。また、サーバーが生成したエラーテキストも伏せられます(KeyCloak は照会対象のユーザー名を引用するためです)。ただし、--tracebackを指定すると、オペレーター自身のターミナルには全文が表示されます。 - 実在するユーザー、グループ、IP を特定し得る引数は、実行時に検出されます。
scripts/smoke_probes.pyに書き込まれることはありません。 - CI では、手間のかからない部分を検証します。プローブ仕様のないツールが登録されるとビルドが失敗します(
tests/test_smoke_probes.py)。そのため、ツールを追加するたびに「どうすれば動作を確認できるか」という問いに向き合うことになります。 scripts/smoke_harness.pyはエンジンであり、KeyCloak 固有の知識は持ちません。これを共有するサーバー間で同一の状態に保っているため、エンジンのバグは一度修正し、このファイルを同期するだけで済みます。このコピーに個別のパッチを当てないでください。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。