Skip to content
Merged
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
68 changes: 67 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,16 @@ Parameters:
- `version` (required): API version (e.g., v1, v1beta1)
- `resource` (required): Resource name (e.g., deployments, services)
- `namespace`: Namespace (required for namespaced resources)
- `label_selector`: Kubernetes label selector for filtering resources (optional)
- `include_annotations`: Whether to include annotations in the output (default: true)
- `exclude_annotation_keys`: List of annotation keys to exclude from output (supports wildcards with *)
- `include_annotation_keys`: List of annotation keys to include in output (if specified, only these are included)

Example:
##### Annotation Filtering

The `list_resources` tool provides powerful annotation filtering capabilities to control metadata output size and prevent truncation issues with large annotations (such as GPU node annotations).

**Basic Usage:**

```json
{
Expand All @@ -215,6 +223,64 @@ Example:
}
```

**Exclude specific annotations (useful for GPU nodes):**

```json
{
"name": "list_resources",
"arguments": {
"resource_type": "clustered",
"group": "",
"version": "v1",
"resource": "nodes",
"exclude_annotation_keys": [
"nvidia.com/*",
"kubectl.kubernetes.io/last-applied-configuration"
]
}
}
```

**Include only specific annotations:**

```json
{
"name": "list_resources",
"arguments": {
"resource_type": "namespaced",
"group": "",
"version": "v1",
"resource": "pods",
"namespace": "default",
"include_annotation_keys": ["app", "version", "prometheus.io/scrape"]
}
}
```

**Disable annotations completely for maximum performance:**

```json
{
"name": "list_resources",
"arguments": {
"resource_type": "namespaced",
"group": "",
"version": "v1",
"resource": "pods",
"namespace": "default",
"include_annotations": false
}
}
```

**Annotation Filtering Rules:**

- By default, `kubectl.kubernetes.io/last-applied-configuration` is excluded to prevent large configuration data
- `exclude_annotation_keys` supports wildcard patterns using `*` (e.g., `nvidia.com/*` excludes all NVIDIA annotations)
- When `include_annotation_keys` is specified, it takes precedence and only those annotations are included
- Setting `include_annotations: false` completely removes all annotations from the output
- Wildcard patterns only support `*` at the end of the key (e.g., `nvidia.com/*`)

#### apply_resource

Applies (creates or updates) a Kubernetes resource.
Expand Down
54 changes: 54 additions & 0 deletions pkg/mcp/helpers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,60 @@
package mcp

import (
"strings"
)

// BoolPtr returns a pointer to the given bool value
func BoolPtr(b bool) *bool {
return &b
}

// filterAnnotations filters annotations based on include/exclude lists
func filterAnnotations(annotations map[string]string, includeKeys, excludeKeys []string) map[string]string {
if annotations == nil {
return nil
}

result := make(map[string]string)

// If includeKeys is specified, only include those keys
if len(includeKeys) > 0 {
for _, key := range includeKeys {
if value, exists := annotations[key]; exists {
result[key] = value
}
}
return result
}

// Otherwise, include all except excluded keys
for key, value := range annotations {
excluded := false
for _, excludeKey := range excludeKeys {
if matchesPattern(key, excludeKey) {
excluded = true
break
}
}
if !excluded {
result[key] = value
}
}

return result
}

// matchesPattern checks if a key matches a pattern (supports wildcards with *)
func matchesPattern(key, pattern string) bool {
if pattern == key {
return true
}

// Simple wildcard matching - only supports * at the end
if strings.HasSuffix(pattern, "*") {
prefix := strings.TrimSuffix(pattern, "*")
return strings.HasPrefix(key, prefix)
}

return false
}
17 changes: 13 additions & 4 deletions pkg/mcp/list_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func (m *Implementation) HandleListResources(ctx context.Context, request mcp.Ca
namespace := mcp.ParseString(request, "namespace", "")
labelSelector := mcp.ParseString(request, "label_selector", "")

// Parse new annotation filtering parameters
includeAnnotations := request.GetBool("include_annotations", true)
excludeAnnotationKeys := request.GetStringSlice(
"exclude_annotation_keys", []string{"kubectl.kubernetes.io/last-applied-configuration"})
includeAnnotationKeys := request.GetStringSlice("include_annotation_keys", []string{})

// Validate parameters
if resourceType == "" {
return mcp.NewToolResultError("resource_type is required"), nil
Expand Down Expand Up @@ -90,10 +96,13 @@ func (m *Implementation) HandleListResources(ctx context.Context, request mcp.Ca

// Extract metadata from each resource
for _, item := range list.Items {
// Get annotations and filter out the last-applied-configuration annotation
annotations := item.GetAnnotations()
if annotations != nil {
delete(annotations, "kubectl.kubernetes.io/last-applied-configuration")
// Process annotations based on parameters
var annotations map[string]string
if includeAnnotations {
rawAnnotations := item.GetAnnotations()
if rawAnnotations != nil {
annotations = filterAnnotations(rawAnnotations, includeAnnotationKeys, excludeAnnotationKeys)
}
}

metadata := metav1.PartialObjectMetadata{
Expand Down
Loading