Integrating with AI Assistants via MCP Server
The openshift-python-wrapper ships with a built-in Model Context Protocol (MCP) server that lets AI assistants like Cursor, Claude Desktop, and other MCP-compatible tools directly manage your OpenShift/Kubernetes cluster resources.
Configure the MCP Server for Cursor
Connect your Cursor IDE to your cluster so the AI assistant can list, create, update, and delete resources on your behalf.
// ~/.cursor/mcp.json
{
"mcpServers": {
"openshift-python-wrapper": {
"command": "openshift-mcp-server"
}
}
}
After saving, restart Cursor and reference the server with @openshift-python-wrapper in your prompts. The server uses your active kubeconfig context automatically.
Note: The
openshift-mcp-servercommand is installed as a script entry point when you install the package. See Installing and Creating Your First Resource for installation instructions.
Configure the MCP Server for Claude Desktop
Set up Claude Desktop to interact with your cluster through natural language.
// macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
// Windows: %APPDATA%\Claude\claude_desktop_config.json
// Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"openshift-python-wrapper": {
"command": "openshift-mcp-server"
}
}
}
Claude Desktop will connect to the server on startup. You can then ask it to list pods, create resources, check logs, and more using natural language.
Configure a Custom Kubeconfig Path
Point the MCP server at a specific kubeconfig when your default location doesn't apply.
{
"mcpServers": {
"openshift-python-wrapper": {
"command": "openshift-mcp-server",
"env": {
"KUBECONFIG": "/home/user/.kube/my-cluster-config"
}
}
}
}
The KUBECONFIG environment variable is passed to the server process at startup. This is useful when managing multiple clusters or when your kubeconfig is in a non-standard location.
Tip: See Connecting to Clusters for all authentication methods supported by openshift-python-wrapper, including tokens, basic auth, and in-cluster config.
Run the MCP Server from Source (Development)
Run the server directly from a cloned repository for development or testing.
git clone https://github.com/RedHatQE/openshift-python-wrapper.git
cd openshift-python-wrapper
uv run mcp_server/server.py
For MCP client configuration when running from source:
{
"mcpServers": {
"openshift-python-wrapper": {
"command": "uv",
"args": ["run", "mcp_server/server.py"],
"cwd": "/path/to/openshift-python-wrapper"
}
}
}
This bypasses the installed entry point and runs the server module directly, which is useful when testing local changes.
List Cluster Resources via AI Chat
Ask your AI assistant to list resources — the MCP server exposes a list_resources tool that supports type filtering, namespaces, label selectors, and limits.
Prompt: "List all pods in the openshift-monitoring namespace with label app=prometheus"
The AI will call the list_resources tool, which maps to:
list_resources(
resource_type="pod",
namespace="openshift-monitoring",
label_selector="app=prometheus",
limit=20
)
Returned data includes name, namespace, UID, creation timestamp, labels, phase, and conditions for each matched resource.
Tip: Use
get_resource_typesto discover all available resource types. The server dynamically scans every module inocp_resources/at startup, so any resource supported by the library — including OpenShift-specific types likeroute,virtualmachine, orclusterserviceversion— is available.
Get Detailed Resource Information
Retrieve a single resource with full metadata, status, and optionally the raw YAML or JSON.
Prompt: "Show me the deployment 'api-server' in namespace 'production' as YAML"
The AI calls:
get_resource(
resource_type="deployment",
name="api-server",
namespace="production",
output_format="yaml" # also accepts "json" or "info"
)
The info format (default) returns structured metadata plus resource-specific details: for pods you get container statuses and node placement; for deployments you get replica counts; for services you get ports and cluster IP.
Create Resources Through Natural Language
Ask the AI to create resources — it can use either YAML content or structured spec parameters.
Prompt: "Create a ConfigMap called 'app-settings' in the 'staging' namespace with keys
database_host=db.staging.svc and log_level=debug"
The AI calls:
create_resource(
resource_type="configmap",
name="app-settings",
namespace="staging",
spec={"data": {"database_host": "db.staging.svc", "log_level": "debug"}},
labels={"managed-by": "mcp-server"}
)
You can also provide full YAML:
create_resource(
resource_type="pod",
name="nginx",
yaml_content="""
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
"""
)
Warning: The MCP server creates real resources on your cluster. Make sure your AI assistant is targeting the correct cluster and namespace before confirming creation operations.
Apply Multi-Document YAML Manifests
Deploy a complete application stack from a single YAML block containing multiple resources.
Prompt: "Apply this manifest to create a namespace, deployment, and service for my app"
The AI calls:
apply_yaml(yaml_content="""
---
apiVersion: v1
kind: Namespace
metadata:
name: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: my-app
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: api
image: myapp/backend:v1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: my-app
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080
""")
The response includes a summary with total_resources, successful, and failed counts, plus per-resource results. Each YAML document is parsed and deployed independently.
Update Resources with Patches
Modify existing resources using merge or strategic-merge patches.
Prompt: "Scale the 'web-frontend' deployment in 'production' to 5 replicas"
The AI calls:
update_resource(
resource_type="deployment",
name="web-frontend",
namespace="production",
patch={"spec": {"replicas": 5}},
patch_type="merge" # or "strategic"
)
The patch_type parameter controls the content type: "merge" uses application/merge-patch+json, while "strategic" uses application/strategic-merge-patch+json.
Delete Resources
Remove resources with optional wait-for-deletion behavior.
Prompt: "Delete the pod 'debug-pod' in namespace 'default' and wait for it to be gone"
The AI calls:
delete_resource(
resource_type="pod",
name="debug-pod",
namespace="default",
wait=True,
timeout=60
)
If the resource doesn't exist, the server returns a success response with a warning rather than an error, making the operation idempotent.
Retrieve Pod Logs
Fetch logs from running or crashed pods with filtering options.
Prompt: "Show me the last 200 lines of logs from pod 'api-server-7f8b9c' container 'app'
in namespace 'production'"
The AI calls:
get_pod_logs(
name="api-server-7f8b9c",
namespace="production",
container="app",
tail_lines=200
)
- Use
since_seconds=3600to get logs from the last hour - Use
previous=Trueto get logs from a crashed container's previous instance - Omit
containerfor single-container pods
Execute Commands in Pods
Run diagnostic commands inside a running pod container.
Prompt: "Check the nginx config in pod 'web-server' namespace 'production'"
The AI calls:
exec_in_pod(
name="web-server",
namespace="production",
command=["nginx", "-t"],
container="nginx"
)
The response includes stdout, stderr, and returncode. If the command fails, the exit code and error output are captured rather than raising an exception.
Warning: Pod exec gives shell-level access to your containers. Ensure your RBAC policies restrict which service accounts and users can perform
execoperations.
Get Resource Events
Retrieve Kubernetes events related to a specific resource for troubleshooting.
Prompt: "Show me the events for pod 'crashloop-pod' in 'default' namespace"
The AI calls:
get_resource_events(
resource_type="pod",
name="crashloop-pod",
namespace="default",
limit=10
)
Events are filtered using field selectors on involvedObject.name, involvedObject.namespace, and involvedObject.kind. Each event includes type (Normal/Warning), reason, message, count, timestamps, and source component.
Troubleshoot a Failing Pod (End-to-End Workflow)
Combine multiple MCP tools in sequence to diagnose pod issues — the AI assistant will chain these calls automatically.
Prompt: "Pod 'payment-svc-6d4f8' in namespace 'checkout' keeps crashing. Help me figure out why."
The AI will typically execute this sequence:
- Check status:
get_resource(resource_type="pod", name="payment-svc-6d4f8", namespace="checkout")— gets phase, container statuses, restart count - Review events:
get_resource_events(resource_type="pod", name="payment-svc-6d4f8", namespace="checkout")— shows scheduling, pulling, crash events - Read current logs:
get_pod_logs(name="payment-svc-6d4f8", namespace="checkout", tail_lines=100)— application output before crash - Read previous crash logs:
get_pod_logs(name="payment-svc-6d4f8", namespace="checkout", previous=True)— logs from the last terminated container - Inspect config:
exec_in_pod(name="payment-svc-6d4f8", namespace="checkout", command=["cat", "/etc/app/config.yaml"])— verify mounted configuration
The AI then synthesizes all the data into a diagnosis with suggested fixes.
Write a Programmatic MCP Client
Connect to the MCP server programmatically using FastMCPClient for automation scripts.
import asyncio
from fastmcp import FastMCPClient
async def main():
async with FastMCPClient() as client:
await client.connect_stdio(cmd=["openshift-mcp-server"])
# Discover available resource types
types = await client.call_tool(
name="get_resource_types",
arguments={"random_string": "x"},
)
print(f"Available types: {types['total_count']}")
# List pods in a namespace
pods = await client.call_tool(
name="list_resources",
arguments={"resource_type": "pod", "namespace": "default", "limit": 5},
)
for pod in pods["resources"]:
print(f" {pod['name']} — {pod.get('phase', 'Unknown')}")
if __name__ == "__main__":
asyncio.run(main())
This uses the same stdio transport that AI assistants use. The FastMCPClient is provided by the fastmcp library, which is already a dependency of openshift-python-wrapper.
Debug MCP Server Issues
Enable debug logging and inspect the server log file when tools aren't behaving as expected.
# Check the MCP server log file
tail -f /tmp/mcp_server_debug.log
# Run with debug-level logging from the simple-logger
SIMPLE_LOGGER_LEVEL=DEBUG openshift-mcp-server
The server writes debug logs to /tmp/mcp_server_debug.log by default, including every resource scan at startup, client creation events, and detailed error tracebacks.
- Verify cluster connectivity independently:
kubectl cluster-info - Check your permissions:
kubectl auth can-i --list - Confirm the entry point is installed:
which openshift-mcp-server
Tip: See Environment Variables and Configuration for other environment variables that affect library behavior.
Available MCP Tools Reference
The MCP server exposes ten tools. All resource type names are case-insensitive (e.g., "Pod", "pod", and "POD" all work).
| Tool | Purpose | Required Parameters |
|---|---|---|
list_resources |
List resources by type with optional filters | resource_type |
get_resource |
Get a single resource by name | resource_type, name |
create_resource |
Create a resource from spec or YAML | resource_type, name, plus spec or yaml_content |
update_resource |
Patch an existing resource | resource_type, name, patch |
delete_resource |
Delete a resource | resource_type, name |
get_pod_logs |
Retrieve pod container logs | name, namespace |
exec_in_pod |
Execute a command in a pod | name, namespace, command |
get_resource_events |
Get events for a resource | resource_type, name |
apply_yaml |
Apply one or more YAML documents | yaml_content |
get_resource_types |
List all discovered resource types | random_string (any value) |
Note: Namespaced resources (pods, deployments, configmaps, etc.) require a
namespaceparameter. Cluster-scoped resources (nodes, namespaces, cluster roles) do not. The server validates this automatically and returns a clear error if a namespace is missing.