-
Notifications
You must be signed in to change notification settings - Fork 178
feat(kubevirt): Add basic VM management toolset #386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
9aa2732 to
4eac816
Compare
a135353 to
24ad072
Compare
This comment was marked as outdated.
This comment was marked as outdated.
@lyarwood +1 from my side on that being nice, the reason we haven't been able to add it there is that we use claude code in the non-interactive setup in |
30c0ec0 to
c01fe35
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work Lee. Please consider creating a single VM package with tool.go that will have all VM's actions in one single place, it would help to avoid duplications and will be much better in terms of readablity and maintainability.
codingben
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Lee.
Just an opinion: For the beginning I see too many folders and scripts to achieve a few VM's actions via MCP tooling. I'd ask the project's maintainers opinion about this, eventually this repository's codebase can be very huge.
Assuming you are talking about the test directory, I agree it is indeed pretty large at the moment but I've already spoken to folks about improvements to the |
pkg/kubernetes/kubernetes.go
Outdated
| // RESTConfig returns the Kubernetes REST configuration | ||
| func (k *Kubernetes) RESTConfig() *rest.Config { | ||
| if k.manager == nil { | ||
| return nil | ||
| } | ||
| return k.manager.cfg | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's already a ToRESTConfig method to cover this functionality and implement the RESTClientGetter interface required for Helm:
kubernetes-mcp-server/pkg/kubernetes/manager.go
Lines 195 to 198 in 7f4edfd
| // ToRESTConfig returns the rest.Config object (genericclioptions.RESTClientGetter) | |
| func (m *Manager) ToRESTConfig() (*rest.Config, error) { | |
| return m.cfg, nil | |
| } |
Similarly, there's already a ToDiscoveryClient method too (I think you're creating it at some point in the toolset).
Nonetheless, we need to prevent accessing any kubernetes API without checking if the resource is allowed by configuration:
kubernetes-mcp-server/pkg/kubernetes/accesscontrol.go
Lines 11 to 36 in cad863f
| // isAllowed checks the resource is in denied list or not. | |
| // If it is in denied list, this function returns false. | |
| func isAllowed( | |
| staticConfig *config.StaticConfig, // TODO: maybe just use the denied resource slice | |
| gvk *schema.GroupVersionKind, | |
| ) bool { | |
| if staticConfig == nil { | |
| return true | |
| } | |
| for _, val := range staticConfig.DeniedResources { | |
| // If kind is empty, that means Group/Version pair is denied entirely | |
| if val.Kind == "" { | |
| if gvk.Group == val.Group && gvk.Version == val.Version { | |
| return false | |
| } | |
| } | |
| if gvk.Group == val.Group && | |
| gvk.Version == val.Version && | |
| gvk.Kind == val.Kind { | |
| return false | |
| } | |
| } | |
| return true | |
| } |
In general, we don't want to directly expose the Kuberentes API to the toolsets implementors and provide whatetever is needed in the kubernetes package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkg/kubernetes/resources.go
Outdated
|
|
||
| // ResourcesListByGVR lists resources using a GroupVersionResource directly. | ||
| // Access control is enforced through the RESTMapper. | ||
| // Use this when you need to query arbitrary resources not covered by ResourcesList. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lyarwood what is the use case where the ResourcesList doesn't work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah apologies, should be fixed by 9cd97b4
Introduces a new KubeVirt toolset providing virtual machine management capabilities through MCP tools. The vm_create tool generates comprehensive creation plans with pre-creation validation of instance types, preferences, and container disk images, enabling AI assistants to help users create VirtualMachines with appropriate resource configurations. The tool supports: - Workload specification via OS names or container disk URLs - Auto-selection of instance types based on size/performance hints - DataSource integration for common OS images - Comprehensive validation and planning before resource creation Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Add lifecycle management tools for starting and stopping VirtualMachines. These tools provide simple, single-action operations that prevent destructive workarounds like delete/recreate. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Add optional autostart parameter to vm_create tool that sets runStrategy to Always instead of Halted, allowing VMs to be created and started in a single operation. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Add GetRequiredString, GetOptionalString, and GetOptionalBool methods to ToolHandlerParams type to eliminate code duplication across kubevirt VM tools. These methods provide a cleaner, reusable API for extracting parameters from tool call arguments. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Extend GetOptionalString method to accept a default value parameter, allowing callers to specify what value to return when a parameter is missing or invalid. This simplifies code by eliminating post-call default value checks. Use variadic parameters to make the default value argument optional in GetOptionalString. Callers can now either provide a default value or omit it to get empty string behavior. This provides more flexibility and cleaner call sites when empty string is the desired default. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Refactor all kubevirt VM tool tests to use external test packages (_test suffix) and test only public behavior through the Tools() API. This ensures tests verify the public interface rather than implementation details. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Implements a new KubeVirt VM pause tool that uses the subresource API to
pause a running VirtualMachine's associated VirtualMachineInstance.
Unlike vm_start and vm_stop which modify the VM's runStrategy, this tool
directly calls the VMI pause subresource endpoint at
/apis/subresources.kubevirt.io/v1/namespaces/{namespace}/virtualmachineinstances/{name}/pause.
Assisted-By: Claude <[email protected]>
Signed-off-by: Lee Yarwood <[email protected]>
Introduces a dedicated vm_delete tool to simplify VirtualMachine deletion. Based on agent evaluation results, multiple agents were searching for a vm_delete tool instead of using the generic resources_delete tool. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Remove direct RESTConfig() exposure from Kubernetes type and add RESTConfigForGVK method that validates resource access through AccessControlRESTMapper before allowing operations. Update all kubevirt tools to use GVK instead of GVR with ResourcesList and use controlled RESTConfigForGVK method instead of creating their own uncontrolled dynamic clients. This prevents toolsets from bypassing the denied resources configuration and ensures all API access goes through the access control layer. Assisted-By: Claude <[email protected]> Signed-off-by: Lee Yarwood <[email protected]>
Summary
This PR introduces an initial KubeVirt toolset for the kubernetes-mcp-server, enabling AI agents to create and manage virtual machines through MCP tools.
New Tools
vm_createCreates VirtualMachines with intelligent parameter handling:
fedora,ubuntu,rhel) or full container disk URLsrunStrategy: Always)Example:
{ "name": "vm_create", "arguments": { "namespace": "my-namespace", "name": "my-vm", "workload": "fedora", "size": "large", "performance": "compute-optimized" } }vm_startStarts halted VirtualMachines by changing runStrategy to Always.
vm_stopStops running VirtualMachines by changing runStrategy to Halted.
vm_pausePauses a running VirtualMachine by calling the
pausesub-resource API of the VMI.vm_troubleshootProvides comprehensive diagnostic guidance for broken VMs:
Key Features
Testing Results
Validated using the gevals (Generative AI Evaluations) framework across 5 different AI agents/models with 6 tasks each:
Agent Performance (Improved Toolset)
Key Achievement: The toolset enables even smaller models like Granite 3.3 8B (which failed all tasks without specialized tools) to achieve perfect success rates.
Design Principles
Implementation Details
A set of
gevalstest result/report documents is available outside of this PR underpkg/toolsets/kubevirt/tests/results/setting out howgevalshas been used to first introduce and then improve the new toolset.