Skip to content

MCP Server Registration

You must register your MCP servers to be discovered and routed by the MCP Gateway. When a server is registered, the gateway automatically discovers and federates its capabilities (tools and prompts), applying a prefix to avoid name collisions across multiple servers.

Overview

MCP Gateway supports federating both MCP Tools and MCP Prompts.

  • Discovery: The gateway's broker automatically discovers available tools and prompts from registered upstream servers.
  • Prefixing: To prevent collisions between capabilities with the same name on different servers, the gateway applies the prefix defined in the MCPServerRegistration to each tool and prompt name (e.g., greet becomes myserver_greet).
  • Routing: When a client calls a tool or requests a prompt, the gateway identifies the target upstream server by the prefix, strips the prefix, and routes the request to the correct server.

To connect an MCP server to MCP Gateway, you must create an HTTPRoute that routes to your MCP server and an MCPServerRegistration resource that references the HTTPRoute.

Prerequisites

Procedure

Step 1: Ensure MCPGatewayExtension exists

An MCPGatewayExtension tells the controller which Gateway this MCP Gateway instance serves. Without it, MCPServerRegistration resources will remain in NotReady status.

Note: Only one MCPGatewayExtension is allowed per namespace. The sectionName field selects which listener on the Gateway to use, but each namespace can only have one MCPGatewayExtension. If you followed the quick start or install guide, an MCPGatewayExtension already exists. Check with kubectl get mcpgatewayextension -A. If one is already present and Ready, skip to Step 2.

If you need to create one:

kubectl apply -f - <<EOF
apiVersion: mcp.kuadrant.io/v1alpha1
kind: MCPGatewayExtension
metadata:
  name: mcp-extension
  namespace: mcp-test
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: mcp-gateway
    namespace: gateway-system
    sectionName: mcp  # must match a listener name on the Gateway
EOF

If your MCPGatewayExtension is in a different namespace than the Gateway, create a ReferenceGrant first:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-mcp-extension
  namespace: gateway-system  # Gateway's namespace
spec:
  from:

    - group: mcp.kuadrant.io
      kind: MCPGatewayExtension
      namespace: mcp-test  # MCPGatewayExtension's namespace
  to:
    - group: gateway.networking.k8s.io
      kind: Gateway
EOF

Wait for it to become ready:

kubectl wait --for=condition=Ready mcpgatewayextension/mcp-extension -n mcp-test --timeout=60s

Step 2: Create an HTTPRoute

Create an HTTPRoute that routes to your MCP server. The hostname must match the wildcard on the mcps listener of your Gateway (e.g. *.mcp.local). This is an internal-only hostname used for routing through the gateway and does not need to be publicly resolvable.

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-mcp-server-route
  namespace: mcp-test
spec:
  parentRefs:

    - name: mcp-gateway
      namespace: gateway-system
      sectionName: mcps
  hostnames:
    - 'my-mcp-server.mcp.local'  # must match the mcps listener wildcard
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: mcp-test-server1    # Your MCP server service name
          port: 9090                # Your MCP server port
EOF

Step 3: Create MCPServerRegistration Resource

Create an MCPServerRegistration resource that references the HTTPRoute:

kubectl apply -f - <<EOF
apiVersion: mcp.kuadrant.io/v1alpha1
kind: MCPServerRegistration
metadata:
  name: my-mcp-server
  namespace: mcp-test
spec:
  prefix: "myserver_"
  targetRef:
    group: "gateway.networking.k8s.io"
    kind: "HTTPRoute"
    name: "my-mcp-server-route"  # Must match the HTTPRoute name
    namespace: "mcp-test"
EOF

Step 4: Verify Registration

Wait for the MCPServerRegistration to become ready (the broker needs a moment to connect and discover tools and prompts):

kubectl wait --for=condition=Ready mcpsr/my-mcp-server -n mcp-test --timeout=120s

Then check the status:

kubectl get mcpsr -A

The READY column should show True and the TOOLS column should show the number of tools discovered. For example:

NAMESPACE   NAME            PREFIX      TARGET               PATH   READY   TOOLS   CREDENTIALS   AGE
mcp-test    my-mcp-server   myserver_   my-mcp-server-route   /mcp   True    5                     30s

If the status is not Ready, check the MCPServerRegistration conditions for details:

kubectl describe mcpsr my-mcp-server -n mcp-test

Step 5: Test Tool Discovery

Verify that your MCP server tools are available through the gateway by using the following commands:

# Step 1: Initialize MCP session and capture session ID
# Use -D to dump headers to a file, then read the session ID
curl -s -D /tmp/mcp_headers -X POST http://mcp.127-0-0-1.sslip.io:8001/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"}}}'

# Extract the MCP session ID from response headers
SESSION_ID=$(grep -i "mcp-session-id:" /tmp/mcp_headers | cut -d' ' -f2 | tr -d '\r')

echo "MCP Session ID: $SESSION_ID"

# Step 2: List tools using the session ID
curl -X POST http://mcp.127-0-0-1.sslip.io:8001/mcp \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: $SESSION_ID" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'

You should now see your MCP server tools in the response, prefixed with your configured prefix (e.g., myserver_).

Step 6: Test Prompt Discovery

Verify that your MCP server prompts are also available through the gateway:

# Use the same SESSION_ID from the previous step
curl -X POST http://mcp.127-0-0-1.sslip.io:8001/mcp \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: $SESSION_ID" \
  -d '{"jsonrpc": "2.0", "id": 3, "method": "prompts/list"}'

You should see your MCP server prompts in the response, also prefixed with your configured prefix.

Step 7: Getting a Prompt

To retrieve a specific prompt, use the prompts/get method with the federated (prefixed) name:

curl -X POST http://mcp.127-0-0-1.sslip.io:8001/mcp \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: $SESSION_ID" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "prompts/get",
    "params": {
      "name": "myserver_gh_pr_review",
      "arguments": {
        "pr_number": "42"
      }
    }
  }'

# Clean up
rm -f /tmp/mcp_headers

You should now see your MCP server tools and prompts in the response, prefixed with your configured prefix (e.g., myserver_).

Disabling a Server

You can temporarily disable a registered server without deleting it. Setting state: Disabled disconnects the broker from the upstream server and removes its tools and prompts from the gateway.

kubectl patch mcpsr my-mcp-server -n mcp-test --type merge -p '{"spec":{"state":"Disabled"}}'

The status condition will show Ready: False with reason Disabled. To re-enable:

kubectl patch mcpsr my-mcp-server -n mcp-test --type merge -p '{"spec":{"state":"Enabled"}}'

The broker reconnects and restores the server's tools and prompts. No other resources need to be recreated.

Next Steps

After you have MCP servers registered, you can explore advanced features: