keycloak-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| KEYCLOAK_URL | Yes | Base URL of the Keycloak server, e.g. https://keycloak.example.com | |
| KEYCLOAK_REALM | No | Realm name | master |
| KEYCLOAK_CLIENT_ID | Yes | Service Account client ID | |
| KEYCLOAK_SITES_INI | No | Path to INI file for IP-to-site labeling | |
| KEYCLOAK_CLIENT_SECRET | Yes | Client secret | |
| KEYCLOAK_DEFAULT_DATE_FROM_HOURS | No | Default look-back window for event tools when date_from is omitted | 24 |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| health_checkA | Report server version and KeyCloak backend connectivity / authentication. Call this at session start (or after a tool-call timeout) to confirm the MCP is up, see which version is running, and verify the KeyCloak Admin API is reachable and the service account can authenticate. Lightweight: it acquires an admin access token via the Client Credentials Grant (reusing the cached client) and does NOT enumerate users, events, or sessions. Always returns the same keys: |
| count_usersA | Get total user count in the realm. |
| search_usersA | Search users by username, email, first name, or last name. Args: query: Search string (partial match). max_results: Maximum results to return (default 20). |
| get_userA | Get detailed user information by exact username (email). Args: username: Exact username (e.g., user@example.com). |
| reset_passwordB | Reset a user's password. Args: username: Exact username (email). password: New password to set. temporary: If True, user must change password on next login. |
| reset_passwords_batchA | Reset passwords for multiple users from CSV text. Each line should be: username,password If password column is empty, a random 12-char password is generated and included in the response (the caller cannot recover it otherwise). Caller-supplied passwords are never echoed back. Args: csv_text: CSV text with username,password per line (header optional). temporary: If True, users must change password on next login. |
| get_user_sessionsC | Get active sessions for a user. Args: username: Exact username (email). |
| logout_userA | Force logout a user by removing all their active sessions. Args: username: Exact username (email). |
| get_user_credentialsA | List the credential types configured for one user (password, otp, webauthn, …). Use this to check a single user's MFA status: an Args: username: Exact username (email). |
| get_totp_usersA | Report how many users have TOTP (OTP) configured across the realm. Enumerates users and inspects each one's credentials for an Args: enabled_only: Only scan enabled users (default True). list_users: Include the list of usernames with TOTP (default True). max_users: Cap the number of users scanned (0 = all). When the cap is hit the percentage covers only the sample, not the realm. |
| get_brute_force_statusA | Check if a user is temporarily locked due to brute force detection. Args: username: Exact username (email). |
| list_user_groupsB | List groups a user belongs to. Args: username: Exact username (email). |
| list_users_by_groupB | List all users in a group. Args: group_name: Group name (partial match). max_results: Maximum results (default 100). |
| get_eventsB | Get KeyCloak events with optional filters. Args: event_type: Event type filter (e.g., LOGIN, LOGIN_ERROR, UPDATE_PASSWORD). username: Filter by exact username (email). Resolved to user ID internally. client_id: Filter by client ID (SP name). ip_address: Filter events by source IP (client-side filter). date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). max_results: Maximum results (default 50). |
| get_login_statsA | Get login success/failure statistics with full pagination. Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). Empty for all. |
| get_login_stats_by_hourA | Get login statistics broken down by hour (local time). Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). Empty for all. |
| get_login_failures_by_ipB | Get login failure statistics broken down by source IP. Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). Empty for all. top: Number of top IPs to show (default 20). |
| get_ip_activityA | Exhaustive investigation of all activity from one source IP address. Unlike Returns a fixed-shape dict (JSON), not formatted text — every key below is always present, even when zero events match. Returns: error: None on success. Set to a descriptive message if event_types resolved to no event types (e.g. empty or all-whitespace/commas); every other key is still present, with an empty/zero result in that case (no data was fetched). ip_address: Echoes the input. site: Site name from KEYCLOAK_SITES_INI, or null if unmatched or unconfigured (see sites_configured to tell those apart). sites_configured: True if KEYCLOAK_SITES_INI was loaded at all. date_from / date_to: The resolved date range actually scanned. event_types: The event types scanned (echoes the input, split). summary: total_events, login_success, login_failure, unique_users, unique_clients, first_seen/last_seen (ISO 8601, null if no match). login_success/login_failure classify EVERY scanned event type by whether its type ends in "_ERROR" (matching the users/clients breakdown below), not just literal LOGIN/LOGIN_ERROR — so widening event_types always keeps these numbers reconciled with the per-user/per-client totals. Always computed over the FULL matched set, unaffected by max_timeline truncation. users: Per-user breakdown (success/failure counts, distinct error codes), sorted by total activity descending. Note: successful LOGIN events often carry only a userId (UUID) while LOGIN_ERROR carries details.username — this tool keys on username-or-userId-or-"unknown", so the same human can legitimately appear under two different keys across success vs. failure events. clients: Per-client (SP) breakdown, same shape, sorted descending. timeline: Chronological event list, capped at max_timeline (most recent kept on overflow — see truncated). max_timeline<=0 returns an empty timeline. truncated: True if timeline was capped; summary/users/clients are never affected by this cap. Args: ip_address: Source IP to investigate. Compared against KeyCloak's recorded ipAddress field after normalizing both sides through Python's ipaddress module (so equivalent IPv6 notations like "::1" and "0:0:0:0:0:0:0:1" match); falls back to a raw string compare if either side doesn't parse as an IP. event_types: Comma-separated KeyCloak event types to scan (default "LOGIN,LOGIN_ERROR"). Widen with e.g. "LOGIN,LOGIN_ERROR,LOGOUT,UPDATE_PASSWORD,CLIENT_LOGIN,CLIENT_LOGIN_ERROR" for a broader sweep. Must resolve to at least one type. date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). Widening the window means fully paginating every event type over that window before filtering — expect it to be slower on large realms. date_to: End date (YYYY-MM-DD). Empty for open-ended. max_timeline: Cap on the number of most-recent timeline entries returned (default 200; <=0 means no timeline entries). Does not affect summary/users/clients. |
| get_login_stats_by_clientC | Get login statistics broken down by client (SP). Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). Empty for all. |
| detect_login_loopsA | Detect users with rapid repeated logins (possible redirect loops). Scans all LOGIN events and finds users who logged in more than Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). Empty for all. threshold: Minimum logins within the window to flag (default 10). window_seconds: Time window in seconds (default 60). top: Number of top users to show (default 20). Use 0 for all. |
| get_password_update_eventsA | Get password update events. Args: date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). max_results: Maximum results (default 100). |
| get_admin_eventsA | Get KeyCloak admin events (changes performed via the Admin REST API). Admin events record operations performed by service accounts or admin users
— e.g. custom user attribute updates ( Args: operation_types: Comma-separated list of CREATE, UPDATE, DELETE, ACTION. resource_types: Comma-separated list of USER, CLIENT, ROLE, GROUP, REALM_ROLE, etc. resource_path: Filter by resource path (e.g. "users/{userId}"). date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). max_results: Maximum results (default 50). max_repr: Max chars of the representation field. 0 = omit, -1 = full. |
| get_user_attribute_historyA | Get admin-side attribute change history for a single user. Queries admin events scoped to Args: username: Exact username (email). date_from: Start date (YYYY-MM-DD). Defaults to last 24h when omitted (KEYCLOAK_DEFAULT_DATE_FROM_HOURS). date_to: End date (YYYY-MM-DD). max_results: Maximum results (default 100). max_repr: Max chars of the representation field. 0 = omit, -1 = full. |
| get_session_statsA | Get active session count per client. |
| get_client_sessionsA | Get active sessions for a specific client (SP). Args: client_id: Client ID (e.g., 'xflow', 'shadowserver'). max_results: Maximum results (default 100). |
| list_clientsA | List all SAML/OIDC clients in the realm. |
| get_realm_rolesA | List all realm-level roles. |
| get_realm_security_defensesA | Show the realm's security-defense settings (read-only). Reports the realm-level security configuration that the admin console groups under "Security defenses":
Use this to verify that brute-force protection is actually turned on and
how aggressively it locks accounts — the per-user |
| daily_briefA | Run a morning Keycloak health check. Checks (all scoped to the last
A single IP with login failures >=
Output tiers:
Args: since_hours: Look-back window in hours (default 18). ip_failure_threshold: Login failures from a single IP that triggers a WARNING (default 50). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/shigechika/keycloak-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server