Google Cloud で MCP サーバーを構築、保護、デプロイする

1. 始める前に

Model Context Protocol(MCP)は、AI モデルとエージェントがツール、データベース、エンタープライズ コンテキストに安全にアクセスできるようにするオープン スタンダードです。2024 年に導入されて以来、このプロトコルはクラウド プロバイダや LLM プロバイダに広く採用されています。最新の仕様である MCP 仕様 2026-07-28(MCP 2.0)では、ステートレス アーキテクチャ、簡素化されたトランスポート、厳密な結果の型指定が定義されています。以前のバージョンとの下位互換性は維持されています。

公式の MCP Python SDK(mcp>=2.0.0)は MCPServer(mcp.server.mcpserver.MCPServer)を提供します。これは、MCP 2.0 の FastMCP に代わる、SSL/TLS 経由のストリーミング可能な HTTP とサーバー送信イベント(SSE)トランスポートを備えた、最新の MCP 仕様(2026-07-28)に準拠した本番環境対応の MCP サーバーを作成するための、高性能でデベロッパー向けのフレームワークです。

この Codelab では、MCP 2.0 Python SDK の MCPServer と uv 依存関係管理を使用して、本番環境グレードの MCP サーバーを構築します。MCP サーバーには、4 つの Google Cloud ツール(Vertex AI Gemini の呼び出し、Google Cloud Storage の検査、Cloud Logging の監査書き込み、Google Cloud リソースの健全性チェック)が装備されます。次に、サーバーをコンテナ化して、Cloud Run と Google Kubernetes Engine(GKE)Autopilot の 2 つの Google Cloud ランタイム ターゲットにデプロイし、Gemini Enterprise Agent Platform で MCP Server を登録して使用します。

演習内容

  • Python 3.12 以降と MCP 仕様 2026-07-28 に準拠した uv を使用して、4 つの Google Cloud ツールで MCPServer をビルドします。
  • マルチステージ Docker ビルドを使用して MCP サーバーをコンテナ化します。
  • IAM 認証と SSL/TLS を適用して、MCP サーバーを保護し、Cloud Run にデプロイします。
  • Workload Identity と TLS を使用した Kubernetes Gateway API を使用して、MCP サーバーを GKE Autopilot に安全にデプロイします。
  • OIDC ベアラー トークン ヘッダーを使用して、セキュアな MCP サーバー エンドポイントを Gemini Enterprise Agent Platform に登録します。

必要なもの

  • 課金を有効にした Google Cloud プロジェクト
  • Google Cloud SDK(gcloud CLI)のインストールと構成。
  • Python 3.12 以降と uv パッケージ マネージャーがインストールされている。
  • docker をインストールしました。
  • kubectl コマンドライン ツールがインストールされている。

2. Google Cloud 環境を設定する

リソースを作成する前に、環境を認証して、必要な Google Cloud API を有効にします。

gcloud CLI を認証する

Google Cloud アカウントにログインします。

gcloud auth login

アクティブな Google Cloud プロジェクト ID を設定します。

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

Google Cloud サービスを有効にする

Cloud Run、GKE、Vertex AI、Artifact Registry、Cloud Build、Cloud Logging、Storage、Compute Engine に必要なすべての API を有効にします。

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 が正常に有効になったことを確認します。

Operation "operations/..." finished successfully.

アプリケーションのデフォルト認証情報を認証する

開発中に Python クライアント ライブラリが Vertex AI と Cloud Storage にローカルでアクセスできるように、環境を認証します。

gcloud auth application-default login

3. MCPServer と uv を使用して MCP サーバーをビルドする

このステップでは、uv を使用して Python プロジェクトを初期化し、4 つの Google Cloud 機能をサポートする MCPServer をビルドします。

uv でプロジェクトを初期化する

サーバー ディレクトリを作成し、uv を初期化します。

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

コードを 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"]

uv を使用して依存関係を同期します。

uv sync

MCPServer コードを記述する

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

MCP サーバーをローカルでテストする

ステップ 1: MCP サーバーを起動する

プライマリ ターミナルで、uv を使用してサーバーを起動します。

uv run python -m src.mcp_server.server

起動ログに、Streamable HTTP サーバーがポート 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)

このターミナルは開いたままにしておきます。

ステップ 2: curl を使用してストリーミング可能な HTTP エンドポイントを確認する

MCP 2.0(MCP 仕様 2026-07-28)では、ステートフルな initialize ハンドシェイクと Mcp-Session-Id ヘッダーがステートレス リクエストに置き換えられます。params._meta でクライアント メタデータとともに MCP-Protocol-Version ヘッダーと Mcp-Method ヘッダーを渡すことで、tools/list を直接呼び出すことができます。

2 つ目のターミナル ウィンドウを開き、Streamable HTTP POST リクエストを送信します。

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 で応答し、JSON-RPC tools/list の結果を直接返します。

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: MCP テスト クライアントを実行する

Streamable HTTP 経由でローカル サーバー上のツールを検出して実行するテストを行うには、テスト クライアント スクリプト 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 を使用してテスト クライアント スクリプトを実行します。

uv run python src/mcp_server/test_client.py

接続、ツールの検出、ツールの実行が成功したことを示す出力が表示されます。

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

確認が完了したら、プライマリ ターミナルで CTRL+C を押してローカル サーバーを停止します。

4. MCP サーバーをコンテナ化する

MCP サーバーを Cloud Run と GKE Autopilot にデプロイするには、uv を利用したマルチステージ Dockerfile を使用して、サーバーを最小限のコンテナ イメージにパッケージ化します。

Dockerfile を作成する

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

イメージをビルドして Artifact Registry に push する

Artifact Registry リポジトリを作成します。

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

Cloud Build がソースのステージング、ログの書き込み、Artifact Registry へのイメージの push を行えるように、必要な IAM 権限をユーザー アカウントとデフォルトの Compute Engine サービス アカウントに付与します。

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 を使用してイメージビルドを送信します。

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

完了すると、コンテナ イメージが Artifact Registry に安全に保存されます。

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

5. IAM と HTTPS を使用して Cloud Run にデプロイする

Cloud Run は、HTTPS / SSL 証明書の自動終了と、きめ細かい Cloud IAM アクセス制御を備えたフルマネージドのサーバーレス環境を提供します。

専用サービス アカウントを作成する

Cloud Run 用に最小権限の Google サービス アカウントを作成します。

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"

Cloud Run にサービスをデプロイする

IAM 認証(--no-allow-unauthenticated)とデフォルトのマネージド SSL を適用して、コンテナを Cloud Run にデプロイします。

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 を取得します。

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

Endpoint Security を確認する

Streamable HTTP エンドポイントへの不正なリクエストを試みると、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

gcloud を使用して OIDC ID トークンを生成し、承認された通信を確認します。

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

ライブツールの実行をテストする: Cloud Storage インスペクタ

リモート MCP サーバーが認証され、応答するようになったので、Google Cloud インフラストラクチャに対して gcs_bucket_inspector ツールの実行をテストします。

ステップ 1: テスト用の Cloud Storage バケットを作成する

テストバケットを作成してサンプル ファイルをアップロードします。

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: リモート GCS ツール テスト クライアントを作成する

Cloud Run に対して認証を行い、gcs_bucket_inspector ツールを呼び出す src/mcp_server/test_gcs_tool.py という名前のテスト クライアント スクリプトを作成します。

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: リモート GCS テスト クライアントを実行する

uv を使用してテスト スクリプトを実行します。

uv run python src/mcp_server/test_gcs_tool.py

Cloud Run MCP サーバーから返されたライブ オブジェクトのメタデータが表示されます。

[*] 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 と TLS を使用して GKE Autopilot にデプロイする

Kubernetes ワークロードの場合、GKE Autopilot はノード プロビジョニングを管理し、Workload Identity は静的サービス アカウント キーを排除します。

GKE Autopilot クラスタをプロビジョニングする

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

Workload Identity を設定する

Google サービス アカウント(GSA)と Kubernetes サービス アカウント(KSA)を作成し、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}"

TLS を使用して Kubernetes Deployment と Gateway API を適用する

ステップ 1: 静的 IP を予約し、nip.io で Google マネージド SSL 証明書をプロビジョニングする

Kubernetes マニフェストを適用する前に、グローバル外部 IP アドレスを予約し、ワイルドカード DNS サービス nip.io(..nip.io)を利用して有効なパブリック ドメイン名(MCP_DOMAIN)を確立します。

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

SSL 証明書のプロビジョニングが完了するまで待つ必要はありません。実際、Google マネージド証明書は、ステップ 3 で Gateway ロードバランサに接続されるまで PROVISIONING 状態のままです。すぐに次のステップに進みます。

ステップ 2: Deployment と Service のマニフェストを作成する

Deployment と内部 Service の定義を含む deployment.yaml を作成します。MCP 2.0(MCP 仕様 2026-07-28)はステートレスであるため、Kubernetes Service にクライアント IP セッション アフィニティは必要ありません。

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 と PROJECT_ID を置き換えて、Deployment を適用します。

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

ステップ 3: Gateway API、HealthCheckPolicy、GCPBackendPolicy のマニフェストを作成する

Gateway、HTTPRoute、HealthCheckPolicy、GCPBackendPolicy を含む gateway.yaml を作成します。

  • HealthCheckPolicy: ポート 8080 で /healthz をプローブするように Google Cloud ロードバランサを構成します。
  • GCPBackendPolicy(バックエンド タイムアウト): timeoutSec: 300 を設定して、ストリーミング可能な HTTP / SSE ストリームの MCP SDK v2 の 300 秒の読み取りタイムアウトに合わせます(省略した場合、GKE Gateway のデフォルトは 30 秒です)。
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、GCPBackendPolicy を適用します。

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

ステップ 4: デプロイを確認し、ポート転送を使用して MCP サーバーをテストする

Google マネージド SSL 証明書と外部 Google Cloud アプリケーション ロードバランサは、プロビジョニングと DNS ルーティングの確立に 5 ~ 15 分かかるため、kubectl port-forward を使用して実行中の GKE Pod をすぐにテストできます。

まず、Pod と Gateway が実行されていることを確認します。

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

次に、ポート転送を使用して、ライブ GKE サービスをローカルでテストします。

  1. ターミナルで、ローカルポート 8080 を GKE ClusterIP サービスに転送します。
kubectl port-forward svc/mcp-server-service 8080:80
  1. 2 番目のターミナルで、Workload Identity を使用して GKE で vertex_ai_generate_content ツールを呼び出すテスト クライアント スクリプト src/mcp_server/test_vertex_tool.py を作成します。
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. ローカルでポート転送されたインスタンスに対してテスト スクリプトを実行します。
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.

これにより、GKE Pod が正常であること、Workload Identity が静的な認証情報なしで Vertex AI に対して正常に認証されていること、ストリーミング可能な HTTP トランスポートが想定どおりに動作していることを確認できます。

ステップ 5: パブリック HTTPS ゲートウェイ エンドポイントを確認する

次のコマンドで証明書のプロビジョニング ステータスを確認します。

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

証明書が ACTIVE になったら、--host フラグを指定して Python テスト クライアントを使用して、公開 HTTPS エンドポイントをテストします。

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 サーバーを Google Cloud Agent Platform と統合する

MCPServer が Cloud Run と GKE Autopilot の HTTPS エンドポイントに安全にデプロイされたら、Google Cloud Agent Platform(Agent Registry)に MCP ツールを登録して検出します。これにより、エンタープライズ エージェントと AI モデルが動的に検出して呼び出すことができます。

1. カスタム Cloud Run MCP サーバーを Agent Platform に登録し、サービス ディスカバリを使用してテストする

ステップ 1: ツールの仕様を抽出する(toolspec.json)

外部またはカスタム MCP サーバーを Agent Registry に登録するには、ライブのステートレス MCP 2.0 サーバーで tools/list をクエリし、ツールレベルの _meta フィールドを削除して、結果を単一のパイプラインの toolspec.json に保存します。

# 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: Agent Registry にサービスを登録する

gcloud agent-registry services create を使用して MCP サーバーをカタログ化します。

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"

サービスが正常に登録されたことを確認します。

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: サービス ディスカバリ テスト クライアントを作成して実行する

Agent Registry mcp-servers カタログからエンドポイントを動的に解決し、Google Cloud IAM で認証し、httpx2 と MCP 2.0 Client を使用してツールを呼び出す src/mcp_server/test_agent_platform.py という名前の Python スクリプトを作成します。

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

テスト スクリプトを実行します。

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 での MCP サーバーの自動検出と登録

Google Kubernetes Engine(GKE)は、Agent Registryとの自動統合を提供します。GKE Deployment マニフェストにラベルとアノテーションを付けると、GKE は MCP サーバーに対して自動的にイントロスペクション スキャンを実行し、ツールをカタログに登録して、toolspec.json を手動で生成またはアップロードすることなく、サービスをコンシューマー側に投影します。

ステップ 1: GKE 自動検出の仕組み

前のセクションで deployment.yaml を適用すると、次の構成で自動検出が有効になります。

  • registry.gke.io/functional-type: "MCP_SERVER": デプロイを Google Cloud Agent Registry に登録するように GKE クラスタ コントローラに通知します。
  • modelcontextprotocol.info/urls: コントローラのイントロスペクションとコンシューマー ルーティング用の外部 HTTPS Gateway エンドポイント(https://${MCP_DOMAIN}/mcp)を提供します。
  • modelcontextprotocol.info/capabilities: HTTP トランスポート エンドポイント(/mcp)を宣言します。
  • iam.gke.io/spiffe-identity-type: agent-identity: エージェント通信用に Workload Identity を構成します。

ステップ 2: Agent Registry で GKE 自動登録を確認する

GKE が MCP サーバーを自動的に検出してリージョン mcp-servers カタログに登録したことを確認します。

# 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: サービス ディスカバリを使用して GKE MCP サーバーをテストする

us-central1 で自動登録されたサーバー名に対して、サービス ディスカバリ スクリプトを使用して GKE MCP Deployment をテストします。

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. リソースをクリーンアップする

この Codelab で使用したリソースについて、Google Cloud アカウントに課金されないようにするには、Cloud Run サービス、GKE クラスタ、サービス アカウント、コンテナ リポジトリを削除します。

Cloud Run サービスを削除する

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

GKE Autopilot クラスタを削除する

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

サービス アカウントと 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}"

Artifact Registry リポジトリを削除する

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

Agent Registry カスタム サービスを削除する

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

Cloud Storage バケットを削除する

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

静的 IP と 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}"

削除のクリーンアップが完了したことを確認します。

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

9. 完了

これで完了です。MCP Python SDK の MCPServer と Google Cloud の uv を使用して、MCP 2.0 サーバーの構築、保護、デプロイに成功しました。

学習した内容

  • ステートレスのストリーミング可能な HTTP 経由で MCP 仕様(2026 年 7 月 28 日)をサポートする MCPServer を構築しました。
  • Vertex AI Gemini、Cloud Storage、Cloud Logging、Resource Health を統合した 4 つの Google Cloud 本番環境ツールを構築しました。
  • IAM 認証と SSL/TLS が適用された Cloud Run での安全なコンテナ デプロイ。
  • Workload Identity と TLS を使用した Kubernetes Gateway API を使用して、GKE Autopilot でシークレットレス認証を構成しました。
  • OIDC 認証ヘッダーを使用して、Gemini Enterprise Agent Platform(Agent Registry)で登録および検出された MCP サーバー エンドポイント。

次のステップ