Virtual MCP servers for curating tools and prompts
When you aggregate all your model context (MCP) servers centrally, you solve for authentication, authorization, and configuration management. At the same time, this aggregation can overwhelm large-language models (LLMs) and AI agents with too many tool and prompt choices.
You can create virtual MCP servers to curate tools and prompts for each situation.
You can narrow the scope for your agentic services and applications by creating virtual MCP servers. These virtual servers filter the complete capabilities based on a curated selection and access only the relevant capabilities with HTTP headers. You can use virtual MCP servers to do the following:
-
Create specialized collections of tools for specific use cases.
-
Reduce the load on LLMs by presenting fewer, more relevant tools and prompts.
-
Group tools and prompts by function, for example, development tools, data analysis tools, and so on.
-
Make it easier for users and agents to find the right tools and prompts.
-
Combine with authorization policies for fine-grained access management.
Virtual MCP servers only filter those tools and prompts that a client can discover by using the tools/list and prompts/list concepts. Virtual MCP servers do not change call routing or authorization.
Create virtual MCP servers
To create virtual Model Context Protocol (MCP) servers for different use cases, you must define the virtual server with an MCPVirtualServer custom resource (CR) that specifies required fields.
When a client includes the virtual MCP server header, the MCP gateway filters responses to only include the specified tools.
An MCPVirtualServer CR must contain the following information:
-
Tool selection: Which tools from the aggregated pool to expose.
-
Description: A human-readable description of the virtual MCP server’s purpose.
-
Access method: Tools are accessed by the
X-Mcp-Virtualserverheader with thenamespace/nameformat.
|
Note
|
Prompt selection is optional. Specify which prompts from the aggregated pool to expose. Prompts are accessed by the |
-
You completed all of the installation and configuration steps for MCP gateway.
-
You registered your MCP servers.
-
You installed the OpenShift CLI (
oc).
-
Create an
MCPVirtualServerCR for a virtual MCP server that curates development tools by using the following example:Example developer toolsMCPVirtualServerCRapiVersion: mcp.kuadrant.io/v1alpha1 kind: MCPVirtualServer metadata: name: <dev_tools> namespace: <mcp_system> spec: description: "Development and debugging tools" tools: - mcpserver1_devtool1 - mcpserver2_headers1 - mcpserver3_debug1-
Replace the
metadata.name:value with the name you want to use. -
Replace the
metadata.namespace:value with the name you want to use. -
Replace the list values in the
spec.tools:parameter with the names of the tools you want to curate to this CR.
-
-
Apply the CR by running the following command:
$ oc apply -f <mcpvs_devtools.yaml>Replace
<mcpvs_devtools.yaml>with the name of your CR. -
Create an
MCPVirtualServerCR for a virtual server that curates data analysis tools and prompts by using the following example:Example data analysis toolsMCPVirtualServerCRapiVersion: mcp.kuadrant.io/v1alpha1 kind: MCPVirtualServer metadata: name: <data_tools> namespace: <mcp_system> spec: description: "Data analysis and reporting tools" tools: - mcpserver2_time - mcpserver2_dozen - mcpserver1_get_stats prompts: - test2_data_summary-
Replace the
metadata.name:value with the name you want to use. -
Replace the
metadata.namespace:value with the namespace you want to use. Themetadata.namespace:value can be any namespace where you have permission to create resources. -
Replace the list values in
spec.tools:with the names of the tools you want to curate to this CR. -
Replace the list values in
spec.prompts:with the names of the prompts you want to curate to this CR.
-
-
Apply the CR by running the following command:
$ oc apply -f <mcpvs_datatools.yaml>Replace
<mcpvs_datatools.yaml>with the name of your CR.
-
Verify that your virtual MCP servers are returning the tools and prompts that you expect to see by following the instructions in "Verifying virtual MCP servers".
Virtual MCP server authorization and filtering
When you create virtual Model Context Protocol (MCP) servers, the capabilities list is the intersection of the authentication and user-based tool or prompt filtering that already exists.
Each registered MCP server retains its AuthPolicy custom resources (CR) and role configurations.
When requests with a virtual MCP server header tools/list and prompts/list come in, the MCP gateway broker component applies filters sequentially. The following are the applied filters in order:
-
Identity-based filtering: The
x-mcp-authorizedheader, injected by theAuthPolicyCR, reduces the tools and prompts list to only the capabilities that the user hasresource_accessroles configured for. -
Virtual MCP server filtering: The
X-Mcp-Virtualserverheader further reduces the available-capabilities list to only those that you defined in theMCPVirtualServerCR.
For example, if the accounting virtual server lists test1_greet and test3_add, but the user only has the greet role on mcp-test/test-server1, that user only sees the tool, test1_greet.
Verify virtual MCP servers
After you create your virtual Model Context Protocol (MCP) servers, you can check that they are returning the tool and prompt lists that you want.
-
You completed all of the installation and configuration steps for MCP gateway.
-
You registered your MCP servers.
-
You installed the OpenShift CLI (
oc). -
You installed the
jqcommand-line JSON processor. -
You applied
MCPVirtualServercustom resource (CRs) for your virtual servers.
-
List all of your virtual MCP servers by running the following command:
$ oc get mcpvirtualserver -AThe expected output is a list of all of the virtual MCP servers that you created.
-
Performs a connectivity and handshake test of your virtual
dev_toolsMCP server by running the followingcurlcommand with the relevant URL and header:$ curl -s -D /tmp/mcp_headers -X POST <http:example.com:port/mcp> \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "test-client", "version": "1.0.0"}}}'Replace
<http:example.com:port/mcp>with the target URL and MCP gateway endpoint.Example output{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-11-25", "capabilities": { "tools": { "listChanged": true } }, "serverInfo": { "name": "Kuadrant MCP Gateway", "version": "0.0.1" } } } -
Extract the MCP session ID from response headers by running the following command:
$ SESSION_ID=$(grep -i "mcp-session-id:" /tmp/mcp_headers | cut -d' ' -f2 | tr -d '\r')Verify that the session ID was extracted by running the following command:
$ echo "MCP Session ID: $SESSION_ID" -
Request the tools from the
dev_toolsvirtual MCP server by running the following command:$ curl -X POST <http:example.com:port/mcp> \ -H "Content-Type: application/json" \ -H "mcp-session-id: $SESSION_ID" \ -H "X-Mcp-Virtualserver: <mcp_system>/<dev_tools>" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | jq '.result.tools[].name'-
Replace
<http:example.com:port/mcp>with the target URL and MCP gateway endpoint. -
Replace
<mcp_system>with the namespace of the MCP gateway. -
Replace
<dev_tools>with the tool headers that you want to request. -
The expected response is a list of only the tools you specified in the
dev_toolsvirtual MCP server specification.
-
-
Request the tools from the
data_toolsvirtual MCP server by running the following command:$ curl -X POST <http:example.com:port/mcp> \ -H "Content-Type: application/json" \ -H "mcp-session-id: $SESSION_ID" \ -H "X-Mcp-Virtualserver: <mcp_system>/<data_tools>" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | jq '.result.tools[].name'-
Replace
<http:example.com:port/mcp>with the target URL and MCP gateway endpoint. -
Replace
<mcp_system>with the namespace of the MCP gateway. -
Replace
<data_tools>with the tool headers that you want to request. -
The expected response is a list of only the tools you specified in the
data_toolsvirtual MCP server specification.
-
-
Request all available tools from your MCP servers by running the following command:
$ curl -X POST <http:example.com:port/mcp> \ -H "mcp-session-id: $SESSION_ID" \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | jq '.result.tools[].name'-
Replace
<http:example.com:port/mcp>with the target URL and MCP gateway endpoint. -
The expected response is a list of all tools from all registered MCP servers.
-
-
Request prompts from the
data_toolsMCP virtual server by running the following command:$ curl -X POST <http:example.com:port/mcp> \ -H "Content-Type: application/json" \ -H "mcp-session-id: $SESSION_ID" \ -H "X-Mcp-Virtualserver: <mcp_system/data_tools>" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "prompts/list"}' | jq '.result.prompts[].name'-
Replace
<http:example.com:port/mcp>with the target URL and MCP gateway endpoint. -
Replace
<mcp_system>with the namespace of the MCP gateway. -
Replace
<data_tools>with the tool headers that you want to request. -
The expected response is a list of only those prompts specified in the
data_toolsvirtual server.
-