Skip to content

VirtualMCPServer CRD: Support non-string argument types in composite tool steps #2921

@jhrozek

Description

@jhrozek

Description

The VirtualMCPServer CRD currently defines composite tool step arguments as map[string]string, which prevents passing non-string values (integers, booleans, arrays, objects) to backend MCP tools.

Current Behavior

In cmd/thv-operator/api/v1alpha1/virtualmcpserver_types.go:281:

Arguments map[string]string `json:"arguments,omitempty"`

When a composite tool step needs to pass an integer argument (e.g., max_results: 5), it must be specified as a string (max_results: "5"), which causes type validation errors in backend tools that expect integer types.

Example Manifests

ArXiv search with max_results (integer parameter)

apiVersion: toolhive.stacklok.dev/v1alpha1
kind: VirtualMCPServer
metadata:
  name: paper-scout
spec:
  compositeTools:
    - name: find_papers
      steps:
        - id: search
          type: tool
          tool: arxiv_search_papers
          arguments:
            query: "{{.params.topic}}"
            max_results: "5"  # ❌ Must be string, but ArXiv expects integer

Error: invalid params: validating "arguments": expected integer, got string

Perplexity chat with messages (array parameter)

apiVersion: toolhive.stacklok.dev/v1alpha1
kind: VirtualMCPServer
metadata:
  name: research-assistant
spec:
  compositeTools:
    - name: ask_perplexity
      steps:
        - id: chat
          type: tool
          tool: perplexity_chat_completions
          arguments:
            model: "sonar"
            # ❌ Cannot pass array - CRD only supports string values
            # messages:
            #   - role: "user"
            #     content: "{{.params.question}}"

Error: Cannot represent array/object types in map[string]string

Expected Behavior

The CRD should support arbitrary JSON types for arguments, matching the internal vmcp implementation which already uses map[string]any in pkg/vmcp/composite/config.go:43:

Arguments map[string]any `yaml:"arguments" json:"arguments"`

Impact

This limitation prevents using many MCP tools in composite workflows when they require:

  • Integer parameters (e.g., max_results, limit, count)
  • Boolean parameters
  • Array parameters (e.g., messages for chat APIs)
  • Object parameters

Suggested Fix

Change the CRD Arguments field to use runtime.RawExtension or apiextensionsv1.JSON to support arbitrary JSON values:

// Option 1: Using apiextensions JSON type
Arguments map[string]apiextensionsv1.JSON `json:"arguments,omitempty"`

// Option 2: Using RawExtension
Arguments runtime.RawExtension `json:"arguments,omitempty"`

This would align the CRD with the internal vmcp config structure and enable full compatibility with backend MCP tools.

Related

Found during vMCP demo development with ArXiv and Perplexity MCP servers.

Metadata

Metadata

Labels

enhancementNew feature or requestgoPull requests that update go codekubernetesItems related to KubernetesvmcpVirtual MCP Server related issues

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions