Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions deployments/charts/service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ destination, but it cannot validate external DNS.
| `services.mcp.scopes` | OAuth scopes advertised in direct-provider mode; ignored when `oidcProxy.enabled` is true. | `[]` |
| `services.mcp.allowedOrigins` | Exact browser origins permitted on `/mcp`; native clients normally omit `Origin`. | `[]` |
| `services.mcp.requestTimeoutSeconds` | Total timeout for each MCP-initiated Gateway request, from 1 through 60 seconds. | `10` |
| `services.mcp.replicas` | Number of MCP replicas. Must remain `1` with `oidcProxy.enabled` because FastMCP 3.4.7 refresh serialization is process-local. | `1` |
| `services.mcp.replicas` | Number of MCP replicas. The OIDC proxy keeps its state in Redis, so it scales out. | `1` |
| `services.mcp.extraEnv` | Additional non-managed environment variables. It cannot override MCP host, port, Gateway origin, or request timeout. | `[]` |
| `services.mcp.extraVolumeMounts` | Additional MCP container volume mounts, including Vault-injected credential files. | `[]` |
| `services.mcp.extraVolumes` | Additional MCP pod volumes. | `[]` |
Expand All @@ -110,7 +110,7 @@ destination, but it cannot validate external DNS.
| `services.mcp.oidcProxy.oidc.clientSecretFile` | Mounted file containing the upstream OIDC client secret. | `/etc/osmo/mcp-auth/client-secret` |
| `services.mcp.oidcProxy.oidc.accessTokenIssuer` | Exact issuer required on upstream API access tokens. | `""` |
| `services.mcp.oidcProxy.oidc.accessTokenRequiredScope` | Short scope value required in the upstream access token's `scp` claim. | `access_as_user` |
| `services.mcp.oidcProxy.redis` | Redis connection used by FastMCP for registrations, authorization state, and encrypted upstream tokens; blank host/port inherit `services.redis`. | See `values.yaml` |
| `services.mcp.oidcProxy.redis.dbNumber` | Logical Redis database for proxy state. Host, port and TLS come from `services.redis`. | `1` |
| `services.mcp.oidcProxy.accessTokenTtlSeconds` | Lifetime of proxy access tokens, from 60 through 3600 seconds. | `600` |
| `services.mcp.oidcProxy.refreshTokenTtlSeconds` | Lifetime of proxy refresh tokens, from 300 through 604800 seconds. | `28800` |
| `services.mcp.oidcProxy.upstreamTimeoutSeconds` | Timeout for upstream OIDC requests, from 1 through 60 seconds. | `10` |
Expand Down
3 changes: 0 additions & 3 deletions deployments/charts/service/ci/mcp-oidc-proxy-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ services:
accessTokenIssuer: https://sts.example.com/example-tenant/
accessTokenRequiredScope: access_as_user
redis:
serviceName: proxy-redis.example.internal
port: 6380
dbNumber: 14
tlsEnabled: true
passwordFile: /etc/osmo/mcp-auth/redis-password
keyPrefix: test:mcp-auth
existingSecret:
Expand Down
18 changes: 7 additions & 11 deletions deployments/charts/service/ci/validate-mcp-chart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,13 @@ assert_route_contains "$PROXY_RENDERED_MANIFEST" mcp-health-not-public \
'envoy.filters.http.ext_authz:'
assert_env_value "$PROXY_MCP_MANIFEST" OSMO_MCP_AUTH_ENABLED true
assert_env_value "$PROXY_MCP_MANIFEST" OSMO_MCP_AUTH_RESOURCE_URL https://osmo.example.com/mcp
assert_env_value "$PROXY_MCP_MANIFEST" OSMO_MCP_AUTH_REDIS_URL rediss://proxy-redis.example.internal:6380/14
assert_env_value "$PROXY_MCP_MANIFEST" OSMO_MCP_AUTH_REDIS_URL rediss://redis:6379/14

# The proxy keeps all state in Redis, so scaling out must render.
if ! helm template test-release "$CHART_DIR" -f "$PROXY_VALUES_FILE" \
--set 'services.mcp.replicas=2' >/dev/null 2>&1; then
fail "MCP OIDC proxy with two replicas failed to render"
fi

# FastMCP advertises its endpoints under /mcp; the gateway publishes that
# prefix and rewrites it off before forwarding to the root paths the MCP SDK
Expand Down Expand Up @@ -254,16 +260,6 @@ expect_render_failure "$PROXY_VALUES_FILE" \
'services.mcp.oidcProxy.enabled requires services.mcp.enabled=true' \
--set 'services.mcp.enabled=false'

expect_render_failure "$PROXY_VALUES_FILE" \
'OIDC proxy with multiple replicas' \
'services.mcp.replicas must be 1 when services.mcp.oidcProxy.enabled=true' \
--set 'services.mcp.replicas=2'

expect_render_failure "$PROXY_VALUES_FILE" \
'invalid OIDC proxy Redis port' \
'services.mcp.oidcProxy.redis.port must be between 1 and 65535' \
--set 'services.mcp.oidcProxy.redis.port=0'

expect_render_failure "$PROXY_VALUES_FILE" \
'OIDC proxy Redis database below range' \
'services.mcp.oidcProxy.redis.dbNumber must be between 0 and 15' \
Expand Down
13 changes: 2 additions & 11 deletions deployments/charts/service/templates/mcp-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
{{- $redisKeyPrefix := "" }}
{{- $redisUrl := "" }}
{{- if $oidcProxyEnabled }}
{{- if ne (int $mcp.replicas) 1 }}
{{- fail "services.mcp.replicas must be 1 when services.mcp.oidcProxy.enabled=true" }}
{{- end }}
{{- $oidcConfigUrl = required "services.mcp.oidcProxy.oidc.configUrl is required when the OIDC proxy is enabled" $oidcProxy.oidc.configUrl }}
{{- $oidcClientId = required "services.mcp.oidcProxy.oidc.clientId is required when the OIDC proxy is enabled" $oidcProxy.oidc.clientId }}
{{- $oidcClientSecretFile = required "services.mcp.oidcProxy.oidc.clientSecretFile is required when the OIDC proxy is enabled" $oidcProxy.oidc.clientSecretFile }}
Expand Down Expand Up @@ -63,14 +60,8 @@
{{- if not (hasPrefix "/" $oidcClientSecretFile) }}
{{- fail "services.mcp.oidcProxy.oidc.clientSecretFile must be an absolute path" }}
{{- end }}
{{- $redisHost := $oidcProxy.redis.serviceName | default .Values.services.redis.serviceName | required "services.mcp.oidcProxy.redis.serviceName or services.redis.serviceName is required" }}
{{- $redisHost := .Values.services.redis.serviceName | required "services.redis.serviceName is required when the MCP OIDC proxy is enabled" }}
{{- $redisPort := .Values.services.redis.port }}
{{- if not (kindIs "invalid" $oidcProxy.redis.port) }}
{{- $redisPort = $oidcProxy.redis.port }}
{{- end }}
{{- if or (lt (int $redisPort) 1) (gt (int $redisPort) 65535) }}
{{- fail "services.mcp.oidcProxy.redis.port must be between 1 and 65535" }}
{{- end }}
{{- if or (lt (int $oidcProxy.redis.dbNumber) 0) (gt (int $oidcProxy.redis.dbNumber) 15) }}
{{- fail "services.mcp.oidcProxy.redis.dbNumber must be between 0 and 15" }}
{{- end }}
Expand Down Expand Up @@ -113,7 +104,7 @@
{{- fail "services.mcp.oidcProxy.existingSecret.redisPasswordKey is required when redis.passwordFile is configured" }}
{{- end }}
{{- end }}
{{- $redisScheme := ternary "rediss" "redis" $oidcProxy.redis.tlsEnabled }}
{{- $redisScheme := ternary "rediss" "redis" .Values.services.redis.tlsEnabled }}
{{- $redisUrl = printf "%s://%s:%v/%v" $redisScheme $redisHost $redisPort $oidcProxy.redis.dbNumber }}
{{- end }}
{{- if not (kindIs "slice" $mcp.allowedOrigins) }}
Expand Down
13 changes: 6 additions & 7 deletions deployments/charts/service/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ services:
##
enabled: false

## Number of MCP replicas. Keep this at 1 while oidcProxy is enabled;
## FastMCP 3.4.7 serializes refreshes within one process.
## Number of MCP replicas. The OIDC proxy keeps all of its state in Redis,
## so more than one replica is supported.
##
replicas: 1

Expand Down Expand Up @@ -187,13 +187,12 @@ services:
accessTokenRequiredScope: access_as_user

## Redis stores proxy registrations, authorization state, and encrypted
## upstream tokens. Empty serviceName/port inherit services.redis.
## upstream tokens. Host, port and TLS come from services.redis; only the
## logical database is chosen here, so proxy state stays isolated from
## OSMO's other Redis users.
##
redis:
serviceName: ""
port: null
dbNumber: 0
tlsEnabled: true
dbNumber: 1
passwordFile: ""
keyPrefix: osmo:mcp-fastmcp
connectTimeoutSeconds: 3
Expand Down
Loading