Google Cloud'da MCP Sunucusu Oluşturma, Güvenliğini Sağlama ve Dağıtma

1. Başlamadan önce

Model Bağlam Protokolü (MCP), yapay zeka modellerinin ve ajanlarının araçlara, veritabanlarına ve kurumsal bağlama güvenli bir şekilde erişmesini sağlayan açık bir standarttır. 2024'te kullanıma sunulan protokol, bulut ve LLM sağlayıcılar tarafından yaygın olarak kullanılmaya başlandı. En yeni spesifikasyon MCP Spec 2026-07-28 (MCP 2.0), önceki sürümlerle geriye dönük uyumluluğu korurken durum bilgisiz bir mimari, basitleştirilmiş aktarımlar ve katı sonuç türleri tanımlar.

Resmi MCP Python SDK'sı (mcp>=2.0.0), SSL/TLS üzerinden akışa alınabilir HTTP ve sunucu tarafından gönderilen etkinlik (SSE) aktarımlarıyla modern MCP Spec (2026-07-28)'e uygun, üretime hazır MCP sunucuları oluşturmak için yüksek performanslı ve geliştirici dostu bir çerçeve olarak MCP 2.0'da FastMCP'ın yerini alan MCPServer (mcp.server.mcpserver.MCPServer) sağlar.

Bu codelab'de, MCP 2.0 Python SDK'sından MCPServer ve uv bağımlılık yönetimini kullanarak üretim düzeyinde bir MCP sunucusu oluşturacaksınız. MCP sunucunuzu dört Google Cloud aracıyla (Vertex AI Gemini çağırma, Google Cloud Storage inceleme, Cloud Logging denetleme yazma ve Google Cloud kaynağı sağlık kontrolü) donatacaksınız. Ardından, sunucuyu kapsayıcıya yerleştirip iki Google Cloud çalışma zamanı hedefine (Cloud Run ve Google Kubernetes Engine (GKE) Autopilot) dağıtacak, MCP sunucusunu Gemini Enterprise Agent Platform'da kaydedip kullanacaksınız.

Yapacaklarınız

  • Python 3.12+ ve MCP Spec 2026-07-28'e uygun uv kullanarak 4 Google Cloud aracıyla MCPServer oluşturun.
  • Çok aşamalı Docker derlemesi kullanarak MCP sunucusunu kapsayıcıya yerleştirin.
  • MCP sunucusunu, zorunlu IAM kimlik doğrulaması ve SSL/TLS ile Cloud Run'a güvenli bir şekilde dağıtın.
  • Workload Identity ve TLS ile Kubernetes Gateway API kullanarak MCP sunucusunu GKE Autopilot'a güvenli bir şekilde dağıtın.
  • OIDC taşıyıcı jeton başlıklarını kullanarak güvenli MCP sunucusu uç noktasını Gemini Enterprise Agent Platform'a kaydedin.

İhtiyacınız olanlar

  • Faturalandırmanın etkin olduğu bir Google Cloud projesi.
  • Google Cloud SDK (gcloud CLI) yüklü ve yapılandırılmış olmalıdır.
  • Python 3.12+ ve uv paket yöneticisi yüklü olmalıdır.
  • docker yüklendi.
  • kubectl komut satırı aracı yüklü olmalıdır.

2. Google Cloud ortamını ayarlama

Kaynak oluşturmadan önce ortamınızın kimliğini doğrulayın ve gerekli Google Cloud API'lerini etkinleştirin.

gcloud CLI'nın kimliğini doğrulama

Google Cloud hesabınıza giriş yapın:

gcloud auth login

Etkin Google Cloud proje kimliğinizi ayarlayın:

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

Google Cloud Hizmetlerini Etkinleştirme

Cloud Run, GKE, Vertex AI, Artifact Registry, Cloud Build, Cloud Logging, Storage ve Compute Engine için gerekli tüm API'leri etkinleştirin:

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}"

API'lerin başarıyla etkinleştirildiğini doğrulayın:

Operation "operations/..." finished successfully.

Uygulama Varsayılan Kimlik Bilgileri'nin kimliğini doğrulama

Python istemci kitaplıklarının geliştirme sırasında Vertex AI ve Cloud Storage'a yerel olarak erişebilmesi için ortamınızın kimliğini doğrulayın:

gcloud auth application-default login

3. MCPServer ve uv ile MCP sunucusunu oluşturma

Bu adımda, uv kullanarak bir Python projesi başlatacak ve dört Google Cloud özelliğini destekleyen bir MCPServer oluşturacaksınız.

Projeyi uv ile başlatma

Sunucu dizinini oluşturun ve uv'ı başlatın:

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

Kodu pyproject.toml dosyasına kopyalayın:

[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"]

uv kullanarak bağımlılıkları senkronize etme:

uv sync

MCPServer kodunu yazma

Sunucu uygulama dosyasını src/mcp_server/server.py konumunda oluşturun:

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,
    )

MCP sunucusunu yerel olarak test etme

1. adım: MCP sunucusunu başlatın

Birincil terminalinizde uv komutunu kullanarak sunucuyu başlatın:

uv run python -m src.mcp_server.server

Streamable HTTP sunucusunun 8080 numaralı bağlantı noktasını dinlediğini onaylayan başlangıç günlüklerini görmeniz gerekir:

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)

Bu terminali açık ve çalışır durumda tutun.

2. adım: curl kullanarak Streamable HTTP uç noktasını doğrulayın

MCP 2.0'da (MCP Spec 2026-07-28) durum bilgisi olan initialize el sıkışması ve Mcp-Session-Id başlığı, durum bilgisi olmayan isteklerle değiştirilir. tools/list işlevini, MCP-Protocol-Version ve Mcp-Method başlıklarını params._meta içinde istemci meta verileriyle birlikte ileterek doğrudan çağırabilirsiniz.

İkinci bir terminal penceresi açın ve Streamable HTTP POST isteği gönderin:

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, HTTP/1.1 200 OK ile yanıt verir ve JSON-RPC tools/list sonucunu doğrudan döndürür:

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",...}]}}

3. adım: MCP Test İstemcisi'ni çalıştırın

Yerel sunucunuzdaki araçları Streamable HTTP üzerinden keşfetme ve yürütme işlemlerini test etmek için bir test istemci komut dosyası oluşturun 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())

uv kullanarak test istemci komut dosyasını çalıştırın:

uv run python src/mcp_server/test_client.py

Başarılı bağlantı, araç keşfi ve araç yürütmeyi gösteren bir çıkış görmelisiniz:

[*] 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}

Doğrulama işlemi tamamlandıktan sonra, yerel sunucuyu durdurmak için birincil terminalinizde CTRL+C tuşuna basın.

4. MCP sunucusunu kapsama alma

MCP sunucusunu Cloud Run ve GKE Autopilot'a dağıtmak için sunucuyu uv tarafından desteklenen çok kademeli bir Dockerfile kullanarak minimal bir kapsayıcı görüntüsüne paketleyin.

Dockerfile oluşturma

mcp-server/Dockerfile içinde:

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"]

Görüntü oluşturma ve Artifact Registry'ye gönderme

Artifact Registry deposu oluşturun:

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

Cloud Build'in kaynakları hazırlayabilmesi, günlükleri yazabilmesi ve görüntüleri Artifact Registry'ye aktarabilmesi için kullanıcı hesabınıza ve varsayılan Compute Engine hizmet hesabına gerekli IAM izinlerini verin:

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"

Cloud Build'i kullanarak görüntü derleme işlemini gönderin:

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}"

İşlem tamamlandığında kapsayıcı resminiz Artifact Registry'de güvenli bir şekilde depolanır:

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

5. IAM ve HTTPS ile Cloud Run'a dağıtma

Cloud Run, otomatik HTTPS / SSL sertifika sonlandırması ve ayrıntılı Cloud IAM erişim denetimi ile tümüyle yönetilen bir sunucusuz ortam sağlar.

Özel hizmet hesabı oluşturma

Cloud Run için en az ayrıcalıklı bir Google hizmet hesabı oluşturun:

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"

Hizmeti Cloud Run'a dağıtma

IAM kimlik doğrulamasının zorunlu kılındığı (--no-allow-unauthenticated) ve varsayılan olarak yönetilen SSL ile container'ı Cloud Run'a dağıtın:

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}"

HTTPS URL'sini alın:

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}"

Uç nokta güvenliğini doğrulama

Streamable HTTP uç noktasına yetkisiz bir istekte bulunulursa 403 Forbidden döndürülür:

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

Yetkili iletişimi doğrulamak için gcloud kullanarak bir OIDC kimlik jetonu oluşturun:

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",...}]}}

Canlı Araç Yürütme Testi: Cloud Storage İnceleyici

Uzak MCP sunucusu kimliği doğrulandıktan ve yanıt vermeye başladıktan sonra gcs_bucket_inspector aracını Google Cloud altyapısında çalıştırmayı test edin.

1. adım: Test Cloud Storage paketi oluşturun

Bir test paketi oluşturun ve örnek dosya yükleyin:

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"

2. adım: Uzak GCS Aracı Test İstemcisi'ni oluşturun

Cloud Run'da kimlik doğrulaması yapmak ve gcs_bucket_inspector aracını çağırmak için src/mcp_server/test_gcs_tool.py adlı bir test istemci komut dosyası oluşturun:

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())

3. adım: Uzak GCS Test İstemcisi'ni çalıştırın

uv kullanarak test komut dosyasını çalıştırın:

uv run python src/mcp_server/test_gcs_tool.py

Cloud Run MCP sunucusundan döndürülen canlı nesne meta verilerini görmelisiniz:

[*] 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. Workload Identity ve TLS ile GKE Autopilot'a dağıtma

Kubernetes iş yükleri için GKE Autopilot, düğüm sağlama işlemini yönetirken Workload Identity, statik hizmet hesabı anahtarlarını ortadan kaldırır.

GKE Autopilot kümesi sağlama

GKE Autopilot kümesi sağlama:

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}"

Workload Identity'yi ayarlama

Google hizmet hesabı (GSA) ve Kubernetes hizmet hesabı (KSA) oluşturun, ardından bunları Workload Identity kullanarak bağlayın:

# 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}"

TLS ile Kubernetes Deployment ve Gateway API'yi uygulama

1. adım: Sabit IP ayırın ve nip.io ile Google tarafından yönetilen SSL sertifikası sağlayın

Kubernetes manifestlerini uygulamadan önce genel bir harici IP adresi ayırın ve joker karakter DNS hizmetinden nip.io (..nip.io) yararlanarak geçerli bir genel alan adı (MCP_DOMAIN) oluşturun:

# 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}"

Devam etmeden önce SSL sertifikasının temel hazırlığının tamamlanmasını beklemeniz gerekmez. Google tarafından yönetilen sertifikalar, 3. adımda ağ geçidi yük dengeleyiciye eklenene kadar PROVISIONING durumunda kalır. Hemen sonraki adımlara geçin.

2. adım: Dağıtım ve hizmet manifestini oluşturun

Dağıtım ve dahili hizmet tanımlarını içeren deployment.yaml oluşturun. MCP 2.0 (MCP Spec 2026-07-28) durum bilgisiz olduğundan Kubernetes Service, istemci IP oturum benzeşimi gerektirmez:

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

MCP_DOMAIN ve PROJECT_ID yerine koyup dağıtımı uygulayın:

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

3. adım: Ağ Geçidi API'si, HealthCheckPolicy ve GCPBackendPolicy manifestini oluşturun

Ağ geçidi, HTTPRoute, HealthCheckPolicy ve GCPBackendPolicy içeren gateway.yaml oluşturun:

  • HealthCheckPolicy: Google Cloud Load Balancer'ı 8080 bağlantı noktasında /healthz'ü yoklayacak şekilde yapılandırır.
  • GCPBackendPolicy (Arka Uç Zaman Aşımı): timeoutSec: 300 değerini, MCP SDK v2'nin yayınlanabilir HTTP / SSE akışları için 300 saniyelik okuma zaman aşımıyla uyumlu olacak şekilde ayarlar (GKE ağ geçidi, atlanırsa varsayılan olarak 30 saniye olur).
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

Gateway, HTTPRoute, HealthCheckPolicy ve GCPBackendPolicy'yi uygulayın:

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

4. adım: Dağıtımı doğrulayın ve bağlantı noktası yönlendirmeyi kullanarak MCP sunucusunu test edin

Google tarafından yönetilen SSL sertifikalarının ve harici Google Cloud Application Load Balancer'ların temel hazırlığı ve DNS yönlendirmesinin oluşturulması 5 ila 15 dakika sürdüğünden, kubectl port-forward kullanarak çalışan GKE pod'larını hemen test edebilirsiniz.

Öncelikle kapsüllerinizin ve ağ geçidinizin çalıştığından emin olun:

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

Ardından, bağlantı noktası yönlendirmeyi kullanarak canlı GKE hizmetini yerel olarak test edin:

  1. Terminalinizde, yerel bağlantı noktası 8080'yı GKE ClusterIP hizmetine yönlendirin:
kubectl port-forward svc/mcp-server-service 8080:80
  1. İkinci bir terminalde, Workload Identity'yi kullanarak GKE'de vertex_ai_generate_content aracını çağırmak için src/mcp_server/test_vertex_tool.py adlı bir test istemci komut dosyası oluşturun:
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. Test komut dosyasını yerel bağlantı noktası yönlendirmeli örnek üzerinde çalıştırın:
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.

Bu, GKE pod'larının sağlıklı olduğunu, Workload Identity'nin statik kimlik bilgileri olmadan Vertex AI'da kimlik doğrulama işlemini başarıyla gerçekleştirdiğini ve Streamable HTTP aktarımının beklendiği gibi çalıştığını doğrular.

5. adım: Herkese açık HTTPS ağ geçidi uç noktasını doğrulayın

Aşağıdaki komutla sertifika sağlama durumunu kontrol edin:

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

Sertifika ACTIVE olduktan sonra, --host işaretini kullanarak Python test istemcisiyle herkese açık HTTPS uç noktasını test edin:

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. MCP sunucusunu Google Cloud Agent Platform ile entegre etme

MCPServer, Cloud Run ve GKE Autopilot'taki HTTPS uç noktalarına güvenli bir şekilde dağıtıldığına göre, kurumsal ajanların ve yapay zeka modellerinin bunları dinamik olarak keşfedip çağırabilmesi için MCP araçlarınızı Google Cloud Agent Platform (Agent Registry) ile kaydedip keşfedin.

1. Özel Cloud Run MCP sunucusunu aracı platformuna kaydetme ve hizmet keşfini kullanarak test etme

1. adım: Araç özelliklerini ayıklayın (toolspec.json)

Agent Registry'ye harici veya özel bir MCP sunucusu kaydetmek için canlı durum bilgisiz MCP 2.0 sunucunuzda tools/list sorgusu gönderin, araç düzeyindeki _meta alanlarını kaldırın ve sonucu tek bir ardışık düzende toolspec.json'e kaydedin:

# 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

2. adım: Hizmeti Aracı Kayıt Defteri'ne kaydedin

MCP sunucunuzu kataloglamak için gcloud agent-registry services create kullanın:

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"

Hizmetin başarıyla kaydedildiğini doğrulayın:

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

3. adım: Hizmet bulma test istemcisi oluşturup çalıştırın

src/mcp_server/test_agent_platform.py adlı bir Python komut dosyası oluşturun. Bu komut dosyası, uç noktayı Agent Registry mcp-servers kataloğundan dinamik olarak çözer, Google Cloud IAM ile kimlik doğrular ve httpx2 ile MCP 2.0 Client kullanarak bir aracı çağırır:

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())

Test komut dosyasını yürütün:

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. GKE ile Otomatik MCP Sunucusu Keşfi ve Kaydı

Google Kubernetes Engine (GKE), Agent Registry ile otomatik entegrasyon sağlar. GKE Deployment manifestinizi etiketleyip açıklama ekleyerek GKE, MCP sunucusuna karşı otomatik olarak bir iç gözlem taraması gerçekleştirir, araçları kataloğa kaydeder ve toolspec.json oluşturup yüklemenize gerek kalmadan hizmeti tüketici tarafına yansıtır.

1. adım: GKE otomatik keşfinin işleyiş şekli

Önceki bölümde deployment.yaml uygulandığında aşağıdaki yapılandırmalar otomatik keşfi etkinleştirmişti:

  • registry.gke.io/functional-type: "MCP_SERVER": Dağıtımı Google Cloud Agent Registry'ye kaydetmesi için GKE küme denetleyicisine bilgi verir.
  • modelcontextprotocol.info/urls: Denetleyici iç gözlemi ve tüketici yönlendirmesi için harici HTTPS ağ geçidi uç noktasını (https://${MCP_DOMAIN}/mcp) sağlar.
  • modelcontextprotocol.info/capabilities: HTTP taşıma uç noktasını (/mcp) bildirir.
  • iam.gke.io/spiffe-identity-type: agent-identity: Ajan tabanlı iletişim için Workload Identity'yi yapılandırır.

2. adım: Aracı Kayıt Defteri'nde GKE otomatik kaydını doğrulayın

GKE'nin MCP sunucunuzu otomatik olarak keşfedip bölgesel mcp-servers kataloğuna kaydettiğini doğrulayın:

# 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

3. adım: Hizmet Bulma'yı kullanarak GKE MCP sunucusunu test edin

us-central1 bölümündeki otomatik olarak kaydedilen sunucu adına karşı hizmet keşfi komut dosyasını kullanarak GKE MCP dağıtımınızı test edin:

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. Kaynakları temizleme

Bu codelab'de kullanılan kaynaklar için Google Cloud hesabınıza ücret yansıtılmasını önlemek amacıyla Cloud Run hizmetini, GKE kümesini, hizmet hesaplarını ve kapsayıcı deposunu silin.

Cloud Run hizmetini silme

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

GKE Autopilot kümesini silme

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

Hizmet Hesaplarını ve IAM Bağlantılarını Silme

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}"

Artifact Registry deposunu silme

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

Aracı Kayıt Defteri Özel Hizmetini Silme

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

Cloud Storage paketini silme

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

Statik IP'yi ve SSL Sertifikasını Silme

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}"

Silme temizleme işleminin tamamlandığını doğrulayın:

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

9. Tebrikler

Tebrikler! Google Cloud'da MCP Python SDK'sından MCPServer ve uv kullanarak MCP 2.0 sunucusunu başarıyla oluşturup güvenliğini sağladınız ve dağıttınız.

İşlediğiniz konular

  • Durumsuz Streamable HTTP üzerinden MCPServer destekleyen MCP Spec (2026-07-28) oluşturuldu.
  • Vertex AI Gemini, Cloud Storage, Cloud Logging ve Resource Health'i entegre eden 4 adet üretim amaçlı Google Cloud aracı geliştirdi.
  • Zorunlu IAM kimlik doğrulaması ve SSL/TLS ile Cloud Run'da güvenli container dağıtımları.
  • Workload Identity ve TLS ile Kubernetes Gateway API kullanarak GKE Autopilot'ta gizli anahtarsız kimlik doğrulamayı yapılandırdıysanız.
  • OIDC yetkilendirme üstbilgilerini kullanarak Gemini Enterprise Agent Platform (Agent Registry) ile kayıtlı ve keşfedilmiş MCP sunucusu uç noktaları.

Sonraki adımlar