Configure vMCP servers
This guide covers common configuration patterns for vMCP using the VirtualMCPServer resource. For a complete field reference, see the VirtualMCPServer CRD specification.
Create an MCPGroup
Before creating a VirtualMCPServer, you need an MCPGroup to organize the backend MCP servers. An MCPGroup is a logical container that groups related MCPServer resources together.
Create a basic MCPGroup:
apiVersion: toolhive.stacklok.dev/v1alpha1
kind: MCPGroup
metadata:
name: my-group
namespace: toolhive-system
spec:
description: Group of backend MCP servers for vMCP aggregation
The MCPGroup must exist in the same namespace as your VirtualMCPServer and be in
a Ready state before the VirtualMCPServer can start. Backend MCPServers
reference this group using the groupRef field in their spec.
Create a VirtualMCPServer
At minimum, a VirtualMCPServer requires a reference to an MCPGroup and an authentication type:
apiVersion: toolhive.stacklok.dev/v1alpha1
kind: VirtualMCPServer
metadata:
name: my-vmcp
namespace: toolhive-system
spec:
groupRef:
name: my-group
incomingAuth:
type: anonymous # Disables authentication; do not use in production
The MCPGroup must exist in the same namespace and be in a Ready state before the VirtualMCPServer can start.
Configure authentication
vMCP uses a two-boundary authentication model: client-to-vMCP (incoming) and vMCP-to-backends (outgoing). See the Authentication guide for complete configuration options including anonymous, OIDC, and Kubernetes service account authentication.
Expose the service
Choose how to expose the vMCP endpoint. The Service resource is created automatically on port 4483.
spec:
serviceType: ClusterIP # Default: cluster-internal (can be exposed via Ingress/Gateway)
# serviceType: LoadBalancer # Direct external access via cloud load balancer
# serviceType: NodePort # Direct external access via node ports
Service types:
- ClusterIP (default): For production, use with Ingress or Gateway API for controlled external access with TLS termination
- LoadBalancer: Direct external access via cloud provider's load balancer (simpler but less control)
- NodePort: Direct access via node ports (typically for development/testing)
The Service is named vmcp-<NAME>, where <NAME> is from metadata.name in
the VirtualMCPServer resource.
Monitor status
Check the VirtualMCPServer status to verify it's ready:
kubectl get virtualmcpserver my-vmcp
Key status fields:
| Field | Description |
|---|---|
phase | Current state (Pending, Ready, Degraded, Failed) |
url | Service URL for client connections |
backendCount | Number of discovered backend MCP servers |
discoveredBackends | Details about each backend and its auth type |