Skip to content
Last updated

Host the MCP Gateway

This guide explains how to deploy Frontegg's MCP Gateway Helm chart in your Kubernetes cluster. The chart packages two services that expose an MCP-compliant authorization and tool routing layer in front of your MCP servers.

ComponentRole
mcp-authServes OAuth, dynamic client registration, authorization, and callback endpoints for MCP clients.
mcp-gwReceives MCP requests and routes or authorizes them against Frontegg.

Both components share a Redis backend for token and session caching and are configured against a Frontegg vendor using region, client credentials, and applicationId.

What the chart deploys

For each release, the chart renders:

  • Deployment/<release>-mcp-gateway-auth, which runs the mcp-auth image.
  • Deployment/<release>-mcp-gateway-gw, which runs the mcp-gw image.
  • Service/<release>-mcp-gateway-auth, a ClusterIP service on mcpAuth.port.
  • Service/<release>-mcp-gateway-gw, a ClusterIP service on mcpGw.port.
  • A shared ServiceAccount, which is optional and enabled by default.
  • HorizontalPodAutoscaler resources per component, which are optional and disabled by default.

The chart does not ship an Ingress, API gateway, or other layer-7 router. You must front the two services with the path-matching ingress or API gateway you already use, such as NGINX Ingress, Traefik, Istio, Envoy, AWS ALB, GCP HTTPS LB, or Kong. See Routing for the path map you need to configure.

Installation

helm repo add frontegg https://frontegg.github.io/helm-charts/
helm repo update
helm upgrade --install mcp-gateway frontegg/mcp-gateway -f my-values.yaml

Minimal values.yaml

Every value under env must be filled in for a working deployment. Names are camelCase in values.yaml and are translated to UPPER_SNAKE_CASE environment variables on both containers. For example, vendorClientId becomes VENDOR_CLIENT_ID.

env:
  # Redis shared cache for sessions and tokens.
  redisHost: my-redis.example.com
  redisPort: "6379"
  redisPassword: "<redis-password>"
  redisDb: "0"
  redisTlsEnabled: "true"
  cacheTtl: "300"

  # Frontegg vendor.
  fronteggRegion: "eu" # eu | us | ca | au | stg
  vendorClientId: "<vendor-client-id>"
  vendorClientSecret: "<vendor-client-secret>"
  applicationId: "<application-id>"

  # The hostname this gateway will be reached at, without scheme.
  fronteggMcpGwHost: "tenant.mcp-gw.frontegg.com"
  # The same host with scheme, used as the OAuth issuer and authorization URL.
  externalAuthorizationUrl: "https://tenant.mcp-gw.frontegg.com"
  # Your hybrid auth backend, with scheme.
  hybridAuthHost: "https://hybrid-auth.customer.example.com"

Optional environment values:

KeyPurpose
approvalFlowWebhookEndpointWebhook that receives tool-call approval requests.
eventWebhookProviderWhere to forward audit events, such as datadog.
eventWebhookUrlDestination URL for the event webhook.
eventWebhookSecretShared secret for signing event webhook deliveries.

These are commented out in the default values.yaml. Uncomment and set them if needed.

Routing

The two services must sit behind a path-matching HTTP router, such as an Ingress controller, service mesh gateway, or cloud API gateway. Configure it so that the following auth-related paths land on mcp-auth and everything else lands on mcp-gw:

PathTarget service
/.well-known/*<release>-mcp-gateway-auth
/authorize<release>-mcp-gateway-auth
/integration-callback<release>-mcp-gateway-auth
/security-stepup-verify<release>-mcp-gateway-auth
/dcr/register<release>-mcp-gateway-auth
Everything else, /<release>-mcp-gateway-gw

Your router must satisfy these requirements:

  • Order and specificity: The auth paths above must win over the catch-all / route. Most ingress controllers do this automatically based on prefix length. On routers that match in declared order, declare the auth rules first.
  • Host header preservation: The Host header of the incoming request must match env.fronteggMcpGwHost. Both services use it to validate issuer URLs. If your gateway rewrites the upstream host, configure it to pass the original host.
  • Single external hostname: Both services are reached on the same external host. Only the path differs.

Common configuration

Image tags

Image tags are pinned in the chart and are bumped by Frontegg as part of releasing a new chart version. Do not override mcpAuth.tag or mcpGw.tag. To pick up a new image, upgrade to a newer chart version:

helm repo update
helm upgrade mcp-gateway frontegg/mcp-gateway -f my-values.yaml

Resources

Each component has independent resources blocks under mcpAuth.resources and mcpGw.resources. Defaults are conservative, with 200m CPU and 256Mi memory requests and a 512Mi memory limit, and are suitable for low-traffic tenants.

Autoscaling

Autoscaling is disabled by default. Enable it per component:

autoscaling:
  mcpGw:
    enabled: true
    minReplicas: 2
    maxReplicas: 10
    targetCPUUtilizationPercentage: 70
  mcpAuth:
    enabled: true
    minReplicas: 2
    maxReplicas: 5
    targetCPUUtilizationPercentage: 70

When autoscaling.<component>.enabled is true, the Deployment's replicas field is omitted so the HPA can manage it.

Probes

All three probes, liveness, readiness, and startup, hit GET /health on port http. Override per component if your environment needs different timings:

mcpGw:
  livenessProbe:
    httpGet:
      path: /health
      port: http
    initialDelaySeconds: 10
    periodSeconds: 10

Pod scheduling

nodeSelector, tolerations, affinity, podAnnotations, podLabels, podSecurityContext, and securityContext are top-level values and apply to both deployments. There is no per-component override today. To schedule the two components differently, install the chart twice with a nameOverride.

Service account

A single ServiceAccount is shared by both deployments. To use an existing one:

serviceAccount:
  create: false
  name: my-existing-sa

Values reference

KeyDefaultDescription
mcpAuth.repository527305576865.dkr.ecr.us-east-1.amazonaws.com/docker-hub/frontegg/hybrid-agen-co-authmcp-auth image repository. Override only for private registry mirrors.
mcpAuth.tagPinned by chartManaged by Frontegg and bumped by chart release. Do not override.
mcpAuth.pullPolicyIfNotPresentImage pull policy.
mcpAuth.replicaCount1Used when autoscaling.mcpAuth.enabled is false.
mcpAuth.port8080Service port. The container always listens on 8080.
mcpAuth.resourcesrequests: {cpu: 200m, memory: 256Mi}, limits: {memory: 512Mi}Default resource requests and limits.
mcpAuth.{liveness,readiness,startup}ProbeGET /health on port httpDefault health probes.
mcpGw.*Mirrors mcpAuth.* defaultsmcp-gw deployment configuration.
imagePullSecrets[]List of name entries for private registry credentials.
nameOverride and fullnameOverride""Name override values.
serviceAccount.createtrueWhether to create a ServiceAccount.
serviceAccount.automounttrueWhether to automount the ServiceAccount token.
serviceAccount.annotations{}Useful for IRSA or Workload Identity.
serviceAccount.name""If empty, defaults to the chart fullname.
service.typeClusterIPApplied to both services.
podAnnotations and podLabels{}Applied to both deployments' pod templates.
podSecurityContext{}Pod-level security context.
securityContextcapabilities.drop: [NET_RAW]Container-level security context.
autoscaling.mcpAuth.enabledfalseWhether autoscaling is enabled for mcp-auth.
autoscaling.mcpAuth.minReplicas and maxReplicas1 and 100Replica bounds for mcp-auth.
autoscaling.mcpAuth.targetCPUUtilizationPercentage80CPU utilization target.
autoscaling.mcpAuth.targetMemoryUtilizationPercentageUnsetSet to enable memory-based scaling.
autoscaling.mcpGw.*Mirrors autoscaling.mcpAuth.*Autoscaling configuration for mcp-gw.
volumes and volumeMounts[]Applied to both deployments.
nodeSelector, tolerations, and affinity{}, [], and {}Applied to both deployments.
env.redisHost""Hostname of the shared Redis instance.
env.redisPort"6379"Redis port.
env.redisPassword""Redis password.
env.redisDb"0"Redis database.
env.redisTlsEnabled"true"Set to "false" for plain Redis.
env.cacheTtl"300"Token and session cache TTL in seconds.
env.fronteggRegion"eu"Supported values are eu, us, ca, au, and stg.
env.vendorClientId""Frontegg vendor client ID.
env.vendorClientSecret""Frontegg vendor client secret.
env.applicationId""Frontegg application ID.
env.fronteggMcpGwHost""External hostname of the gateway, without scheme.
env.externalAuthorizationUrl""Same hostname with scheme, published as the OAuth issuer.
env.hybridAuthHost""URL of your hybrid auth service, with scheme.
env.approvalFlowWebhookEndpointCommentedWebhook for approval-flow callbacks.
env.eventWebhookProviderCommentedExample: datadog.
env.eventWebhookUrlCommentedDestination URL for event webhooks.
env.eventWebhookSecretCommentedShared secret for signing event webhooks.

Every key under .Values.env is converted from camelCase to UPPER_SNAKE_CASE and emitted as a container environment variable on both containers. To add a new environment variable, add a key under env.

Verify the install

# Watch the rollout.
kubectl rollout status deploy/<release>-mcp-gateway-auth
kubectl rollout status deploy/<release>-mcp-gateway-gw

# Health checks. Both should return 200.
kubectl port-forward svc/<release>-mcp-gateway-auth 8080:8080 &
curl -fsS http://localhost:8080/health

kubectl port-forward svc/<release>-mcp-gateway-gw 8081:8080 &
curl -fsS http://localhost:8081/health

Upgrade the chart

There are no CRDs and no persistent state owned by the chart. Redis lives outside it.

Image versions are tied to chart versions. Each chart release pins the matching mcp-auth and mcp-gw images. To roll out a new image, upgrade the chart:

helm repo update
helm upgrade mcp-gateway frontegg/mcp-gateway --version <new-chart-version> -f my-values.yaml

Do not override mcpAuth.tag or mcpGw.tag in your values file. Those are managed by Frontegg as part of the chart release.