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
55 changes: 55 additions & 0 deletions tools/annotations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package tools

import "github.com/mark3labs/mcp-go/mcp"

// readOnlyAnnotation is for tools that don't change cluster state.
// Repeated calls have no additional effect (idempotent). The cluster is an
// external system, so openWorld is true.
func readOnlyAnnotation(title string) mcp.ToolOption {
return mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: title,
ReadOnlyHint: mcp.ToBoolPtr(true),
DestructiveHint: mcp.ToBoolPtr(false),
IdempotentHint: mcp.ToBoolPtr(true),
OpenWorldHint: mcp.ToBoolPtr(true),
})
}

// destructiveAnnotation is for tools that delete or otherwise destroy
// cluster state. Not idempotent — a second delete typically returns
// "not found".
func destructiveAnnotation(title string) mcp.ToolOption {
return mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: title,
ReadOnlyHint: mcp.ToBoolPtr(false),
DestructiveHint: mcp.ToBoolPtr(true),
IdempotentHint: mcp.ToBoolPtr(false),
OpenWorldHint: mcp.ToBoolPtr(true),
})
}

// creationAnnotation is for tools that create a new resource. Not
// destructive in the data-loss sense, but not idempotent — recreating a
// resource that already exists errors with "already exists".
func creationAnnotation(title string) mcp.ToolOption {
return mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: title,
ReadOnlyHint: mcp.ToBoolPtr(false),
DestructiveHint: mcp.ToBoolPtr(false),
IdempotentHint: mcp.ToBoolPtr(false),
OpenWorldHint: mcp.ToBoolPtr(true),
})
}

// idempotentMutationAnnotation is for update / scale / suspend / resume
// tools that drive a resource toward a desired final state. Repeating
// with the same arguments produces no further change.
func idempotentMutationAnnotation(title string) mcp.ToolOption {
return mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: title,
ReadOnlyHint: mcp.ToBoolPtr(false),
DestructiveHint: mcp.ToBoolPtr(false),
IdempotentHint: mcp.ToBoolPtr(true),
OpenWorldHint: mcp.ToBoolPtr(true),
})
}
5 changes: 5 additions & 0 deletions tools/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func RegisterConfigMapTools(s kai.ServerInterface, cm kai.ClusterManager) {
func RegisterConfigMapToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, factory ConfigMapFactory) {
createConfigMapTool := mcp.NewTool("create_configmap",
mcp.WithDescription("Create a new ConfigMap in the specified namespace"),
creationAnnotation("Create configmap"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the ConfigMap"),
Expand All @@ -69,6 +70,7 @@ func RegisterConfigMapToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMana

getConfigMapTool := mcp.NewTool("get_configmap",
mcp.WithDescription("Get detailed information about a specific ConfigMap"),
readOnlyAnnotation("Get configmap"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the ConfigMap"),
Expand All @@ -81,6 +83,7 @@ func RegisterConfigMapToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMana

listConfigMapsTool := mcp.NewTool("list_configmaps",
mcp.WithDescription("List ConfigMaps in the current namespace or across all namespaces"),
readOnlyAnnotation("List configmaps"),
mcp.WithBoolean("all_namespaces",
mcp.Description("Whether to list ConfigMaps across all namespaces"),
),
Expand All @@ -95,6 +98,7 @@ func RegisterConfigMapToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMana

deleteConfigMapTool := mcp.NewTool("delete_configmap",
mcp.WithDescription("Delete a ConfigMap from the specified namespace"),
destructiveAnnotation("Delete configmap"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the ConfigMap to delete"),
Expand All @@ -107,6 +111,7 @@ func RegisterConfigMapToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMana

updateConfigMapTool := mcp.NewTool("update_configmap",
mcp.WithDescription("Update an existing ConfigMap"),
idempotentMutationAnnotation("Update configmap"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the ConfigMap to update"),
Expand Down
7 changes: 7 additions & 0 deletions tools/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ import (
func RegisterContextTools(s kai.ServerInterface, cm kai.ClusterManager) {
listContextsTool := mcp.NewTool("list_contexts",
mcp.WithDescription("List all available Kubernetes contexts"),
readOnlyAnnotation("List contexts"),
)
s.AddTool(listContextsTool, listContextsHandler(cm))

getCurrentContextTool := mcp.NewTool("get_current_context",
mcp.WithDescription("Get the currently active Kubernetes context"),
readOnlyAnnotation("Get current context"),
)
s.AddTool(getCurrentContextTool, getCurrentContextHandler(cm))

switchContextTool := mcp.NewTool("switch_context",
mcp.WithDescription("Switch to a different Kubernetes context"),
idempotentMutationAnnotation("Switch context"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the context to switch to"),
Expand All @@ -33,6 +36,7 @@ func RegisterContextTools(s kai.ServerInterface, cm kai.ClusterManager) {

loadKubeconfigTool := mcp.NewTool("load_kubeconfig",
mcp.WithDescription("Load a kubeconfig file and register it as a new context"),
creationAnnotation("Load kubeconfig"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name to assign to this context"),
Expand All @@ -45,6 +49,7 @@ func RegisterContextTools(s kai.ServerInterface, cm kai.ClusterManager) {

deleteContextTool := mcp.NewTool("delete_context",
mcp.WithDescription("Remove a context from the manager"),
destructiveAnnotation("Delete context"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the context to delete"),
Expand All @@ -54,6 +59,7 @@ func RegisterContextTools(s kai.ServerInterface, cm kai.ClusterManager) {

renameContextTool := mcp.NewTool("rename_context",
mcp.WithDescription("Rename an existing context"),
creationAnnotation("Rename context"),
mcp.WithString("old_name",
mcp.Required(),
mcp.Description("Current name of the context"),
Expand All @@ -67,6 +73,7 @@ func RegisterContextTools(s kai.ServerInterface, cm kai.ClusterManager) {

describeContextTool := mcp.NewTool("describe_context",
mcp.WithDescription("Get detailed information about a specific context"),
readOnlyAnnotation("Describe context"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the context to describe"),
Expand Down
7 changes: 7 additions & 0 deletions tools/cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func RegisterCronJobTools(s kai.ServerInterface, cm kai.ClusterManager) {
func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, factory CronJobFactory) {
createCronJobTool := mcp.NewTool("create_cronjob",
mcp.WithDescription("Create a new CronJob in the specified namespace"),
creationAnnotation("Create cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob"),
Expand Down Expand Up @@ -115,6 +116,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

getCronJobTool := mcp.NewTool("get_cronjob",
mcp.WithDescription("Get information about a specific CronJob"),
readOnlyAnnotation("Get cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob"),
Expand All @@ -127,6 +129,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

listCronJobsTool := mcp.NewTool("list_cronjobs",
mcp.WithDescription("List CronJobs in the current namespace or across all namespaces"),
readOnlyAnnotation("List cronjobs"),
mcp.WithBoolean("all_namespaces",
mcp.Description("Whether to list CronJobs across all namespaces"),
),
Expand All @@ -141,6 +144,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

deleteCronJobTool := mcp.NewTool("delete_cronjob",
mcp.WithDescription("Delete a CronJob from the specified namespace"),
destructiveAnnotation("Delete cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob to delete"),
Expand All @@ -153,6 +157,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

updateCronJobTool := mcp.NewTool("update_cronjob",
mcp.WithDescription("Update an existing CronJob"),
idempotentMutationAnnotation("Update cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob to update"),
Expand Down Expand Up @@ -180,6 +185,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

suspendCronJobTool := mcp.NewTool("suspend_cronjob",
mcp.WithDescription("Suspend a CronJob to prevent it from creating new jobs"),
idempotentMutationAnnotation("Suspend cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob to suspend"),
Expand All @@ -192,6 +198,7 @@ func RegisterCronJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

resumeCronJobTool := mcp.NewTool("resume_cronjob",
mcp.WithDescription("Resume a suspended CronJob"),
idempotentMutationAnnotation("Resume cronjob"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the CronJob to resume"),
Expand Down
13 changes: 13 additions & 0 deletions tools/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func RegisterDeploymentTools(s kai.ServerInterface, cm kai.ClusterManager) {
func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, factory DeploymentFactory) {
listDeploymentTool := mcp.NewTool("list_deployments",
mcp.WithDescription("List deployments in the current namespace or across all namespaces"),
readOnlyAnnotation("List deployments"),
mcp.WithBoolean("all_namespaces",
mcp.Description("Whether to list deployments across all namespaces"),
),
Expand All @@ -62,6 +63,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

describeDeploymentTool := mcp.NewTool("describe_deployment",
mcp.WithDescription("Get detailed information about a specific deployment"),
readOnlyAnnotation("Describe deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -75,6 +77,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

createDeploymentTool := mcp.NewTool("create_deployment",
mcp.WithDescription("Create a new deployment in the current namespace"),
creationAnnotation("Create deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand Down Expand Up @@ -110,6 +113,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

getDeploymentTool := mcp.NewTool("get_deployment",
mcp.WithDescription("Get basic information about a specific deployment"),
readOnlyAnnotation("Get deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -123,6 +127,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

updateDeploymentTool := mcp.NewTool("update_deployment",
mcp.WithDescription("Update an existing deployment"),
idempotentMutationAnnotation("Update deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment to update"),
Expand Down Expand Up @@ -157,6 +162,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

deleteDeploymentTool := mcp.NewTool("delete_deployment",
mcp.WithDescription("Delete a deployment from the cluster"),
destructiveAnnotation("Delete deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment to delete"),
Expand All @@ -170,6 +176,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

scaleDeploymentTool := mcp.NewTool("scale_deployment",
mcp.WithDescription("Scale a deployment to a specified number of replicas"),
idempotentMutationAnnotation("Scale deployment"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment to scale"),
Expand All @@ -187,6 +194,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutStatusTool := mcp.NewTool("rollout_status_deployment",
mcp.WithDescription("Check the rollout status of a deployment"),
readOnlyAnnotation("Get rollout status"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -200,6 +208,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutHistoryTool := mcp.NewTool("rollout_history_deployment",
mcp.WithDescription("View the rollout history of a deployment"),
readOnlyAnnotation("Get rollout history"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -213,6 +222,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutUndoTool := mcp.NewTool("rollout_undo_deployment",
mcp.WithDescription("Roll back a deployment to a previous revision"),
destructiveAnnotation("Undo rollout"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -229,6 +239,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutRestartTool := mcp.NewTool("rollout_restart_deployment",
mcp.WithDescription("Restart a deployment by recreating its pods"),
creationAnnotation("Restart rollout"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -242,6 +253,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutPauseTool := mcp.NewTool("rollout_pause_deployment",
mcp.WithDescription("Pause a deployment rollout"),
idempotentMutationAnnotation("Pause rollout"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand All @@ -255,6 +267,7 @@ func RegisterDeploymentToolsWithFactory(s kai.ServerInterface, cm kai.ClusterMan

rolloutResumeTool := mcp.NewTool("rollout_resume_deployment",
mcp.WithDescription("Resume a paused deployment rollout"),
idempotentMutationAnnotation("Resume rollout"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the deployment"),
Expand Down
5 changes: 5 additions & 0 deletions tools/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func RegisterIngressTools(s kai.ServerInterface, cm kai.ClusterManager) {
func RegisterIngressToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, factory IngressFactory) {
createIngressTool := mcp.NewTool("create_ingress",
mcp.WithDescription("Create a new Ingress in the specified namespace for HTTP/HTTPS routing"),
creationAnnotation("Create ingress"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Ingress"),
Expand Down Expand Up @@ -77,6 +78,7 @@ func RegisterIngressToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

getIngressTool := mcp.NewTool("get_ingress",
mcp.WithDescription("Get information about a specific Ingress"),
readOnlyAnnotation("Get ingress"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Ingress"),
Expand All @@ -89,6 +91,7 @@ func RegisterIngressToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

listIngressesTool := mcp.NewTool("list_ingresses",
mcp.WithDescription("List Ingresses in the current namespace or across all namespaces"),
readOnlyAnnotation("List ingresses"),
mcp.WithBoolean("all_namespaces",
mcp.Description("Whether to list Ingresses across all namespaces"),
),
Expand All @@ -103,6 +106,7 @@ func RegisterIngressToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

updateIngressTool := mcp.NewTool("update_ingress",
mcp.WithDescription("Update an existing Ingress"),
idempotentMutationAnnotation("Update ingress"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Ingress to update"),
Expand Down Expand Up @@ -133,6 +137,7 @@ func RegisterIngressToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManage

deleteIngressTool := mcp.NewTool("delete_ingress",
mcp.WithDescription("Delete an Ingress from the specified namespace"),
destructiveAnnotation("Delete ingress"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Ingress to delete"),
Expand Down
5 changes: 5 additions & 0 deletions tools/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func RegisterJobTools(s kai.ServerInterface, cm kai.ClusterManager) {
func RegisterJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, factory JobFactory) {
createJobTool := mcp.NewTool("create_job",
mcp.WithDescription("Create a new Job in the specified namespace"),
creationAnnotation("Create job"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Job"),
Expand Down Expand Up @@ -98,6 +99,7 @@ func RegisterJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, f

getJobTool := mcp.NewTool("get_job",
mcp.WithDescription("Get information about a specific Job"),
readOnlyAnnotation("Get job"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Job"),
Expand All @@ -110,6 +112,7 @@ func RegisterJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, f

listJobsTool := mcp.NewTool("list_jobs",
mcp.WithDescription("List Jobs in the current namespace or across all namespaces"),
readOnlyAnnotation("List jobs"),
mcp.WithBoolean("all_namespaces",
mcp.Description("Whether to list Jobs across all namespaces"),
),
Expand All @@ -124,6 +127,7 @@ func RegisterJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, f

deleteJobTool := mcp.NewTool("delete_job",
mcp.WithDescription("Delete a Job from the specified namespace"),
destructiveAnnotation("Delete job"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Job to delete"),
Expand All @@ -136,6 +140,7 @@ func RegisterJobToolsWithFactory(s kai.ServerInterface, cm kai.ClusterManager, f

updateJobTool := mcp.NewTool("update_job",
mcp.WithDescription("Update an existing Job (limited to mutable fields like labels and parallelism)"),
idempotentMutationAnnotation("Update job"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the Job to update"),
Expand Down
Loading
Loading