Guides

Deploy a Remote MCP Server to GKE in 30 Minutes

Deploy a Remote MCP Server to GKE in 30 Minutes

Quick answer

Deploy a remote MCP server on GKE in 30 minutes. Scalable, secure, and perfect for giving LLMs reliable context. Step-by-step guide with FastMCP.

Ever felt like your LLM is swimming in a murky swamp when it comes to deterministic tasks like math? That’s where the Model Context Protocol (MCP) comes in, letting you build tools that give your AI a clear channel to accurate data. And with Google Kubernetes Engine (GKE), you can deploy a remote MCP server that’s scalable, secure, and ready for action—all in about half an hour.

Why GKE for Your MCP Server?

Running an MCP server on GKE is like building a sturdy capybara lodge in the middle of a bustling swamp. It’s scalable, centralized, and secure. GKE Autopilot handles traffic spikes effortlessly, teams share a single server instead of running redundant local ones, and the Kubernetes Gateway API with SSL keeps everything encrypted and safe from prying caimans.

What You’ll Need

  • Python 3.10+
  • uv (package manager)
  • Google Cloud SDK (gcloud)
  • kubectl

Step 1: Set Up Your Environment

Start by creating a project folder and setting your Google Cloud credentials. Then kick off a GKE Autopilot cluster in the background—it’ll be ready by the time you finish the rest.

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
mkdir mcp-on-gke && cd mcp-on-gke
gcloud auth login
gcloud config set project $PROJECT_ID
gcloud container clusters create-auto mcp-cluster --region $REGION --release-channel rapid --async

Step 2: Build a Simple Math MCP Server

Using FastMCP, we’ll create a server with two tools: add and subtract. This is perfect for offloading math from your LLM—because even the smartest capybara can struggle with arithmetic.

uv init
uv add fastmcp
uv add asyncio

Create server.py with the following code:

from fastmcp import FastMCP
from starlette.requests import Request
from starlette.responses import PlainTextResponse
import asyncio
import logging

logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)

mcp_port=3000

server = FastMCP("Math Server")

@server.tool()
def add(a: int, b: int) -> int:
    """Add two numbers together."""
    return a + b

@server.tool()
def subtract(a: int, b: int) -> int:
    """Subtract the second number from the first."""
    return a - b

@server.custom_route("/healthz", methods=["GET"])
async def health_check(request: Request) -> PlainTextResponse:
    return PlainTextResponse("OK")

if __name__ == "__main__":
    logger.info(f"MCP server started on port {mcp_port}")
    asyncio.run(server.run_async(transport="streamable-http", host="0.0.0.0", port=mcp_port))

Step 3: Test Locally

Create a test script and run the server locally to verify everything works.

# test_mcp_server.py
from fastmcp import Client
import asyncio

client = Client("https://localhost:3000/mcp")

async def test_remote_server():
    async with client:
        await client.ping()
        tools = await client.list_tools()
        print(f"Available tools: {tools}")
        result = await client.call_tool("add", {"a": 5, "b": 3})
        print(f"Result of addition: {result}")
        result = await client.call_tool("subtract", {"a": 5, "b": 3})
        print(f"Result of subtraction: {result}")

asyncio.run(test_remote_server())

Run uv run server.py and in another terminal uv run test_mcp_server.py. You should see the tools and results printed.

Step 4: Containerize and Deploy

Create a Dockerfile, build the image, and push it to Artifact Registry. Then deploy to GKE using a Deployment and Service.

# Dockerfile
FROM python:3.10-slim
COPY --from=ghcr.io/astral-sh/uv:0.4.15 /uv /bin/uv
WORKDIR /app
COPY pyproject.toml .
COPY server.py .
RUN uv sync
CMD ["uv", "run", "server.py"]
gcloud artifacts repositories create mcp-repo --repository-format=docker --location=$REGION
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/mcp-repo/math-mcp-server:latest

Once the cluster is ready, get credentials and apply the deployment YAML.

gcloud container clusters get-credentials mcp-cluster --region $REGION
kubectl apply -f deployment.yaml

Step 5: Secure with SSL and Gateway API

Reserve a static IP, point your domain to it, and create a Google-managed SSL certificate. Then apply the Gateway configuration to route HTTPS traffic to your MCP server.

gcloud compute addresses create mcp-server-ip --global
export MCP_SERVER_IP=$(gcloud compute addresses describe mcp-server-ip --global --format="value(address)")
echo "Your IP: $MCP_SERVER_IP"
gcloud compute ssl-certificates create mcp-cert --domains mcp.yourdomain.com --global
kubectl apply -f gateway.yaml

After a few minutes, test with your domain: https://mcp.yourdomain.com/mcp.

Clean Up

When you’re done, delete the resources to avoid charges.

kubectl delete -f deployment.yaml
kubectl delete -f gateway.yaml
gcloud compute addresses delete mcp-server-ip --global
gcloud compute ssl-certificates delete mcp-cert --global
gcloud artifacts repositories delete mcp-repo --location=$REGION
gcloud container clusters delete mcp-cluster --region $REGION

For more on MCP and GKE, check out the official MCP docs and GKE Gateway API docs. And if you’re comparing cloud platforms, see our Google Cloud review.

Original announcement published on Google Cloud.