fullnameOverride: "kubectl-mcp-server" replicas: 1 image: repository: asia-southeast1-docker.pkg.dev/meesho-devops-admin-0622/prd/devop/kubectl-mcp-server tag: v2 pullPolicy: IfNotPresent labels: bu: infra team: devops serviceAccount: create: true annotations: {} name: "" # RBAC — ClusterRole + ClusterRoleBinding for the pod ServiceAccount. # The role grants get/list/watch ONLY (no create/update/patch/delete) and # deliberately excludes `secrets`. This is the enforcement layer behind the # server's own deny-by-default allowlist (no write/secret tools registered). rbac: create: true podAnnotations: {} podSecurityContext: {} securityContext: runAsNonRoot: true runAsUser: 1000 allowPrivilegeEscalation: false capabilities: drop: - ALL priorityClassName: "" nodeSelector: {} tolerations: [] affinity: {} resources: requests: cpu: 250m memory: 512Mi limits: cpu: 1000m memory: 1Gi # --- MCP server settings --------------------------------------------------- # The image ENTRYPOINT is `k8s-rca-mcp`, configured ENTIRELY via env vars # (there are NO CLI args). transport: http is streamable-http for Bifrost / # HTTP MCP clients. mcp: mode: single # single | multi (federation hub) transport: http host: "0.0.0.0" port: 8000 # --- inbound auth on the MCP endpoint -------------------------------------- # Bearer token. On http transport the server REFUSES TO START unless the # MCP_AUTH_TOKEN env var is present OR allowAnonymous is true. The token is # NOT stored in values/git — it is pulled from Vault (see externalSecrets). # Clients send: Authorization: Bearer auth: allowAnonymous: false # --- secrets from Vault (external-secrets.io) ------------------------------ # One ExternalSecret extracts a Vault path into the Secret `-creds`, # which the Deployment injects with `envFrom`. Every key at the Vault path # becomes a container env var verbatim, so store them as env var NAMES: # MCP_AUTH_TOKEN — inbound bearer (always) # per backend — e.g. SUPPLY_MCP_TOKEN (multi mode only), # matching the registry's `tokenEnv:` below externalSecrets: enabled: true refreshInterval: "150s" secretStoreRef: name: vault-backend kind: ClusterSecretStore dataFrom: # Vault path holding the tokens — set per cluster in the override. secretKey: "" # Optional: pin a specific Vault secret version. version: "" # Override the synced Secret name (default: -creds). secretName: "" # Extra envFrom sources (merged after the Vault creds secret), e.g. a # manually-created Secret for local testing without Vault. envFrom: [] # --- federation (only used when mcp.mode == multi) ------------------------- # The hub holds NO remote kubeconfigs. It forwards each tool call to the # target cluster's own single-mode MCP using a per-backend bearer token. # Those tokens live in Vault (keys named to match each `tokenEnv:` below). federation: forwardTimeout: 30 # Rendered into a ConfigMap mounted at /etc/k8s-rca-mcp/clusters.yaml. # Exactly one entry must be `self: true`. clusters: - name: self self: true # - name: supply # endpoint: https://kubectl-mcp-server.supply.stg.meesho.int/mcp # tokenEnv: SUPPLY_MCP_TOKEN # <- must be a key at the Vault path # NOTE: tcpSocket, not httpGet — under streamable-http transport FastMCP # serves ONLY /mcp (GET /health 404s; upstream's chart gets this wrong). # /mcp itself returns 406 to plain GETs, so TCP is the reliable signal. livenessProbe: tcpSocket: port: 8000 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: tcpSocket: port: 8000 initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 service: port: 8000 type: ClusterIP # Ingress — 2.0.0-chart style. nginx-* classes render a networking.k8s.io # Ingress; contour-* classes (with createContourGateway: true) render the # standard Meesho HTTPProxy parent/child pair plus the -intra variant. createContourGateway: true ingress: enabled: true ingressClassName: nginx-internal servicePortNumber: 8000 hosts: - host: "" paths: - path: / pathType: Prefix annotations: kubernetes.io/ingress.class: nginx-internal nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" nginx.ingress.kubernetes.io/limit-rps: "10" nginx.ingress.kubernetes.io/limit-connections: "20" slowStart: enabled: false window: "120s" aggression: 1 minPercent: 10