donvini94/intern-trial-day-assignment-mcp
If you are the rightful owner of intern-trial-day-assignment-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
This project is a reference implementation for a student internship trial task, demonstrating how to build an MCP server that integrates with Keycloak's Admin REST API.
Keycloak MCP Server - Student Internship Reference
This project is a reference implementation for a student internship trial task. It demonstrates how to build an MCP (Model Context Protocol) server that integrates with Keycloak's Admin REST API.
Learning Objectives
By studying this codebase, students will learn:
- API Integration: How to work with OAuth2/OIDC authentication
- MCP Server Development: Building tools that AI assistants can use
- Python Best Practices: Type hints, error handling, documentation, and project structure
- Security: Proper handling of credentials and tokens
- Testing: Writing tests for API clients
Project Structure
.
README.md # This file
pyproject.toml # Project configuration and dependencies
.env.example # Template for environment variables
.env # Your actual credentials (never commit!)
test_keycloak_connectivity.py # Exploration script showing API discovery
exceptions.py # Custom exception classes
types.py # Type definitions for API responses
client.py # Keycloak API client implementation
client_expectation.py # Keycloak API client implementation that I expected you to produce today
server.py # MCP server implementation
server_expectation.py # MCP server implementation that I expected you to produce today
tests/ # Test files (to be created)
test_client.py
Requirements
- Python 3.13 or higher
- A running Keycloak instance (local or remote)
- A Keycloak client with appropriate permissions
Setup Instructions
1. Install Dependencies
This project uses uv for dependency management:
# Install runtime dependencies
uv pip install -e .
# Or install with development dependencies (recommended)
uv pip install -e ".[dev]"
2. Configure Keycloak Access
Create a .env file in the project root (use .env.example as a template):
KEYCLOAK_URL=http://localhost:8080
CLIENT_ID=admin-cli
CLIENT_SECRET=your-secret-here
Important: Never commit the .env file! It's already in .gitignore.
How to Get Keycloak Credentials
- Log in to your Keycloak Admin Console
- Select the realm you want to work with (usually "master")
- Go to "Clients" in the left menu
- Create a new client or use an existing one (e.g., "admin-cli")
- Under "Credentials" tab, copy the client secret
- Ensure the client has "Service Account Enabled" turned on
- Under "Service Account Roles", assign appropriate admin roles
3. Test Connectivity
Before running the full MCP server, verify your Keycloak connection works:
python test_keycloak_connectivity.py
This script demonstrates:
- How to discover OIDC endpoints
- How to authenticate using client credentials
- How to make authenticated API requests
Expected output:
[{'id': 'master', 'realm': 'master', ...}, ...]
Found 2 realms
Running the MCP Server
Start the server
# Using the defined entry point
uv run keycloak-mcp
# Or directly with Python
python server.py
The server runs in stdio mode, which means it communicates via standard input/output. This is the standard MCP transport mechanism.
Using with an MCP Client
To use this server with an MCP-compatible client (like Claude Desktop), add it to your MCP configuration:
{
"mcpServers": {
"keycloak": {
"command": "uv",
"args": ["run", "keycloak-mcp"],
"env": {
"KEYCLOAK_URL": "http://localhost:8080",
"CLIENT_ID": "admin-cli",
"CLIENT_SECRET": "your-secret-here"
}
}
}
}
Available MCP Tools
1. get_realms()
Get a list of all realms in the Keycloak server.
Example:
realms = get_realms()
# Returns: [{'id': 'master', 'realm': 'master', ...}, ...]
2. get_users(realm, max_users=100)
Get users from a specific realm.
Parameters:
realm(str): The realm name (e.g., "master")max_users(int): Maximum number of users to return (default: 100)
Example:
users = get_users("master", 50)
# Returns: [{'id': '...', 'username': 'john.doe', ...}, ...]
3. get_user_info(realm, user_id)
Get detailed information about a specific user.
Parameters:
realm(str): The realm nameuser_id(str): The user's UUID (not the username!)
Example:
user = get_user_info("master", "8a9b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d")
# Returns: {'id': '...', 'username': 'john.doe', 'email': '...', ...}
Code Architecture
test_keycloak_connectivity.py
This file is intentionally written in a REPL-style to show the thought process of exploring an unknown API. It demonstrates:
- Using
.well-known/openid-configurationto discover endpoints - Implementing OAuth2 client credentials flow
- Making authenticated API requests
Note: This file doesn't include error handling by design - it's meant for exploration and learning.
exceptions.py
Defines custom exception classes:
KeycloakError: Base exception for all Keycloak errorsKeycloakAuthError: Authentication failuresKeycloakAPIError: API request failuresKeycloakConfigError: Configuration errors
Why custom exceptions? They make error handling more specific and provide better debugging information.
keycloak_models.py
Contains Pydantic Models for API responses:
RealmRepresentation: Structure of a realm objectUserRepresentation: Structure of a user objectTokenResponse: Structure of an OAuth2 token response
Why Pydantic? Provides type hints and validation for API responses, improving IDE autocomplete and type checking.
client.py
The core API client implementation. Key features:
- Input validation: Fails fast with clear errors
- Token management: Automatically obtains and refreshes tokens
- Error handling: Converts HTTP errors to custom exceptions
- Retry logic: Automatically retries on token expiration
- Type hints: Full type annotations for better IDE support
server.py
The MCP server implementation. Key features:
- Environment validation: Checks config at startup
- Tool definitions: Exposes Keycloak operations as MCP tools
- Error propagation: Proper error messages for MCP clients
- Comprehensive documentation: Clear docstrings for all tools
Common Issues and Troubleshooting
"Missing required environment variables"
Problem: The .env file is missing or incomplete.
Solution: Create a .env file with all required variables (see .env.example).
"Authentication failed"
Problem: Invalid client credentials or Keycloak is unreachable.
Solutions:
- Verify
KEYCLOAK_URLis correct and Keycloak is running - Check that
CLIENT_IDandCLIENT_SECRETare correct - Ensure the client has "Service Account Enabled"
- Verify the client has necessary permissions
"Realm doesn't exist" (404 error)
Problem: Trying to access a non-existent realm.
Solution: Use get_realms() first to see available realms, then use the exact realm name.
Import errors for custom modules
Problem: Python can't find exceptions.py, types.py, or client.py.
Solution: Make sure you're running from the project root directory.
Extension Ideas for Students
Once you understand the basic implementation, try these challenges:
-
Add more tools:
- Get roles for a realm
- Create/update/delete users
- Manage realm settings
-
Improve error handling:
- Add retry logic with exponential backoff
- Better error messages with suggestions
-
Add caching:
- Cache realm list for X minutes
- Cache user lookups
-
Add async support:
- Convert the client to use
httpxinstead ofrequests - Make all methods async
- Convert the client to use
-
Add more tests:
- Unit tests for the client
- Integration tests with a test Keycloak instance
- Mock tests using
responseslibrary
Resources
- Keycloak Admin REST API Documentation
- OAuth2 Client Credentials Flow
- OpenID Connect Discovery
- FastMCP Documentation
- MCP Protocol Specification
License
This is educational material for student internship trials. Use freely for learning purposes.
Questions?
If you have questions about this implementation, consider:
- Reading the inline code comments
- Checking the Keycloak documentation
- Experimenting with
test_keycloak_connectivity.py - Running the code with debug logging enabled