helm

MetaMCP Helm Chart

Deploys MetaMCP and a declarative provisioning system that:

In short: this chart both installs MetaMCP and can pre‑configure it (servers → namespaces → endpoints) from values.yaml. No manual clicking or ad‑hoc scripts required.

Endpoints

Install

helm upgrade --install metamcp icoretech/metamcp \
  -n metamcp --create-namespace \
  --set auth.betterAuthSecret=change-me \
  --set env.APP_URL=http://metamcp-metamcp.metamcp.svc.cluster.local:12008

Notes

Provisioning model

Declare everything under provision.*:

Example

auth:
  betterAuthSecret: dev-secret
env:
  APP_URL: http://metamcp-metamcp.<namespace>.svc.cluster.local:12008

users:
  - email: admin@example.com
    password: change-me
    name: Admin

provision:
  enabled: true
  servers:
    # STDIO executed by MetaMCP
    - name: stdio-everything
      type: STDIO
      command: "npx"
      args: ["-y","@modelcontextprotocol/server-everything","stdio"]

    # Streamable HTTP & SSE servers deployed by this chart and auto-registered
    - name: http-everything
      type: STREAMABLE_HTTP
      port: 3001
      node:
        package: "@modelcontextprotocol/server-everything"
        version: "latest"
        args: ["streamableHttp","--port","3001"]
    - name: sse-everything
      type: SSE
      port: 3001
      node:
        package: "@modelcontextprotocol/server-everything"
        version: "latest"
        args: ["sse","--port","3001"]

  namespaces:
    - name: lab
      description: "Sandbox tools"
      servers: ["stdio-everything","http-everything","sse-everything"]

  endpoints:
    - name: lab
      namespace: lab
      description: "Public lab endpoint"
      transport: SSE
      # Optional auth controls (match UI):
      enableApiKeyAuth: true
      useQueryParamAuth: false
      enableOauth: false

User seeding (required when provisioning is enabled)

Provisioning authenticates using the first entry in users. When provision.enabled: true, you must define at least one user (the schema enforces this). The chart can also generate an API key for that user and store it in a Secret named like <release>-metamcp-apikey-<email-slug>.

disablePublicSignup: true
users:
  - email: admin@example.com
    password: change-me
    name: Admin
    createApiKey: true
    apiKeyName: cli

Reconciliation modes (Flux/Helm upgrades)

By default the provisioning job runs after every Helm install and upgrade and will upsert Namespaces/Endpoints to match values. You can tune this behavior:

Notes

Examples

Continuous upsert (Git is the source of truth):

provision:
  enabled: true
  runOnUpgrade: true
  updateExisting: true

Seed once, keep UI changes later:

provision:
  enabled: true
  runOnUpgrade: false
  updateExisting: false

Provisioning authentication

STDIO examples

Inline env (awsdocs):

provision:
  enabled: true
  servers:
    - name: awsdocs
      type: STDIO
      command: "uvx"
      args: ["awslabs.aws-documentation-mcp-server@latest"]
      env:
        FASTMCP_LOG_LEVEL: "ERROR"
        AWS_DOCUMENTATION_PARTITION: "aws"

Secret-backed env (figma):

provision:
  enabled: true
  servers:
    - name: figma
      type: STDIO
      command: "npx"
      args: ["-y", "figma-developer-mcp", "--stdio"]
      envFrom:
        - secretRef:
            name: figma-mcp-env

Configuration reference

Values

Key Type Default Description
affinity object {}  
auth.betterAuthSecret string ""  
autoscaling.enabled bool false  
autoscaling.maxReplicas int 5  
autoscaling.minReplicas int 1  
autoscaling.targetCPUUtilizationPercentage int 80  
autoscaling.targetMemoryUtilizationPercentage string nil  
disablePublicSignup bool false  
env object {}  
extraEnv list []  
extraEnvFrom list []  
fullnameOverride string ""  
gatewayAPI.enabled bool false  
gatewayAPI.hosts list []  
gatewayAPI.mapBackendPaths bool true  
image.pullPolicy string "IfNotPresent"  
image.repository string "ghcr.io/metatool-ai/metamcp"  
image.tag string "2.4.22"  
imagePullSecrets list []  
ingress.annotations object {}  
ingress.className string ""  
ingress.enabled bool false  
ingress.hosts[0].host string "metamcp.local"  
ingress.hosts[0].paths[0].path string "/"  
ingress.hosts[0].paths[0].pathType string "ImplementationSpecific"  
ingress.mapBackendPaths bool true  
ingress.tls list []  
nameOverride string ""  
nodeSelector object {}  
podAnnotations object {}  
podLabels object {}  
podSecurityContext object {}  
postgres.auth.database string "metamcp"  
postgres.auth.password string "metamcp"  
postgres.auth.username string "metamcp"  
postgres.enabled bool true  
postgres.image string "postgres:16"  
postgres.persistence.enabled bool false  
postgres.persistence.size string "1Gi"  
postgres.persistence.storageClassName string ""  
provision.enabled bool false  
provision.endpoints list []  
provision.namespaces list []  
provision.runOnUpgrade bool true  
provision.servers list []  
provision.updateExisting bool true  
replicaCount int 1  
resources object {}  
securityContext object {}  
service.port int 12008  
service.type string "ClusterIP"  
serviceAccount.annotations object {}  
serviceAccount.automount bool true  
serviceAccount.create bool true  
serviceAccount.name string ""  
tolerations list []  
users list []  

Design highlights

provision: enabled: true servers: - name: figma type: STDIO command: “npx” args: [“-y”, “figma-developer-mcp”, “–stdio”] # Plain env (non-secret) env: LOG_LEVEL: debug # Secret-backed env for STDIO: use envFrom to pull all keys from a Secret/ConfigMap envFrom: - secretRef: name: figma-mcp-env