Skip to content
Open
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 charts/infrahub-enterprise/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 4.23.2
version: 4.24.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
Expand All @@ -27,5 +27,5 @@ appVersion: "1.11.10"

dependencies:
- name: infrahub
version: "4.35.2"
version: "4.36.0"
repository: "oci://registry.opsmill.io/opsmill/chart"
2 changes: 1 addition & 1 deletion charts/infrahub-enterprise/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Use the overlay only on a cluster that assigns a uid of its own. Plain Kubernete

| Repository | Name | Version |
|------------|------|---------|
| oci://registry.opsmill.io/opsmill/chart | infrahub | 4.35.1 |
| oci://registry.opsmill.io/opsmill/chart | infrahub | 4.36.0 |

## Values

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bumped the bundled `infrahub` dependency to `4.36.0`, which bumps the `infrahub-mcp` subchart to `0.2.0` (image `v1.2.1`). See the [infrahub-mcp 1.2.1 release notes](https://github.com/opsmill/infrahub-mcp/releases/tag/v1.2.1).
4 changes: 2 additions & 2 deletions charts/infrahub-mcp/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ maintainers:
- name: OpsMill
url: https://github.com/opsmill
type: application
version: 0.1.0
appVersion: "v1.1.6"
version: 0.2.0
appVersion: "v1.2.1"
62 changes: 59 additions & 3 deletions charts/infrahub-mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,43 @@ Helm chart for Infrahub MCP Server on Kubernetes

**Homepage:** <https://github.com/opsmill/infrahub-helm>

## Production example

The defaults (`mcp.authMode: none`, `mcp.readOnly: false`) give every client that
reaches the MCP server read and write access through one shared API token. For a
production deployment, require each client to send its own Infrahub API token,
block write operations, and serve the MCP server under `/mcp` on the Infrahub
host.

In `token-passthrough` mode each client sends its own Infrahub API token, and the
server calls Infrahub with that token. The chart needs no shared API token, so
leave `infrahub.apiToken` unset. Install the chart with these values:

```yaml
infrahub:
# In-cluster URL of the Infrahub server: http://<infrahub-release>-infrahub-server:8000
address: "http://infrahub-infrahub-server:8000"

mcp:
# Each request must carry an Infrahub API token in the `Authorization` header.
authMode: "token-passthrough"
# Hide write tools and block GraphQL mutations.
readOnly: true

ingress:
enabled: true
ingressClassName: nginx
# The Infrahub server's ingress hostname
hostname: infrahub.example.com
path: /mcp
pathType: Prefix
tls: true
```

When you install the MCP server with the `infrahub` or `infrahub-enterprise`
chart, set `infrahub-mcp.enabled: true` and put these values under the
`infrahub-mcp:` key (`infrahub.infrahub-mcp:` for `infrahub-enterprise`).

## Maintainers

| Name | Email | Url |
Expand Down Expand Up @@ -36,12 +73,17 @@ Helm chart for Infrahub MCP Server on Kubernetes
| image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.opsmill.io/opsmill/infrahub-mcp","tag":""}` | Container image configuration |
| image.tag | string | `""` | Tag defaults to chart appVersion if not specified |
| imagePullSecrets | list | `[]` | Image pull secrets for private registries |
| infrahub | object | `{"address":"","apiToken":{"existingSecret":"","existingSecretKey":"INFRAHUB_API_TOKEN","value":""}}` | Infrahub connection settings |
| infrahub | object | `{"address":"","apiToken":{"existingSecret":"","existingSecretKey":"INFRAHUB_API_TOKEN","value":""},"password":{"existingSecret":"","existingSecretKey":"INFRAHUB_PASSWORD","value":""},"username":""}` | Infrahub connection settings |
| infrahub.address | string | `""` | Infrahub server address (e.g. "http://infrahub-infrahub-server:8000") |
| infrahub.apiToken | object | `{"existingSecret":"","existingSecretKey":"INFRAHUB_API_TOKEN","value":""}` | API token for authenticating with Infrahub |
| infrahub.apiToken.existingSecret | string | `""` | Name of an existing Secret containing the API token. Takes precedence over `value` when set. |
| infrahub.apiToken.existingSecretKey | string | `"INFRAHUB_API_TOKEN"` | Key within the existing Secret that holds the API token |
| infrahub.apiToken.value | string | `""` | API token value, rendered as a plain-text env var. Prefer `existingSecret` for production deployments. |
| infrahub.password | object | `{"existingSecret":"","existingSecretKey":"INFRAHUB_PASSWORD","value":""}` | Password for `username` |
| infrahub.password.existingSecret | string | `""` | Name of an existing Secret containing the password. Takes precedence over `value` when set. |
| infrahub.password.existingSecretKey | string | `"INFRAHUB_PASSWORD"` | Key within the existing Secret that holds the password |
| infrahub.password.value | string | `""` | Password value, rendered as a plain-text env var. Prefer `existingSecret` for production deployments. |
| infrahub.username | string | `""` | Infrahub username. Set it with `password` instead of `apiToken`; the server refuses to start when both are set. |
| ingress | object | `{"annotations":{},"enabled":false,"extraHosts":[],"extraTls":[],"hostname":"","ingressClassName":"","path":"/mcp","pathType":"Prefix","tls":false}` | Ingress configuration for exposing the MCP server externally. To serve the MCP server on the same host as Infrahub (e.g. under a "/mcp" path prefix), set `hostname` to the Infrahub server's ingress hostname and keep the default `path`. |
| ingress.annotations | object | `{}` | Annotations to configure on the ingress |
| ingress.enabled | bool | `false` | Whether to enable Ingress for the MCP server |
Expand All @@ -53,8 +95,9 @@ Helm chart for Infrahub MCP Server on Kubernetes
| ingress.pathType | string | `"Prefix"` | PathType for the ingress rule |
| ingress.tls | bool | `false` | Enable TLS for `hostname` using the secret "<fullname>-tls" |
| livenessProbe | object | `{"failureThreshold":3,"httpGet":{"path":"/health","port":"http"},"initialDelaySeconds":5,"periodSeconds":10,"timeoutSeconds":5}` | Liveness probe configuration |
| mcp | object | `{"authMode":"none","branching":{"maxRetries":5,"pattern":"mcp/session-{date}-{hex}"},"cache":{"enabled":false,"listTtl":300,"readTtl":3600},"dereferenceSchemas":false,"logLevel":"info","observability":{"otelEnabled":false,"pingIntervalMs":0,"prometheusEnabled":false},"rateLimit":{"burst":0,"rps":0},"readOnly":false,"retry":{"baseDelay":1,"maxAttempts":0}}` | MCP server configuration |
| mcp | object | `{"authMode":"none","authScopesWrite":"write","branching":{"maxRetries":5,"pattern":"mcp/session-{date}-{hex}"},"cache":{"enabled":false,"listTtl":300,"readTtl":3600},"dereferenceSchemas":false,"host":"0.0.0.0","logLevel":"info","observability":{"otelEnabled":false,"pingIntervalMs":0,"prometheusEnabled":false},"oidc":{"audience":"","baseUrl":"","clientId":"","clientSecret":{"existingSecret":"","existingSecretKey":"INFRAHUB_MCP_OIDC_CLIENT_SECRET","value":""},"configUrl":"","userClaim":"email"},"rateLimit":{"burst":0,"rps":0},"readOnly":false,"retry":{"baseDelay":1,"maxAttempts":0},"schemaExpandPeers":true,"tokenPassthroughHeader":"Authorization"}` | MCP server configuration |
| mcp.authMode | string | `"none"` | Authentication mode: "none", "token-passthrough", "basic-passthrough", "oidc" |
| mcp.authScopesWrite | string | `"write"` | OAuth scopes (comma-separated) a client token must hold to call write tools |
| mcp.branching | object | `{"maxRetries":5,"pattern":"mcp/session-{date}-{hex}"}` | Branching configuration |
| mcp.branching.maxRetries | int | `5` | Max retries for branch creation on name collision |
| mcp.branching.pattern | string | `"mcp/session-{date}-{hex}"` | Branch name pattern for auto-created branches |
Expand All @@ -63,18 +106,31 @@ Helm chart for Infrahub MCP Server on Kubernetes
| mcp.cache.listTtl | int | `300` | TTL in seconds for list operations |
| mcp.cache.readTtl | int | `3600` | TTL in seconds for read operations |
| mcp.dereferenceSchemas | bool | `false` | Enable JSON $ref dereferencing in schemas |
| mcp.host | string | `"0.0.0.0"` | Address the HTTP server binds to. The port is `service.targetPort`. |
| mcp.logLevel | string | `"info"` | Log level: "debug", "info", "warning", "error" |
| mcp.observability | object | `{"otelEnabled":false,"pingIntervalMs":0,"prometheusEnabled":false}` | Observability configuration |
| mcp.observability.otelEnabled | bool | `false` | Enable OpenTelemetry tracing |
| mcp.observability.pingIntervalMs | int | `0` | Ping keepalive interval in milliseconds (0 = disabled) |
| mcp.observability.prometheusEnabled | bool | `false` | Enable Prometheus metrics endpoint |
| mcp.oidc | object | `{"audience":"","baseUrl":"","clientId":"","clientSecret":{"existingSecret":"","existingSecretKey":"INFRAHUB_MCP_OIDC_CLIENT_SECRET","value":""},"configUrl":"","userClaim":"email"}` | OIDC configuration, used when `authMode` is "oidc" |
| mcp.oidc.audience | string | `""` | Expected token audience claim |
| mcp.oidc.baseUrl | string | `""` | Public URL where clients reach the MCP server (required when `authMode` is "oidc") |
| mcp.oidc.clientId | string | `""` | OAuth client ID registered with the identity provider (required when `authMode` is "oidc") |
| mcp.oidc.clientSecret | object | `{"existingSecret":"","existingSecretKey":"INFRAHUB_MCP_OIDC_CLIENT_SECRET","value":""}` | OAuth client secret. Leave empty to use PKCE. |
| mcp.oidc.clientSecret.existingSecret | string | `""` | Name of an existing Secret containing the client secret. Takes precedence over `value` when set. |
| mcp.oidc.clientSecret.existingSecretKey | string | `"INFRAHUB_MCP_OIDC_CLIENT_SECRET"` | Key within the existing Secret that holds the client secret |
| mcp.oidc.clientSecret.value | string | `""` | Client secret value, rendered as a plain-text env var. Prefer `existingSecret` for production deployments. |
| mcp.oidc.configUrl | string | `""` | OIDC discovery URL (required when `authMode` is "oidc") |
| mcp.oidc.userClaim | string | `"email"` | JWT claim used as the user identity |
| mcp.rateLimit | object | `{"burst":0,"rps":0}` | Rate limiting configuration |
| mcp.rateLimit.burst | int | `0` | Burst allowance (0 = disabled) |
| mcp.rateLimit.burst | int | `0` | Burst allowance (0 = twice `rps`) |
| mcp.rateLimit.rps | int | `0` | Requests per second (0 = disabled) |
| mcp.readOnly | bool | `false` | Enable read-only mode (blocks all write operations) |
| mcp.retry | object | `{"baseDelay":1,"maxAttempts":0}` | Retry configuration |
| mcp.retry.baseDelay | int | `1` | Base delay between retries in seconds |
| mcp.retry.maxAttempts | int | `0` | Max retry attempts (0 = disabled) |
| mcp.schemaExpandPeers | bool | `true` | Include one level of related peer schemas in schema detail responses. When false, relationships are returned as flat peer references. |
| mcp.tokenPassthroughHeader | string | `"Authorization"` | HTTP header that carries the client's credential when `authMode` is "token-passthrough" or "basic-passthrough" |
| nameOverride | string | `""` | Override the chart name |
| nodeSelector | object | `{}` | Node selector for pod scheduling |
| podAnnotations | object | `{}` | Pod annotations |
Expand Down
37 changes: 37 additions & 0 deletions charts/infrahub-mcp/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,43 @@

{{ template "chart.homepageLine" . }}

## Production example

The defaults (`mcp.authMode: none`, `mcp.readOnly: false`) give every client that
reaches the MCP server read and write access through one shared API token. For a
production deployment, require each client to send its own Infrahub API token,
block write operations, and serve the MCP server under `/mcp` on the Infrahub
host.

In `token-passthrough` mode each client sends its own Infrahub API token, and the
server calls Infrahub with that token. The chart needs no shared API token, so
leave `infrahub.apiToken` unset. Install the chart with these values:

```yaml
infrahub:
# In-cluster URL of the Infrahub server: http://<infrahub-release>-infrahub-server:8000
address: "http://infrahub-infrahub-server:8000"

mcp:
# Each request must carry an Infrahub API token in the `Authorization` header.
authMode: "token-passthrough"
# Hide write tools and block GraphQL mutations.
readOnly: true

ingress:
enabled: true
ingressClassName: nginx
# The Infrahub server's ingress hostname
hostname: infrahub.example.com
path: /mcp
pathType: Prefix
tls: true
```

When you install the MCP server with the `infrahub` or `infrahub-enterprise`
chart, set `infrahub-mcp.enabled: true` and put these values under the
`infrahub-mcp:` key (`infrahub.infrahub-mcp:` for `infrahub-enterprise`).

{{ template "chart.maintainersSection" . }}

{{ template "chart.requirementsSection" . }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added values for the infrahub-mcp settings that the chart did not set: `infrahub.username` and `infrahub.password`, `mcp.host`, `mcp.tokenPassthroughHeader`, `mcp.authScopesWrite`, `mcp.oidc.*` and `mcp.schemaExpandPeers`. The chart now sets `MCP_PORT` from `service.targetPort`, so changing the port also changes the port the server listens on.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bumped the `infrahub-mcp` image to `v1.2.1`. See the [infrahub-mcp 1.2.1 release notes](https://github.com/opsmill/infrahub-mcp/releases/tag/v1.2.1).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Corrected the description of `mcp.rateLimit.burst`: `0` sets the burst allowance to twice `mcp.rateLimit.rps`; it does not disable bursts.
54 changes: 54 additions & 0 deletions charts/infrahub-mcp/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,60 @@ spec:
- name: INFRAHUB_API_TOKEN
value: {{ .Values.infrahub.apiToken.value | quote }}
{{- end }}
{{- if .Values.infrahub.username }}
- name: INFRAHUB_USERNAME
value: {{ .Values.infrahub.username | quote }}
{{- end }}
{{- if .Values.infrahub.password.existingSecret }}
- name: INFRAHUB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.infrahub.password.existingSecret }}
key: {{ .Values.infrahub.password.existingSecretKey }}
{{- else if .Values.infrahub.password.value }}
- name: INFRAHUB_PASSWORD
value: {{ .Values.infrahub.password.value | quote }}
{{- end }}
- name: MCP_HOST
value: {{ .Values.mcp.host | quote }}
- name: MCP_PORT
value: {{ .Values.service.targetPort | quote }}
- name: INFRAHUB_MCP_AUTH_MODE
value: {{ .Values.mcp.authMode | quote }}
- name: INFRAHUB_MCP_TOKEN_PASSTHROUGH_HEADER
value: {{ .Values.mcp.tokenPassthroughHeader | quote }}
- name: INFRAHUB_MCP_AUTH_SCOPES_WRITE
value: {{ .Values.mcp.authScopesWrite | quote }}
{{- with .Values.mcp.oidc }}
{{- if .configUrl }}
- name: INFRAHUB_MCP_OIDC_CONFIG_URL
value: {{ .configUrl | quote }}
{{- end }}
{{- if .clientId }}
- name: INFRAHUB_MCP_OIDC_CLIENT_ID
value: {{ .clientId | quote }}
{{- end }}
{{- if .clientSecret.existingSecret }}
- name: INFRAHUB_MCP_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .clientSecret.existingSecret }}
key: {{ .clientSecret.existingSecretKey }}
{{- else if .clientSecret.value }}
- name: INFRAHUB_MCP_OIDC_CLIENT_SECRET
value: {{ .clientSecret.value | quote }}
{{- end }}
{{- if .baseUrl }}
- name: INFRAHUB_MCP_OIDC_BASE_URL
value: {{ .baseUrl | quote }}
{{- end }}
{{- if .audience }}
- name: INFRAHUB_MCP_OIDC_AUDIENCE
value: {{ .audience | quote }}
{{- end }}
- name: INFRAHUB_MCP_OIDC_USER_CLAIM
value: {{ .userClaim | quote }}
{{- end }}
- name: INFRAHUB_MCP_READ_ONLY
value: {{ .Values.mcp.readOnly | quote }}
- name: INFRAHUB_MCP_LOG_LEVEL
Expand Down Expand Up @@ -89,6 +141,8 @@ spec:
value: {{ .Values.mcp.observability.pingIntervalMs | quote }}
- name: INFRAHUB_MCP_DEREFERENCE_SCHEMAS
value: {{ .Values.mcp.dereferenceSchemas | quote }}
- name: INFRAHUB_MCP_SCHEMA_EXPAND_PEERS
value: {{ .Values.mcp.schemaExpandPeers | quote }}
{{- range $key, $value := .Values.extraEnv }}
- name: {{ $key }}
value: {{ $value | quote }}
Expand Down
48 changes: 47 additions & 1 deletion charts/infrahub-mcp/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,57 @@ infrahub:
existingSecret: ""
# -- Key within the existing Secret that holds the API token
existingSecretKey: "INFRAHUB_API_TOKEN"
# -- Infrahub username. Set it with `password` instead of `apiToken`; the
# server refuses to start when both are set.
username: ""
# -- Password for `username`
password:
# -- Password value, rendered as a plain-text env var. Prefer
# `existingSecret` for production deployments.
value: ""
# -- Name of an existing Secret containing the password. Takes precedence
# over `value` when set.
existingSecret: ""
# -- Key within the existing Secret that holds the password
existingSecretKey: "INFRAHUB_PASSWORD"

# -- MCP server configuration
mcp:
# -- Authentication mode: "none", "token-passthrough", "basic-passthrough", "oidc"
authMode: "none"
# -- HTTP header that carries the client's credential when `authMode` is
# "token-passthrough" or "basic-passthrough"
tokenPassthroughHeader: "Authorization"
# -- OAuth scopes (comma-separated) a client token must hold to call write tools
authScopesWrite: "write"
# -- OIDC configuration, used when `authMode` is "oidc"
oidc:
# -- OIDC discovery URL (required when `authMode` is "oidc")
configUrl: ""
# -- OAuth client ID registered with the identity provider (required when `authMode` is "oidc")
clientId: ""
# -- OAuth client secret. Leave empty to use PKCE.
clientSecret:
# -- Client secret value, rendered as a plain-text env var. Prefer
# `existingSecret` for production deployments.
value: ""
# -- Name of an existing Secret containing the client secret. Takes
# precedence over `value` when set.
existingSecret: ""
# -- Key within the existing Secret that holds the client secret
existingSecretKey: "INFRAHUB_MCP_OIDC_CLIENT_SECRET"
# -- Public URL where clients reach the MCP server (required when `authMode` is "oidc")
baseUrl: ""
# -- Expected token audience claim
audience: ""
# -- JWT claim used as the user identity
userClaim: "email"
# -- Enable read-only mode (blocks all write operations)
readOnly: false
# -- Log level: "debug", "info", "warning", "error"
logLevel: "info"
# -- Address the HTTP server binds to. The port is `service.targetPort`.
host: "0.0.0.0"

# -- Branching configuration
branching:
Expand All @@ -71,7 +113,7 @@ mcp:
rateLimit:
# -- Requests per second (0 = disabled)
rps: 0
# -- Burst allowance (0 = disabled)
# -- Burst allowance (0 = twice `rps`)
burst: 0

# -- Retry configuration
Expand All @@ -93,6 +135,10 @@ mcp:
# -- Enable JSON $ref dereferencing in schemas
dereferenceSchemas: false

# -- Include one level of related peer schemas in schema detail responses.
# When false, relationships are returned as flat peer references.
schemaExpandPeers: true

# -- Additional environment variables (key: value pairs)
extraEnv: {}

Expand Down
Loading
Loading