kom is a tool designed for Kubernetes operations, serving as an SDK-level wrapper for kubectl and client-go. It provides a range of functionalities to manage Kubernetes resources, including creating, updating, deleting, and retrieving resources. The project supports operations on various Kubernetes resource types and can handle Custom Resource Definitions (CRD).
By using kom, you can easily perform actions such as creating, reading, updating, and deleting resources, fetching logs, and managing files within PODs.
- Easy to Use:
komoffers a comprehensive set of features, including create, update, delete, retrieve, and list operations for both built-in and CRD resources. - Multi-Cluster Support: With RegisterCluster, you can easily manage multiple Kubernetes clusters.
- Chained Invocation:
komprovides chained invocation, making resource operations simpler and more intuitive. - CRD Support:
komsupports custom resource definitions (CRDs), allowing you to define and manage custom resources effortlessly. - Callback Mechanism Support: Enables easy extension of business logic without tight coupling to Kubernetes operations.
- POD File Operations: Supports file management within PODs, making it easy to upload, download, and delete files.
- Support the encapsulation of high-frequency operations, such as restarting deployments and scaling (expanding or shrinking capacity).
- Support SQL queries for k8s resources.
select * from pod wheremetadata.namespace='kube-system' ormetadata.namespace='default' order bymetadata.creationTimestampasc
k8m is a lightweight Kubernetes management tool, implemented as a single file and based on kom and amis, supporting multiple platform architectures.
- Download: Get the latest version from https://github.com/weibaohui/k8m.
- Run: Start with the command
./k8mand access http://127.0.0.1:3618.
import (
"github.com/weibaohui/kom/callbacks"
"github.com/weibaohui/kom"
)
func main() {
// Register the callback functions
callbacks.RegisterInit()
// Register clusters
defaultKubeConfig := os.Getenv("KUBECONFIG")
if defaultKubeConfig == "" {
defaultKubeConfig = filepath.Join(homedir.HomeDir(), ".kube", "config")
}
_, _ = kom.Clusters().RegisterInCluster()
_, _ = kom.Clusters().RegisterByPathWithID(defaultKubeConfig, "default")
kom.Clusters().Show()
// Additional logic
}Supports multiple tools including querying, listing, deleting, and describing operations for any resource, as well as POD log reading operations.
// Start MCP Server with one line of code
mcp.RunMCPServer("kom mcp server", "0.0.1", 9096)# Launch from source
go run main.go
# MCP Server access address
http://IP:9096/sse# Compile
go build main.go
# Run
./main
# MCP Server access address
http://IP:9096/sseSuitable for integration with MCP tools such as Cursor, Claude Desktop, Windsurf, etc. Additionally, you can use these software's UI interfaces for adding.
{
"mcpServers": {
"kom": {
"type": "sse",
"url": "http://IP:9096/sse"
}
}
}| Category | Method | Description |
|---|---|---|
| Cluster Management (1) | list_clusters |
List all registered Kubernetes clusters |
| Deployment Management (12) | scale_deployment |
Scale Deployment |
restart_deployment |
Restart Deployment | |
stop_deployment |
Stop Deployment | |
restore_deployment |
Restore Deployment | |
update_tag_deployment |
Update Deployment image tag | |
rollout_history_deployment |
Query Deployment upgrade history | |
rollout_undo_deployment |
Rollback Deployment | |
rollout_pause_deployment |
Pause Deployment upgrade | |
rollout_resume_deployment |
Resume Deployment upgrade | |
rollout_status_deployment |
Query Deployment upgrade status | |
hpa_list_deployment |
Query Deployment's HPA list | |
list_deployment_pods |
Get list of Pods managed by Deployment | |
| Dynamic Resource Management (incl. CRD, 8) | get_k8s_resource |
Get k8s resource |
describe_k8s_resource |
Describe k8s resource | |
delete_k8s_resource |
Delete k8s resource | |
list_k8s_resource |
List k8s resources | |
list_k8s_event |
List k8s events | |
patch_k8s_resource |
Update k8s resource using JSON Patch | |
label_k8s_resource |
Add or remove labels for k8s resource | |
annotate_k8s_resource |
Add or remove annotations for k8s resource | |
| Node Management (8) | taint_node |
Add taint to node |
untaint_node |
Remove taint from node | |
cordon_node |
Set Cordon on node | |
uncordon_node |
Remove Cordon from node | |
drain_node |
Drain node | |
get_node_resource_usage |
Query node resource usage | |
get_node_ip_usage |
Query Pod IP resource usage on node | |
get_node_pod_count |
Query Pod count on node | |
| Pod Management (14) | list_pod_files |
List Pod files |
list_all_pod_files |
List all Pod files | |
delete_pod_file |
Delete Pod file | |
upload_file_to_pod |
Upload file to Pod, supports text content | |
get_pod_logs |
Get Pod logs | |
run_command_in_pod |
Execute command in Pod | |
get_pod_linked_service |
Get Pod's linked Service | |
get_pod_linked_ingress |
Get Pod's linked Ingress | |
get_pod_linked_endpoints |
Get Pod's linked Endpoints | |
get_pod_linked_pvc |
Get Pod's linked PVC | |
get_pod_linked_pv |
Get Pod's linked PV | |
get_pod_linked_env |
Get Pod runtime environment variables via env command | |
get_pod_linked_env_from_yaml |
Get Pod runtime environment variables from Pod yaml | |
get_pod_resource_usage |
Get Pod resource usage including CPU and memory requests, limits, allocatable and usage ratios | |
| YAML Management (2) | apply_yaml |
Apply YAML resource |
delete_yaml |
Delete YAML resource | |
| Storage Management (3) | set_default_storageclass |
Set default StorageClass |
get_storageclass_pvc_count |
Get PVC count under StorageClass | |
get_storageclass_pv_count |
Get PV count under StorageClass | |
| Ingress Management (1) | set_default_ingressclass |
Set default IngressClass |
mcp.RunMCPServer("kom mcp server", "0.0.1", 3619)- Open Claude Desktop settings panel
- Add MCP Server address in API configuration area
- Enable SSE event listening function
- Verify connection status
- Enter Cursor settings interface
- Find extension service configuration option
- Add MCP Server URL (e.g., http://localhost:9096/sse)
- Access configuration center
- Set API server address
// RegisterInCluster cluster, named InCluster
kom.Clusters().RegisterInCluster()
// Register two named clusters with IDs "orb" and "docker-desktop"
kom.Clusters().RegisterByPathWithID("/Users/kom/.kube/orb", "orb")
kom.Clusters().RegisterByPathWithID("/Users/kom/.kube/config", "docker-desktop")
// Register a cluster named "default". kom.DefaultCluster() will return this cluster.
kom.Clusters().RegisterByPathWithID("/Users/kom/.kube/config", "default")kom.Clusters().Show()// Use the default cluster to query pods in the kube-system namespace
// First, it will try to return the instance with ID "InCluster". If it doesn't exist,
// it will try to return the instance with ID "default".
// If neither of these exist, it will return any instance in the clusters list.
var pods []corev1.Pod
err = kom.DefaultCluster().Resource(&corev1.Pod{}).Namespace("kube-system").List(&pods).Error// Select the "orb" cluster and query pods in the kube-system namespace
var pods []corev1.Pod
err = kom.Cluster("orb").Resource(&corev1.Pod{}).Namespace("kube-system").List(&pods).ErrorDefine a Deployment object and use kom for resource operations.
var item v1.Deployment
var items []v1.Deploymentitem = v1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "nginx",
Namespace: "default",
},
Spec: v1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{Name: "test", Image: "nginx:1.14.2"},
},
},
},
},
}
err := kom.DefaultCluster().Resource(&item).Create(&item).Error// Retrieve the Deployment named "nginx" in the "default" namespace
err := kom.DefaultCluster().Resource(&item).Namespace("default").Name("nginx").Get(&item).Error// List Deployments in the "default" namespace
err := kom.DefaultCluster().Resource(&item).Namespace("default").List(&items).Error
// List Deployments in all namespace
err := kom.DefaultCluster().Resource(&item).AllNamespace().List(&items).Error
err := kom.DefaultCluster().Resource(&item).Namespace("*").List(&items).Error// List Deployments in the "default" namespace with the label "app=nginx"
err := kom.DefaultCluster().Resource(&item).Namespace("default").WithLabelSelector("app=nginx").List(&items).Error// List Deployments in the "default" namespace with labels "app=nginx" and "m=n"
err := kom.DefaultCluster().Resource(&item).Namespace("default").WithLabelSelector("app=nginx").WithLabelSelector("m=n").List(&items).Error// List Deployments in the "default" namespace with the field "metadata.name=test-deploy"
err := kom.DefaultCluster().Resource(&item).Namespace("default").WithFieldSelector("metadata.name=test-deploy").List(&items).Error// Update the Deployment named "nginx" by adding an annotation
err := kom.DefaultCluster().Resource(&item).Namespace("default").Name("nginx").Get(&item).Error
if item.Spec.Template.Annotations == nil {
item.Spec.Template.Annotations = map[string]string{}
}
item.Spec.Template.Annotations["kom.kubernetes.io/restartedAt"] = time.Now().Format(time.RFC3339)
err = kom.DefaultCluster().Resource(&item).Update(&item).Error// Patch update to add a label and set replicas to 5 for the Deployment "nginx"
patchData := `{
"spec": {
"replicas": 5
},
"metadata": {
"labels": {
"new-label": "new-value"
}
}
}`
err := kom.DefaultCluster().Resource(&item).Patch(&item, types.StrategicMergePatchType, patchData).Error// Delete the Deployment named "nginx"
err := kom.DefaultCluster().Resource(&item).Namespace("default").Name("nginx").Delete().Error// Specify GVK to retrieve resources
var list []corev1.Event
err := kom.DefaultCluster().GVK("events.k8s.io", "v1", "Event").Namespace("default").List(&list).Error// Watch changes to Pod resources in the "default" namespace
var watcher watch.Interface
var pod corev1.Pod
err := kom.DefaultCluster().Resource(&pod).Namespace("default").Watch(&watcher).Error
if err != nil {
fmt.Printf("Create Watcher Error %v", err)
return err
}
go func() {
defer watcher.Stop()
for event := range watcher.ResultChan() {
err := kom.DefaultCluster().Tools().ConvertRuntimeObjectToTypedObject(event.Object, &pod)
if err != nil {
fmt.Printf("Failed to convert object to *v1.Pod type: %v", err)
return
}
// Handle events
switch event.Type {
case watch.Added:
fmt.Printf("Added Pod [ %s/%s ]\n", pod.Namespace, pod.Name)
case watch.Modified:
fmt.Printf("Modified Pod [ %s/%s ]\n", pod.Namespace, pod.Name)
case watch.Deleted:
fmt.Printf("Deleted Pod [ %s/%s ]\n", pod.Namespace, pod.Name)
}
}
}()// Describe a Deployment named nginx in default namespace
var describeResult []byte
err := kom.DefaultCluster().Resource(&item).Namespace("default").Name("nginx").Describe(&describeResult).Error
fmt.Printf("describeResult: %s", describeResult)yaml := `apiVersion: v1
kind: ConfigMap
metadata:
name: example-config
namespace: default
data:
key: value
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: nginx
`
// Initial Apply creates the resources and returns results for each resource
results := kom.DefaultCluster().Applier().Apply(yaml)
// Subsequent Apply updates the resources and returns results for each resource
results = kom.DefaultCluster().Applier().Apply(yaml)
// Delete removes the resources and returns results for each resource
results = kom.DefaultCluster().Applier().Delete(yaml)// Retrieve Pod logs
var stream io.ReadCloser
err := kom.DefaultCluster().Namespace("default").Name("random-char-pod").Ctl().Pod().ContainerName("container").GetLogs(&stream, &corev1.PodLogOptions{}).Error
reader := bufio.NewReader(stream)
line, _ := reader.ReadString('\n')
fmt.Println(line)To execute a command inside a Pod, specify the container name. This triggers Exec() type callbacks.
// Execute the "ps -ef" command inside the Pod
var execResult string
err := kom.DefaultCluster().Namespace("default").Name("random-char-pod").ContainerName("container").Command("ps", "-ef").ExecuteCommand(&execResult).Error
fmt.Printf("execResult: %s", execResult)// List files in the /etc directory within the Pod
kom.DefaultCluster().Namespace("default").Name("nginx").Ctl().Pod().ContainerName("nginx").ListFiles("/etc")// Download the /etc/hosts file from inside the Pod
kom.DefaultCluster().Namespace("default").Name("nginx").Ctl().Pod().ContainerName("nginx").DownloadFile("/etc/hosts")// Upload text content to /etc/demo.txt inside the Pod
kom.DefaultCluster().Namespace("default").Name("nginx").Ctl().Pod().ContainerName("nginx").SaveFile("/etc/demo.txt", "txt-context")
// Directly upload a os.File to /etc/ inside the Pod
file, _ := os.Open(tempFilePath)
kom.DefaultCluster().Namespace("default").Name("nginx").Ctl().Pod().ContainerName("nginx").UploadFile("/etc/", file)// Delete the /etc/xyz file inside the Pod
kom.DefaultCluster().Namespace("default").Name("nginx").Ctl().Pod().ContainerName("nginx").DeleteFile("/etc/xyz")Without defining a CR, you can still perform CRUD operations similar to built-in Kubernetes resources. To work with a CRD, define the object as unstructured.Unstructured, and specify the Group, Version, and Kind. For convenience, kom.DefaultCluster().CRD(group, version, kind) can be used to simplify the process. Below is an example of working with CRDs:
First, define a generic object to handle CRD responses.
var item unstructured.Unstructuredyaml := `apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct`
result := kom.DefaultCluster().Applier().Apply(yaml)item = unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "stable.example.com/v1",
"kind": "CronTab",
"metadata": map[string]interface{}{
"name": "test-crontab",
"namespace": "default",
},
"spec": map[string]interface{}{
"cronSpec": "* * * * */8",
"image": "test-crontab-image",
},
},
}
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Namespace(item.GetNamespace()).Name(item.GetName()).Create(&item).Errorerr := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Name(item.GetName()).Namespace(item.GetNamespace()).Get(&item).Errorvar crontabList []unstructured.Unstructured
// list in default namespace
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Namespace(crontab.GetNamespace()).List(&crontabList).Error
// list in all namespace
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").AllNamespace().List(&crontabList).Error
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Namespace("*").List(&crontabList).ErrorpatchData := `{
"spec": {
"image": "patch-image"
},
"metadata": {
"labels": {
"new-label": "new-value"
}
}
}`
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Name(crontab.GetName()).Namespace(crontab.GetNamespace()).Patch(&crontab, types.StrategicMergePatchType, patchData).Errorerr := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Name(crontab.GetName()).Namespace(crontab.GetNamespace()).Delete().Errorvar watcher watch.Interface
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Namespace("default").Watch(&watcher).Error
if err != nil {
fmt.Printf("Create Watcher Error %v", err)
}
go func() {
defer watcher.Stop()
for event := range watcher.ResultChan() {
var item *unstructured.Unstructured
item, err := kom.DefaultCluster().Tools().ConvertRuntimeObjectToUnstructuredObject(event.Object)
if err != nil {
fmt.Printf("Unable to convert object to Unstructured type: %v", err)
return
}
// Handle events
switch event.Type {
case watch.Added:
fmt.Printf("Added Unstructured [ %s/%s ]\n", item.GetNamespace(), item.GetName())
case watch.Modified:
fmt.Printf("Modified Unstructured [ %s/%s ]\n", item.GetNamespace(), item.GetName())
case watch.Deleted:
fmt.Printf("Deleted Unstructured [ %s/%s ]\n", item.GetNamespace(), item.GetName())
}
}
}()// Describe a Deployment named nginx in the default namespace
var describeResult []byte
err := kom.DefaultCluster().CRD("stable.example.com", "v1", "CronTab").Namespace("default").Name(item.GetName()).Describe(&describeResult).Error
fmt.Printf("describeResult: %s", describeResult)Retrieve various types of information about the cluster:
// Cluster documentation
kom.DefaultCluster().Status().Docs()
// Cluster resource information
kom.DefaultCluster().Status().APIResources()
// List of registered CRDs in the cluster
kom.DefaultCluster().Status().CRDList()
// Cluster version information
kom.DefaultCluster().Status().ServerVersion()kom has a built-in callback mechanism, allowing for custom callback functions that execute after specific operations. If a callback function returns true, the subsequent operation continues; otherwise, it terminates.
- Available callbacks include:
get,list,create,update,patch,delete,exec,logs, andwatch. - Default callback names:
"kom:get","kom:list","kom:create","kom:update","kom:patch","kom:watch","kom:delete","kom:pod:exec","kom:pod:logs".
- Ordering: Callbacks execute in the order of registration by default. Set execution order using
.After("kom:get")or.Before("kom:get"). - Deletion: Remove a callback with
.Delete("kom:get"). - Replacement: Replace a callback with
.Replace("kom:get", cb).
// Register callback for Get operation
kom.DefaultCluster().Callback().Get().Register("get", cb)
// Register callback for List operation
kom.DefaultCluster().Callback().List().Register("list", cb)
// Register callback for Create operation
kom.DefaultCluster().Callback().Create().Register("create", cb)
// Register callback for Update operation
kom.DefaultCluster().Callback().Update().Register("update", cb)
// Register callback for Patch operation
kom.DefaultCluster().Callback().Patch().Register("patch", cb)
// Register callback for Delete operation
kom.DefaultCluster().Callback().Delete().Register("delete", cb)
// Register callback for Watch operation
kom.DefaultCluster().Callback().Watch().Register("watch", cb)
// Register callback for Pod Exec operation
kom.DefaultCluster().Callback().Exec().Register("exec", cb)
// Register callback for Log retrieval
kom.DefaultCluster().Callback().Logs().Register("logs", cb)
// Delete callback for Get operation
kom.DefaultCluster().Callback().Get().Delete("get")
// Replace callback for Get operation
kom.DefaultCluster().Callback().Get().Replace("get", cb)
// Specify callback execution order
kom.DefaultCluster().Callback().After("kom:get").Register("get", cb)
kom.DefaultCluster().Callback().Before("kom:create").Register("create", cb)
// Example Scenarios
// 1. Perform permission check before Create operation. If unauthorized, return an error, halting further execution.
// 2. After List operation, filter results, removing resources that do not meet specific criteria.Define a custom callback function to include specific operations:
func cb(k *kom.Kubectl) error {
stmt := k.Statement
gvr := stmt.GVR
ns := stmt.Namespace
name := stmt.Name
// Print information
fmt.Printf("Get %s/%s(%s)\n", ns, name, gvr)
fmt.Printf("Command %s/%s(%s %s)\n", ns, name, stmt.Command, stmt.Args)
return nil
// return fmt.Errorf("error") // Return error to stop further callback execution
}- Query k8s resources through the SQL() method, which is simple and efficient.
- The table names support the full names and abbreviations of all resources registered within the cluster, including CRD resources. As long as they are registered on the cluster, they can be queried.
- Typical table names include: pod, deployment, service, ingress, pvc, pv, node, namespace, secret, configmap, serviceaccount, role, rolebinding, clusterrole, clusterrolebinding, crd, cr, hpa, daemonset, statefulset, job, cronjob, limitrange, horizontalpodautoscaler, poddisruptionbudget, networkpolicy, endpoints, ingressclass, mutatingwebhookconfiguration, validatingwebhookconfiguration, customresourcedefinition, storageclass, persistentvolumeclaim, persistentvolume, horizontalpodautoscaler, podsecurity. All of them can be queried.
- The query fields currently only support "*"
- The query conditions currently support =,!=, >=, <=, <>, like, in, not in, and, or, between.
- The sorting fields currently support sorting on a single field. By default, they are sorted in descending order according to the creation time.
sql := "select * from deploy where metadata.namespace='kube-system' or metadata.namespace='default' order by metadata.creationTimestamp asc "
var list []v1.Deployment
err := kom.DefaultCluster().Sql(sql).List(&list).Error
for _, d := range list {
fmt.Printf("List Items foreach %s,%s at %s \n", d.GetNamespace(), d.GetName(), d.GetCreationTimestamp())
} // vm is the CRD of Kubevirt
sql := "select * from vm where (metadata.namespace='kube-system' or metadata.namespace='default' ) "
var list []unstructured.Unstructured
err := kom.DefaultCluster().Sql(sql).List(&list).Error
for _, d := range list {
fmt.Printf("List Items foreach %s,%s\n", d.GetNamespace(), d.GetName())
}// Query the pod list
err := kom.DefaultCluster().From("pod").
Where("metadata.namespace =? or metadata.namespace=? ", "kube-system", "default").
Order("metadata.creationTimestamp desc").
List(&list).Errorerr = kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Restart()<<<<<<< HEAD
=======
origin/main
// Set the replica count of the nginx deployment to 3
err = kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Scale(3)// Update the container image tag of the nginx deployment
err = kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Deployment().ReplaceImageTag("main","20241124")// Query the rollout history of the nginx deployment
result, err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().History()// Rollback the nginx deployment
result, err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Undo()
// Rollback the nginx deployment to a specific version (query the history)
result, err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Undo("6")// Pause the rollout process
err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Pause()// Resume the rollout process
err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Resume()// Check the status of the nginx deployment rollout
result, err := kom.DefaultCluster().Resource(&Deployment{}).Namespace("default").Name("nginx").Ctl().Rollout().Status()err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Node().Taint("dedicated=special-user:NoSchedule")err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Node().UnTaint("dedicated=special-user:NoSchedule")err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Node().Cordon()err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Node().UnCordon()err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Node().Drain()err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Label("name=zhangsan")err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Label("name-")err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Annotate("name=zhangsan")err = kom.DefaultCluster().Resource(&Node{}).Name("kind-control-plane").Ctl().Annotate("name-")To connect Cursor to the KOM MCP server:
- Ensure the MCP server is running in your Minikube cluster:
kubectl get pods -l app=kom-mcp-server- Set up port forwarding:
kubectl port-forward svc/kom-mcp-server 9096:9096- Create a
.cursor/mcp.jsonfile in your project root with the following content:
{
"mcpServers": {
"kom": {
"url": "http://localhost:9096/sse",
"env": {
"API_KEY": "value"
}
}
}
}- Restart Cursor to apply the configuration.
If you can't connect to the MCP server:
- Check if the pod is running:
kubectl get pods -l app=kom-mcp-server- Check pod logs:
kubectl logs -l app=kom-mcp-server- Verify port forwarding is working, getting a 404 error means this IS working:
curl -v localhost:9096/health