README
¶
Virtual MCP Server (vmcp)
The Virtual MCP Server (vmcp) is a standalone binary that aggregates multiple MCP (Model Context Protocol) servers from a ToolHive group into a single unified interface. It acts as an aggregation proxy that consolidates tools, resources, and prompts from all workloads in the group.
Reference: See THV-2106 Virtual MCP Server Proposal for complete design details.
Features
Implemented (Phase 1)
- ✅ Group-Based Backend Management: Automatic workload discovery from ToolHive groups
- ✅ Tool Aggregation: Combines tools from multiple MCP servers with conflict resolution (prefix, priority, manual)
- ✅ Resource & Prompt Aggregation: Unified access to resources and prompts from all backends
- ✅ Request Routing: Intelligent routing of tool/resource/prompt requests to correct backends
- ✅ Session Management: MCP protocol session tracking with TTL-based cleanup
- ✅ Health Endpoints:
/healthand/pingfor service monitoring - ✅ Configuration Validation:
vmcp validatecommand for config verification
In Progress
- 🚧 Incoming Authentication (Issue #165): OIDC, local, anonymous authentication
- 🚧 Outgoing Authentication (Issue #160): RFC 8693 token exchange for backend API access
- 🚧 Token Caching: Memory and Redis cache providers
- 🚧 Health Monitoring (Issue #166): Circuit breakers, backend health checks
Future (Phase 2+)
- 📋 Authorization: Cedar policy-based access control
- 📋 Composite Tools: Multi-step workflows with elicitation support
- 📋 Advanced Routing: Load balancing, failover strategies
Installation
From Source
# Build the binary
task build-vmcp
# Or install to GOPATH/bin
task install-vmcp
Using Container Image
# Build the container image
task build-vmcp-image
# Or pull from GitHub Container Registry
docker pull ghcr.io/stacklok/toolhive/vmcp:latest
Quick Start
# 1. Create a ToolHive group
thv group create my-team
# 2. Run some MCP servers in the group
thv run github --name github-mcp --group my-team
thv run fetch --name fetch-mcp --group my-team
# 3. Create a vmcp configuration file (see examples/vmcp-config.yaml)
cat > vmcp-config.yaml <<EOF
name: "my-vmcp"
group: "my-team"
incoming_auth:
type: anonymous
outgoing_auth:
source: inline
default:
type: pass_through
aggregation:
conflict_resolution: prefix
conflict_resolution_config:
prefix_format: "{workload}_"
EOF
# 4. Validate the configuration
vmcp validate --config vmcp-config.yaml
# 5. Start the Virtual MCP Server
vmcp serve --config vmcp-config.yaml
# 6. Test the health endpoint
curl http://127.0.0.1:4483/health
# {"status":"ok"}
# 7. Connect your MCP client to http://127.0.0.1:4483/mcp
# The client will see aggregated tools from all backends:
# - github-mcp_create_issue, github-mcp_list_repos, ...
# - fetch-mcp_fetch, ...
Usage
CLI Commands
Start the Server
vmcp serve --config /path/to/vmcp-config.yaml
Validate Configuration
vmcp validate --config /path/to/vmcp-config.yaml
Show Version
vmcp version
Configuration
vmcp uses a YAML configuration file to define:
- Group Reference: ToolHive group containing MCP server workloads
- Incoming Authentication: Client → Virtual MCP authentication boundary
- Outgoing Authentication: Virtual MCP → Backend API token exchange
- Tool Aggregation: Conflict resolution and filtering strategies
- Operational Settings: Timeouts, health checks, circuit breakers
See examples/vmcp-config.yaml for a complete example.
Authentication Model
Virtual MCP implements two independent authentication boundaries:
1. Incoming Authentication (Client → Virtual MCP)
Validates client requests to Virtual MCP using tokens with aud=vmcp:
incoming_auth:
type: oidc
oidc:
issuer: "https://keycloak.example.com/realms/myrealm"
client_id: "vmcp-client"
audience: "vmcp" # Token must have aud=vmcp
2. Outgoing Authentication (Virtual MCP → Backend APIs)
Performs RFC 8693 token exchange to obtain backend API-specific tokens. These tokens are NOT for authenticating to backend MCP servers, but for the backend MCP servers to use when calling upstream APIs (GitHub API, Jira API, etc.):
outgoing_auth:
backends:
github:
type: token_exchange
token_exchange:
audience: "github-api" # Token for GitHub API
scopes: ["repo", "read:org"] # GitHub API scopes
Key Point: Backend MCP servers receive pre-validated tokens and use them directly to call external APIs. They don't validate tokens themselves—security relies on network isolation and properly scoped API tokens.
Tool Aggregation & Conflict Resolution
Virtual MCP aggregates tools from all workloads in the group and provides three strategies for handling naming conflicts:
1. Prefix Strategy (Default)
Automatically prefixes all tool names with the workload identifier:
aggregation:
conflict_resolution: prefix
conflict_resolution_config:
prefix_format: "{workload}_" # github_create_pr, jira_create_pr
2. Priority Strategy
First workload in priority order wins; conflicting tools from others are dropped:
aggregation:
conflict_resolution: priority
conflict_resolution_config:
priority_order: ["github", "jira", "slack"]
3. Manual Strategy
Explicitly define overrides for all tools:
aggregation:
conflict_resolution: manual
tools:
- workload: "github"
overrides:
create_pr:
name: "gh_create_pr"
description: "Create a GitHub pull request"
Architecture
┌─────────────┐
│ MCP Client │
└──────┬──────┘
│
▼
┌─────────────────────────────────┐
│ Virtual MCP Server (vmcp) │
│ ┌───────────────────────────┐ │
│ │ Middleware Chain │ │
│ │ - Auth │ │
│ │ - Authz │ │
│ │ - Audit │ │
│ │ - Telemetry │ │
│ └───────────────────────────┘ │
│ ┌───────────────────────────┐ │
│ │ Router / Aggregator │ │
│ └───────────────────────────┘ │
└────┬─────────┬─────────┬────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Backend │ │ Backend │ │ Backend │
│ MCP 1 │ │ MCP 2 │ │ MCP 3 │
└─────────┘ └─────────┘ └─────────┘
Development
Building
# Build binary
task build-vmcp
# Build container image
task build-vmcp-image
# Build everything
task build-all-images
Testing
# Run tests
go test ./pkg/vmcp/...
# Run with coverage
go test -cover ./pkg/vmcp/...
Differences from ToolHive (thv)
| Feature | thv | vmcp |
|---|---|---|
| Purpose | Run individual MCP servers | Aggregate multiple MCP servers |
| Architecture | Single server per instance | Multiple backends per instance |
| Configuration | RunConfig format | vMCP config format |
| Use Case | Development, testing | Production, multi-server deployments |
| Middleware | Per-server | Global + per-backend overrides |
Contributing
vmcp is part of the ToolHive project. Please see the main CONTRIBUTING.md for contribution guidelines.
License
Apache 2.0 - See LICENSE for details.