Skip to content

Commit 4b5c52d

Browse files
Merge pull request #1 from yaswanthkumar1995/feat/1122-helm-mcp-servers-chart
feat: Add mcp-servers Helm chart with resource templates (#1122) add Helm chart for deploying MCP servers
2 parents f424458 + 83c541e commit 4b5c52d

15 files changed

Lines changed: 694 additions & 0 deletions

charts/mcp-servers/.helmignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.DS_Store
2+
.idea/
3+
.vscode/
4+
*.swp
5+
*.tmp
6+
*.bak
7+
charts/
8+
tmp/
9+
dist/
10+
node_modules/

charts/mcp-servers/Chart.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: v2
2+
name: mcp-servers
3+
description: Deploy one or more Model Context Protocol (MCP) servers.
4+
type: application
5+
version: 0.1.0
6+
appVersion: "0.1.0"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{- if not .Values.mcpServers }}
2+
mcp-servers chart installed.
3+
4+
No MCP servers were configured. Set `mcpServers` in values to deploy workloads.
5+
{{- else }}
6+
mcp-servers chart installed.
7+
8+
Deployed MCP servers:
9+
{{- range $i, $s := .Values.mcpServers }}
10+
{{- if (default true $s.enabled) }}
11+
- {{ $s.name }}
12+
{{- end }}
13+
{{- end }}
14+
{{- end }}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{{/*
2+
Common template helpers.
3+
*/}}
4+
5+
{{- define "mcp-servers.chart" -}}
6+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" -}}
7+
{{- end -}}
8+
9+
{{- define "mcp-servers.labels" -}}
10+
helm.sh/chart: {{ include "mcp-servers.chart" . }}
11+
app.kubernetes.io/managed-by: {{ .Release.Service }}
12+
app.kubernetes.io/instance: {{ .Release.Name }}
13+
{{- end -}}
14+
15+
{{- define "mcp-servers.serverName" -}}
16+
{{- $server := .server -}}
17+
{{- default $server.name $server.fullnameOverride | trunc 63 | trimSuffix "-" -}}
18+
{{- end -}}
19+
20+
{{- define "mcp-servers.serverFullname" -}}
21+
{{- $root := .root -}}
22+
{{- $server := .server -}}
23+
{{- $name := include "mcp-servers.serverName" (dict "server" $server) -}}
24+
{{- if $server.fullnameOverride -}}
25+
{{- $server.fullnameOverride | trunc 63 | trimSuffix "-" -}}
26+
{{- else if $server.nameOverride -}}
27+
{{- printf "%s-%s" $root.Release.Name $server.nameOverride | trunc 63 | trimSuffix "-" -}}
28+
{{- else -}}
29+
{{- printf "%s-%s" $root.Release.Name $name | trunc 63 | trimSuffix "-" -}}
30+
{{- end -}}
31+
{{- end -}}
32+
33+
{{- define "mcp-servers.selectorLabels" -}}
34+
{{- $root := .root -}}
35+
{{- $server := .server -}}
36+
app.kubernetes.io/name: {{ include "mcp-servers.serverName" (dict "server" $server) }}
37+
app.kubernetes.io/instance: {{ $root.Release.Name }}
38+
{{- end -}}
39+
40+
{{- define "mcp-servers.commonLabels" -}}
41+
{{- $root := .root -}}
42+
{{- $server := .server -}}
43+
{{ include "mcp-servers.labels" $root }}
44+
{{ include "mcp-servers.selectorLabels" (dict "root" $root "server" $server) }}
45+
{{- with $root.Values.global.labels }}
46+
{{ toYaml . }}
47+
{{- end }}
48+
{{- with $server.labels }}
49+
{{ toYaml . }}
50+
{{- end }}
51+
{{- end -}}
52+
53+
{{- define "mcp-servers.commonAnnotations" -}}
54+
{{- $root := .root -}}
55+
{{- $server := .server -}}
56+
{{- with $root.Values.global.annotations }}
57+
{{ toYaml . }}
58+
{{- end }}
59+
{{- with $server.annotations }}
60+
{{ toYaml . }}
61+
{{- end }}
62+
{{- end -}}
63+
64+
{{- define "mcp-servers.serviceAccountName" -}}
65+
{{- $root := .root -}}
66+
{{- $server := .server -}}
67+
{{- $sa := default (dict) $server.serviceAccount -}}
68+
{{- $saCreate := default $root.Values.global.serviceAccount.create $sa.create -}}
69+
{{- $saName := default $root.Values.global.serviceAccount.name $sa.name -}}
70+
{{- if $saCreate -}}
71+
{{- if $saName -}}
72+
{{- $saName -}}
73+
{{- else -}}
74+
{{ include "mcp-servers.serverFullname" (dict "root" $root "server" $server) }}
75+
{{- end -}}
76+
{{- else -}}
77+
{{- default "default" $saName -}}
78+
{{- end -}}
79+
{{- end -}}
80+
81+
{{- define "mcp-servers.imagePullSecrets" -}}
82+
{{- $root := .root -}}
83+
{{- $server := .server -}}
84+
{{- $globalIps := default $root.Values.imagePullSecrets $root.Values.global.imagePullSecrets -}}
85+
{{- $ips := default $globalIps $server.imagePullSecrets -}}
86+
{{- if $ips }}
87+
imagePullSecrets:
88+
{{- toYaml $ips | nindent 2 }}
89+
{{- end }}
90+
{{- end -}}
91+
92+
{{- define "mcp-servers.containerPorts" -}}
93+
{{- $server := .server -}}
94+
{{- $ports := default (list (dict "name" "http" "containerPort" 8080)) $server.ports -}}
95+
ports:
96+
{{- range $p := $ports }}
97+
- name: {{ required "mcpServers[].ports[].name is required" $p.name }}
98+
containerPort: {{ required "mcpServers[].ports[].containerPort is required" $p.containerPort }}
99+
protocol: {{ default "TCP" $p.protocol }}
100+
{{- end }}
101+
{{- end -}}
102+
103+
{{- define "mcp-servers.servicePorts" -}}
104+
{{- $server := .server -}}
105+
{{- $svc := default (dict) $server.service -}}
106+
{{- $ports := default (list (dict "name" "http" "port" 80 "targetPort" "http")) $svc.ports -}}
107+
ports:
108+
{{- range $p := $ports }}
109+
- name: {{ required "mcpServers[].service.ports[].name is required" $p.name }}
110+
port: {{ required "mcpServers[].service.ports[].port is required" $p.port }}
111+
targetPort: {{ default $p.name $p.targetPort }}
112+
protocol: {{ default "TCP" $p.protocol }}
113+
{{- end }}
114+
{{- end -}}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
{{- $root := . -}}
2+
{{- range $i, $server := $root.Values.mcpServers }}
3+
{{- if (default true $server.enabled) }}
4+
{{- $fullname := include "mcp-servers.serverFullname" (dict "root" $root "server" $server) -}}
5+
apiVersion: apps/v1
6+
kind: Deployment
7+
metadata:
8+
name: {{ $fullname }}
9+
labels:
10+
{{ include "mcp-servers.commonLabels" (dict "root" $root "server" $server) | nindent 4 }}
11+
{{- $ann := include "mcp-servers.commonAnnotations" (dict "root" $root "server" $server) }}
12+
{{- if $ann }}
13+
annotations:
14+
{{ $ann | nindent 4 }}
15+
{{- end }}
16+
spec:
17+
replicas: {{ default 1 $server.replicas }}
18+
selector:
19+
matchLabels:
20+
{{ include "mcp-servers.selectorLabels" (dict "root" $root "server" $server) | nindent 6 }}
21+
template:
22+
metadata:
23+
labels:
24+
{{ include "mcp-servers.selectorLabels" (dict "root" $root "server" $server) | nindent 8 }}
25+
{{- with $root.Values.global.podLabels }}
26+
{{ toYaml . | nindent 8 }}
27+
{{- end }}
28+
{{- with $server.podLabels }}
29+
{{ toYaml . | nindent 8 }}
30+
{{- end }}
31+
{{- if or $root.Values.global.podAnnotations $server.podAnnotations }}
32+
annotations:
33+
{{- with $root.Values.global.podAnnotations }}
34+
{{ toYaml . | nindent 8 }}
35+
{{- end }}
36+
{{- with $server.podAnnotations }}
37+
{{ toYaml . | nindent 8 }}
38+
{{- end }}
39+
{{- end }}
40+
spec:
41+
serviceAccountName: {{ include "mcp-servers.serviceAccountName" (dict "root" $root "server" $server) }}
42+
{{ include "mcp-servers.imagePullSecrets" (dict "root" $root "server" $server) | nindent 6 }}
43+
{{- with $root.Values.global.podSecurityContext }}
44+
securityContext:
45+
{{ toYaml . | nindent 8 }}
46+
{{- end }}
47+
containers:
48+
- name: {{ include "mcp-servers.serverName" (dict "server" $server) }}
49+
image: "{{ required "mcpServers[].image.repository is required" $server.image.repository }}:{{ default "latest" $server.image.tag }}"
50+
imagePullPolicy: {{ default "IfNotPresent" $server.image.pullPolicy }}
51+
{{- if $server.command }}
52+
command:
53+
{{ toYaml $server.command | nindent 12 }}
54+
{{- end }}
55+
{{- if $server.args }}
56+
args:
57+
{{ toYaml $server.args | nindent 12 }}
58+
{{- end }}
59+
{{ include "mcp-servers.containerPorts" (dict "server" $server) | nindent 10 }}
60+
{{- with (default $root.Values.global.securityContext $server.securityContext) }}
61+
securityContext:
62+
{{ toYaml . | nindent 12 }}
63+
{{- end }}
64+
{{- with $server.env }}
65+
env:
66+
{{ toYaml . | nindent 12 }}
67+
{{- end }}
68+
{{- with $server.envFrom }}
69+
envFrom:
70+
{{ toYaml . | nindent 12 }}
71+
{{- end }}
72+
{{- $resources := default $root.Values.global.resources $server.resources -}}
73+
{{- with $resources }}
74+
resources:
75+
{{ toYaml . | nindent 12 }}
76+
{{- end }}
77+
{{- $persistence := merge (default (dict) $server.persistence) $root.Values.global.persistence -}}
78+
{{- if and $persistence.enabled $persistence.mountPath }}
79+
volumeMounts:
80+
- name: data
81+
mountPath: {{ $persistence.mountPath }}
82+
{{- with $server.volumeMounts }}
83+
{{ toYaml . | nindent 12 }}
84+
{{- end }}
85+
{{- else if $server.volumeMounts }}
86+
volumeMounts:
87+
{{ toYaml $server.volumeMounts | nindent 12 }}
88+
{{- end }}
89+
{{- if or $server.volumes (and $persistence.enabled $persistence.mountPath) }}
90+
volumes:
91+
{{- if and $persistence.enabled $persistence.mountPath }}
92+
- name: data
93+
persistentVolumeClaim:
94+
claimName: {{ default (printf "%s-data" $fullname) $persistence.existingClaim }}
95+
{{- end }}
96+
{{- with $server.volumes }}
97+
{{ toYaml . | nindent 8 }}
98+
{{- end }}
99+
{{- end }}
100+
{{- $nodeSelector := default $root.Values.global.nodeSelector $server.nodeSelector -}}
101+
{{- with $nodeSelector }}
102+
nodeSelector:
103+
{{ toYaml . | nindent 8 }}
104+
{{- end }}
105+
{{- $tolerations := default $root.Values.global.tolerations $server.tolerations -}}
106+
{{- with $tolerations }}
107+
tolerations:
108+
{{ toYaml . | nindent 8 }}
109+
{{- end }}
110+
{{- $affinity := default $root.Values.global.affinity $server.affinity -}}
111+
{{- with $affinity }}
112+
affinity:
113+
{{ toYaml . | nindent 8 }}
114+
{{- end }}
115+
{{- with $server.topologySpreadConstraints }}
116+
topologySpreadConstraints:
117+
{{ toYaml . | nindent 8 }}
118+
{{- end }}
119+
---
120+
{{- end }}
121+
{{- end }}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- $root := . -}}
2+
{{- range $i, $server := $root.Values.mcpServers }}
3+
{{- if (default true $server.enabled) }}
4+
{{- $hpa := default $root.Values.global.hpa $server.hpa -}}
5+
{{- if $hpa.enabled }}
6+
{{- $fullname := include "mcp-servers.serverFullname" (dict "root" $root "server" $server) -}}
7+
apiVersion: autoscaling/v2
8+
kind: HorizontalPodAutoscaler
9+
metadata:
10+
name: {{ $fullname }}
11+
labels:
12+
{{ include "mcp-servers.commonLabels" (dict "root" $root "server" $server) | nindent 4 }}
13+
spec:
14+
scaleTargetRef:
15+
apiVersion: apps/v1
16+
kind: Deployment
17+
name: {{ $fullname }}
18+
minReplicas: {{ default 1 $hpa.minReplicas }}
19+
maxReplicas: {{ default 3 $hpa.maxReplicas }}
20+
{{- with $hpa.metrics }}
21+
metrics:
22+
{{ toYaml . | nindent 4 }}
23+
{{- end }}
24+
---
25+
{{- end }}
26+
{{- end }}
27+
{{- end }}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{{- $root := . -}}
2+
{{- range $i, $server := $root.Values.mcpServers }}
3+
{{- if (default true $server.enabled) }}
4+
{{- $serverHttpRoute := default (dict) $server.httpRoute -}}
5+
{{- $hrEnabled := default $root.Values.global.httpRoute.enabled $serverHttpRoute.enabled -}}
6+
{{- if $hrEnabled }}
7+
{{- $fullname := include "mcp-servers.serverFullname" (dict "root" $root "server" $server) -}}
8+
apiVersion: gateway.networking.k8s.io/v1
9+
kind: HTTPRoute
10+
metadata:
11+
name: {{ $fullname }}
12+
labels:
13+
{{ include "mcp-servers.commonLabels" (dict "root" $root "server" $server) | nindent 4 }}
14+
{{- $hrAnnotations := default $root.Values.global.httpRoute.annotations $serverHttpRoute.annotations -}}
15+
{{- with $hrAnnotations }}
16+
annotations:
17+
{{ toYaml . | nindent 4 }}
18+
{{- end }}
19+
spec:
20+
{{- $hrParentRefs := default $root.Values.global.httpRoute.parentRefs $serverHttpRoute.parentRefs -}}
21+
{{- with $hrParentRefs }}
22+
parentRefs:
23+
{{ toYaml . | nindent 4 }}
24+
{{- end }}
25+
{{- $hrHostnames := default $root.Values.global.httpRoute.hostnames $serverHttpRoute.hostnames -}}
26+
{{- with $hrHostnames }}
27+
hostnames:
28+
{{ toYaml . | nindent 4 }}
29+
{{- end }}
30+
{{- $hrRules := default $root.Values.global.httpRoute.rules $serverHttpRoute.rules -}}
31+
{{- if $hrRules }}
32+
rules:
33+
{{ toYaml $hrRules | nindent 4 }}
34+
{{- else }}
35+
{{- $hrPort := default $root.Values.global.httpRoute.port $serverHttpRoute.port -}}
36+
rules:
37+
- backendRefs:
38+
- name: {{ $fullname }}
39+
port: {{ default 80 $hrPort }}
40+
{{- end }}
41+
---
42+
{{- end }}
43+
{{- end }}
44+
{{- end }}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{{- $root := . -}}
2+
{{- range $i, $server := $root.Values.mcpServers }}
3+
{{- if (default true $server.enabled) }}
4+
{{- $serverIngress := default (dict) $server.ingress -}}
5+
{{- $ingEnabled := default $root.Values.global.ingress.enabled $serverIngress.enabled -}}
6+
{{- if $ingEnabled }}
7+
{{- $fullname := include "mcp-servers.serverFullname" (dict "root" $root "server" $server) -}}
8+
apiVersion: networking.k8s.io/v1
9+
kind: Ingress
10+
metadata:
11+
name: {{ $fullname }}
12+
labels:
13+
{{ include "mcp-servers.commonLabels" (dict "root" $root "server" $server) | nindent 4 }}
14+
{{- $ingAnnotations := default $root.Values.global.ingress.annotations $serverIngress.annotations -}}
15+
{{- with $ingAnnotations }}
16+
annotations:
17+
{{ toYaml . | nindent 4 }}
18+
{{- end }}
19+
spec:
20+
{{- $ingClassName := default $root.Values.global.ingress.className $serverIngress.className -}}
21+
{{- if $ingClassName }}
22+
ingressClassName: {{ $ingClassName }}
23+
{{- end }}
24+
{{- $ingTLS := default $root.Values.global.ingress.tls $serverIngress.tls -}}
25+
{{- if $ingTLS }}
26+
tls:
27+
{{ toYaml $ingTLS | nindent 4 }}
28+
{{- end }}
29+
rules:
30+
{{- $ingHosts := default $root.Values.global.ingress.hosts $serverIngress.hosts -}}
31+
{{- range $host := $ingHosts }}
32+
- host: {{ required "ingress.hosts[].host is required" $host.host }}
33+
http:
34+
paths:
35+
{{- range $p := $host.paths }}
36+
- path: {{ default "/" $p.path }}
37+
pathType: {{ default "Prefix" $p.pathType }}
38+
backend:
39+
service:
40+
name: {{ $fullname }}
41+
port:
42+
name: {{ default "http" $p.servicePortName }}
43+
{{- end }}
44+
{{- end }}
45+
---
46+
{{- end }}
47+
{{- end }}
48+
{{- end }}

0 commit comments

Comments
 (0)