The Keycloak MCP Server uses smart port assignment that automatically adapts to your deployment mode:
0 (random)8080 (fixed)Benefits:
How it works:
When you set quarkus.http.port=0, the operating system automatically assigns an available port.
Benefits:
-p 8080:8080)# SSE Server Configuration
# Port 0 = random port (avoids conflicts in local dev)
# Overridden to 8080 in containers via QUARKUS_HTTP_PORT env var
quarkus.http.port=0
quarkus.http.host=0.0.0.0
# Container configuration (Jib)
quarkus.jib.ports=8080
quarkus.jib.environment-variables.QUARKUS_HTTP_PORT=8080
# Build
mvn clean package
# Run with random port
java -jar target/quarkus-app/quarkus-run.jar
# Output shows assigned port:
# __ ____ __ _____ ___ __ ____ ______
# --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
# -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
# --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
# Listening on: http://0.0.0.0:54321 ← Random port assigned
Finding the assigned port:
# From logs
grep "Listening on:" server.log
# Or use lsof
lsof -i -P | grep java
If you need a specific port for local development:
# Option 1: System property
java -Dquarkus.http.port=8080 -jar target/quarkus-app/quarkus-run.jar
# Option 2: Environment variable
export QUARKUS_HTTP_PORT=8080
java -jar target/quarkus-app/quarkus-run.jar
# Option 3: Command line for Quarkus dev mode
mvn quarkus:dev -Dquarkus.http.port=8080
# Build native
mvn clean package -Pnative
# Run with random port
./target/keycloak-mcp-server-0.3.0-runner
# Override port
QUARKUS_HTTP_PORT=8080 ./target/keycloak-mcp-server-0.3.0-runner
The container automatically uses port 8080 via environment variable:
# Run container (port 8080 is automatic)
docker run -d \
-p 8080:8080 \
-e KC_URL=http://host.docker.internal:8180 \
-e KC_USER=admin \
-e KC_PASSWORD=admin \
quay.io/sshaaf/keycloak-mcp-server:latest
# Access SSE endpoint
curl http://localhost:8080/mcp/sse
You can override the container port if needed:
# Use different port in container
docker run -d \
-p 9090:9090 \
-e QUARKUS_HTTP_PORT=9090 \
-e KC_URL=http://host.docker.internal:8180 \
-e KC_USER=admin \
-e KC_PASSWORD=admin \
quay.io/sshaaf/keycloak-mcp-server:latest
# Access on custom port
curl http://localhost:9090/mcp/sse
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak-mcp-server
spec:
replicas: 1
selector:
matchLabels:
app: keycloak-mcp-server
template:
metadata:
labels:
app: keycloak-mcp-server
spec:
containers:
- name: server
image: quay.io/sshaaf/keycloak-mcp-server:latest
ports:
- containerPort: 8080
name: http
env:
- name: KC_URL
value: "http://keycloak:8080"
- name: KC_USER
value: "admin"
- name: KC_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-admin
key: password
---
apiVersion: v1
kind: Service
metadata:
name: keycloak-mcp-server
spec:
selector:
app: keycloak-mcp-server
ports:
- name: http
port: 80
targetPort: 8080
type: LoadBalancer
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak-mcp-server
spec:
template:
spec:
containers:
- name: server
image: quay.io/sshaaf/keycloak-mcp-server:latest
ports:
- containerPort: 9090
name: http
env:
- name: QUARKUS_HTTP_PORT
value: "9090"
- name: KC_URL
value: "http://keycloak:8080"
# Just run - port assigned automatically
java -jar target/quarkus-app/quarkus-run.jar
# Check logs for actual port
# Listening on: http://0.0.0.0:54321
# Terminal 1 - First instance
java -jar target/quarkus-app/quarkus-run.jar
# Listening on: http://0.0.0.0:54321
# Terminal 2 - Second instance (different port automatically)
java -jar target/quarkus-app/quarkus-run.jar
# Listening on: http://0.0.0.0:54322
# Terminal 3 - Third instance
java -jar target/quarkus-app/quarkus-run.jar
# Listening on: http://0.0.0.0:54323
No port conflicts! Each instance gets its own port automatically.
# In CI pipeline - no need to manage ports
for i in {1..10}; do
java -jar target/quarkus-app/quarkus-run.jar &
done
# All 10 instances run simultaneously without conflicts
Solution: Check the startup logs:
# Run and capture logs
java -jar target/quarkus-app/quarkus-run.jar 2>&1 | tee server.log
# Or grep for the port
java -jar target/quarkus-app/quarkus-run.jar 2>&1 | grep "Listening on"
Solution: Override with environment variable:
# Add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
export QUARKUS_HTTP_PORT=8080
# Or create a .env file
echo "QUARKUS_HTTP_PORT=8080" > .env
source .env
java -jar target/quarkus-app/quarkus-run.jar
Check:
docker ps shows 0.0.0.0:8080->8080/tcpdocker logs <container-id>docker exec <container-id> env | grep QUARKUS_HTTP_PORTSolution:
# Ensure port mapping is correct
docker run -p 8080:8080 quay.io/sshaaf/keycloak-mcp-server:latest
# Verify container is listening
docker exec <container-id> netstat -tlnp | grep 8080
Solution:
# Find what is using the port
lsof -i :8080
# Use a different port
QUARKUS_HTTP_PORT=9090 java -jar target/quarkus-app/quarkus-run.jar
# Or use port 0 (default - random port)
unset QUARKUS_HTTP_PORT
java -jar target/quarkus-app/quarkus-run.jar
If you need to programmatically discover the assigned port:
import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.event.Observes;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import io.quarkus.logging.Log;
public class PortDiscovery {
@ConfigProperty(name = "quarkus.http.port")
int httpPort;
void onStart(@Observes StartupEvent ev) {
Log.info("Server started on port: " + httpPort);
}
}
#!/bin/bash
# Start server in background
java -jar target/quarkus-app/quarkus-run.jar > server.log 2>&1 &
PID=$!
# Wait for startup
sleep 5
# Extract port from logs
PORT=$(grep "Listening on:" server.log | grep -oP 'http://[^:]+:\K\d+')
echo "Server running on port: $PORT"
echo "SSE endpoint: http://localhost:$PORT/mcp/sse"
# Use the port
curl "http://localhost:$PORT/mcp/sse"
| Scenario | Configuration | Port |
|---|---|---|
| Local JAR/Native | Default | Random (0) |
| Local with override | QUARKUS_HTTP_PORT=8080 |
8080 |
| Container (default) | Automatic via Jib | 8080 |
| Container (custom) | -e QUARKUS_HTTP_PORT=9090 |
9090 |
| Kubernetes/OpenShift | Default | 8080 |
| Multiple local instances | Default | Random (each different) |
No Port Conflicts: Random ports eliminate conflicts in local development Parallel Testing: Run multiple instances simultaneously Container-Friendly: Fixed port 8080 for predictable networking Flexible: Easy to override when needed CI/CD Ready: No port management in automated pipelines Production Ready: Fixed ports for containers and cloud deployments
Default Behavior:
0 (random) - perfect for development8080 (fixed) - perfect for deploymentThe best of both worlds!