toolhive icon indicating copy to clipboard operation
toolhive copied to clipboard

Add ExcludeAll option for tool filtering in VirtualMCPServer aggregation

Open JAORMX opened this issue 4 weeks ago • 2 comments

Problem

The current WorkloadToolConfig.Filter field is an allow-list of tool names:

  • Filter: ["tool1", "tool2"] → allows only those tools
  • Filter: [] or Filter: nil → allows ALL tools (no filtering applied)

There's no way to exclude all tools from a backend in VirtualMCPServer aggregation. This limits flexibility in several scenarios:

  1. Composite-only VirtualMCPServer: You want to expose only composite tools without any direct backend tools
  2. Temporary disabling: Disable all tools from a backend without removing it from the group
  3. Selective enablement: Keep group membership but control tool exposure at the VirtualMCPServer level

Technical Context

Using Go's nil vs empty slice distinction (nil = allow all, [] = allow none) is elegant but problematic with Kubernetes CRDs due to JSON serialization with omitempty - the distinction is lost after API server round-trips.

Proposed Solution

1. Per-workload excludeAll boolean

Add an ExcludeAll field to WorkloadToolConfig:

spec:
  aggregation:
    tools:
      - workload: backend-a
        filter: ["echo"]        # Allow only echo tool
      - workload: backend-b
        excludeAll: true        # Exclude all tools from this backend
type WorkloadToolConfig struct {
    Workload   string            `json:"workload"`
    Filter     []string          `json:"filter,omitempty"`
    Overrides  map[string]...    `json:"overrides,omitempty"`
    ExcludeAll bool              `json:"excludeAll,omitempty"`  // NEW
}

2. Global excludeAllTools at aggregation level

Add a global flag to exclude all tools from all backends, useful for composite-only VirtualMCPServers:

spec:
  aggregation:
    excludeAllTools: true       # Exclude all backend tools globally
    conflictResolution: prefix
  composite:
    tools:
      - name: my-workflow
        # ... composite tool definition
type AggregationConfig struct {
    ConflictResolution string                `json:"conflictResolution,omitempty"`
    Tools              []WorkloadToolConfig  `json:"tools,omitempty"`
    ExcludeAllTools    bool                  `json:"excludeAllTools,omitempty"`  // NEW
}

This enables a clean pattern for composite-only VirtualMCPServers that orchestrate backend tools without exposing them directly.

Behavior Matrix

Config Behavior
excludeAllTools: true All backend tools excluded globally
excludeAll: true (per-workload) All tools from that specific backend excluded
filter: ["tool1"] Only listed tools allowed
filter: [] or omitted All tools allowed (current behavior)

Use Case Example

Expose only a composite workflow tool, hiding the underlying backend tools:

apiVersion: mcp.toolhive.stacklok.com/v1alpha1
kind: VirtualMCPServer
metadata:
  name: workflow-only-vmcp
spec:
  groupRef:
    name: my-backends
  aggregation:
    excludeAllTools: true  # Hide all direct backend tools
  composite:
    tools:
      - name: analyze-and-report
        description: "Runs analysis workflow across multiple backends"
        steps:
          - name: fetch-data
            tool: backend-a/fetch
          - name: process
            tool: backend-b/process
            dependsOn: [fetch-data]

Clients see only analyze-and-report, not the underlying fetch or process tools.

JAORMX avatar Nov 27 '25 19:11 JAORMX

Hey, can do this task ?

ignorant05 avatar Nov 27 '25 19:11 ignorant05

@ignorant05 of course!

JAORMX avatar Nov 27 '25 21:11 JAORMX