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-Virtualserver header with the namespace/name format.

Note

Prompt selection is optional. Specify which prompts from the aggregated pool to expose. Prompts are accessed by the X-Mcp-Virtualserver header with the namespace/name format.

Prerequisites
  • You completed all of the installation and configuration steps for MCP gateway.

  • You registered your MCP servers.

  • You installed the OpenShift CLI (oc).

Procedure
  1. Create an MCPVirtualServer CR for a virtual MCP server that curates development tools by using the following example:

    Example developer tools MCPVirtualServer CR
    apiVersion: 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.

  2. Apply the CR by running the following command:

    $ oc apply -f <mcpvs_devtools.yaml>

    Replace <mcpvs_devtools.yaml> with the name of your CR.

  3. Create an MCPVirtualServer CR for a virtual server that curates data analysis tools and prompts by using the following example:

    Example data analysis tools MCPVirtualServer CR
    apiVersion: 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. The metadata.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.

  4. Apply the CR by running the following command:

    $ oc apply -f <mcpvs_datatools.yaml>

    Replace <mcpvs_datatools.yaml> with the name of your CR.

Next step
  • 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:

  1. Identity-based filtering: The x-mcp-authorized header, injected by the AuthPolicy CR, reduces the tools and prompts list to only the capabilities that the user has resource_access roles configured for.

  2. Virtual MCP server filtering: The X-Mcp-Virtualserver header further reduces the available-capabilities list to only those that you defined in the MCPVirtualServer CR.

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.

Prerequisites
  • 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 jq command-line JSON processor.

  • You applied MCPVirtualServer custom resource (CRs) for your virtual servers.

Procedure
  1. List all of your virtual MCP servers by running the following command:

    $ oc get mcpvirtualserver -A

    The expected output is a list of all of the virtual MCP servers that you created.

  2. Performs a connectivity and handshake test of your virtual dev_tools MCP server by running the following curl command 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"
        }
      }
    }
  3. 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"
  4. Request the tools from the dev_tools virtual 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_tools virtual MCP server specification.

  5. Request the tools from the data_tools virtual 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_tools virtual MCP server specification.

  6. 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.

  7. Request prompts from the data_tools MCP 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_tools virtual server.