From 39b846484f42d21813bd1f712fac2347185f3028 Mon Sep 17 00:00:00 2001 From: Arnold Wang Date: Mon, 20 Jul 2026 13:53:15 -0700 Subject: [PATCH] [chore][MCP] Clean up configuration comments --- charts/retool/Chart.yaml | 2 +- charts/retool/templates/_helpers.tpl | 9 +- .../retool/templates/deployment_backend.yaml | 5 +- charts/retool/templates/deployment_mcp.yaml | 5 +- charts/retool/templates/ingress.yaml | 2 - charts/retool/values.yaml | 149 ++++++++---------- values.yaml | 149 ++++++++---------- 7 files changed, 132 insertions(+), 189 deletions(-) diff --git a/charts/retool/Chart.yaml b/charts/retool/Chart.yaml index 5eaeda6e..0e55baea 100644 --- a/charts/retool/Chart.yaml +++ b/charts/retool/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: retool description: A Helm chart for Kubernetes type: application -version: 6.11.10 +version: 6.11.11 maintainers: - name: Retool Engineering email: engineering+helm@retool.com diff --git a/charts/retool/templates/_helpers.tpl b/charts/retool/templates/_helpers.tpl index e1a32bf4..7a6fdccb 100644 --- a/charts/retool/templates/_helpers.tpl +++ b/charts/retool/templates/_helpers.tpl @@ -34,11 +34,8 @@ limit used by Service names and label values. {{- end }} {{/* -Resolve the public host that serves MCP OAuth metadata routes. An explicit -mcp.config.oauthMainDomain wins; when unset, fall back to the common backend -BASE_DOMAIN value from .Values.env. Secret-backed or valueFrom-style BASE_DOMAIN -settings are intentionally not inferred because their values are not available -at template time. +Resolve the public OAuth host. mcp.config.oauthMainDomain takes precedence over +env.BASE_DOMAIN. Secret-backed values cannot be resolved at template time. */}} {{- define "retool.mcp.oauthMainDomain" -}} {{- $mcpConfig := (.Values.mcp.config | default dict) -}} @@ -876,7 +873,7 @@ Usage: {{- include "retool.agentSandbox.backendEnvVars" . | nindent 10 }} {{- end -}} {{/* -Set MCP server service name +Return the MCP server Service name. */}} {{- define "retool.mcp.name" -}} {{ include "retool.fullnameWithSuffix" (list . "mcp") }} diff --git a/charts/retool/templates/deployment_backend.yaml b/charts/retool/templates/deployment_backend.yaml index 87e28028..26c427fd 100644 --- a/charts/retool/templates/deployment_backend.yaml +++ b/charts/retool/templates/deployment_backend.yaml @@ -288,10 +288,7 @@ spec: {{ toYaml . | indent 10 }} {{- end }} {{- if .Values.mcp.enabled }} - {{- /* The backend serves /api/oauth2/introspect and rejects the call unless - OAUTH_INTROSPECTION_AUTH_TOKEN matches what MCP sends. Pull it from the - same source the MCP deployment uses so they stay in sync. Skip if the - operator already set the token on the backend. */}} + {{- /* Share MCP's introspection token unless either workload overrides it. */}} {{- $mcpConfig := .Values.mcp.config | default dict }} {{- $chartOwnedConfigSecret := eq (include "shouldIncludeConfigSecretsEnvVars" . | trim) "1" }} {{- $mcpEnvHasIntrospectionToken := false }} diff --git a/charts/retool/templates/deployment_mcp.yaml b/charts/retool/templates/deployment_mcp.yaml index 34335271..a85b1380 100644 --- a/charts/retool/templates/deployment_mcp.yaml +++ b/charts/retool/templates/deployment_mcp.yaml @@ -149,10 +149,7 @@ spec: - name: RETOOL_BACKEND_URL value: {{ $mcpConfig.retoolBackendUrl | default (printf "http://%s:%v" (include "retool.fullname" .) .Values.service.externalPort) | quote }} {{- include "retool.agentSandbox.proxyEnvVars" . | nindent 10 }} - {{- /* - Prefer an explicit mcp.config.retoolGitServerUrl; otherwise, when the - git server is split into its own deployment, auto-point MCP at it. - */}} + {{- /* Route git API calls directly to the split Service unless overridden. */}} {{- $retoolGitServerUrl := $mcpConfig.retoolGitServerUrl }} {{- if and (not $retoolGitServerUrl) (include "retool.gitServer.separateEnabled" .) }} {{- $retoolGitServerUrl = include "retool.gitServer.url" . }} diff --git a/charts/retool/templates/ingress.yaml b/charts/retool/templates/ingress.yaml index 7d59ff1e..0fa630fb 100644 --- a/charts/retool/templates/ingress.yaml +++ b/charts/retool/templates/ingress.yaml @@ -49,7 +49,6 @@ spec: number: {{ .port }} {{- end }} {{- end }} - # MCP-related paths must be added before the main path to avoid less specific paths being matched first. {{- if ( and ((.Values.mcp).enabled) $mcpIngress.enabled ) }} {{- range $mcpIngress.paths }} {{- include "retool.ingress.mcpPath" (dict "root" $ "path" . "backendInternalPort" $backendInternalPort) | nindent 10 }} @@ -91,7 +90,6 @@ spec: number: {{ .port }} {{- end }} {{- end }} - # MCP-related paths must be added before the main path to avoid less specific paths being matched first. {{- if ( and (($.Values.mcp).enabled) $mcpIngress.enabled ) }} {{- range $mcpIngress.paths }} {{- include "retool.ingress.mcpPath" (dict "root" $ "path" . "backendInternalPort" $backendInternalPort) | nindent 10 }} diff --git a/charts/retool/values.yaml b/charts/retool/values.yaml index afa05175..04decbee 100644 --- a/charts/retool/values.yaml +++ b/charts/retool/values.yaml @@ -610,32 +610,45 @@ multiplayer: annotations: {} labels: {} +# MCP enablement examples: +# +# Simplest: use the chart-managed OAuth introspection token. BASE_DOMAIN must +# be the public Retool origin already served by your ingress: +# +# env: +# BASE_DOMAIN: https://retool.example.com +# mcp: +# enabled: true +# +# With an explicit public host and an existing Kubernetes Secret: +# +# mcp: +# enabled: true +# config: +# oauthMainDomain: retool.example.com +# oauthIntrospectionAuthTokenSecretName: retool-mcp-oauth +# oauthIntrospectionAuthTokenSecretKey: token +# +# The chart injects the token into both MCP and the backend. The MCP ingress +# routes below are enabled by default; reproduce their mapping when ingress is +# managed outside this chart. mcp: - # Run Retool's MCP server as a separate deployment. Independent of the - # .Values.rr.enabled master switch (the MCP server needs its own OAuth - # introspection config, so it is opt-in): set true to enable. + # Set to true to deploy the MCP server. enabled: false replicaCount: 1 - # Annotations for MCP server pods annotations: {} - # Labels for MCP server pods labels: {} - # MCP-specific environment variables. Can include valueFrom entries. - # Use this for MCP-only env vars that are not exposed under mcp.config. + # Additional MCP environment variables, including valueFrom entries. + # Use for settings not exposed under mcp.config. environmentVariables: [] - # MCP server configuration. - # The chart always sets RETOOL_BACKEND_URL, defaulting to the release's - # internal Retool service, e.g. http://:. - # For other config keys, the chart only emits environment variables when you set - # them. When unset, the MCP service uses its runtime defaults: - # enabledToolsets: all available toolsets - # apps, resources, workflows, folders, environments, users, - # groups, organization, user_invites, feedback, r2_themes + # MCP settings translated to environment variables. RETOOL_BACKEND_URL + # defaults to http://:. Other unset settings + # use the MCP runtime defaults: # maxTransportSessions: 1000 # sessionIdleTimeoutMs: 3600000 (1 hour) # sessionSweepIntervalMs: 60000 (1 minute) @@ -647,69 +660,60 @@ mcp: # # Defaults to the release's internal Retool service when unset. # retoolBackendUrl: # - # # Internal URL used by the MCP server to call the Retool git server. - # # Unset by default. + # # Optional override for MCP git-server API calls. When unset: + # # - If rr.gitServer.separate.enabled is true, the chart automatically + # # sets RETOOL_GIT_SERVER_URL to the split git-server Service URL. + # # - If rr.gitServer.separate.enabled is false, MCP automatically uses + # # retoolBackendUrl. # retoolGitServerUrl: # - # # Optional public Retool origin used for client-facing MCP upload URLs - # # when the request Host header is not enough. Do not include /mcp. + # # Public Retool origin for client-facing upload URLs when the request Host + # # header is insufficient. Do not include /mcp. # mcpServiceExternalUrl: # # # Deprecated alias for mcpServiceExternalUrl. # retoolUrl: # - # # Public Retool host that serves MCP OAuth metadata routes and - # # /api/oauth2/* endpoints. Defaults to env.BASE_DOMAIN when unset. This is - # # usually the same host users use to access Retool, not an oauth.* - # # subdomain. The MCP service expects a host here, but the chart also - # # accepts URL-shaped values and strips http(s)://. + # # Public Retool host serving OAuth metadata and /api/oauth2/*. Defaults to + # # env.BASE_DOMAIN and is usually the Retool application host, not an + # # oauth.* subdomain. URL-shaped values are accepted with the scheme removed. # oauthMainDomain: # - # # Secret-backed token used by MCP to call /api/oauth2/introspect. When - # # unset, the chart auto-generates one in the release Secret on first deploy - # # if chart-owned config secrets are enabled. Set this when using an - # # externally managed Secret instead. The chart injects the same token into - # # the main Retool backend (which serves /api/oauth2/introspect), so no - # # separate backend env configuration is needed. The exception is setting - # # OAUTH_INTROSPECTION_AUTH_TOKEN in mcp.environmentVariables: the MCP pod - # # then uses that value and the backend is not auto-wired, so you must also - # # set OAUTH_INTROSPECTION_AUTH_TOKEN in the global env: block. + # # Secret containing the OAuth introspection token shared by MCP and the + # # backend. When chart-owned secrets are enabled, omitting this generates a + # # token. If the token is instead set through mcp.environmentVariables, set + # # the same backend value through top-level env, environmentVariables, or + # # environmentSecrets. # oauthIntrospectionAuthTokenSecretName: # oauthIntrospectionAuthTokenSecretKey: oauthIntrospectionAuthToken # - # # Literal token override for development/testing only. Prefer the - # # secret-backed setting above for real deployments. + # # Literal token for development only; prefer the secret-backed setting. # oauthIntrospectionAuthToken: # - # # Optional override for the secret-backed private key used by MCP to sign - # # agent sandbox requests. When unset and rr.agentSandbox is enabled, MCP - # # reuses rr.agentSandbox.externalSecret.name with key jwt-private-key. + # # Secret containing the private key used to sign agent sandbox requests. + # # Defaults to the rr.agentSandbox external Secret and jwt-private-key key. # agentSandboxJwtPrivateKeySecretName: # agentSandboxJwtPrivateKeySecretKey: jwt-private-key # - # # Literal private key override for development/testing only. When unset and - # # rr.agentSandbox is enabled, MCP can reuse rr.agentSandbox.jwtPrivateKey. - # # Prefer the secret-backed setting above for real deployments. + # # Literal private key for development only. Defaults to + # # rr.agentSandbox.jwtPrivateKey when the agent sandbox is enabled. # agentSandboxJwtPrivateKey: # - # # Optional Node.js options for the MCP server process. Unset by default. + # # Node.js options for the MCP server process. # nodeOptions: --max_old_space_size=1024 # - # # Optional MCP service configuration. If enabledToolsets is unset, all - # # available toolsets are enabled by default. + # # Restrict the enabled toolsets. All available toolsets are enabled when unset. # enabledToolsets: # - apps # - resources - # # Optional max concurrent MCP transport sessions. Renders as - # # MCP_MAX_TRANSPORT_SESSIONS. If unset, the MCP service uses its runtime - # # default. + # # Maximum concurrent transport sessions. # maxTransportSessions: 1000 # sessionIdleTimeoutMs: 1800000 # sessionSweepIntervalMs: 60000 # sessionGaugeEmitIntervalMs: 30000 - # Resources for MCP server pods. MCP runs from the backend image and does not - # horizontally scale yet, so its default memory limit is higher than multiplayer. + # MCP pod resources. The server does not horizontally scale yet, so its + # default memory limit is higher than multiplayer's. resources: requests: cpu: "200m" @@ -717,49 +721,24 @@ mcp: limits: memory: "4096Mi" - # Public ingress routes for MCP-related OAuth metadata. When MCP is enabled, - # this config creates a dedicated backend API Service named - # -backend-internal for metadata routes that require the backend API - # listener, truncated to fit Kubernetes' 63-character DNS label limit when - # needed. + # Backend API Service for the OAuth authorization-server metadata route. backendMetadata: service: enabled: true - # Service port that exposes the backend API listener for metadata routes - # that should not fall through to the static frontend server or MCP - # service. portName: http-api externalPort: 3001 internalPort: 3001 annotations: {} labels: {} - # Public MCP-related ingress paths. Paths are emitted in order before the main - # Retool route: - # - OAuth authorization-server metadata hits the backend API service. - # - Protected-resource metadata, /mcp, and /mcp subpaths hit the MCP service. - # - # If you manage ingress outside this Helm chart, mcp.enabled only creates the - # chart-side resources. Your external ingress must route these paths, in this - # order before the "/" catch-all: - # - # -backend-internal:3001 - # /.well-known/oauth-authorization-server - # - # -mcp:4010 - # /.well-known/oauth-protected-resource - # /mcp (Prefix) - # - # :3000 - # / (Prefix) - # - # Otherwise OAuth metadata requests can fall through to the frontend and - # return HTML instead of JSON. If you use nameOverride, fullnameOverride, or a - # non-default release name, service names may differ; run "kubectl get svc" - # after installation and look for the main Retool service, the *-backend-internal - # service, and the *-mcp service. + # Public MCP routes, rendered before the main Retool route. External ingress + # must preserve this order and target mapping: + # Exact /.well-known/oauth-authorization-server -> -backend-internal:3001 + # Exact /.well-known/oauth-protected-resource -> -mcp:4010 + # Prefix /mcp -> -mcp:4010 + # Prefix / -> :3000 ingress: - # This conditional is dependent on mcp.enabled. + # Also requires mcp.enabled. enabled: true paths: - path: /.well-known/oauth-authorization-server @@ -770,9 +749,9 @@ mcp: - path: /mcp pathType: Prefix - # HTTPRoute rules for MCP when using Gateway API instead of ingress. + # Equivalent Gateway API routes. httpRoute: - # This conditional is dependent on mcp.enabled. + # Also requires mcp.enabled. enabled: true rules: - path: /.well-known/oauth-authorization-server @@ -845,8 +824,6 @@ codeExecutor: # this switch; set a component's `enabled` to true/false to override the master # for that component only. The gitServer and blobStorage blocks below # provide the React Retool git server and the object storage the stack needs. -# (The MCP server is configured separately at the top level: it needs its own -# OAuth opt-in and is intentionally independent of this master switch.) rr: enabled: false diff --git a/values.yaml b/values.yaml index afa05175..04decbee 100644 --- a/values.yaml +++ b/values.yaml @@ -610,32 +610,45 @@ multiplayer: annotations: {} labels: {} +# MCP enablement examples: +# +# Simplest: use the chart-managed OAuth introspection token. BASE_DOMAIN must +# be the public Retool origin already served by your ingress: +# +# env: +# BASE_DOMAIN: https://retool.example.com +# mcp: +# enabled: true +# +# With an explicit public host and an existing Kubernetes Secret: +# +# mcp: +# enabled: true +# config: +# oauthMainDomain: retool.example.com +# oauthIntrospectionAuthTokenSecretName: retool-mcp-oauth +# oauthIntrospectionAuthTokenSecretKey: token +# +# The chart injects the token into both MCP and the backend. The MCP ingress +# routes below are enabled by default; reproduce their mapping when ingress is +# managed outside this chart. mcp: - # Run Retool's MCP server as a separate deployment. Independent of the - # .Values.rr.enabled master switch (the MCP server needs its own OAuth - # introspection config, so it is opt-in): set true to enable. + # Set to true to deploy the MCP server. enabled: false replicaCount: 1 - # Annotations for MCP server pods annotations: {} - # Labels for MCP server pods labels: {} - # MCP-specific environment variables. Can include valueFrom entries. - # Use this for MCP-only env vars that are not exposed under mcp.config. + # Additional MCP environment variables, including valueFrom entries. + # Use for settings not exposed under mcp.config. environmentVariables: [] - # MCP server configuration. - # The chart always sets RETOOL_BACKEND_URL, defaulting to the release's - # internal Retool service, e.g. http://:. - # For other config keys, the chart only emits environment variables when you set - # them. When unset, the MCP service uses its runtime defaults: - # enabledToolsets: all available toolsets - # apps, resources, workflows, folders, environments, users, - # groups, organization, user_invites, feedback, r2_themes + # MCP settings translated to environment variables. RETOOL_BACKEND_URL + # defaults to http://:. Other unset settings + # use the MCP runtime defaults: # maxTransportSessions: 1000 # sessionIdleTimeoutMs: 3600000 (1 hour) # sessionSweepIntervalMs: 60000 (1 minute) @@ -647,69 +660,60 @@ mcp: # # Defaults to the release's internal Retool service when unset. # retoolBackendUrl: # - # # Internal URL used by the MCP server to call the Retool git server. - # # Unset by default. + # # Optional override for MCP git-server API calls. When unset: + # # - If rr.gitServer.separate.enabled is true, the chart automatically + # # sets RETOOL_GIT_SERVER_URL to the split git-server Service URL. + # # - If rr.gitServer.separate.enabled is false, MCP automatically uses + # # retoolBackendUrl. # retoolGitServerUrl: # - # # Optional public Retool origin used for client-facing MCP upload URLs - # # when the request Host header is not enough. Do not include /mcp. + # # Public Retool origin for client-facing upload URLs when the request Host + # # header is insufficient. Do not include /mcp. # mcpServiceExternalUrl: # # # Deprecated alias for mcpServiceExternalUrl. # retoolUrl: # - # # Public Retool host that serves MCP OAuth metadata routes and - # # /api/oauth2/* endpoints. Defaults to env.BASE_DOMAIN when unset. This is - # # usually the same host users use to access Retool, not an oauth.* - # # subdomain. The MCP service expects a host here, but the chart also - # # accepts URL-shaped values and strips http(s)://. + # # Public Retool host serving OAuth metadata and /api/oauth2/*. Defaults to + # # env.BASE_DOMAIN and is usually the Retool application host, not an + # # oauth.* subdomain. URL-shaped values are accepted with the scheme removed. # oauthMainDomain: # - # # Secret-backed token used by MCP to call /api/oauth2/introspect. When - # # unset, the chart auto-generates one in the release Secret on first deploy - # # if chart-owned config secrets are enabled. Set this when using an - # # externally managed Secret instead. The chart injects the same token into - # # the main Retool backend (which serves /api/oauth2/introspect), so no - # # separate backend env configuration is needed. The exception is setting - # # OAUTH_INTROSPECTION_AUTH_TOKEN in mcp.environmentVariables: the MCP pod - # # then uses that value and the backend is not auto-wired, so you must also - # # set OAUTH_INTROSPECTION_AUTH_TOKEN in the global env: block. + # # Secret containing the OAuth introspection token shared by MCP and the + # # backend. When chart-owned secrets are enabled, omitting this generates a + # # token. If the token is instead set through mcp.environmentVariables, set + # # the same backend value through top-level env, environmentVariables, or + # # environmentSecrets. # oauthIntrospectionAuthTokenSecretName: # oauthIntrospectionAuthTokenSecretKey: oauthIntrospectionAuthToken # - # # Literal token override for development/testing only. Prefer the - # # secret-backed setting above for real deployments. + # # Literal token for development only; prefer the secret-backed setting. # oauthIntrospectionAuthToken: # - # # Optional override for the secret-backed private key used by MCP to sign - # # agent sandbox requests. When unset and rr.agentSandbox is enabled, MCP - # # reuses rr.agentSandbox.externalSecret.name with key jwt-private-key. + # # Secret containing the private key used to sign agent sandbox requests. + # # Defaults to the rr.agentSandbox external Secret and jwt-private-key key. # agentSandboxJwtPrivateKeySecretName: # agentSandboxJwtPrivateKeySecretKey: jwt-private-key # - # # Literal private key override for development/testing only. When unset and - # # rr.agentSandbox is enabled, MCP can reuse rr.agentSandbox.jwtPrivateKey. - # # Prefer the secret-backed setting above for real deployments. + # # Literal private key for development only. Defaults to + # # rr.agentSandbox.jwtPrivateKey when the agent sandbox is enabled. # agentSandboxJwtPrivateKey: # - # # Optional Node.js options for the MCP server process. Unset by default. + # # Node.js options for the MCP server process. # nodeOptions: --max_old_space_size=1024 # - # # Optional MCP service configuration. If enabledToolsets is unset, all - # # available toolsets are enabled by default. + # # Restrict the enabled toolsets. All available toolsets are enabled when unset. # enabledToolsets: # - apps # - resources - # # Optional max concurrent MCP transport sessions. Renders as - # # MCP_MAX_TRANSPORT_SESSIONS. If unset, the MCP service uses its runtime - # # default. + # # Maximum concurrent transport sessions. # maxTransportSessions: 1000 # sessionIdleTimeoutMs: 1800000 # sessionSweepIntervalMs: 60000 # sessionGaugeEmitIntervalMs: 30000 - # Resources for MCP server pods. MCP runs from the backend image and does not - # horizontally scale yet, so its default memory limit is higher than multiplayer. + # MCP pod resources. The server does not horizontally scale yet, so its + # default memory limit is higher than multiplayer's. resources: requests: cpu: "200m" @@ -717,49 +721,24 @@ mcp: limits: memory: "4096Mi" - # Public ingress routes for MCP-related OAuth metadata. When MCP is enabled, - # this config creates a dedicated backend API Service named - # -backend-internal for metadata routes that require the backend API - # listener, truncated to fit Kubernetes' 63-character DNS label limit when - # needed. + # Backend API Service for the OAuth authorization-server metadata route. backendMetadata: service: enabled: true - # Service port that exposes the backend API listener for metadata routes - # that should not fall through to the static frontend server or MCP - # service. portName: http-api externalPort: 3001 internalPort: 3001 annotations: {} labels: {} - # Public MCP-related ingress paths. Paths are emitted in order before the main - # Retool route: - # - OAuth authorization-server metadata hits the backend API service. - # - Protected-resource metadata, /mcp, and /mcp subpaths hit the MCP service. - # - # If you manage ingress outside this Helm chart, mcp.enabled only creates the - # chart-side resources. Your external ingress must route these paths, in this - # order before the "/" catch-all: - # - # -backend-internal:3001 - # /.well-known/oauth-authorization-server - # - # -mcp:4010 - # /.well-known/oauth-protected-resource - # /mcp (Prefix) - # - # :3000 - # / (Prefix) - # - # Otherwise OAuth metadata requests can fall through to the frontend and - # return HTML instead of JSON. If you use nameOverride, fullnameOverride, or a - # non-default release name, service names may differ; run "kubectl get svc" - # after installation and look for the main Retool service, the *-backend-internal - # service, and the *-mcp service. + # Public MCP routes, rendered before the main Retool route. External ingress + # must preserve this order and target mapping: + # Exact /.well-known/oauth-authorization-server -> -backend-internal:3001 + # Exact /.well-known/oauth-protected-resource -> -mcp:4010 + # Prefix /mcp -> -mcp:4010 + # Prefix / -> :3000 ingress: - # This conditional is dependent on mcp.enabled. + # Also requires mcp.enabled. enabled: true paths: - path: /.well-known/oauth-authorization-server @@ -770,9 +749,9 @@ mcp: - path: /mcp pathType: Prefix - # HTTPRoute rules for MCP when using Gateway API instead of ingress. + # Equivalent Gateway API routes. httpRoute: - # This conditional is dependent on mcp.enabled. + # Also requires mcp.enabled. enabled: true rules: - path: /.well-known/oauth-authorization-server @@ -845,8 +824,6 @@ codeExecutor: # this switch; set a component's `enabled` to true/false to override the master # for that component only. The gitServer and blobStorage blocks below # provide the React Retool git server and the object storage the stack needs. -# (The MCP server is configured separately at the top level: it needs its own -# OAuth opt-in and is intentionally independent of this master switch.) rr: enabled: false