Membangun, Mengamankan, dan Men-deploy Server MCP di Google Cloud

1. Sebelum memulai

Model Context Protocol (MCP) adalah standar terbuka yang memungkinkan model dan agen AI mengakses alat, database, dan konteks perusahaan secara aman. Sejak diperkenalkan pada tahun 2024, protokol ini telah diadopsi secara luas oleh penyedia Cloud dan LLM. Spesifikasi terbaru MCP Spec 2026-07-28 (MCP 2.0) mendefinisikan arsitektur tanpa status, transportasi yang disederhanakan, dan pengetikan hasil yang ketat, sekaligus tetap kompatibel dengan versi sebelumnya.

MCP Python SDK resmi (mcp>=2.0.0) menyediakan MCPServer (mcp.server.mcpserver.MCPServer), yang menggantikan FastMCP di MCP 2.0 sebagai framework berperforma tinggi dan mudah digunakan developer untuk membuat server MCP siap produksi yang sesuai dengan Spesifikasi MCP modern (28-07-2026) dengan transport HTTP yang Dapat Di-streaming dan Server-Sent Events (SSE) melalui SSL/TLS.

Dalam codelab ini, Anda akan membangun server MCP tingkat produksi menggunakan MCPServer dari MCP 2.0 Python SDK dan pengelolaan dependensi uv. Anda akan melengkapi server MCP dengan empat alat Google Cloud (pemanggilan Gemini Vertex AI, pemeriksaan Google Cloud Storage, penulisan audit Cloud Logging, dan pemeriksaan kesehatan resource Google Cloud). Kemudian, Anda akan membuat container server dan men-deploy-nya ke dua target runtime Google Cloud: Cloud Run dan Google Kubernetes Engine (GKE) Autopilot, serta mendaftarkan dan menggunakan Server MCP di Platform Agen Gemini Enterprise.

Yang akan Anda lakukan

  • Buat MCPServer dengan 4 alat Google Cloud menggunakan Python 3.12+ dan uv yang sesuai dengan MCP Spec 2026-07-28.
  • Masukkan server MCP ke dalam container menggunakan build Docker multi-tahap.
  • Amankan dan deploy server MCP ke Cloud Run dengan autentikasi dan SSL/TLS IAM yang diterapkan.
  • Amankan dan deploy server MCP ke GKE Autopilot menggunakan Workload Identity dan Kubernetes Gateway API dengan TLS.
  • Daftarkan endpoint server MCP yang aman dengan Gemini Enterprise Agent Platform menggunakan header token pembawa OIDC.

Yang Anda butuhkan

  • Project Google Cloud yang mengaktifkan penagihan.
  • Google Cloud SDK (CLI gcloud) diinstal dan dikonfigurasi.
  • Python 3.12+ dan pengelola paket uv terinstal.
  • docker telah diinstal.
  • Alat command line kubectl telah diinstal.

2. Menyiapkan lingkungan Google Cloud

Sebelum membuat resource, autentikasi lingkungan Anda dan aktifkan API Google Cloud yang diperlukan.

Melakukan autentikasi gcloud CLI

Login ke akun Google Cloud Anda:

gcloud auth login

Tetapkan ID project Google Cloud aktif Anda:

export PROJECT_ID=$(gcloud config get-value project)
gcloud config set project ${PROJECT_ID}

Mengaktifkan Layanan Google Cloud

Aktifkan semua API yang diperlukan untuk Cloud Run, GKE, Vertex AI, Artifact Registry, Cloud Build, Cloud Logging, Storage, dan Compute Engine:

gcloud services enable \
    agentregistry.googleapis.com \
    run.googleapis.com \
    container.googleapis.com \
    artifactregistry.googleapis.com \
    aiplatform.googleapis.com \
    logging.googleapis.com \
    storage.googleapis.com \
    compute.googleapis.com \
    iam.googleapis.com \
    cloudbuild.googleapis.com \
    --project="${PROJECT_ID}"

Pastikan API berhasil diaktifkan:

Operation "operations/..." finished successfully.

Mengautentikasi Kredensial Default Aplikasi

Lakukan autentikasi lingkungan Anda agar library klien Python dapat mengakses Vertex AI dan Cloud Storage secara lokal selama pengembangan:

gcloud auth application-default login

3. Membangun Server MCP dengan MCPServer dan uv

Pada langkah ini, Anda akan melakukan inisialisasi project Python menggunakan uv dan membangun MCPServer yang mendukung empat kemampuan Google Cloud.

Menginisialisasi Project dengan uv

Buat direktori server dan lakukan inisialisasi uv:

mkdir -p mcp-server/src/mcp_server
cd mcp-server
uv init --lib

Salin kode ke dalam file pyproject.toml:

[project]
name = "secure-mcp-gcp-server"
version = "0.1.0"
description = "MCP server with Google Cloud tools supporting MCP Spec 2026-07-28 over Streamable HTTP"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "mcp>=2.0.0",
    "google-genai>=1.0.0",
    "google-cloud-storage>=2.14.0",
    "google-cloud-logging>=3.11.0",
    "google-cloud-resource-manager>=1.12.0",
    "uvicorn>=0.30.0",
    "httpx2>=0.1.0",
    "pydantic>=2.7.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/mcp_server"]

Sinkronkan dependensi menggunakan uv:

uv sync

Menulis Kode MCPServer

Buat file penerapan server di src/mcp_server/server.py:

import logging
import os
from typing import Any

from google import genai
from google.cloud import logging as cloud_logging
from google.cloud import storage
from mcp.server.mcpserver import MCPServer
from starlette.requests import Request
from starlette.responses import PlainTextResponse

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("mcp-gcp-server")

# Initialize MCPServer conforming to MCP Spec 2026-07-28
mcp = MCPServer(
    "Google Cloud Production Tools",
    instructions="MCP Server conforming to MCP Spec 2026-07-28 for Vertex AI, Cloud Storage, Audit Logging, and Health Inspection.",
)


@mcp.custom_route("/healthz", methods=["GET"])
async def health_check(request: Request) -> PlainTextResponse:
    """Kubernetes readiness and liveness probe health check endpoint."""
    return PlainTextResponse("OK")


@mcp.tool(description="Generate content or answer questions using Vertex AI Gemini model.")
def vertex_ai_generate_content(
    prompt: str,
    model_name: str = "gemini-2.5-flash",
    project_id: str | None = None,
    location: str = "us-central1",
) -> str:
    """Invokes Vertex AI Gemini API using official google-genai SDK."""
    target_project = project_id or os.getenv("GCP_PROJECT") or os.getenv("GOOGLE_CLOUD_PROJECT")
    if not target_project:
        return "Error: GCP project ID not configured."

    try:
        client = genai.Client(vertexai=True, project=target_project, location=location)
        response = client.models.generate_content(
            model=model_name,
            contents=prompt,
        )
        return response.text or "No text returned from Gemini."
    except Exception as e:
        logger.error("Vertex AI Tool Error: %s", e)
        return f"Error executing Vertex AI tool: {e!s}"


@mcp.tool(description="List objects and inspect metadata for a specified Google Cloud Storage bucket.")
def gcs_bucket_inspector(
    bucket_name: str,
    max_results: int = 10,
    prefix: str | None = None,
) -> dict[str, Any]:
    """Inspects GCS bucket content and metadata conforming to MCP Spec 2026-07-28 resultType schema."""
    try:
        client = storage.Client()
        bucket = client.bucket(bucket_name)
        blobs = list(client.list_blobs(bucket, max_results=max_results, prefix=prefix))
        items = [{"name": b.name, "size_bytes": b.size, "updated": str(b.updated)} for b in blobs]
        return {
            "resultType": "complete",
            "bucket_name": bucket_name,
            "object_count_sample": len(items),
            "objects": items,
        }
    except Exception as e:
        logger.error("GCS Inspector Error: %s", e)
        return {"resultType": "complete", "error": f"Failed to inspect GCS bucket: {e!s}"}


@mcp.tool(description="Write structured operational or security audit log records to Google Cloud Logging.")
def cloud_logging_audit_writer(
    log_name: str,
    message: str,
    severity: str = "INFO",
    metadata: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """Sends structured audit entry to Cloud Logging."""
    try:
        client = cloud_logging.Client()
        logger_instance = client.logger(log_name)
        payload = {"message": message, "metadata": metadata or {}, "source": "mcp-server-gcp"}
        logger_instance.log_struct(payload, severity=severity.upper())
        return {
            "resultType": "complete",
            "status": "success",
            "log_name": log_name,
            "recorded_message": message,
        }
    except Exception as e:
        logger.error("Cloud Logging Error: %s", e)
        return {"resultType": "complete", "error": f"Failed to record audit log: {e!s}"}


@mcp.tool(description="Check health and operational state of Google Cloud project resources.")
def gcp_resource_health_checker(project_id: str | None = None) -> dict[str, Any]:
    """Returns project resource summary and status."""
    target_project = project_id or os.getenv("GOOGLE_CLOUD_PROJECT") or "unknown-project"
    return {
        "resultType": "complete",
        "status": "HEALTHY",
        "project_id": target_project,
        "mcp_spec_version": "2026-07-28",
        "_meta": {
            "io.modelcontextprotocol/protocolVersion": "2026-07-28",
            "io.modelcontextprotocol/serverInfo": {"name": "mcp-gcp-server", "version": "0.1.0"},
        },
        "transports_enabled": ["Streamable HTTP"],
        "ssl_tls_enabled": True,
    }


if __name__ == "__main__":
    port = int(os.getenv("PORT", "8080"))
    logger.info("Starting MCPServer on port %d (Streamable HTTP Transport, Spec 2026-07-28)...", port)
    mcp.run(
        transport="streamable-http",
        host="0.0.0.0",
        port=port,
        stateless_http=True,
        json_response=True,
    )

Menguji Server MCP Secara Lokal

Langkah 1: Mulai Server MCP

Di terminal utama, mulai server menggunakan uv:

uv run python -m src.mcp_server.server

Anda akan melihat log startup yang mengonfirmasi bahwa server HTTP Streamable memproses port 8080:

INFO:mcp-gcp-server:Starting MCPServer on port 8080 (Streamable HTTP Transport, Spec 2026-07-28)...
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:mcp.server.streamable_http_manager:StreamableHTTP session manager started
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)

Biarkan terminal ini tetap terbuka dan berjalan.

Langkah 2: Verifikasi Endpoint HTTP Streamable menggunakan curl

Di MCP 2.0 (MCP Spec 2026-07-28), handshake initialize stateful dan header Mcp-Session-Id digantikan oleh permintaan stateless. Anda dapat memanggil tools/list secara langsung dengan meneruskan header MCP-Protocol-Version dan Mcp-Method beserta metadata klien di params._meta.

Buka jendela terminal kedua dan kirim permintaan POST HTTP yang dapat di-streaming:

cd mcp-server
curl -i -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {
          "name": "curl-test",
          "version": "1.0.0"
        },
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'

MCPServer akan merespons dengan HTTP/1.1 200 OK dan menampilkan hasil JSON-RPC tools/list secara langsung:

HTTP/1.1 200 OK
date: Wed, 12 Aug 2026 14:55:00 GMT
server: uvicorn

content-type: application/json

{"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"vertex_ai_generate_content",...},{"name":"gcs_bucket_inspector",...},{"name":"cloud_logging_audit_writer",...},{"name":"gcp_resource_health_checker",...}]}}

Langkah 3: Jalankan Klien Pengujian MCP

Untuk menguji penemuan dan eksekusi alat di server lokal Anda melalui HTTP yang Dapat Di-streaming, buat skrip klien pengujian src/mcp_server/test_client.py:

import asyncio
from mcp import Client
from mcp.types import TextContent


async def test_mcp_server() -> None:
    """Connects to the local MCP v2.0 server, lists tools, and invokes health check."""
    server_url = "http://localhost:8080/mcp"
    print(f"[*] Connecting to local MCPServer at {server_url} (Streamable HTTP)...")

    async with Client(server_url) as client:
        print(
            f"[+] Connected (protocol: {client.protocol_version}, "
            f"server: {client.server_info.name if client.server_info else 'unknown'})."
        )

        # List available tools
        tools_response = await client.list_tools()
        print("\n[*] Discovered MCP Tools:")
        for tool in tools_response.tools:
            print(f"  - {tool.name}: {tool.description}")

        # Invoke gcp_resource_health_checker tool
        print("\n[*] Invoking tool: gcp_resource_health_checker...")
        health_result = await client.call_tool("gcp_resource_health_checker", {})
        print("[+] Result:")
        for content in health_result.content:
            if isinstance(content, TextContent):
                print(content.text)


if __name__ == "__main__":
    asyncio.run(test_mcp_server())

Jalankan skrip klien pengujian menggunakan uv:

uv run python src/mcp_server/test_client.py

Anda akan melihat output yang menunjukkan koneksi yang berhasil, penemuan alat, dan eksekusi alat:

[*] Connecting to local MCPServer at http://localhost:8080/mcp (Streamable HTTP)...
[+] Connected (protocol: 2026-07-28, server: Google Cloud Production Tools).

[*] Discovered MCP Tools:
  - vertex_ai_generate_content: Generate content or answer questions using Vertex AI Gemini model.
  - gcs_bucket_inspector: List objects and inspect metadata for a specified Google Cloud Storage bucket.
  - cloud_logging_audit_writer: Write structured operational or security audit log records to Google Cloud Logging.
  - gcp_resource_health_checker: Check health and operational state of Google Cloud project resources.

[*] Invoking tool: gcp_resource_health_checker...
[+] Result:
{"resultType": "complete", "status": "HEALTHY", "project_id": "my-gcp-project", "mcp_spec_version": "2026-07-28", "_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/serverInfo": {"name": "mcp-gcp-server", "version": "0.1.0"}}, "transports_enabled": ["Streamable HTTP"], "ssl_tls_enabled": true}

Setelah diverifikasi, tekan CTRL+C di terminal utama Anda untuk menghentikan server lokal.

4. Mengemas Server MCP dalam Kontainer

Untuk men-deploy server MCP ke Cloud Run dan GKE Autopilot, kemas server ke dalam image container minimal menggunakan Dockerfile multi-tahap yang didukung oleh uv.

Buat Dockerfile

Di mcp-server/Dockerfile:

FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder

WORKDIR /app
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy

COPY pyproject.toml uv.lock* /app/
RUN uv sync --no-install-project --no-dev

COPY README.md /app/
COPY src /app/src
RUN uv sync --no-dev

FROM python:3.12-slim-bookworm

WORKDIR /app
COPY --from=builder /app /app

ENV PATH="/app/.venv/bin:$PATH"
ENV PORT=8080
ENV PYTHONUNBUFFERED=1

EXPOSE 8080
CMD ["python", "-m", "src.mcp_server.server"]

Membangun dan Mengirim Image ke Artifact Registry

Buat repositori Artifact Registry:

gcloud artifacts repositories create mcp-servers \
    --repository-format=docker \
    --location=us-central1 \
    --description="Docker repository for MCP Servers" \
    --project="${PROJECT_ID}"

Berikan izin IAM yang diperlukan ke akun pengguna Anda dan akun layanan Compute Engine default agar Cloud Build dapat menyiapkan sumber, menulis log, dan mengirimkan image ke Artifact Registry:

export USER_EMAIL=$(gcloud config get-value account)

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="user:${USER_EMAIL}" \
    --role="roles/cloudbuild.builds.editor"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="user:${USER_EMAIL}" \
    --role="roles/storage.admin"

export DEFAULT_SA=$(gcloud iam service-accounts list \
    --filter="email:compute@developer.gserviceaccount.com" \
    --format="value(email)" \
    --project="${PROJECT_ID}")

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${DEFAULT_SA}" \
    --role="roles/storage.objectViewer"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${DEFAULT_SA}" \
    --role="roles/artifactregistry.writer"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${DEFAULT_SA}" \
    --role="roles/logging.logWriter"

Kirim build image menggunakan Cloud Build:

export IMAGE_URI="us-central1-docker.pkg.dev/${PROJECT_ID}/mcp-servers/secure-mcp-server:latest"

gcloud builds submit . --tag="${IMAGE_URI}" --project="${PROJECT_ID}"

Setelah selesai, image container Anda akan disimpan dengan aman di Artifact Registry:

SUCCESS: Image published to us-central1-docker.pkg.dev/.../secure-mcp-server:latest

5. Men-deploy ke Cloud Run dengan IAM & HTTPS

Cloud Run menyediakan lingkungan serverless yang terkelola sepenuhnya dengan penghentian sertifikat HTTPS / SSL otomatis dan kontrol akses Cloud IAM yang terperinci.

Membuat Akun Layanan Khusus

Buat Akun Layanan Google dengan hak istimewa terendah untuk Cloud Run:

gcloud iam service-accounts create mcp-server-cr-sa \
    --display-name="MCP Server Cloud Run SA" \
    --project="${PROJECT_ID}"

export SA_EMAIL="mcp-server-cr-sa@${PROJECT_ID}.iam.gserviceaccount.com"

# Grant Vertex AI, Logging, and GCS permissions
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${SA_EMAIL}" \
    --role="roles/aiplatform.user"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${SA_EMAIL}" \
    --role="roles/logging.logWriter"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${SA_EMAIL}" \
    --role="roles/storage.objectViewer"

Men-deploy Layanan ke Cloud Run

Deploy container ke Cloud Run dengan autentikasi IAM yang diterapkan (--no-allow-unauthenticated) dan SSL terkelola default:

gcloud run deploy secure-mcp-server \
    --image="${IMAGE_URI}" \
    --platform=managed \
    --region=us-central1 \
    --service-account="${SA_EMAIL}" \
    --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
    --no-allow-unauthenticated \
    --ingress=all \
    --project="${PROJECT_ID}"

Ambil URL HTTPS:

export CLOUD_RUN_URL=$(gcloud run services describe secure-mcp-server --platform=managed --region=us-central1 --format='value(status.url)' --project="${PROJECT_ID}")
echo "Cloud Run HTTPS Endpoint: ${CLOUD_RUN_URL}"

Memverifikasi Endpoint Security

Mencoba permintaan yang tidak sah ke endpoint HTTP Streamable akan menampilkan 403 Forbidden:

curl -i -X POST "${CLOUD_RUN_URL}/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {
          "name": "curl-test",
          "version": "1.0.0"
        },
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
HTTP/2 403
content-type: text/html; charset=UTF-8
date: Mon, 11 Aug 2026 14:00:00 GMT

Buat token ID OIDC menggunakan gcloud untuk memverifikasi komunikasi yang diotorisasi:

export ID_TOKEN=$(gcloud auth print-identity-token --audiences="${CLOUD_RUN_URL}")

curl -i -X POST "${CLOUD_RUN_URL}/mcp" \
  -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {
          "name": "curl-test",
          "version": "1.0.0"
        },
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
HTTP/2 200
content-type: application/json

{"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"vertex_ai_generate_content",...},{"name":"gcs_bucket_inspector",...},{"name":"cloud_logging_audit_writer",...},{"name":"gcp_resource_health_checker",...}]}}

Pengujian Eksekusi Alat Langsung: Cloud Storage Inspector

Setelah server MCP jarak jauh diautentikasi dan merespons, uji eksekusi alat gcs_bucket_inspector terhadap infrastruktur Google Cloud.

Langkah 1: Buat Bucket Cloud Storage Uji Coba

Buat bucket pengujian dan upload file sampel:

export BUCKET_NAME="${PROJECT_ID}-mcp-demo"

# Create Cloud Storage bucket
gcloud storage buckets create "gs://${BUCKET_NAME}" \
    --location=us-central1 \
    --project="${PROJECT_ID}"

# Upload sample file
echo "Hello from Secure MCP on Google Cloud!" > sample.txt
gcloud storage cp sample.txt "gs://${BUCKET_NAME}/sample.txt"

Langkah 2: Buat Klien Pengujian Alat GCS Jarak Jauh

Buat skrip klien pengujian bernama src/mcp_server/test_gcs_tool.py untuk melakukan autentikasi terhadap Cloud Run dan memanggil alat gcs_bucket_inspector:

import asyncio
import os
import subprocess
import httpx2
from mcp import Client
from mcp.client.streamable_http import streamable_http_client
from mcp.types import TextContent


async def test_gcs_tool() -> None:
    """Authenticates to Cloud Run via OIDC and invokes the gcs_bucket_inspector tool."""
    cloud_run_url = os.getenv("CLOUD_RUN_URL")
    bucket_name = os.getenv("BUCKET_NAME")

    if not cloud_run_url or not bucket_name:
        print("[!] Please set both CLOUD_RUN_URL and BUCKET_NAME environment variables.")
        return

    # Generate Google OIDC ID token for Cloud Run authentication
    id_token = subprocess.check_output(
        ["gcloud", "auth", "print-identity-token", f"--audiences={cloud_run_url.rstrip('/')}"],
        text=True,
    ).strip()

    headers = {"Authorization": f"Bearer {id_token}"}
    server_url = f"{cloud_run_url.rstrip('/')}/mcp"

    print(f"[*] Connecting to remote Cloud Run MCP server at {server_url} (Streamable HTTP)...")
    async with httpx2.AsyncClient(
        headers=headers,
        timeout=httpx2.Timeout(30.0, read=300.0),
    ) as http_client:
        transport = streamable_http_client(server_url, http_client=http_client)
        async with Client(transport) as client:
            print(
                f"[+] Authenticated and connected (protocol: {client.protocol_version})."
            )

            # List tools
            tools_response = await client.list_tools()
            print(f"[*] Verified {len(tools_response.tools)} available tools on Cloud Run.")

            # Invoke gcs_bucket_inspector tool
            print(f"\n[*] Invoking tool: gcs_bucket_inspector on '{bucket_name}'...")
            result = await client.call_tool(
                "gcs_bucket_inspector", {"bucket_name": bucket_name}
            )

            print("[+] Response from Cloud Run MCP Server:")
            for content in result.content:
                if isinstance(content, TextContent):
                    print(content.text)


if __name__ == "__main__":
    asyncio.run(test_gcs_tool())

Langkah 3: Jalankan Klien Pengujian GCS Jarak Jauh

Jalankan skrip pengujian menggunakan uv:

uv run python src/mcp_server/test_gcs_tool.py

Anda akan melihat metadata objek live yang ditampilkan dari server MCP Cloud Run:

[*] Connecting to remote Cloud Run MCP server at https://secure-mcp-server-...-uc.a.run.app/mcp (Streamable HTTP)...
[+] Authenticated and connected (protocol: 2026-07-28).
[*] Verified 4 available tools on Cloud Run.

[*] Invoking tool: gcs_bucket_inspector on 'my-project-mcp-demo'...
[+] Response from Cloud Run MCP Server:
{"resultType":"complete","bucket_name":"my-project-mcp-demo","object_count_sample":1,"objects":[{"name":"sample.txt","size_bytes":39,"updated":"..."}]}

6. Men-deploy ke Autopilot GKE dengan Workload Identity & TLS

Untuk workload Kubernetes, GKE Autopilot mengelola penyediaan node, sedangkan Workload Identity menghilangkan kunci akun layanan statis.

Menyediakan Cluster GKE Autopilot

Sediakan cluster GKE Autopilot:

gcloud container clusters create-auto mcp-gke-cluster \
    --location=us-central1 \
    --project="${PROJECT_ID}"

gcloud container clusters get-credentials mcp-gke-cluster \
    --location=us-central1 \
    --project="${PROJECT_ID}"

Menyiapkan Workload Identity

Buat Akun Layanan Google (GSA) dan Akun Layanan Kubernetes (KSA), lalu tautkan menggunakan Workload Identity:

# 1. Create GSA
gcloud iam service-accounts create mcp-gke-sa \
    --display-name="GKE MCP Service Account" \
    --project="${PROJECT_ID}"

export GSA_EMAIL="mcp-gke-sa@${PROJECT_ID}.iam.gserviceaccount.com"

# 2. Grant IAM Roles to GSA
gcloud projects add-iam-policy-binding "${PROJECT_ID}" --member="serviceAccount:${GSA_EMAIL}" --role="roles/aiplatform.user"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" --member="serviceAccount:${GSA_EMAIL}" --role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" --member="serviceAccount:${GSA_EMAIL}" --role="roles/storage.objectViewer"

# 3. Create KSA
kubectl create serviceaccount mcp-server-ksa --namespace default

# 4. Annotate KSA
kubectl annotate serviceaccount mcp-server-ksa \
    --namespace default \
    iam.gke.io/gcp-service-account="${GSA_EMAIL}"

# 5. Bind KSA to GSA
gcloud iam service-accounts add-iam-policy-binding "${GSA_EMAIL}" \
    --role="roles/iam.workloadIdentityUser" \
    --member="serviceAccount:${PROJECT_ID}.svc.id.goog[default/mcp-server-ksa]" \
    --project="${PROJECT_ID}"

Menerapkan Deployment & Gateway API Kubernetes dengan TLS

Langkah 1: Mencadangkan IP Statis & Menyediakan Sertifikat SSL yang Dikelola Google dengan nip.io

Cadangkan alamat IP eksternal global dan manfaatkan layanan DNS wildcard nip.io (..nip.io) untuk membuat nama domain publik yang valid (MCP_DOMAIN) sebelum menerapkan manifes Kubernetes:

# Reserve global static IP address for GKE Gateway Load Balancer
gcloud compute addresses create mcp-server-ip \
    --global \
    --project="${PROJECT_ID}"

export MCP_IP=$(gcloud compute addresses describe mcp-server-ip --global --format="value(address)" --project="${PROJECT_ID}")
export MCP_DOMAIN="mcp.${MCP_IP}.nip.io"

echo "Reserved Static IP: ${MCP_IP}"
echo "Configured nip.io Domain: ${MCP_DOMAIN}"

# Provision Google-managed SSL certificate
gcloud compute ssl-certificates create mcp-server-cert \
    --domains="${MCP_DOMAIN}" \
    --global \
    --project="${PROJECT_ID}"

Anda tidak perlu menunggu hingga penyediaan sertifikat SSL selesai sebelum melanjutkan. Faktanya, sertifikat yang dikelola Google tetap dalam status PROVISIONING hingga dilampirkan ke Gateway Load Balancer di Langkah 3. Segera lanjutkan ke langkah berikutnya.

Langkah 2: Buat Manifes Deployment dan Layanan

Buat deployment.yaml yang berisi definisi Deployment dan Service internal. Karena MCP 2.0 (MCP Spec 2026-07-28) bersifat stateless, Service Kubernetes tidak memerlukan afinitas sesi IP klien:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-server-deployment
  namespace: default
  labels:
    app: mcp-server
    # GKE takes this label and registers the deployment as an MCP server to Agent Registry
    registry.gke.io/functional-type: "MCP_SERVER"
  annotations:
    # Endpoint URL where the GKE controller can access this MCP server
    modelcontextprotocol.info/urls: |
      - https://MCP_DOMAIN/mcp
    # Defines structural capabilities for the MCP server card
    modelcontextprotocol.info/capabilities: |
      card:
        endpoint: "/mcp"
        protocol: "HTTP"
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mcp-server
  template:
    metadata:
      labels:
        app: mcp-server
      annotations:
        # Workload Identity annotation for identity and access management
        iam.gke.io/spiffe-identity-type: agent-identity
    spec:
      serviceAccountName: mcp-server-ksa
      containers:
      - name: mcp-server
        image: us-central1-docker.pkg.dev/PROJECT_ID/mcp-servers/secure-mcp-server:latest
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: PORT
          value: "8080"
        - name: GOOGLE_CLOUD_PROJECT
          value: "PROJECT_ID"
        resources:
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "1000m"
            memory: "1Gi"
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 15
---
apiVersion: v1
kind: Service
metadata:
  name: mcp-server-service
  namespace: default
  labels:
    app: mcp-server
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
    name: http
  selector:
    app: mcp-server

Ganti MCP_DOMAIN dan PROJECT_ID, lalu terapkan deployment:

sed -e "s|MCP_DOMAIN|${MCP_DOMAIN}|g" \
    -e "s|PROJECT_ID|${PROJECT_ID}|g" \
    deployment.yaml | kubectl apply -f -

Langkah 3: Buat Manifes Gateway API, HealthCheckPolicy, dan GCPBackendPolicy

Buat gateway.yaml yang berisi Gateway, HTTPRoute, HealthCheckPolicy, dan GCPBackendPolicy:

  • HealthCheckPolicy: Mengonfigurasi Load Balancer Google Cloud untuk melakukan pemeriksaan /healthz di port 8080.
  • GCPBackendPolicy (Backend Timeout): Menetapkan timeoutSec: 300 agar selaras dengan waktu tunggu baca 300 detik MCP SDK v2 untuk aliran HTTP / SSE yang Dapat Di-streaming (GKE Gateway secara default adalah 30 detik jika tidak ditentukan).
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mcp-gateway
  namespace: default
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      options:
        networking.gke.io/pre-shared-certs: mcp-server-cert
  addresses:
  - type: NamedAddress
    value: mcp-server-ip
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mcp-http-route
  namespace: default
spec:
  parentRefs:
  - name: mcp-gateway
  hostnames:
  - "MCP_DOMAIN"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: mcp-server-service
      port: 80
---
apiVersion: networking.gke.io/v1
kind: HealthCheckPolicy
metadata:
  name: mcp-health-check-policy
  namespace: default
spec:
  default:
    checkIntervalSec: 15
    timeoutSec: 5
    healthyThreshold: 1
    unhealthyThreshold: 2
    config:
      type: HTTP
      httpHealthCheck:
        port: 8080
        requestPath: /healthz
  targetRef:
    group: ""
    kind: Service
    name: mcp-server-service
---
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: mcp-backend-policy
  namespace: default
spec:
  default:
    # Aligns with MCP SDK v2's 300s read timeout for Streamable HTTP / SSE streams
    # (GKE Gateway defaults to 30s if omitted)
    timeoutSec: 300
  targetRef:
    group: ""
    kind: Service
    name: mcp-server-service

Terapkan Gateway, HTTPRoute, HealthCheckPolicy, dan GCPBackendPolicy:

sed "s/MCP_DOMAIN/${MCP_DOMAIN}/g" gateway.yaml | kubectl apply -f -

Langkah 4: Verifikasi Deployment dan Uji Server MCP menggunakan Penerusan Port

Karena sertifikat SSL yang dikelola Google dan Load Balancer Aplikasi Google Cloud eksternal memerlukan waktu 5 hingga 15 menit untuk disediakan dan membuat perutean DNS, Anda dapat langsung menguji pod GKE yang sedang berjalan menggunakan kubectl port-forward.

Pertama, pastikan pod dan Gateway Anda berjalan:

kubectl get pods -l app=mcp-server
kubectl get gateway mcp-gateway
NAME                                     READY   STATUS    RESTARTS   AGE
mcp-server-deployment-7b8f9495c5-x2n8q   1/1     Running   0          45s
mcp-server-deployment-7b8f9495c5-z4k9p   1/1     Running   0          45s

NAME          CLASS                             ADDRESS          PROGRAMMED   AGE
mcp-gateway   gke-l7-global-external-managed   34.120.x.x       True         2m

Selanjutnya, uji layanan GKE aktif secara lokal menggunakan penerusan port:

  1. Di terminal Anda, teruskan port lokal 8080 ke layanan ClusterIP GKE:
kubectl port-forward svc/mcp-server-service 8080:80
  1. Di terminal kedua, buat skrip klien pengujian bernama src/mcp_server/test_vertex_tool.py untuk memanggil alat vertex_ai_generate_content di GKE menggunakan Workload Identity:
import argparse
import asyncio
import os
from mcp import Client
from mcp.types import TextContent


async def test_vertex_tool(server_url: str) -> None:
    """Connects to the MCP v2.0 server and invokes the vertex_ai_generate_content tool."""
    print(f"[*] Connecting to MCPServer at {server_url} (Streamable HTTP)...")

    async with Client(server_url) as client:
        print(
            f"[+] Connected (protocol: {client.protocol_version}, "
            f"server: {client.server_info.name if client.server_info else 'unknown'})."
        )

        # List available tools
        tools_response = await client.list_tools()
        print(f"[*] Discovered {len(tools_response.tools)} MCP Tools:")
        for tool in tools_response.tools:
            print(f"  - {tool.name}")

        # Invoke vertex_ai_generate_content tool
        prompt = "Explain in 2 sentences why Model Context Protocol (MCP) Streamable HTTP is great for cloud deployments."
        print(f"\n[*] Invoking tool: vertex_ai_generate_content with prompt: '{prompt}'...")

        result = await client.call_tool(
            "vertex_ai_generate_content",
            {
                "prompt": prompt,
                "model_name": "gemini-2.5-flash",
            },
        )

        print("\n[+] Response from Vertex AI Gemini:")
        for content in result.content:
            if isinstance(content, TextContent):
                print(content.text)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Test Vertex AI MCP Tool on MCPServer.")
    parser.add_argument(
        "--host",
        default=os.getenv("MCP_URL", "http://localhost:8080/mcp"),
        help="MCP Server host or URL (default: http://localhost:8080/mcp or $MCP_URL)",
    )
    args = parser.parse_args()

    # Normalize URL format
    url = args.host
    if not url.startswith("http://") and not url.startswith("https://"):
        url = f"https://{url}"
    if not url.endswith("/mcp"):
        url = f"{url.rstrip('/')}/mcp"

    asyncio.run(test_vertex_tool(url))
  1. Jalankan skrip pengujian terhadap instance yang diteruskan port lokal:
uv run python src/mcp_server/test_vertex_tool.py --host="http://localhost:8080/mcp"
[*] Connecting to MCPServer at http://localhost:8080/mcp (Streamable HTTP)...
[+] Connected (protocol: 2026-07-28, server: Google Cloud Production Tools).
[*] Discovered 4 MCP Tools:
  - vertex_ai_generate_content
  - gcs_bucket_inspector
  - cloud_logging_audit_writer
  - gcp_resource_health_checker

[*] Invoking tool: vertex_ai_generate_content with prompt: 'Explain in 2 sentences why Model Context Protocol (MCP) Streamable HTTP is great for cloud deployments.'...

[+] Response from Vertex AI Gemini:
MCP Streamable HTTP enables lightweight, stateless HTTP interactions that scale effortlessly across cloud-native platforms like GKE and Cloud Run. It simplifies infrastructure management by using standard HTTP/HTTPS protocols while preserving rich bidirectional streaming for AI agents.

Hal ini mengonfirmasi bahwa pod GKE dalam kondisi baik, Workload Identity berhasil melakukan autentikasi terhadap Vertex AI tanpa kredensial statis, dan transport HTTP yang dapat di-streaming beroperasi seperti yang diharapkan.

Langkah 5: Verifikasi Endpoint Gateway HTTPS Publik

Periksa status penyediaan sertifikat dengan:

gcloud compute ssl-certificates describe mcp-server-cert --global --format="value(managed.status)"

Setelah sertifikat ACTIVE, uji endpoint HTTPS publik menggunakan klien pengujian Python dengan tanda --host:

uv run python src/mcp_server/test_vertex_tool.py --host="https://${MCP_DOMAIN}/mcp"
[*] Connecting to MCPServer at https://mcp.34.120.x.x.nip.io/mcp (Streamable HTTP)...
[+] Connected (protocol: 2026-07-28, server: Google Cloud Production Tools).
[*] Discovered 4 MCP Tools:
  - vertex_ai_generate_content
  - gcs_bucket_inspector
  - cloud_logging_audit_writer
  - gcp_resource_health_checker

[*] Invoking tool: vertex_ai_generate_content with prompt: 'Explain in 2 sentences why Model Context Protocol (MCP) Streamable HTTP is great for cloud deployments.'...

[+] Response from Vertex AI Gemini:
MCP Streamable HTTP enables lightweight, stateless HTTP interactions that scale effortlessly across cloud-native platforms like GKE and Cloud Run. It simplifies infrastructure management by using standard HTTP/HTTPS protocols while preserving rich bidirectional streaming for AI agents.

7. Mengintegrasikan Server MCP dengan Platform Agen Google Cloud

Setelah MCPServer di-deploy dengan aman ke endpoint HTTPS di Cloud Run dan GKE Autopilot, daftarkan dan temukan alat MCP Anda dengan Google Cloud Agent Platform (Agent Registry) sehingga agen perusahaan dan model AI dapat menemukannya dan memanggilnya secara dinamis.

1. Mendaftarkan Server MCP Cloud Run Kustom ke Agent Platform & Menguji menggunakan Penemuan Layanan

Langkah 1: Ekstrak Spesifikasi Alat (toolspec.json)

Untuk mendaftarkan server MCP eksternal atau kustom di Agent Registry, kueri tools/list di server MCP 2.0 stateless aktif Anda, hapus kolom _meta tingkat alat, dan simpan hasilnya ke toolspec.json dalam satu pipeline:

# 1. Generate identity token
export ID_TOKEN=$(gcloud auth print-identity-token --audiences="${CLOUD_RUN_URL}")

# 2. Query, parse, sanitize and save in one single pipeline
curl -s -X POST "${CLOUD_RUN_URL}/mcp" \
  -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {
          "name": "cli",
          "version": "1.0.0"
        },
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }' \
  | sed -n 's/^data: //p; /^{/p' \
  | jq '.result | del(.tools[]._meta)' > toolspec.json

Langkah 2: Daftarkan Layanan di Agent Registry

Gunakan gcloud agent-registry services create untuk mengatalogkan server MCP Anda:

export SERVER_NAME="secure-mcp-server"
export DISPLAY_NAME="Google Cloud MCPServer"
export REGION="global"

gcloud agent-registry services create "${SERVER_NAME}" \
  --project="${PROJECT_ID}" \
  --location="${REGION}" \
  --display-name="${DISPLAY_NAME}" \
  --mcp-server-spec-type="tool-spec" \
  --mcp-server-spec-content=toolspec.json \
  --interfaces="url=${CLOUD_RUN_URL}/mcp,protocolBinding=jsonrpc"

Pastikan layanan berhasil didaftarkan:

gcloud agent-registry services describe "${SERVER_NAME}" --location="${REGION}"
name: projects/PROJECT_ID/locations/global/services/secure-mcp-server
displayName: Google Cloud MCPServer
interfaces:
- protocolBinding: JSONRPC
  url: https://secure-mcp-server-xxxx.a.run.app/mcp
mcpServerSpec:
  type: TOOL_SPEC

Langkah 3: Buat dan Jalankan Klien Pengujian Penemuan Layanan

Buat skrip Python bernama src/mcp_server/test_agent_platform.py yang secara dinamis menyelesaikan endpoint dari katalog mcp-servers Agent Registry, melakukan autentikasi dengan Google Cloud IAM, dan memanggil alat menggunakan httpx2 dan MCP 2.0 Client:

import asyncio
import os
import subprocess
import httpx2  # MCP SDK 2.x utilizes httpx2 instead of httpx
from mcp import Client
from mcp.client.streamable_http import streamable_http_client


async def main() -> None:
    server_name = os.getenv("SERVER_NAME", "secure-mcp-server")
    location = os.getenv("REGION", "global")

    # 1. Discover endpoint URL from Google Cloud Agent Registry (mcp-servers catalog)
    print(f"[*] Discovering '{server_name}' in '{location}' from Agent Registry...")
    url = subprocess.check_output(
        [
            "gcloud",
            "agent-registry",
            "mcp-servers",
            "list",
            f"--location={location}",
            f"--filter=displayName='{server_name}' OR mcpServerId ~ ':{server_name}$'",
            "--format=value(interfaces[0].url)",
            "--limit=1",
        ],
        text=True,
    ).strip()

    if not url:
        raise RuntimeError(
            f"No endpoint URL found for '{server_name}' in location '{location}'. "
            "Verify the server is registered and has an interface URL configured."
        )
    print(f"[+] Discovered Endpoint: {url}")

    # 2. Generate IAM identity token if connecting to Cloud Run
    headers: dict[str, str] = {}
    if "run.app" in url:
        audience = url.split("/mcp")[0]
        token = subprocess.check_output(
            ["gcloud", "auth", "print-identity-token", f"--audiences={audience}"],
            text=True,
        ).strip()
        headers["Authorization"] = f"Bearer {token}"

    # 3. Configure a custom httpx2 Client with MCP-safe timeouts
    # We set read to 300s to ensure the long-lived SSE/GET stream stays open
    async with httpx2.AsyncClient(
        headers=headers,
        timeout=httpx2.Timeout(30.0, read=300.0),
    ) as http_client:

        # 4. Initialize Streamable HTTP Transport (yielding a 2-tuple in MCP v2.x)
        transport = streamable_http_client(url, http_client=http_client)

        # 5. Connect using the clean high-level Client interface
        async with Client(transport) as client:
            print("[+] Session active. Connected successfully.")

            # Verify tools registered in the catalog (Attributes are snake_case in MCP v2)
            tools_response = await client.list_tools()
            print(f"[+] Discovered {len(tools_response.tools)} tools:")
            for tool in tools_response.tools:
                print(f"    - {tool.name}")

            # Test executing the health check tool
            print("\n[*] Invoking tool: gcp_resource_health_checker...")
            result = await client.call_tool("gcp_resource_health_checker", {})
            print(f"[+] Tool Output from Agent Platform:\n{result.content[0].text}")


if __name__ == "__main__":
    asyncio.run(main())

Jalankan skrip pengujian:

uv run python src/mcp_server/test_agent_platform.py
[*] Discovering 'secure-mcp-server' in 'global' from Agent Registry...
[+] Discovered Endpoint: https://secure-mcp-server-xxxx.a.run.app/mcp
[+] Session active. Connected successfully.
[+] Discovered 4 tools:
    - vertex_ai_generate_content
    - gcs_bucket_inspector
    - cloud_logging_audit_writer
    - gcp_resource_health_checker

[*] Invoking tool: gcp_resource_health_checker...
[+] Tool Output from Agent Platform:
{"resultType": "complete", "status": "HEALTHY", "mcp_spec_version": "2026-07-28"}

2. Penemuan dan Pendaftaran Server MCP Otomatis dengan GKE

Google Kubernetes Engine (GKE) menyediakan integrasi otomatis dengan Agent Registry. Dengan memberi label dan anotasi pada manifes Deployment GKE, GKE secara otomatis melakukan pemindaian introspeksi terhadap server MCP, mendaftarkan alat ke dalam katalog, dan memproyeksikan layanan ke sisi konsumen tanpa perlu membuat atau mengupload toolspec.json secara manual.

Langkah 1: Cara Kerja Penemuan Otomatis GKE

Jika deployment.yaml Anda diterapkan di bagian sebelumnya, konfigurasi berikut akan mengaktifkan penemuan otomatis:

  • registry.gke.io/functional-type: "MCP_SERVER": Memberi tahu pengontrol cluster GKE untuk mendaftarkan deployment ke Google Cloud Agent Registry.
  • modelcontextprotocol.info/urls: Menyediakan endpoint Gateway HTTPS eksternal (https://${MCP_DOMAIN}/mcp) untuk inspeksi pengontrol dan perutean konsumen.
  • modelcontextprotocol.info/capabilities: Mendeklarasikan endpoint transportasi HTTP (/mcp).
  • iam.gke.io/spiffe-identity-type: agent-identity: Mengonfigurasi Workload Identity untuk komunikasi berbasis agen.

Langkah 2: Verifikasi Pendaftaran Otomatis GKE di Agent Registry

Verifikasi bahwa GKE otomatis menemukan dan mendaftarkan server MCP Anda ke katalog mcp-servers regional:

# List the automatically registered GKE MCP server in us-central1
gcloud agent-registry mcp-servers list \
  --location=us-central1 \
  --format="table(displayName, tools.len():label=TOOLS)"
DISPLAY_NAME           TOOLS
mcp-server-deployment  4

Langkah 3: Uji Server MCP GKE menggunakan Penemuan Layanan

Uji deployment MCP GKE Anda menggunakan skrip penemuan layanan terhadap nama server yang terdaftar otomatis di us-central1:

SERVER_NAME="mcp-server-deployment" \
REGION=us-central1 \
uv run python src/mcp_server/test_agent_platform.py
[*] Discovering 'mcp-server-deployment' in 'us-central1' from Agent Registry...
[+] Discovered Endpoint: https://mcp.34.120.x.x.nip.io/mcp
[+] Session active. Connected successfully.
[+] Discovered 4 tools:
    - vertex_ai_generate_content
    - gcs_bucket_inspector
    - cloud_logging_audit_writer
    - gcp_resource_health_checker

[*] Invoking tool: gcp_resource_health_checker...
[+] Tool Output from Agent Platform:
{"resultType": "complete", "status": "HEALTHY", "mcp_spec_version": "2026-07-28"}

8. Membersihkan resource

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, hapus layanan Cloud Run, cluster GKE, akun layanan, dan repositori container.

Menghapus Layanan Cloud Run

gcloud run services delete secure-mcp-server \
    --platform=managed \
    --region=us-central1 \
    --quiet \
    --project="${PROJECT_ID}"

Menghapus Cluster GKE Autopilot

gcloud container clusters delete mcp-gke-cluster \
    --location=us-central1 \
    --quiet \
    --project="${PROJECT_ID}"

Menghapus Akun Layanan & Binding IAM

gcloud iam service-accounts delete "mcp-server-cr-sa@${PROJECT_ID}.iam.gserviceaccount.com" --quiet --project="${PROJECT_ID}"
gcloud iam service-accounts delete "mcp-gke-sa@${PROJECT_ID}.iam.gserviceaccount.com" --quiet --project="${PROJECT_ID}"

Menghapus Repositori Artifact Registry

gcloud artifacts repositories delete mcp-servers \
    --location=us-central1 \
    --quiet \
    --project="${PROJECT_ID}"

Menghapus Layanan Kustom Agent Registry

gcloud agent-registry services delete secure-mcp-server \
    --location=global \
    --quiet \
    --project="${PROJECT_ID}"

Menghapus Bucket Cloud Storage

gcloud storage rm --recursive "gs://${BUCKET_NAME}" --quiet

Menghapus IP Statis & Sertifikat SSL

gcloud compute ssl-certificates delete mcp-server-cert --global --quiet --project="${PROJECT_ID}"
gcloud compute addresses delete mcp-server-ip --global --quiet --project="${PROJECT_ID}"

Verifikasi bahwa pembersihan penghapusan selesai:

Deleted service [secure-mcp-server].
Deleted cluster [mcp-gke-cluster].
Deleted repository [mcp-servers].

9. Selamat

Selamat! Anda telah berhasil membangun, mengamankan, dan men-deploy Server MCP 2.0 menggunakan MCPServer dari MCP Python SDK dan uv di Google Cloud.

Yang telah Anda pelajari

  • Membuat MCPServer yang mendukung Spesifikasi MCP (28-07-2026) melalui HTTP Streamable tanpa status.
  • Membangun 4 alat Google Cloud produksi yang mengintegrasikan Vertex AI Gemini, Cloud Storage, Cloud Logging, dan Resource Health.
  • Deployment container yang diamankan di Cloud Run dengan autentikasi IAM dan SSL/TLS yang diterapkan.
  • Mengonfigurasi autentikasi tanpa secret di GKE Autopilot dengan Workload Identity dan Kubernetes Gateway API dengan TLS.
  • Endpoint server MCP yang terdaftar dan ditemukan dengan Gemini Enterprise Agent Platform (Agent Registry) menggunakan header otorisasi OIDC.

Langkah berikutnya