first commit

This commit is contained in:
2025-12-29 14:25:55 +11:00
commit 0c4891f55d
10 changed files with 488 additions and 0 deletions

14
Chart.yaml Normal file
View File

@@ -0,0 +1,14 @@
apiVersion: v2
name: kubernetes-mcp-server
description: Helm Chart for the Kubernetes MCP Server
home: https://github.com/containers/kubernetes-mcp-server
keywords:
- kubernetes
- mcp
maintainers:
- name: Andrew Block
email: ablock@redhat.com
- name: Marc Nuri
email: marc.nuri@redhat.com
version: 0.1.0
appVersion: "latest"

76
README.md Normal file
View File

@@ -0,0 +1,76 @@
# kubernetes-mcp-server
![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
Helm Chart for the Kubernetes MCP Server
**Homepage:** <https://github.com/containers/kubernetes-mcp-server>
## Maintainers
| Name | Email | Url |
| ---- | ------ | --- |
| Andrew Block | <ablock@redhat.com> | |
| Marc Nuri | <marc.nuri@redhat.com> | |
## Installing the Chart
The Chart can be installed quickly and easily to a Kubernetes cluster. Since an _Ingress_ is added as part of the default install of the Chart, the `ingress.host` Value must be specified.
Install the Chart using the following command from the root of this directory:
```shell
helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server oci://ghcr.io/containers/charts/kubernetes-mcp-server --set ingress.host=<hostname>
```
### Optimized OpenShift Deployment
Functionality has been added to the Chart to simplify the deployment to OpenShift Cluster.
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | |
| config.port | string | `"{{ .Values.service.port }}"` | |
| configFilePath | string | `"/etc/kubernetes-mcp-server/config.toml"` | |
| defaultPodSecurityContext | object | `{"seccompProfile":{"type":"RuntimeDefault"}}` | Default Security Context for the Pod when one is not provided |
| defaultSecurityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsNonRoot":true}` | Default Security Context for the Container when one is not provided |
| extraVolumeMounts | list | `[]` | Additional volumeMounts on the output Deployment definition. |
| extraVolumes | list | `[]` | Additional volumes on the output Deployment definition. |
| fullnameOverride | string | `""` | |
| image | object | `{"pullPolicy":"IfNotPresent","registry":"quay.io","repository":"containers/kubernetes_mcp_server","version":"latest"}` | This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ |
| image.pullPolicy | string | `"IfNotPresent"` | This sets the pull policy for images. |
| image.version | string | `"latest"` | This sets the tag or sha digest for the image. |
| imagePullSecrets | list | `[]` | This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ |
| ingress | object | `{"annotations":{},"className":"","enabled":true,"host":"","hosts":null,"path":"/","pathType":"ImplementationSpecific","termination":"edge","tls":null}` | This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ |
| livenessProbe | object | `{"httpGet":{"path":"/healthz","port":"http"}}` | Liveness and readiness probes for the container. |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | |
| openshift | bool | `false` | Enable OpenShift specific features |
| podAnnotations | object | `{}` | For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ |
| podLabels | object | `{}` | For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ |
| podSecurityContext | object | `{}` | Define the Security Context for the Pod |
| readinessProbe.httpGet.path | string | `"/healthz"` | |
| readinessProbe.httpGet.port | string | `"http"` | |
| replicaCount | int | `1` | This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ |
| resources | object | `{"limits":{"cpu":"100m","memory":"128Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}` | Resource requests and limits for the container. |
| securityContext | object | `{}` | Define the Security Context for the Container |
| service | object | `{"port":8080,"type":"ClusterIP"}` | This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ |
| service.port | int | `8080` | This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports |
| service.type | string | `"ClusterIP"` | This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types |
| serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ |
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template |
| tolerations | list | `[]` | |
## Updating the README
The contents of the README.md file is generated using [helm-docs](https://github.com/norwoodj/helm-docs). Whenever changes are introduced to the Chart and its _Values_, the documentation should be regenerated.
Execute the following command to regenerate the documentation from within the Helm Chart directory.
```shell
helm-docs -t README.md.gotmpl
```

40
README.md.gotmpl Normal file
View File

@@ -0,0 +1,40 @@
{{ template "chart.header" . }}
{{ template "chart.deprecationWarning" . }}
{{ template "chart.badgesSection" . }}
{{ template "chart.description" . }}
{{ template "chart.homepageLine" . }}
{{ template "chart.maintainersSection" . }}
{{ template "chart.sourcesSection" . }}
{{ template "chart.requirementsSection" . }}
## Installing the Chart
The Chart can be installed quickly and easily to a Kubernetes cluster. Since an _Ingress_ is added as part of the default install of the Chart, the `ingress.host` Value must be specified.
Install the Chart using the following command from the root of this directory:
```shell
helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server oci://ghcr.io/containers/charts/kubernetes-mcp-server --set ingress.host=<hostname>
```
### Optimized OpenShift Deployment
Functionality has been added to the Chart to simplify the deployment to OpenShift Cluster.
{{ template "chart.valuesSection" . }}
## Updating the README
The contents of the README.md file is generated using [helm-docs](https://github.com/norwoodj/helm-docs). Whenever changes are introduced to the Chart and its _Values_, the documentation should be regenerated.
Execute the following command to regenerate the documentation from within the Helm Chart directory.
```shell
helm-docs -t README.md.gotmpl
```

73
templates/_helpers.tpl Normal file
View File

@@ -0,0 +1,73 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "kubernetes-mcp-server.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "kubernetes-mcp-server.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "kubernetes-mcp-server.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "kubernetes-mcp-server.labels" -}}
helm.sh/chart: {{ include "kubernetes-mcp-server.chart" . }}
{{ include "kubernetes-mcp-server.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "kubernetes-mcp-server.selectorLabels" -}}
app.kubernetes.io/name: {{ include "kubernetes-mcp-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "kubernetes-mcp-server.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "kubernetes-mcp-server.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the image path for the passed in image field
*/}}
{{- define "kubernetes-mcp-server.image" -}}
{{- if eq (substr 0 7 .version) "sha256:" -}}
{{- printf "%s/%s@%s" .registry .repository .version -}}
{{- else -}}
{{- printf "%s/%s:%s" .registry .repository .version -}}
{{- end -}}
{{- end -}}

10
templates/configmap.yaml Normal file
View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "kubernetes-mcp-server.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 4 }}
data:
config.toml: |
{{- tpl (toToml .Values.config) . | replace ".0" "" | nindent 4 }}

82
templates/deployment.yaml Normal file
View File

@@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubernetes-mcp-server.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "kubernetes-mcp-server.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "kubernetes-mcp-server.serviceAccountName" . }}
securityContext:
{{- tpl (toYaml (default .Values.defaultPodSecurityContext .Values.podSecurityContext)) . | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- tpl (toYaml (default .Values.defaultSecurityContext .Values.securityContext)) . | nindent 12 }}
image: "{{ template "kubernetes-mcp-server.image" .Values.image }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
args:
- "--config"
- "{{ .Values.configFilePath }}"
{{- with .Values.livenessProbe }}
livenessProbe:
{{- tpl (toYaml .) . | nindent 12 }}
{{- end }}
{{- with .Values.readinessProbe }}
readinessProbe:
{{- tpl (toYaml .) . | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- tpl (toYaml .) . | nindent 12 }}
{{- end }}
volumeMounts:
- name: config
mountPath: {{ .Values.configFilePath | dir }}
{{- with .Values.extraVolumeMounts }}
{{- tpl (toYaml .) . | nindent 12 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "kubernetes-mcp-server.fullname" . }}
{{- with .Values.extraVolumes }}
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- tpl (toYaml .) . | nindent 8 }}
{{- end }}

38
templates/ingress.yaml Normal file
View File

@@ -0,0 +1,38 @@
{{- if .Values.ingress.enabled -}}
{{- $host := required "Ingress hostname must be specified" (tpl .Values.ingress.host .) }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "kubernetes-mcp-server.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 4 }}
annotations:
{{- if eq .Values.openshift true }}
route.openshift.io/termination: {{ .Values.ingress.termination }}
{{- end }}
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
- hosts:
- "{{ $host }}"
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
- host: "{{ $host }}"
http:
paths:
- path: {{ .Values.ingress.path }}
pathType: {{ .Values.ingress.pathType }}
backend:
service:
name: {{ include "kubernetes-mcp-server.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}

16
templates/service.yaml Normal file
View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "kubernetes-mcp-server.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "kubernetes-mcp-server.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "kubernetes-mcp-server.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubernetes-mcp-server.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- tpl (toYaml .) . | nindent 4 }}
{{- end }}
{{- end }}

126
values.yaml Normal file
View File

@@ -0,0 +1,126 @@
# -- Enable OpenShift specific features
openshift: true
# -- This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
replicaCount: 1
# -- This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/
image:
registry: quay.io
repository: containers/kubernetes_mcp_server
# -- This sets the tag or sha digest for the image.
version: latest
# -- This sets the pull policy for images.
pullPolicy: IfNotPresent
# -- This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
imagePullSecrets: []
# This is to override the chart name.
nameOverride: ""
fullnameOverride: ""
# -- This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/
serviceAccount:
# -- Specifies whether a service account should be created
create: true
# -- Annotations to add to the service account
annotations: {}
# -- The name of the service account to use.
# -- If not set and create is true, a name is generated using the fullname template
name: ""
# -- This is for setting Kubernetes Annotations to a Pod.
# -- For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
podAnnotations: {}
# -- This is for setting Kubernetes Labels to a Pod.
# -- For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
podLabels: {}
# -- Default Security Context for the Pod when one is not provided
defaultPodSecurityContext:
seccompProfile:
type: RuntimeDefault
# -- Define the Security Context for the Pod
podSecurityContext: {}
# -- Default Security Context for the Container when one is not provided
defaultSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
# -- Define the Security Context for the Container
securityContext: {}
# -- This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/
service:
# -- This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
type: ClusterIP
# -- This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports
port: 8080
# -- This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/
ingress:
enabled: true
className: "openshift-default"
annotations:
nginx.ingress.kubernetes.io/ingress.class: "openshift-default"
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-dns01-cloudflare"
host: "mcp.apilab.us"
path: /
pathType: ImplementationSpecific
termination: edge
hosts: mcp.apilab.us
tls:
secretName: mcp-tls
hosts:
- mcp.apilab.us
# -- Resource requests and limits for the container.
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
# -- Liveness and readiness probes for the container.
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /healthz
port: http
# -- Additional volumes on the output Deployment definition.
extraVolumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# -- Additional volumeMounts on the output Deployment definition.
extraVolumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}
# Path to the configuration file inside the container
configFilePath: /etc/kubernetes-mcp-server/config.toml
# MCP Server configuration options. See https://github.com/containers/kubernetes-mcp-server/blob/main/pkg/config/config.go for details.
config:
port: "{{ .Values.service.port }}"