Skip to content

Commit 4315bf5

Browse files
authored
Merge pull request #183 from IBM/helm-notes
Helm NOTES.TXT
2 parents 1c8ccd5 + 9ccd851 commit 4315bf5

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed

charts/README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,71 @@ For every setting see the [full annotated `values.yaml`](https://github.com/IBM/
269269
2. Update templates or `values.yaml`.
270270
3. Test with `helm lint` and `helm template`.
271271
4. Open a pull request-thank you!
272+
273+
## Features
274+
275+
* 🗂️ Multi-service stack – Deploys MCP Gateway (`n` replicas), Fast-Time-Server (`n` replicas), Postgres 17, Redis, PGAdmin 4 and Redis-Commander out of the box.
276+
* 🎛️ Idiomatic naming – All objects use helper templates (`mcp-stack.fullname`, chart labels) so release names and overrides stay collision-free.
277+
* 🔐 Secrets & credentials – `mcp-stack-gateway-secret` (Basic-Auth creds, JWT signing key, encryption salt, …) and `postgres-secret` (DB user / password / database name), both injected via `envFrom`.
278+
* ⚙️ Config as code – `mcp-stack-gateway-config` (\~40 tunables) and `postgres-config` for the DB name.
279+
* 🔗 Derived URLs – Pods build `DATABASE_URL` and `REDIS_URL` from explicit host/port/user/pass variables—no hard-coding.
280+
* ❤️‍🩹 Health management – Readiness and liveness probes on every deployment; the Gateway also has a startupProbe.
281+
* 🚦 Resource safeguards – CPU and memory requests/limits set for all containers.
282+
* 💾 Stateful storage – PV + PVC for Postgres (`/var/lib/postgresql/data`), storage class selectable.
283+
* 🌐 Networking & access – ClusterIP services, optional NGINX Ingress, and `NOTES.txt` with port-forward plus safe secret-fetch commands (password, bearer token, `JWT_SECRET_KEY`).
284+
* 📈 Replicas & availability – Gateway (3) and Fast-Time-Server (2) provide basic HA; stateful components run single-instance.
285+
* 📦 Helm best-practice layout – Clear separation of Deployments, Services, ConfigMaps, Secrets, PVC/PV and Ingress; chart version 0.2.0.
286+
287+
---
288+
289+
## TODO / Future roadmap
290+
291+
1. 🔄 Post-deploy hook to register MCP Servers with MCP Gateway
292+
2. ⏳ Add startup probes for slow-booting services
293+
3. 🛡️ Implement Kubernetes NetworkPolicies to restrict internal traffic
294+
4. ⚙️ Add Horizontal Pod Autoscaler (HPA) support
295+
5. 📊 Expose Prometheus metrics and add scrape annotations
296+
6. 📈 Bundle Grafana dashboards via ConfigMaps (optional)
297+
7. 🔐 Integrate External Secrets support (e.g., AWS Secrets Manager)
298+
8. 🧪 Add Helm test hooks to validate deployments
299+
9. 🔍 Add `values.schema.json` for values validation and better UX
300+
10. 🧰 Move static configuration to templated `ConfigMaps` where possible
301+
11. 📁 Include persistent storage toggle in `values.yaml` for easier local/dev setup
302+
12. 🧼 Add Helm pre-delete hook for cleanup tasks (e.g., deregistering from external systems)
303+
13. 🧩 Package optional CRDs if needed in the future (e.g., for custom integrations)
304+
305+
## Debug / start fresh (delete namespace)
306+
307+
```bash
308+
# 0. Create and customize the values
309+
cp values.yaml my-values.yaml
310+
311+
# 1. Verify the release name and namespace
312+
helm list -A | grep mcp-stack
313+
314+
# 2. Uninstall the Helm release (removes Deployments, Services, Secrets created by the chart)
315+
helm uninstall mcp-stack -n mcp-private
316+
317+
# 3. Delete any leftover PersistentVolumeClaims *if* you don't need the data
318+
kubectl delete pvc --all -n mcp-private
319+
320+
# 4. Remove the namespace itself (skips if you want to keep it)
321+
kubectl delete namespace mcp-private
322+
323+
# 5. Optional: confirm nothing is left
324+
helm list -A | grep mcp-stack # should return nothing
325+
kubectl get ns | grep mcp-private # should return nothing
326+
327+
# 6. Re-create the namespace (if you deleted it)
328+
kubectl create namespace mcp-private
329+
330+
# 7. Re-install the chart with your values file
331+
helm upgrade --install mcp-stack . \
332+
--namespace mcp-private \
333+
-f my-values.yaml \
334+
--wait --timeout 15m --debug
335+
336+
# 8. Check status
337+
kubectl get all -n mcp-private
338+
helm status mcp-stack -n mcp-private --show-desc
339+
```

charts/mcp-stack/templates/NOTES.txt

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
{{- /*
2+
NOTES.txt for the "mcp-stack" Helm chart
3+
• Rendered after every install/upgrade.
4+
• Surfaces endpoints, credentials and helper commands so you can
5+
start interacting with the stack right away.
6+
• Set showSecrets to show secrets.
7+
*/ -}}
8+
9+
{{- $ns := .Release.Namespace }}
10+
{{- $fullName := include "mcp-stack.fullname" . }}
11+
12+
{{- /* ─── show / hide secrets ───────────────────────────── */}}
13+
{{- $showSecrets := false }} {{/* set to true to reveal passwords & keys */}}
14+
15+
{{- /* ─── Resource names (keep in sync with _helpers.tpl) ─ */}}
16+
{{- $gatewaySvc := printf "%s-mcpgateway" $fullName }}
17+
{{- $ftSvc := printf "%s-mcp-fast-time-server" $fullName }}
18+
{{- $postgresSvc := printf "%s-postgres" $fullName }}
19+
{{- $redisSvc := printf "%s-redis" $fullName }}
20+
{{- $pgadminSvc := printf "%s-pgadmin" $fullName }}
21+
22+
{{- $gwSecret := printf "%s-gateway-secret" $fullName }}
23+
{{- $pgSecret := include "mcp-stack.postgresSecretName" . }}
24+
25+
{{- /* ─── Secret look-ups (only used when $showSecrets=true) */}}
26+
{{- $basicAuthPass := "" }}
27+
{{- $jwtKey := "" }}
28+
{{- $pgPass := "" }}
29+
{{- if $showSecrets }}
30+
{{- with (lookup "v1" "Secret" $ns $gwSecret) }}
31+
{{- $basicAuthPass = index .data "BASIC_AUTH_PASSWORD" | b64dec }}
32+
{{- $jwtKey = index .data "JWT_SECRET_KEY" | b64dec }}
33+
{{- end }}
34+
{{- with (lookup "v1" "Secret" $ns $pgSecret) }}
35+
{{- $pgPass = index .data "POSTGRES_PASSWORD" | b64dec }}
36+
{{- end }}
37+
{{- end }}
38+
39+
{{- /* ─── Convenience ports ─────────────────────────────── */}}
40+
{{- $gwPort := .Values.mcpContextForge.service.port | default 80 }}
41+
{{- $pgPort := .Values.postgres.service.port | default 5432 }}
42+
{{- $redisPort := .Values.redis.service.port | default 6379 }}
43+
{{- $pgAdminPort := .Values.pgadmin.service.port | default 80 }}
44+
45+
🎉 **{{ .Chart.Name }}** has been successfully deployed to namespace **{{ $ns }}**!
46+
47+
{{- /* ════════════ MCP Gateway ════════════ */}}
48+
🔗 **MCP Gateway**
49+
{{- if .Values.mcpContextForge.ingress.enabled }}
50+
• Ingress URL : https://{{ .Values.mcpContextForge.ingress.host }}{{ .Values.mcpContextForge.ingress.path | default "/" }}
51+
{{- else }}
52+
• Service URL : http://{{ $gatewaySvc }}.{{ $ns }}.svc.cluster.local:{{ $gwPort }}
53+
{{- end }}
54+
• Basic-Auth :
55+
user = {{ .Values.mcpContextForge.secret.BASIC_AUTH_USER }}
56+
{{- if $showSecrets }}
57+
password = {{ $basicAuthPass }}
58+
{{- else }}
59+
password : <hidden>
60+
{{- end }}
61+
(kubectl = `kubectl -n {{ $ns }} get secret {{ $gwSecret }} -o jsonpath="{.data.BASIC_AUTH_PASSWORD}" | base64 -d`)
62+
{{- if $showSecrets }}
63+
• JWT signing key (JWT_SECRET_KEY) = {{ $jwtKey }}
64+
{{- else }}
65+
• JWT signing key (JWT_SECRET_KEY) : <hidden>
66+
{{- end }}
67+
(kubectl = `kubectl -n {{ $ns }} get secret {{ $gwSecret }} -o jsonpath="{.data.JWT_SECRET_KEY}" | base64 -d`)
68+
• Port-forward : `kubectl -n {{ $ns }} port-forward svc/{{ $gatewaySvc }} 4444:{{ $gwPort }}`
69+
70+
{{- /* ════════════ Fast-Time-Server ════════════ */}}
71+
🔗 **Fast-Time-Server (SSE)**
72+
• Cluster URL : http://{{ $ftSvc }}.{{ $ns }}.svc.cluster.local
73+
• Via Gateway : {{- if .Values.mcpContextForge.ingress.enabled }} https://{{ .Values.mcpContextForge.ingress.host }}/fast-time {{- else }} http://localhost:4444/fast-time {{- end }}
74+
75+
{{- /* ════════════ Datastores ════════════ */}}
76+
💾 **Postgres**
77+
• Host / Port : {{ $postgresSvc }}.{{ $ns }}.svc.cluster.local:{{ $pgPort }}
78+
• DB : {{ .Values.postgres.credentials.database }}
79+
• User : {{ .Values.postgres.credentials.user }}
80+
{{- if $showSecrets }}
81+
• Password : {{ $pgPass | default "<secret-not-yet-created>" }}
82+
{{- else }}
83+
• Password : <hidden>
84+
{{- end }}
85+
(kubectl = `kubectl -n {{ $ns }} get secret {{ $pgSecret }} -o jsonpath="{.data.POSTGRES_PASSWORD}" | base64 -d`)
86+
87+
🔑 **Redis**
88+
• Host / Port : {{ $redisSvc }}.{{ $ns }}.svc.cluster.local:{{ $redisPort }}
89+
90+
📊 **PGAdmin**
91+
• URL : http://{{ $pgadminSvc }}.{{ $ns }}.svc.cluster.local:{{ $pgAdminPort }}
92+
• Login : {{ .Values.pgadmin.env.email }} / (same Postgres password)
93+
94+
{{- /* ════════════ Quick-start ════════════ */}}
95+
🚀 **Quick-start**
96+
97+
```bash
98+
# 1) Forward the Gateway locally (skip if using ingress):
99+
kubectl -n {{ $ns }} port-forward svc/{{ $gatewaySvc }} 4444:{{ $gwPort }} &
100+
101+
# 2) Obtain a JWT via Basic-Auth (requires 'jq'):
102+
{{- if $showSecrets }}
103+
export GW_TOKEN=$(curl -s -u '{{ .Values.mcpContextForge.secret.BASIC_AUTH_USER }}:{{ $basicAuthPass }}' \
104+
-X POST http://localhost:4444/auth/login | jq -r '.access_token')
105+
{{- else }}
106+
# export GW_TOKEN=(fetch after you retrieve the password with kubectl)
107+
{{- end }}
108+
109+
# 3) Register the Fast-Time-Server with the Gateway:
110+
curl -s -X POST \
111+
-H "Authorization: Bearer $GW_TOKEN" \
112+
-H "Content-Type: application/json" \
113+
-d '{"name":"local_time","url":"http://{{ $ftSvc }}.{{ $ns }}.svc.cluster.local/sse"}' \
114+
http://localhost:4444/gateways
115+
```
116+
117+
📚 **Further reading**
118+
* [https://ibm.github.io/mcp-context-forge/deployment/helm/](https://ibm.github.io/mcp-context-forge/deployment/helm/)
119+
* [https://ibm.github.io/mcp-context-forge/testing/basic/](https://ibm.github.io/mcp-context-forge/testing/basic/)

0 commit comments

Comments
 (0)