virtualmcp

package
v0.6.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2025 License: Apache-2.0 Imports: 16 Imported by: 0

README

VirtualMCPServer E2E Tests

This directory contains end-to-end tests for the VirtualMCPServer controller that run against a real Kubernetes cluster.

Prerequisites

  • A Kubernetes cluster with the ToolHive operator installed
  • kubectl configured to access the cluster
  • The VirtualMCPServer CRDs installed

Note: The Ginkgo CLI is automatically installed by the task commands when running tests.

Running the Tests

The easiest way to run the tests is using the task command from the operator directory, which will:

  1. Create a Kind cluster
  2. Install CRDs
  3. Deploy the operator
  4. Run all tests from test/e2e/thv-operator/virtualmcp (including setup)
  5. Clean up the cluster
# Run from the project root
task thv-operator-e2e-test
Manual Testing

The tests will:

  • Use the kubeconfig from $KUBECONFIG or ~/.kube/config
  • Create all necessary resources (MCPGroup, MCPServers, VirtualMCPServer)
  • Run comprehensive MCP protocol tests
  • Clean up resources after completion
cd test/e2e/thv-operator/virtualmcp
ginkgo -v
Customizing Test Parameters

You can customize the kubeconfig path using the KUBECONFIG environment variable:

export KUBECONFIG="/path/to/kubeconfig"
ginkgo -v
Running Specific Tests
# Run only discovered mode tests
ginkgo -v --focus="Discovered Mode"

# Run tests and get verbose output
ginkgo -vv

Test Structure

Files
  • suite_test.go - Ginkgo test suite setup with kubeconfig loading
  • virtualmcp_discovered_mode_test.go - Tests VirtualMCPServer with discovered mode aggregation
  • helpers.go - Common helper functions for interacting with Kubernetes resources
  • README.md - This file
Test Descriptions
Discovered Mode Tests (virtualmcp_discovered_mode_test.go)

Comprehensive E2E tests for VirtualMCPServer in discovered mode, which automatically discovers and aggregates tools from backend MCP servers in a group:

  • Creates two backend MCPServers (fetch and osv) both using streamable-http transport
  • Verifies VirtualMCPServer aggregates tools from all backends in the group
  • Tests tool calls through the VirtualMCPServer proxy
  • Validates discovered mode configuration and backend discovery
  • Uses prefix conflict resolution strategy to namespace tools from different backends

Environment Variables

Variable Description Default
KUBECONFIG Path to kubeconfig file ~/.kube/config

Adding New Tests

To add new test cases:

  1. Create a new test file following the naming pattern *_test.go
  2. Use the shared k8sClient and ctx variables from suite_test.go
  3. Use helper functions from helpers.go when possible
  4. Follow Ginkgo BDD style with Describe, Context, and It blocks

Example:

var _ = Describe("VirtualMCPServer Feature", func() {
    Context("when testing feature X", func() {
        It("should behave as expected", func() {
            // Test implementation
        })
    })
})

Troubleshooting

Tests fail with "kubeconfig file should exist"

Ensure your KUBECONFIG environment variable points to a valid kubeconfig file, or that ~/.kube/config exists.

Tests fail with "VirtualMCPServer should exist"

Make sure:

  1. The ToolHive operator is running in your cluster
  2. The VirtualMCPServer CRDs are installed
  3. The tests create their own VirtualMCPServer resources for testing
Tests timeout waiting for resources

Check:

  1. The operator is running: kubectl get pods -n toolhive-system
  2. The operator logs for errors: kubectl logs -n toolhive-system -l app.kubernetes.io/name=thv-operator
  3. The VirtualMCPServer status: kubectl get virtualmcpserver -n <namespace> <name> -o yaml

Documentation

Index

Constants

View Source
const InstrumentedBackendScript = `` /* 1379-byte string literal not displayed */

InstrumentedBackendScript is an instrumented backend script that tracks Bearer tokens

View Source
const MockOIDCServerHTTPScript = `` /* 1627-byte string literal not displayed */

MockOIDCServerHTTPScript is a mock OIDC server script with HTTP (for testing with private IPs)

Variables

This section is empty.

Functions

func CleanupMockServer

func CleanupMockServer(ctx context.Context, c client.Client, namespace, serverName, tlsSecretName string)

CleanupMockServer cleans up a mock server deployment, service, and optionally its TLS secret

func DeployInstrumentedBackendServer

func DeployInstrumentedBackendServer(ctx context.Context, c client.Client, namespace, serverName string)

DeployInstrumentedBackendServer deploys a backend server that logs all headers

func DeployMockOIDCServerHTTP

func DeployMockOIDCServerHTTP(ctx context.Context, c client.Client, namespace, serverName string)

DeployMockOIDCServerHTTP deploys a mock OIDC server with HTTP (for testing)

func GetInstrumentedBackendStats

func GetInstrumentedBackendStats(ctx context.Context, c client.Client, namespace, serviceName string) (map[string]int, error)

GetInstrumentedBackendStats queries the /stats endpoint of the instrumented backend

func GetMCPGroupBackends

func GetMCPGroupBackends(ctx context.Context, c client.Client, groupName, namespace string) ([]mcpv1alpha1.MCPServer, error)

GetMCPGroupBackends returns the list of backend MCPServers in an MCPGroup Note: MCPGroup status contains the list of servers in the group

func GetMockOIDCStats

func GetMockOIDCStats(ctx context.Context, c client.Client, namespace, serviceName string) (map[string]int, error)

GetMockOIDCStats queries the /stats endpoint of the mock OIDC server

func GetPodLogsForDeployment

func GetPodLogsForDeployment(ctx context.Context, c client.Client, namespace, deploymentName string) string

GetPodLogsForDeployment returns logs from pods for a deployment (for debugging)

func GetServiceStats

func GetServiceStats(ctx context.Context, c client.Client, namespace, serviceName string, port int) (string, error)

GetServiceStats queries the /stats endpoint of a service and returns the stats

func GetVirtualMCPServerPods

func GetVirtualMCPServerPods(ctx context.Context, c client.Client, vmcpServerName, namespace string) (*corev1.PodList, error)

GetVirtualMCPServerPods returns all pods for a VirtualMCPServer

func GetVirtualMCPServerStatus

func GetVirtualMCPServerStatus(
	ctx context.Context,
	c client.Client,
	name, namespace string,
) (*mcpv1alpha1.VirtualMCPServerStatus, error)

GetVirtualMCPServerStatus returns the current status of a VirtualMCPServer

func HasCondition

func HasCondition(vmcpServer *mcpv1alpha1.VirtualMCPServer, conditionType string, expectedStatus string) bool

HasCondition checks if a VirtualMCPServer has a specific condition type with expected status

func WaitForCondition

func WaitForCondition(
	ctx context.Context,
	c client.Client,
	name, namespace string,
	conditionType string,
	expectedStatus string,
	timeout time.Duration,
)

WaitForCondition waits for a VirtualMCPServer to have a specific condition

func WaitForPodsReady

func WaitForPodsReady(ctx context.Context, c client.Client, namespace string, labels map[string]string, timeout time.Duration)

WaitForPodsReady waits for all pods matching labels to be ready

func WaitForVirtualMCPServerReady

func WaitForVirtualMCPServerReady(ctx context.Context, c client.Client, name, namespace string, timeout time.Duration)

WaitForVirtualMCPServerReady waits for a VirtualMCPServer to reach Ready status

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL