ocp-mcp
# ocp-mcp
An MCP (Model Context Protocol) server for managing multiple OpenShift Container Platform (OCP) clusters through AI assistants like GitHub Copilot, Windsurf, or any MCP-compatible client.
## Features
- **Multi-cluster management** — register and switch between dev, UAT, and production clusters
- **Built-in org cluster map** — pre-configured aliases for standard environments
- **Dedicated OAuth support** — works with separate `oauth-openshift.*` hostnames
- **60+ tools** covering the full range of OpenShift/Kubernetes operations
- **Real-time metrics** — CPU/memory usage for pods and nodes (`top_pods`, `top_nodes`)
- **Observability** — PrometheusRules, ServiceMonitors, PodMonitors, AlertmanagerConfigs
- **OCP-native** — Routes, DeploymentConfigs, Builds, BuildConfigs, ImageStreams
- **Operational** — force-delete stuck pods, find failing pods, rollback deployments
- **Secure** — secrets are never returned in plain text; tokens are in-memory only
## Prerequisites
- Python 3.11+
- [uv](https://docs.astral.sh/uv/) package manager
- Access to one or more OpenShift 4.x clusters
## Installation
```bash
# Clone the repository
git clone <repo-url>
cd ocp-mcp
# Install dependencies
uv sync
```
### Corporate Artifactory Setup
If your organization requires downloading packages through Artifactory:
**Option 1: Environment variables**
```bash
export UV_INDEX_URL="https://<artifactory-host>/artifactory/api/pypi/<pypi-repo>/simple"
export UV_INDEX_USERNAME="<your-username>"
export UV_INDEX_PASSWORD="<your-password-or-token>"
uv sync
```
**Option 2: Project-level config** (add to `pyproject.toml`)
```toml
[[tool.uv.index]]
name = "artifactory"
url = "https://<artifactory-host>/artifactory/api/pypi/<pypi-repo>/simple"
default = true
```
Then run `uv sync` as normal.
## Running the MCP Server
```bash
uv run ocp-mcp
```
The server runs over **stdio** transport, which is what VS Code, Windsurf, and other MCP clients expect.
## Client Configuration
### VS Code (GitHub Copilot)
Add to your VS Code MCP settings (`.vscode/mcp.json` or user settings):
```json
{
"mcpServers": {
"ocp-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/ocp-mcp", "ocp-mcp"]
}
}
}
```
### Windsurf
Add to your Windsurf MCP configuration:
```json
{
"mcpServers": {
"ocp-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/ocp-mcp", "ocp-mcp"]
}
}
}
```
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"ocp-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/ocp-mcp", "ocp-mcp"]
}
}
}
```
> Replace `/path/to/ocp-mcp` with the absolute path to this repository.
## Built-in Cluster Map
The server ships with pre-configured aliases for standard org environments:
| Alias | API URL | OAuth URL |
|-----------|------------------------------------------|--------------------------------------------------|
| `dev` | `https://api.ocp.dev.com:6443` | `https://oauth-openshift.ocp.dev.com:6443` |
| `uat-g1` | `https://api.ocp-uat-g1.com:6443` | `https://oauth-openshift.ocp-uat-g1.com:6443` |
| `uat-g2` | `https://api.ocp-uat-g2.com:6443` | `https://oauth-openshift.ocp-uat-g2.com:6443` |
| `prod-g1` | `https://api.ocp-prod-g1.com:6443` | `https://oauth-openshift.ocp-prod-g1.com:6443` |
| `prod-g2` | `https://api.ocp-prod-g2.com:6443` | `https://oauth-openshift.ocp-prod-g2.com:6443` |
## Quick Start
Once the MCP server is connected to your AI client, use these commands in chat:
### Register all standard clusters at once
```
register_standard_clusters(username="your-user", password="your-pass", set_default_alias="dev")
```
### Register with per-environment credentials
```
register_standard_clusters(
username="shared-user",
password="shared-pass",
credentials_by_alias={
"prod-g1": {"username": "prod-admin", "password": "prod-pass"},
"prod-g2": {"username": "prod-admin", "password": "prod-pass"}
},
set_default_alias="dev"
)
```
### Register a single custom cluster
```
register_cluster(
alias="custom",
api_url="https://api.my-cluster.com:6443",
oauth_url="https://oauth-openshift.my-cluster.com:6443",
username="admin",
password="secret"
)
```
### Switch default cluster
```
set_default_cluster(alias="uat-g1")
```
### Target a specific cluster (any tool)
```
list_pods(namespace="my-app", cluster_alias="prod-g1")
```
## Available Tools
### Cluster Management
| Tool | Description |
|------|-------------|
| `register_cluster` | Register an OpenShift cluster with credentials and optional OAuth URL |
| `register_standard_clusters` | Register all built-in org clusters in one call |
| `list_clusters` | List all registered clusters |
| `list_standard_clusters` | List built-in cluster aliases and URLs |
| `set_default_cluster` | Set the default cluster for subsequent commands |
| `remove_cluster` | Remove a registered cluster |
| `refresh_cluster_token` | Re-authenticate and refresh an expired OAuth token |
### Namespaces / Projects
| Tool | Description |
|------|-------------|
| `list_namespaces` | List all namespaces (projects) in a cluster |
### Pods
| Tool | Description |
|------|-------------|
| `list_pods` | List all Pods in a namespace |
| `get_pod` | Get detailed Pod info (status, containers, IPs, resource requests/limits) |
| `get_pod_logs` | Get logs from a Pod (container, tail lines, since_seconds, timestamps, previous) |
| `get_all_container_logs` | Get logs from ALL containers in a multi-container Pod |
| `get_previous_pod_logs` | Get logs from the previous crashed/terminated instance |
| `get_pod_events` | Get events for a specific Pod |
### Pod Operations
| Tool | Description |
|------|-------------|
| `list_terminating_pods` | List pods stuck in Terminating state |
| `force_delete_pod` | Force-delete a single stuck Terminating pod (grace_period=0) |
| `force_delete_all_terminating_pods` | Force-delete ALL stuck Terminating pods in a namespace |
| `list_failing_pods` | Find pods in CrashLoopBackOff, ImagePullBackOff, OOMKilled, etc. |
| `list_pods_not_ready` | List pods where at least one container is not ready |
### Deployments
| Tool | Description |
|------|-------------|
| `list_deployments` | List all Deployments in a namespace |
| `get_deployment` | Get detailed Deployment info (strategy, containers, conditions) |
| `scale_deployment` | Scale a Deployment to N replicas |
| `rollout_restart` | Trigger a rolling restart of a Deployment |
| `get_deployment_rollout_status` | Get rollout progress, conditions, and generation info |
| `get_deployment_revision_history` | List revision history (ReplicaSets) with images and change cause |
| `rollback_deployment` | Roll back a Deployment to a previous revision |
| `get_deployment_image_info` | Get image repo/tag/version for a Deployment |
| `list_deployments_image_info` | Get image info for all Deployments in a namespace |
### DeploymentConfigs (OpenShift)
| Tool | Description |
|------|-------------|
| `list_deploymentconfigs` | List all OpenShift DeploymentConfigs in a namespace |
| `get_deploymentconfig` | Get detailed DeploymentConfig info (triggers, strategy, containers) |
| `scale_deploymentconfig` | Scale a DeploymentConfig to N replicas |
### StatefulSets
| Tool | Description |
|------|-------------|
| `list_statefulsets` | List all StatefulSets in a namespace |
| `get_statefulset` | Get detailed StatefulSet info (volumes, service name) |
| `scale_statefulset` | Scale a StatefulSet to N replicas |
### DaemonSets
| Tool | Description |
|------|-------------|
| `list_daemonsets` | List all DaemonSets in a namespace |
| `get_daemonset` | Get detailed DaemonSet info (node selector, containers) |
### ReplicaSets
| Tool | Description |
|------|-------------|
| `list_replicasets` | List all ReplicaSets in a namespace |
### Services
| Tool | Description |
|------|-------------|
| `list_services` | List all Services in a namespace (ports, selectors, type) |
### Routes (OpenShift)
| Tool | Description |
|------|-------------|
| `list_routes` | List all OpenShift Routes in a namespace |
| `get_route` | Get detailed Route info (host, TLS, backends) |
### Ingresses
| Tool | Description |
|------|-------------|
| `list_ingresses` | List all Ingresses in a namespace |
| `get_ingress` | Get detailed Ingress info (rules, TLS, annotations) |
### Horizontal Pod Autoscalers
| Tool | Description |
|------|-------------|
| `list_hpas` | List all HPAs in a namespace |
| `get_hpa` | Get detailed HPA info (target ref, min/max/current replicas) |
### Jobs & CronJobs
| Tool | Description |
|------|-------------|
| `list_jobs` | List all Jobs in a namespace |
| `get_job` | Get detailed Job info (completions, conditions, containers) |
| `list_cronjobs` | List all CronJobs in a namespace |
| `get_cronjob` | Get detailed CronJob info (schedule, concurrency, history) |
### ConfigMaps
| Tool | Description |
|------|-------------|
| `list_configmaps` | List all ConfigMaps in a namespace |
| `get_configmap` | Get a ConfigMap including its data |
### Secrets
| Tool | Description |
|------|-------------|
| `list_secrets` | List Secrets in a namespace (metadata only, no values) |
| `get_secret_metadata` | Get Secret metadata (type, keys, labels — no values) |
### Nodes
| Tool | Description |
|------|-------------|
| `list_nodes` | List all nodes (roles, capacity, conditions) |
| `get_node` | Get detailed node info (taints, allocatable, OS/runtime info) |
### Storage
| Tool | Description |
|------|-------------|
| `list_pvcs` | List all PersistentVolumeClaims in a namespace |
| `get_pvc` | Get detailed PVC info (capacity, storage class, conditions) |
### Network Policies
| Tool | Description |
|------|-------------|
| `list_network_policies` | List all NetworkPolicies in a namespace |
### Events
| Tool | Description |
|------|-------------|
| `list_events` | List events in a namespace (sorted by time) |
| `get_pod_events` | Get events for a specific Pod |
### Metrics (Observe)
| Tool | Description |
|------|-------------|
| `top_pods` | Real-time CPU/memory usage for all pods in a namespace |
| `top_pod` | Real-time CPU/memory usage for a specific pod |
| `top_nodes` | Real-time CPU/memory usage for all cluster nodes |
| `pod_resource_usage_vs_requests` | Compare actual usage vs requests/limits for right-sizing |
### Monitoring (Observe)
| Tool | Description |
|------|-------------|
| `list_prometheus_rules` | List PrometheusRules (alerting/recording rules) in a namespace |
| `get_prometheus_rule` | Get detailed rule groups, expressions, severity, and summaries |
| `list_service_monitors` | List ServiceMonitors (Prometheus scrape targets) |
| `list_pod_monitors` | List PodMonitors (Prometheus pod scrape targets) |
| `list_alertmanager_configs` | List AlertmanagerConfig resources |
### Builds (OpenShift)
| Tool | Description |
|------|-------------|
| `list_buildconfigs` | List all BuildConfigs in a namespace |
| `get_buildconfig` | Get detailed BuildConfig info (strategy, source, triggers) |
| `list_builds` | List all Builds in a namespace |
| `get_build` | Get detailed Build info (phase, duration, output image, log snippet) |
### ImageStreams (OpenShift)
| Tool | Description |
|------|-------------|
| `list_imagestreams` | List all ImageStreams in a namespace |
| `get_imagestream` | Get detailed ImageStream info with all tags and image references |
### Quotas & Limits
| Tool | Description |
|------|-------------|
| `list_resource_quotas` | List ResourceQuotas with used vs hard limits |
| `list_limit_ranges` | List LimitRanges (default requests, limits, min, max) |
| `list_service_accounts` | List ServiceAccounts in a namespace |
### Resource Deletion
| Tool | Description |
|------|-------------|
| `delete_resource` | Delete a resource by kind and name |
Supported kinds for deletion: `Pod`, `Deployment`, `StatefulSet`, `DaemonSet`, `ReplicaSet`, `Service`, `ConfigMap`, `Secret`, `Job`, `CronJob`, `PersistentVolumeClaim`, `Ingress`, `NetworkPolicy`, `HorizontalPodAutoscaler`.
## Usage Examples
Here are some common tasks you can ask the AI to perform:
**Debugging a failing pod:**
> "Show me the logs for pod my-app-xyz in namespace production on prod-g1"
**Find all crashing pods:**
> "List all failing pods in namespace my-app on prod-g1"
**Force-delete stuck pods:**
> "Force-delete all terminating pods in namespace my-app on uat-g1"
**Get logs from all containers in a pod:**
> "Get logs from all containers in pod my-app-xyz in namespace production"
**Check resource usage (Observe > Metrics):**
> "Show me CPU and memory usage for all pods in namespace my-app on prod-g1"
**Right-size pods:**
> "Compare actual resource usage vs requests for pods in namespace my-app on dev"
**Check node capacity and usage:**
> "Show me top nodes by CPU usage on prod-g1"
**Comparing deployments across environments:**
> "List the image tags for all deployments in namespace my-app on dev and uat-g1"
**Rollback a bad deployment:**
> "Roll back deployment api-server in namespace my-app on prod-g1 to the previous revision"
**Scaling for load:**
> "Scale deployment api-server to 5 replicas in namespace my-app on prod-g1"
**Checking routes:**
> "List all routes in namespace my-app on uat-g1"
**Investigating events:**
> "Show me recent events in namespace my-app on prod-g2"
**Check alerting rules (Observe > Alerting):**
> "List all PrometheusRules in namespace openshift-monitoring on prod-g1"
**View builds:**
> "List recent builds in namespace my-app on dev"
**Check image streams:**
> "Show me all tags for imagestream my-app in namespace my-app on dev"
**Check quotas:**
> "Show me resource quotas and usage in namespace my-app on prod-g1"
## Token Management
- Tokens are acquired via OCP's OAuth implicit flow and stored in memory only.
- If a token expires, use `refresh_cluster_token(alias="dev")` to re-authenticate.
- Restarting the MCP server clears all tokens — re-register clusters on restart.
## Security Notes
- **No secrets exposed**: `list_secrets` and `get_secret_metadata` return only metadata (type, keys, labels) — never secret values.
- **No persistent credentials**: Tokens and passwords are held in-memory for the server process lifetime only.
- **SSL verification**: Enabled by default. Set `verify_ssl=False` only for test clusters with self-signed certificates.
## Development
```bash
# Install with dev dependencies
uv sync --extra dev
# Run tests
uv run pytest
# Run linter
uv run ruff check src/ tests/
```
## Project Structure
```
ocp-mcp/
├── pyproject.toml
├── README.md
├── src/ocp_mcp/
│ ├── server.py # MCP server entry point
│ ├── cluster_manager.py # Multi-cluster registry and API client management
│ ├── auth.py # OCP OAuth token acquisition
│ ├── models.py # Pydantic response models
│ ├── exceptions.py # Custom exceptions
│ └── tools/
│ ├── registry.py # Cluster registration tools
│ ├── deployments.py # Deployment operations + rollout + rollback
│ ├── ocp_deploymentconfigs.py # DeploymentConfig operations (OCP)
│ ├── workloads.py # StatefulSets, DaemonSets, ReplicaSets
│ ├── jobs.py # Jobs and CronJobs
│ ├── resources.py # Pods, Namespaces, Services, delete_resource
│ ├── pod_ops.py # Force-delete, terminating/failing/not-ready pods
│ ├── logs.py # Pod log retrieval (single, all containers, previous)
│ ├── events.py # Namespace and Pod events
│ ├── metrics.py # Real-time pod/node metrics + usage vs requests
│ ├── monitoring.py # PrometheusRules, ServiceMonitors, PodMonitors
│ ├── hpa.py # Horizontal Pod Autoscalers
│ ├── configmaps.py # ConfigMap operations
│ ├── secrets.py # Secret metadata (no values)
│ ├── quotas.py # ResourceQuotas, LimitRanges, ServiceAccounts
│ ├── image_info.py # Deployment image/tag inspection
│ ├── nodes.py # Node listing and details
│ ├── storage.py # PersistentVolumeClaim operations
│ ├── routes.py # OpenShift Route operations
│ ├── ocp_builds.py # Builds, BuildConfigs, ImageStreams (OCP)
│ └── networking.py # Ingresses and NetworkPolicies
└── tests/
├── test_auth.py
└── test_cluster_manager.py
```
## License
Internal use.
TDQS
Scored across 77 tools
Most tools target distinct resource types (list_* vs get_* per kind), and overlap is limited to a few areas like logs (get_pod_logs, get_all_container_logs, get_previous_pod_logs) and deployment operations (rollout_restart, rollback_deployment, get_deployment_revision_history). Descriptions clarify these related tools, so an agent can usually pick the right one, but the sheer number increases selection risk.
The dominant pattern is verb_noun in snake_case (list_pods, get_deployment, scale_statefulset), which is predictable. However, there are deviations like rollout_restart (noun_verb), top_pods/top_nodes (no list/get prefix), and pod_resource_usage_vs_requests (descriptive phrase) that break the strict pattern.
With 77 tools, the surface is very large and far exceeds the typical well-scoped range. While OpenShift is broad, many tools are similar list/get variants for different resource kinds, making the server feel overloaded. This volume could overwhelm agents and increase decision cost.
The server covers a wide range of OpenShift resources with list/get, scaling, logs, events, and monitoring. However, there are notable gaps: no create/update for most resources, delete only for a few kinds, and missing some common resources like roles/rolebindings. Core operational workflows are present, but full lifecycle coverage is incomplete.