diff --git a/charts/stackrox-mcp/README.md b/charts/stackrox-mcp/README.md index c7c256d..771eba7 100644 --- a/charts/stackrox-mcp/README.md +++ b/charts/stackrox-mcp/README.md @@ -142,6 +142,18 @@ The following table lists the configurable parameters of the StackRox MCP chart | `openshift.route.tls.insecureEdgeTerminationPolicy` | Policy for insecure edge traffic | `Redirect` | | `openshift.route.tls.destinationCACertificate` | CA certificate for pod verification | `""` | +### MCP Gateway Integration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `mcpGateway.enabled` | Enable MCP Gateway integration | `false` | +| `mcpGateway.gateway.name` | Name of the MCP Gateway resource | `mcp-gateway` | +| `mcpGateway.gateway.namespace` | Namespace of the MCP Gateway resource | `gateway-system` | +| `mcpGateway.hostname` | Internal routing hostname for the HTTPRoute | `.mcp.local` | +| `mcpGateway.toolPrefix` | Prefix for tools exposed via the gateway | `stackrox_` | + +**Note:** Requires [MCP Gateway](https://github.com/Kuadrant/mcp-gateway) to be installed on the cluster. The chart validates that the required CRDs (`gateway.networking.k8s.io/v1/HTTPRoute` and `mcp.kuadrant.io/v1alpha1/MCPServerRegistration`) are available and fails with a descriptive error if they are not. When MCP Gateway is enabled, `replicaCount` must be set to `1` — the Gateway API's HTTPRoute bypasses Service-level session affinity, so multiple replicas would break stateful MCP sessions. See [MCP Gateway Integration](../../docs/mcp-gateway-integration.md) for details. + ### Scheduling | Parameter | Description | Default | @@ -351,6 +363,8 @@ helm install stackrox-mcp charts/stackrox-mcp \ ### High Availability Setup +**Note:** High availability with multiple replicas is not supported when MCP Gateway is enabled (`mcpGateway.enabled=true`). See [MCP Gateway Integration](#mcp-gateway-integration) for details. + For high availability with multiple replicas: ```yaml diff --git a/charts/stackrox-mcp/templates/_helpers.tpl b/charts/stackrox-mcp/templates/_helpers.tpl index ca65311..61cb8a5 100644 --- a/charts/stackrox-mcp/templates/_helpers.tpl +++ b/charts/stackrox-mcp/templates/_helpers.tpl @@ -46,7 +46,7 @@ Image reference */}} {{- define "stackrox-mcp.image" -}} {{- $tag := .Values.image.tag | default .Chart.AppVersion }} -{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository $tag }} +{{- print .Values.image.registry "/" .Values.image.repository ":" $tag }} {{- end }} {{/* diff --git a/charts/stackrox-mcp/templates/http-route.yaml b/charts/stackrox-mcp/templates/http-route.yaml new file mode 100644 index 0000000..b036861 --- /dev/null +++ b/charts/stackrox-mcp/templates/http-route.yaml @@ -0,0 +1,29 @@ +{{- if .Values.mcpGateway.enabled }} +{{- if gt (int .Values.replicaCount) 1 }} +{{- fail "When MCP Gateway is enabled (mcpGateway.enabled=true), replicaCount must be set to 1. Multiple replicas will cause MCP client connections to land on different pods, breaking stateful MCP sessions. Set replicaCount=1 in your values." }} +{{- end }} +{{- if not (.Capabilities.APIVersions.Has "gateway.networking.k8s.io/v1/HTTPRoute") }} +{{- fail "MCP Gateway integration requires the Gateway API (gateway.networking.k8s.io/v1/HTTPRoute). Install Gateway API CRDs before enabling mcpGateway." }} +{{- end }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "stackrox-mcp.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "stackrox-mcp.labels" . | nindent 4 }} +spec: + parentRefs: + - name: {{ .Values.mcpGateway.gateway.name }} + namespace: {{ .Values.mcpGateway.gateway.namespace }} + hostnames: + - {{ .Values.mcpGateway.hostname | default (printf "%s.mcp.local" (include "stackrox-mcp.fullname" .)) | quote }} + rules: + - matches: + - path: + type: PathPrefix + value: /mcp + backendRefs: + - name: {{ include "stackrox-mcp.fullname" . }} + port: {{ .Values.service.port }} +{{- end }} diff --git a/charts/stackrox-mcp/templates/mcp-server-registration.yaml b/charts/stackrox-mcp/templates/mcp-server-registration.yaml new file mode 100644 index 0000000..87236fb --- /dev/null +++ b/charts/stackrox-mcp/templates/mcp-server-registration.yaml @@ -0,0 +1,19 @@ +{{- if .Values.mcpGateway.enabled }} +{{- if not (.Capabilities.APIVersions.Has "mcp.kuadrant.io/v1alpha1/MCPServerRegistration") }} +{{- fail "MCP Gateway integration requires the MCPServerRegistration CRD (mcp.kuadrant.io/v1alpha1/MCPServerRegistration). Install MCP Gateway (https://github.com/Kuadrant/mcp-gateway) before enabling mcpGateway." }} +{{- end }} +apiVersion: mcp.kuadrant.io/v1alpha1 +kind: MCPServerRegistration +metadata: + name: {{ include "stackrox-mcp.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "stackrox-mcp.labels" . | nindent 4 }} +spec: + toolPrefix: {{ .Values.mcpGateway.toolPrefix | quote }} + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: {{ include "stackrox-mcp.fullname" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/stackrox-mcp/values.yaml b/charts/stackrox-mcp/values.yaml index 81f9eab..4fb2d04 100644 --- a/charts/stackrox-mcp/values.yaml +++ b/charts/stackrox-mcp/values.yaml @@ -184,6 +184,22 @@ config: configManager: enabled: true +# MCP Gateway integration (opt-in) +# Requires MCP Gateway (https://github.com/Kuadrant/mcp-gateway) to be installed on the cluster +mcpGateway: + enabled: false + + # Main MCP Gateway reference (this is usually Gateway that gathers all MCP servers) + gateway: + name: mcp-gateway + namespace: gateway-system + + # Hostname for the HTTPRoute + hostname: "" + + # Tool prefix to avoid naming conflicts when aggregating tools through the gateway + toolPrefix: stackrox_ + # Additional environment variables (advanced use) # These will be added directly to the container extraEnv: [] diff --git a/docs/mcp-gateway-integration.md b/docs/mcp-gateway-integration.md new file mode 100644 index 0000000..520f6be --- /dev/null +++ b/docs/mcp-gateway-integration.md @@ -0,0 +1,62 @@ +# MCP Gateway Integration + +This guide describes how to integrate the StackRox MCP server with [MCP Gateway](https://github.com/Kuadrant/mcp-gateway), enabling tool aggregation behind a centralized gateway endpoint. + +## Overview + +MCP Gateway is an Envoy-based system that aggregates multiple MCP servers behind a single endpoint. It uses Gateway API resources and a custom `MCPServerRegistration` CRD to discover and route requests to backend MCP servers. + +When enabled, the Helm chart creates: +- **HTTPRoute** — routes `/mcp` traffic from the gateway to the StackRox MCP service +- **MCPServerRegistration** — registers the server with the gateway using a tool prefix to avoid naming conflicts + +## Prerequisites + +- [MCP Gateway](https://github.com/Kuadrant/mcp-gateway) installed on the cluster ([OpenShift installation guide](https://github.com/Kuadrant/mcp-gateway/tree/main/config/openshift)) + +The Helm chart validates that the required CRDs are available and fails with a descriptive error if they are not. + +## Installation + +**Important:** When MCP Gateway is enabled, `replicaCount` must be set to `1`. The Gateway API's HTTPRoute bypasses Kubernetes Service-level session affinity, so multiple replicas would cause MCP client connections to land on different pods, breaking stateful MCP sessions. + +```bash +helm install stackrox-mcp charts/stackrox-mcp \ + --namespace stackrox-mcp \ + --create-namespace \ + --set replicaCount=1 \ + --set mcpGateway.enabled=true \ + --set mcpGateway.hostname=stackrox-mcp.mcp.local \ + --set config.central.url= +``` + +## Configuration Reference + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `mcpGateway.enabled` | Enable MCP Gateway integration | `false` | +| `mcpGateway.gateway.name` | Name of the MCP Gateway resource | `mcp-gateway` | +| `mcpGateway.gateway.namespace` | Namespace of the MCP Gateway resource | `gateway-system` | +| `mcpGateway.hostname` | Internal routing hostname for the HTTPRoute | `.mcp.local` | +| `mcpGateway.toolPrefix` | Prefix for tools exposed via the gateway | `stackrox_` | + +## Verification + +```bash +curl -X POST https://$(oc get routes -n gateway-system -o jsonpath='{ .items[0].spec.host }')/mcp \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' +``` + +## Architecture + +``` +MCP Client + → MCP Gateway (gateway-system namespace) + → HTTPRoute (/mcp) + → StackRox MCP Service (stackrox-mcp namespace) + → StackRox MCP Pod(s) + → StackRox Central API +``` + +The gateway aggregates tools from all registered MCP servers. StackRox MCP tools are exposed with the configured prefix (e.g., `stackrox_get_deployments_for_cve`).