This document describes operations for managing Virtual MCP Servers. Virtual servers aggregate tools from multiple backend MCP servers into a single unified endpoint.
For the full design and architecture details, see Virtual MCP Server Design Document.
Watch the video demonstration of Virtual MCP Server creation and management through the web UI:
- A valid JWT token (saved to a file, e.g.,
.token) - Registry URL (e.g.,
http://localhostfor local development)
| Command | Description |
|---|---|
vs-create |
Create a virtual MCP server from JSON config |
vs-list |
List all virtual MCP servers |
vs-get |
Get virtual MCP server details |
vs-update |
Update a virtual MCP server |
vs-delete |
Delete a virtual MCP server |
vs-toggle |
Enable or disable a virtual server |
vs-rate |
Rate a virtual MCP server (1-5 stars) |
vs-rating |
Get rating information |
Virtual servers are created from a JSON configuration file. Here is an example that combines tools from Context7 (documentation search) and CurrentTime (timezone) servers:
{
"path": "/virtual/combined-tools",
"server_name": "Combined Context7 and CurrentTime Tools",
"description": "Virtual server aggregating documentation search tools from Context7 and timezone tools from CurrentTime server",
"tool_mappings": [
{
"tool_name": "resolve-library-id",
"backend_server_path": "/context7"
},
{
"tool_name": "query-docs",
"backend_server_path": "/context7"
},
{
"tool_name": "current_time_by_timezone",
"alias": "get-current-time",
"backend_server_path": "/currenttime/"
}
],
"required_scopes": [],
"tool_scope_overrides": [],
"tags": [
"documentation",
"time",
"timezone",
"libraries",
"combined"
],
"supported_transports": [
"streamable-http"
],
"is_enabled": true
}See cli/examples/virtual-server-combined-example.json for the full example.
| Field | Required | Description |
|---|---|---|
path |
Yes | Virtual server path (e.g., /virtual/dev-tools) |
server_name |
Yes | Display name for the virtual server |
description |
No | Description of the virtual server |
tool_mappings |
Yes | Array of tool mappings (at least one required) |
required_scopes |
No | Server-level scope requirements |
tool_scope_overrides |
No | Per-tool scope overrides |
tags |
No | Tags for categorization |
supported_transports |
No | Supported transports (default: ["streamable-http"]) |
is_enabled |
No | Whether to enable on creation (default: true) |
| Field | Required | Description |
|---|---|---|
tool_name |
Yes | Original tool name on backend server |
backend_server_path |
Yes | Backend server path (e.g., /github) |
alias |
No | Renamed tool name in virtual server |
backend_version |
No | Pin to specific backend version |
description_override |
No | Override tool description |
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-create --config cli/examples/virtual-server-combined-example.jsonExample Output:
Virtual server created: /virtual/combined-tools
{
"message": "Virtual server created successfully",
"virtual_server": {
"path": "/virtual/combined-tools",
"server_name": "Combined Context7 and CurrentTime Tools",
"description": "Virtual server aggregating documentation search tools from Context7 and timezone tools from CurrentTime server",
"is_enabled": false,
"tool_count": 3
}
}
# List all virtual servers
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-list
# List only enabled virtual servers
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-list --enabled-only
# Output as JSON
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-list --jsonuv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-get --path /virtual/combined-toolsExample Output:
Virtual MCP Server: /virtual/combined-tools
------------------------------------------------------------
Name: Combined Context7 and CurrentTime Tools
Status: enabled
Description: Virtual server aggregating documentation search tools from Context7 and timezone tools from CurrentTime server
Rating: 0.0 stars
Tags: documentation, time, timezone, libraries, combined
Transports: streamable-http
Required Scopes: None
Tool Mappings (3):
- resolve-library-id
Backend: /context7
- query-docs
Backend: /context7
- current_time_by_timezone -> get-current-time
Backend: /currenttime/
Created: 2026-02-17T13:35:22.803009Z
Updated: 2026-02-17T13:35:41.075488Z
Created By: admin
# Enable
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-toggle --path /virtual/combined-tools --enabled true
# Disable
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-toggle --path /virtual/combined-tools --enabled falseuv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-update --path /virtual/combined-tools --config updated-config.json# With confirmation prompt
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-delete --path /virtual/combined-tools
# Skip confirmation
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-delete --path /virtual/combined-tools --forceuv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-rate --path /virtual/combined-tools --rating 5uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
vs-rating --path /virtual/combined-toolsVirtual servers support fine-grained access control through scopes. Virtual servers are configured in scope definitions exactly the same way as regular MCP servers - you simply use the virtual server path (e.g., /virtual/scoped-tools) as the server identifier.
For comprehensive documentation on how access control works, see Virtual MCP Server Access Control in the Fine-Grained Access Control documentation.
See Scope-Based Access Control Example for a virtual server configuration with scopes.
Use required_scopes to require users to have specific scopes to access the virtual server:
{
"required_scopes": ["virtual-server/access"]
}Use tool_scope_overrides to require additional scopes for specific tools:
{
"tool_scope_overrides": [
{
"tool_alias": "sensitive-tool",
"required_scopes": ["virtual-server/admin"]
}
]
}An end-to-end test script is provided for testing scope-based access control:
# Run the E2E test (with automatic cleanup)
./tests/integration/test_virtual_server_scopes_e2e.sh \
--registry-url http://localhost \
--token-file .token
# Run without cleanup (saves credentials for UI testing)
./tests/integration/test_virtual_server_scopes_e2e.sh \
--registry-url http://localhost \
--token-file .token \
--no-cleanup
# View saved credentials
cat /tmp/.vs-credsThe test script creates:
- A virtual server with scope-based access control
- A user group with matching scopes
- An M2M service account for API testing
- A regular user for UI testing
See test_virtual_server_scopes_e2e.sh for details.
All virtual server management operations can also be performed through the web UI. The UI provides a guided wizard for creating virtual servers with:
- Server configuration form
- Tool selection from registered backend servers
- Tool aliasing and scope configuration
- Real-time validation
Instead of passing --registry-url each time, you can set environment variables:
export REGISTRY_URL=http://localhost
export TOKEN_FILE=.token
# Then run commands without flags
uv run python api/registry_management.py vs-list