Skip to content

Commit abc6e42

Browse files
Merge pull request #161 from matzew/sync-downstream-20260226-1523
NO-JIRA: Sync downstream
2 parents 8155183 + 7a62d37 commit abc6e42

12 files changed

Lines changed: 164 additions & 118 deletions

File tree

.github/workflows/mcpchecker.yaml

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,24 @@ on:
99
issue_comment:
1010
types: [created]
1111

12+
# Automatically run kubevirt evals when kubevirt-related files change
13+
pull_request:
14+
paths:
15+
- 'pkg/toolsets/kubevirt/**'
16+
- 'evals/tasks/kubevirt/**'
17+
- 'build/kubevirt.mk'
18+
1219
# Allow manual workflow dispatch for testing
1320
workflow_dispatch:
1421
inputs:
1522
suite:
16-
description: 'Which task suite to run (kubernetes, kiali, or all)'
23+
description: 'Which task suite to run (kubernetes, kubevirt, kiali, or all)'
1724
required: false
1825
default: 'kubernetes'
1926
type: choice
2027
options:
2128
- kubernetes
29+
- kubevirt
2230
- kiali
2331
- all
2432
task-filter:
@@ -59,12 +67,14 @@ jobs:
5967
if: |
6068
github.event_name == 'schedule' ||
6169
github.event_name == 'workflow_dispatch' ||
70+
github.event_name == 'pull_request' ||
6271
(github.event_name == 'issue_comment' &&
6372
github.event.issue.pull_request &&
6473
contains(github.event.comment.body, '/run-mcpchecker'))
6574
outputs:
6675
should-run: ${{ steps.check.outputs.should-run }}
6776
kiali-run: ${{ steps.check.outputs.kiali-run }}
77+
kubevirt-run: ${{ steps.check.outputs.kubevirt-run }}
6878
label-selector: ${{ steps.check.outputs.label-selector }}
6979
pr-number: ${{ steps.check.outputs.pr-number }}
7080
pr-sha: ${{ steps.check.outputs.pr-sha }}
@@ -94,25 +104,33 @@ jobs:
94104
echo "should-run=false" >> $GITHUB_OUTPUT
95105
echo "User ${{ github.event.comment.user.login }} does not have permission to trigger evaluations"
96106
fi
107+
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
108+
echo "should-run=true" >> $GITHUB_OUTPUT
109+
echo "is-pr=true" >> $GITHUB_OUTPUT
110+
echo "pr-number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
111+
echo "pr-sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
97112
else
98113
echo "should-run=true" >> $GITHUB_OUTPUT
99114
echo "is-pr=false" >> $GITHUB_OUTPUT
100115
echo "pr-sha=${{ github.sha }}" >> $GITHUB_OUTPUT
101116
fi
102117
103118
# Suite selection:
119+
# - For pull_request, always run kubevirt (triggered by kubevirt path changes).
104120
# - For workflow_dispatch, use the provided input.
105121
# - For other triggers (schedule/issue_comment), default to kubernetes.
106122
SUITE="${{ github.event.inputs.suite || 'kubernetes' }}"
107123
TASK_FILTER="${{ github.event.inputs.task-filter || '' }}"
108124
109-
if [[ "${{ github.event_name }}" == "issue_comment" ]]; then
110-
# Parse comment: /run-mcpchecker [suite]. Suite = kubernetes | kiali | all
125+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
126+
SUITE_INPUT="kubevirt"
127+
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
128+
# Parse comment: /run-mcpchecker [suite]. Suite = kubernetes | kubevirt | kiali | all
111129
COMMENT_BODY="${{ github.event.comment.body }}"
112130
COMMENT_BODY="${COMMENT_BODY//[[:space:]]/ }"
113131
read -r _ FIRST_WORD _ <<< "$COMMENT_BODY"
114132
case "${FIRST_WORD,,}" in
115-
kiali|all)
133+
kubevirt|kiali|all)
116134
SUITE_INPUT="${FIRST_WORD,,}"
117135
;;
118136
kubernetes)
@@ -127,17 +145,25 @@ jobs:
127145
# Select label-selector and infrastructure based on suite
128146
# All suites use the same eval.yaml file; suite controls label-selector + infra.
129147
case "$SUITE" in
148+
kubevirt)
149+
echo "label-selector=suite=kubevirt" >> $GITHUB_OUTPUT
150+
echo "kiali-run=false" >> $GITHUB_OUTPUT
151+
echo "kubevirt-run=true" >> $GITHUB_OUTPUT
152+
;;
130153
kiali)
131154
echo "label-selector=suite=kiali" >> $GITHUB_OUTPUT
132155
echo "kiali-run=true" >> $GITHUB_OUTPUT
156+
echo "kubevirt-run=false" >> $GITHUB_OUTPUT
133157
;;
134158
all)
135159
echo "label-selector=" >> $GITHUB_OUTPUT # No filter: run all taskSets
136160
echo "kiali-run=true" >> $GITHUB_OUTPUT
161+
echo "kubevirt-run=true" >> $GITHUB_OUTPUT
137162
;;
138163
*)
139164
echo "label-selector=suite=kubernetes" >> $GITHUB_OUTPUT
140165
echo "kiali-run=false" >> $GITHUB_OUTPUT
166+
echo "kubevirt-run=false" >> $GITHUB_OUTPUT
141167
;;
142168
esac
143169
@@ -168,10 +194,20 @@ jobs:
168194
if: needs.check-trigger.outputs.kiali-run == 'true'
169195
run: make setup-kiali
170196

197+
- name: Install KubeVirt
198+
if: needs.check-trigger.outputs.kubevirt-run == 'true'
199+
run: make kubevirt-install
200+
171201
- name: Start MCP server
172202
run: make run-server
173203
env:
174-
TOOLSETS: ${{ needs.check-trigger.outputs.kiali-run == 'true' && 'kiali' || '' }}
204+
TOOLSETS: >-
205+
${{
206+
(needs.check-trigger.outputs.kiali-run == 'true' && needs.check-trigger.outputs.kubevirt-run == 'true' && 'kiali,kubevirt') ||
207+
(needs.check-trigger.outputs.kiali-run == 'true' && 'kiali') ||
208+
(needs.check-trigger.outputs.kubevirt-run == 'true' && 'kubevirt') ||
209+
''
210+
}}
175211
176212
- name: Run mcpchecker evaluation
177213
id: mcpchecker

README.md

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ If you're using the native binaries you don't need to have Node or Python instal
4646
- **✅ High-Performance / Low-Latency**: Directly interacts with the Kubernetes API server without the overhead of calling and waiting for external commands.
4747
- **✅ Multi-Cluster**: Can interact with multiple Kubernetes clusters simultaneously (as defined in your kubeconfig files).
4848
- **✅ Cross-Platform**: Available as a native binary for Linux, macOS, and Windows, as well as an npm package, a Python package, and container/Docker image.
49-
- **✅ Configurable**: Supports [command-line arguments](#configuration) to configure the server behavior.
49+
- **✅ Configurable**: Supports [command-line arguments](#configuration), [TOML configuration files](docs/configuration.md), and environment variables.
5050
- **✅ Well tested**: The server has an extensive test suite to ensure its reliability and correctness across different Kubernetes environments.
51+
- **📚 Documentation**: Comprehensive [user documentation](docs/) including setup guides, configuration reference, and observability.
5152

5253
## 🚀 Getting Started <a id="getting-started"></a>
5354

@@ -199,7 +200,9 @@ uvx kubernetes-mcp-server@latest --help
199200
| `--stateless` | If set, the MCP server will run in stateless mode, disabling tool and prompt change notifications. This is useful for container deployments, load balancing, and serverless environments where maintaining client state is not desired. |
200201
| `--toolsets` | Comma-separated list of toolsets to enable. Check the [🛠️ Tools and Functionalities](#tools-and-functionalities) section for more information. |
201202
| `--disable-multi-cluster` | If set, the MCP server will disable multi-cluster support and will only use the current context from the kubeconfig file. This is useful if you want to restrict the MCP server to a single cluster. |
202-
| `--cluster-provider`. | Cluster provider strategy to use (one of: kubeconfig, in-cluster, kcp, disabled). If not set, the server will auto-detect based on the environment. |
203+
| `--cluster-provider` | Cluster provider strategy to use (one of: kubeconfig, in-cluster, kcp, disabled). If not set, the server will auto-detect based on the environment. |
204+
205+
> **Note**: Most CLI options have equivalent TOML configuration fields. The `--disable-multi-cluster` flag is equivalent to setting `cluster_provider_strategy = "disabled"` in TOML. See the [Configuration Reference](docs/configuration.md) for all TOML options.
203206
204207
### TOML Configuration Files
205208

@@ -216,6 +219,12 @@ log_level = 2
216219
read_only = true
217220
toolsets = ["core", "config", "helm", "kubevirt"]
218221

222+
# Deny access to sensitive resources
223+
[[denied_resources]]
224+
group = ""
225+
version = "v1"
226+
kind = "Secret"
227+
219228
[telemetry]
220229
endpoint = "http://localhost:4317"
221230
```
@@ -224,8 +233,10 @@ For comprehensive TOML configuration documentation, including:
224233
- All configuration options and their defaults
225234
- Drop-in configuration files for modular settings
226235
- Dynamic configuration reload via SIGHUP
236+
- Denied resources for restricting access to sensitive resource types
227237
- Server instructions for MCP Tool Search
228-
- Custom MCP prompts
238+
- [Custom MCP prompts](docs/prompts.md)
239+
- [OAuth/OIDC authentication](docs/KEYCLOAK_OIDC_SETUP.md) for HTTP mode
229240

230241
See the **[Configuration Reference](docs/configuration.md)**.
231242

@@ -255,9 +266,8 @@ The following sets of tools are available (toolsets marked with ✓ in the Defau
255266
| core | Most common tools for Kubernetes management (Pods, Generic Resources, Events, etc.) ||
256267
| helm | Tools for managing Helm charts and releases ||
257268
| kcp | Manage kcp workspaces and multi-tenancy features | |
258-
| openshift | OpenShift-specific tools for cluster management and troubleshooting, check the [OpenShift documentation](docs/OPENSHIFT.md) for more details. | |
259269
| kubevirt | KubeVirt virtual machine management tools | |
260-
| observability | Cluster observability tools for querying Prometheus metrics and Alertmanager alerts | |
270+
| observability | Cluster observability tools for querying Prometheus metrics and Alertmanager alerts | |
261271
| ossm | Most common tools for managing OSSM, check the [OSSM documentation](https://github.com/openshift/openshift-mcp-server/blob/main/docs/OSSM.md) for more details. | |
262272

263273
<!-- AVAILABLE-TOOLSETS-END -->
@@ -554,25 +564,6 @@ Common use cases:
554564

555565
</details>
556566

557-
<details>
558-
559-
<summary>openshift</summary>
560-
561-
- **plan_mustgather** - Plan for collecting a must-gather archive from an OpenShift cluster, must-gather is a tool for collecting cluster data related to debugging and troubleshooting like logs, kubernetes resources, etc.
562-
- `node_name` (`string`) - Optional node to run the mustgather pod. If not provided, a random control-plane node will be selected automatically
563-
- `node_selector` (`string`) - Optional node label selector to use, only relevant when specifying a command and image which needs to capture data on a set of cluster nodes simultaneously
564-
- `host_network` (`boolean`) - Optionally run the must-gather pods in the host network of the node. This is only relevant if a specific gather image needs to capture host-level data
565-
- `gather_command` (`string`) - Optionally specify a custom gather command to run a specialized script, eg. /usr/bin/gather_audit_logs (default: /usr/bin/gather)
566-
- `all_component_images` (`boolean`) - Optional when enabled, collects and runs multiple must gathers for all operators and components on the cluster that have an annotated must-gather image available
567-
- `images` (`array`) - Optional list of images to use for gathering custom information about specific operators or cluster components. If not specified, OpenShift's default must-gather image will be used by default
568-
- `source_dir` (`string`) - Optional to set a specific directory where the pod will copy gathered data from (default: /must-gather)
569-
- `timeout` (`string`) - Timeout of the gather process eg. 30s, 6m20s, or 2h10m30s
570-
- `namespace` (`string`) - Optional to specify an existing privileged namespace where must-gather pods should run. If not provided, a temporary namespace will be created
571-
- `keep_resources` (`boolean`) - Optional to retain all temporary resources when the mustgather completes, otherwise temporary resources created will be advised to be cleaned up
572-
- `since` (`string`) - Optional to collect logs newer than a relative duration like 5s, 2m5s, or 3h6m10s. If unspecified, all available logs will be collected
573-
574-
</details>
575-
576567

577568
<!-- AVAILABLE-TOOLSETS-TOOLS-END -->
578569

@@ -605,7 +596,13 @@ Common use cases:
605596

606597
## Helm Chart
607598

608-
A [Helm Chart](https://helm.sh) is available to simplify the deployment of the Kubernetes MCP server. Additional details can be found in the [chart README](./charts/kubernetes-mcp-server/README.md).
599+
A [Helm Chart](https://helm.sh) is available to simplify the deployment of the Kubernetes MCP server.
600+
601+
```shell
602+
helm install kubernetes-mcp-server oci://ghcr.io/containers/charts/kubernetes-mcp-server
603+
```
604+
605+
For configuration options including OAuth, telemetry, and resource limits, see the [chart README](./charts/kubernetes-mcp-server/README.md) and [values.yaml](./charts/kubernetes-mcp-server/values.yaml).
609606

610607
## 🧑‍💻 Development <a id="development"></a>
611608

docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ Toolsets group related tools together. Enable only the toolsets you need to redu
259259
| helm | Tools for managing Helm charts and releases | ✓ |
260260
| kcp | Manage kcp workspaces and multi-tenancy features | |
261261
| kubevirt | KubeVirt virtual machine management tools | |
262-
| observability | Cluster observability tools for querying Prometheus metrics and Alertmanager alerts | |
262+
| observability | Cluster observability tools for querying Prometheus metrics and Alertmanager alerts | |
263263
| ossm | Most common tools for managing OSSM, check the [OSSM documentation](https://github.com/openshift/openshift-mcp-server/blob/main/docs/OSSM.md) for more details. | |
264264

265265
<!-- AVAILABLE-TOOLSETS-END -->

evals/claude-code/eval.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ config:
4343
toolPattern: "helm_.*"
4444
minToolCalls: 1
4545
maxToolCalls: 10
46+
# KubeVirt tasks
47+
- glob: ../tasks/kubevirt/*/*.yaml
48+
labelSelector:
49+
suite: kubevirt
50+
assertions:
51+
toolsUsed:
52+
- server: kubernetes
53+
toolPattern: ".*"
54+
minToolCalls: 1
55+
maxToolCalls: 20
4656
# Kiali tasks
4757
- glob: ../tasks/*/*/*.yaml
4858
labelSelector:

evals/openai-agent/eval.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ config:
4343
toolPattern: "helm_.*"
4444
minToolCalls: 1
4545
maxToolCalls: 10
46+
# KubeVirt tasks
47+
- glob: ../tasks/kubevirt/*/*.yaml
48+
labelSelector:
49+
suite: kubevirt
50+
assertions:
51+
toolsUsed:
52+
- server: kubernetes
53+
toolPattern: ".*"
54+
minToolCalls: 1
55+
maxToolCalls: 20
4656
# Kiali tasks
4757
- glob: ../tasks/*/*/*.yaml
4858
labelSelector:

evals/tasks/kubernetes/fix-service-with-no-endpoints/fix-service-with-no-endpoints.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ steps:
1212
cleanup:
1313
file: cleanup.sh
1414
prompt:
15-
inline: "Our frontend application in the webshop-frontend namespace is reporting connection errors. The logs show: 'Error: connection to web-app-service.webshop-frontend.svc.cluster.local failed: connection refused'. Can you help diagnose and fix this issue?"
15+
inline: "Our frontend application in the webshop-frontend namespace is reporting connection errors. The logs show: 'Error: connection to web-app-service.webshop-frontend.svc.cluster.local failed: connection refused'. Can you help diagnose why pods aren't running and fix the deployment?"

evals/tasks/kubernetes/multi-container-pod-communication/multi-container-pod-communication.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ steps:
1717
1. A 'web-server' nginx instance that serves traffic
1818
2. A 'logger' busybox instance that processes those logs from a shared volume, 'logs-volume' with 'tail -f /var/log/nginx/access.log'
1919
20+
Both containers should be defined in spec.containers (not as init containers or sidecars).
2021
Both containers should mount logs-volume at '/var/log/nginx'.
21-
The logger should only start once the web server is ready. The pod should be considered ready when the web server is serving traffic.
22+
The pod should be considered ready when the web server is serving traffic.

pkg/config/config_default.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,24 @@ import (
66
"github.com/BurntSushi/toml"
77
)
88

9-
func Default() *StaticConfig {
10-
defaultConfig := StaticConfig{
9+
// BaseDefault returns the upstream base defaults before any
10+
// build-time overrides are applied. This is useful for understanding
11+
// the raw upstream configuration independent of downstream customization.
12+
func BaseDefault() *StaticConfig {
13+
return &StaticConfig{
1114
ListOutput: "table",
1215
Toolsets: []string{"core", "config", "helm"},
1316
}
14-
overrides := defaultOverrides()
15-
mergedConfig := mergeConfig(defaultConfig, overrides)
16-
return &mergedConfig
1717
}
1818

19-
// HasDefaultOverrides indicates whether the internal defaultOverrides function
20-
// provides any overrides or an empty StaticConfig.
21-
func HasDefaultOverrides() bool {
19+
// Default returns the effective default configuration, with any
20+
// downstream build-time overrides (from defaultOverrides) merged
21+
// on top of the base defaults.
22+
func Default() *StaticConfig {
23+
base := BaseDefault()
2224
overrides := defaultOverrides()
23-
var buf bytes.Buffer
24-
if err := toml.NewEncoder(&buf).Encode(overrides); err != nil {
25-
// If marshaling fails, assume no overrides
26-
return false
27-
}
28-
return len(bytes.TrimSpace(buf.Bytes())) > 0
25+
merged := mergeConfig(*base, overrides)
26+
return &merged
2927
}
3028

3129
// mergeConfig applies non-zero values from override to base using TOML serialization

0 commit comments

Comments
 (0)