Mengubah bahasa alami menjadi tindakan Google Cloud yang nyata dengan Gemini + MCP di Cloud Run

1. Pengantar

Codelab ini memandu Anda membuat server MCP (Model Context Protocol) kustom menggunakan Python, men-deploy-nya ke Google Cloud Run, dan menghubungkannya dengan Gemini CLI untuk menjalankan operasi Google Cloud Storage yang sebenarnya menggunakan bahasa alami.

Alur Arsitektur: Gemini CLI → Cloud Run → MCP

e149713a547f4157.png

Bayangkan ini: Anda membuka terminal dan mengetik perintah sederhana di Agen AI, seperti yang ditunjukkan di bawah:

  • List my GCS buckets
  • Create a GCS bucket named <bucket-name>
  • Tell me about the metadata of my GCS object

Dalam hitungan detik, cloud Anda akan mendengarkan dan menjalankan. Tidak ada perintah yang rumit. Tidak perlu beralih tab tanpa akhir. Hanya bahasa sederhana yang berubah menjadi tindakan cloud nyata.

Yang akan Anda lakukan

Anda akan membangun dan men-deploy server MCP kustom yang menghubungkan Gemini CLI dengan Google Cloud Storage.

Anda akan:

  • Membangun server MCP berbasis Python
  • Mem-build aplikasi dalam container
  • Deploy ke Cloud Run
  • Mengamankannya menggunakan IAM dan token identitas
  • Menghubungkannya dengan Gemini CLI
  • Menjalankan operasi GCS langsung menggunakan bahasa alami

Yang akan Anda pelajari

  • Apa itu MCP (Model Context Protocol) dan cara kerjanya
  • Cara membangun kemampuan pemanggilan alat menggunakan Python
  • Cara men-deploy aplikasi dalam container ke Cloud Run
  • Cara Gemini CLI berintegrasi dengan server MCP eksternal
  • Cara mengautentikasi layanan Cloud Run dengan aman
  • Cara menjalankan operasi Google Cloud Storage yang sebenarnya menggunakan AI

Yang Anda butuhkan

  • Browser web Chrome
  • Akun Gmail
  • Project Google Cloud dengan penagihan diaktifkan
  • Gemini CLI (Sudah terinstal di Google Cloud Shell)
  • Pemahaman dasar tentang Python dan Google Cloud

Codelab ini mengharapkan pengguna memiliki pengetahuan dasar tentang Python

2. Sebelum memulai

Membuat project

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project .
  3. Anda akan menggunakan Cloud Shell, lingkungan command line yang berjalan di Google Cloud yang telah dilengkapi dengan bq. Klik Activate Cloud Shell di bagian atas konsol Google Cloud.

Gambar tombol Activate Cloud Shell

  1. Setelah terhubung ke Cloud Shell, Anda dapat memeriksa bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke project ID Anda menggunakan perintah berikut:
gcloud auth list
  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda.
gcloud config list project
  1. Jika project Anda belum ditetapkan, gunakan perintah berikut untuk menetapkannya:
gcloud config set project <YOUR_PROJECT_ID>
  1. Aktifkan API yang diperlukan melalui perintah yang ditampilkan di bawah. Proses ini mungkin memerlukan waktu beberapa menit, jadi bersabarlah.
gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

Jika diminta untuk memberikan otorisasi, klik Otorisasi untuk melanjutkan.

5e681903144bdfbe.png

Setelah perintah berhasil dieksekusi, Anda akan melihat pesan yang mirip dengan yang ditampilkan di bawah:

Operation "operations/..." finished successfully.

Jika ada API yang terlewat, Anda dapat mengaktifkannya selama proses penerapan.

Baca dokumentasi untuk mempelajari perintah gcloud dan penggunaannya.

Menyiapkan project Python

Di bagian ini, Anda akan membuat project Python yang akan menghosting server MCP dan mengonfigurasi dependensinya untuk deployment ke Cloud Run.

Buat direktori project

Mulai dengan membuat folder baru bernama mcp-on-cloudrun untuk menyimpan kode sumber Anda:

mkdir gcs-mcp-server && cd gcs-mcp-server

Buat requirements.txt

touch requirements.txt
cloudshell edit ~/gcs-mcp-server/requirements.txt

Tambahkan teks berikut ke file:

fastmcp
google-cloud-storage
google-api-core
pydantic

Simpan file.

3. Membuat server MCP

Di bagian ini, Anda akan membuat server MCP yang mengekspos operasi Google Cloud Storage sebagai alat yang dapat dipanggil.

Server ini akan:

  • Mendaftarkan alat MCP
  • Terhubung ke Google Cloud Storage
  • Menjalankan melalui HTTP
  • Dapat di-deploy ke Cloud Run

Sekarang, mari kita buat logika MCP inti di dalam main.py.

Di bawah ini adalah kode lengkap yang menentukan beberapa alat untuk mengelola Google Cloud Storage - mulai dari mencantumkan dan membuat bucket hingga mengupload, mendownload, dan mengelola blob

Membuat file aplikasi utama

Di dalam direktori mcp-on-cloudrun, buat file baru bernama main.py:

touch main.py

Buka file menggunakan Cloud Shell Editor:

cloudshell edit ~/gcs-mcp-server/main.py

Tambahkan sumber berikut ke konten file main.py:

import asyncio
import logging
import os
from datetime import timedelta
from typing import List, Dict, Any
from fastmcp import FastMCP
from google.cloud import storage
from google.api_core import exceptions

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

mcp = FastMCP(name="MyEnhancedGCSMCPServer")
# ---------------------------------------------------------
# 1️⃣ Simple Greeting
# ---------------------------------------------------------
@mcp.tool
def sayhi(name: str) -> str:
  """Returns a friendly greetings"""
  return f"Hello {name}! It's a pleasure to connect from your enhanced MCP Server."

# ---------------------------------------------------------
# 2️⃣ List all GCS buckets
# ---------------------------------------------------------
@mcp.tool
def list_gcs_buckets() -> List[str]:
  """Lists all GCS buckets in the project."""
  try:
      storage_client = storage.Client()
      buckets = storage_client.list_buckets()
      return [bucket.name for bucket in buckets]
  except exceptions.Forbidden as e:
      return [f"Error: Permission denied to list buckets. Details: {e}"]
  except Exception as e:
      return [f"An unexpected error occurred: {e}"]

# ---------------------------------------------------------
# 3️⃣ Create a new bucket
# ---------------------------------------------------------
@mcp.tool
def create_bucket(bucket_name: str, location: str = "US") -> str:
  """Creates a new GCS bucket. Bucket names must be globally unique."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      bucket.location = location
      storage_client.create_bucket(bucket)
      return f"✅ Bucket '{bucket_name}' created successfully in '{location}'."
  except exceptions.Conflict:
      return f"⚠️ Error: Bucket '{bucket_name}' already exists."
  except exceptions.Forbidden as e:
      return f"❌ Error: Permission denied to create bucket. Details: {e}"
  except Exception as e:
      return f"❌ Unexpected error: {e}"

# ---------------------------------------------------------
# 4️⃣ Delete a bucket
# ---------------------------------------------------------
@mcp.tool
def delete_bucket(bucket_name: str) -> str:
  """Deletes a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      bucket.delete(force=True)
      return f"🗑️ Bucket '{bucket_name}' deleted successfully."
  except exceptions.NotFound:
      return f"⚠️ Error: Bucket '{bucket_name}' not found."
  except exceptions.Forbidden as e:
      return f"❌ Error: Permission denied to delete bucket. Details: {e}"
  except Exception as e:
      return f"❌ Unexpected error: {e}"

# ---------------------------------------------------------
# 5️⃣ List objects in a bucket
# ---------------------------------------------------------
@mcp.tool
def list_objects(bucket_name: str) -> List[str]:
  """Lists all objects in a specified GCS bucket."""
  try:
      storage_client = storage.Client()
      blobs = storage_client.list_blobs(bucket_name)
      return [blob.name for blob in blobs]
  except exceptions.NotFound:
      return [f"⚠️ Error: Bucket '{bucket_name}' not found."]
  except Exception as e:
      return [f"❌ Unexpected error: {e}"]
# ---------------------------------------------------------
# Delete file from a bucket
# ---------------------------------------------------------
@mcp.tool
def delete_blob(bucket_name: str, blob_name: str) -> str:
  """Deletes a blob from a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      blob = bucket.blob(blob_name)
      blob.delete()
      return f"🗑️ Blob '{blob_name}' deleted from bucket '{bucket_name}'."
  except exceptions.NotFound:
      return f"⚠️ Error: Bucket '{bucket_name}' or blob '{blob_name}' not found."
  except exceptions.Forbidden as e:
      return f" Permission denied. Details: {e}"
  except Exception as e:
      return f" Unexpected error: {e}"

# ---------------------------------------------------------
# Get bucket metadata
# ---------------------------------------------------------
@mcp.tool
def get_bucket_metadata(bucket_name: str) -> Dict[str, Any]:
  """Retrieves metadata for a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.get_bucket(bucket_name)
      return {
          "id": bucket.id,
          "name": bucket.name,
          "location": bucket.location,
          "storage_class": bucket.storage_class,
          "created": bucket.time_created.isoformat() if bucket.time_created else None,
          "updated": bucket.updated.isoformat() if bucket.updated else None,
          "versioning_enabled": bucket.versioning_enabled,
      }
  except exceptions.NotFound:
      return {"error": f" Bucket '{bucket_name}' not found."}
  except Exception as e:
      return {"error": f" Unexpected error: {e}"}

# ---------------------------------------------------------
# Get object metadata
# ---------------------------------------------------------
@mcp.tool
def get_blob_metadata(bucket_name: str, blob_name: str) -> Dict[str, Any]:
  """Retrieves metadata for a specific blob."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      blob = bucket.get_blob(blob_name)
      if not blob:
          return {"error": f" Blob '{blob_name}' not found in '{bucket_name}'."}
      return {
          "name": blob.name,
          "bucket": blob.bucket.name,
          "size": blob.size,
          "content_type": blob.content_type,
          "updated": blob.updated.isoformat() if blob.updated else None,
          "storage_class": blob.storage_class,
          "crc32c": blob.crc32c,
          "md5_hash": blob.md5_hash,
      }
  except exceptions.NotFound:
      return {"error": f" Bucket '{bucket_name}' not found."}
  except Exception as e:
      return {"error": f" Unexpected error: {e}"}

# ---------------------------------------------------------
# 🚀 Entry Point
# ---------------------------------------------------------
if __name__ == "__main__":
  port = int(os.getenv("PORT", 8080))
  logger.info(f"🚀 Starting Enhanced GCS MCP Server on port {port}")
  asyncio.run(
      mcp.run_async(
          transport="http",
          host="0.0.0.0",
          port=port,
      )
  )

Simpan file setelah menambahkan kode.

Struktur project Anda sekarang akan terlihat seperti ini:

gcs-mcp-server/
├── requirements.txt
└── main.py

Mari kita pahami kode secara singkat:

Impor dan Penyiapan:

Kode dimulai dengan mengimpor library yang diperlukan.

  • Standard Libraries: asyncio untuk eksekusi asinkron, logging untuk menampilkan pesan status, dan os untuk variabel lingkungan.
  • FastMCP: Framework inti yang digunakan untuk membuat server Model Context Protocol.
  • Google Cloud Storage: Library google.cloud.storage diimpor untuk berinteraksi dengan GCS, bersama dengan exceptions untuk penanganan error.

Inisialisasi:

Kita mengonfigurasi format logging untuk membantu men-debug dan melacak identitas server. Selain itu, kita mengonfigurasi instance FastMCP bernama MyEnhancedGCSMCPServer. Objek ini (mcp) akan digunakan untuk mendaftarkan semua alat (fungsi) yang diekspos server. Kami menentukan alat berikut:

  • list_gcs_buckets: Mengambil daftar semua bucket penyimpanan di project Google Cloud terkait.
  • create_bucket: Membuat bucket baru dengan nama dan lokasi tertentu.
  • delete_bucket: Menghapus bucket yang ada.
  • list_objects: Mencantumkan semua file (blob) di dalam bucket tertentu.
  • delete_blob: Menghapus satu file tertentu dari bucket.
  • get_bucket_metadata: Menampilkan detail teknis tentang bucket (Lokasi, Kelas Penyimpanan, status Pembuatan versi, Waktu pembuatan).
  • get_blob_metadata: Menampilkan detail teknis tentang file tertentu (Ukuran, Jenis Konten, Hash MD5, Terakhir Diperbarui).

Titik Masuk:

Mengonfigurasi port, dengan nilai default 8080 jika tidak disetel. Kemudian, asyncio.run() menggunakan asyncio.run() untuk memulai server secara asinkron dengan mcp.run_async. Terakhir, server dikonfigurasi untuk berjalan melalui HTTP (host 0.0.0.0), sehingga dapat diakses untuk permintaan jaringan masuk.

4. Mengontainerisasi Server MCP

Di bagian ini, Anda akan membuat Dockerfile agar server MCP dapat di-deploy ke Cloud Run.

Cloud Run memerlukan aplikasi dalam container. Anda akan menentukan cara aplikasi Anda dibuat dan dimulai.

Buat Dockerfile

Buat file baru bernama Dockerfile:

touch Dockerfile

Buka di Cloud Shell Editor:

cloudshell edit ~/gcs-mcp-server/Dockerfile

Tambahkan konfigurasi Docker

Tempelkan konten berikut ke Dockerfile:

FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y \
   build-essential \
   gcc \
   && rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade pip
COPY . .
RUN pip install -r requirements.txt
ENV PORT=8080
EXPOSE 8080
CMD ["python", "main.py"]

Simpan file setelah menambahkan konten. Struktur project Anda sekarang akan terlihat seperti ini:

gcs-mcp-server/
├── requirements.txt
├── main.py
└── Dockerfile

5. Men-deploy ke Cloud Run

Sekarang deploy server MCP Anda langsung dari sumber.

Jalankan perintah berikut di Cloud Shell:

gcloud run deploy gcs-mcp-server \
   --no-allow-unauthenticated \
   --region=us-central1 \
   --source=. \
   --labels=session=buildersdayblr

Saat diminta untuk

  • Izinkan pemanggilan tanpa autentikasi? → Tidak

Cloud Build akan:

  • Membangun image container
  • Kirim ke Artifact Registry
  • Deploy ke Cloud Run

Masukkan Y untuk mengonfirmasi bahwa repositori Artifact Registry dapat dibuat.

Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-central1] will be created.

Do you want to continue (Y/n)?  Y

Setelah deployment berhasil, Anda akan melihat pesan berhasil dengan URL layanan Cloud Run.

Anda juga dapat memverifikasi deployment dari Konsol Google Cloud di bagian Cloud Run → Services.

53f95a2aa7a169d6.png

6. Konfigurasi Gemini CLI

Sejauh ini, kita telah membangun dan men-deploy server MCP di Cloud Run.

Sekarang saatnya bagian yang menyenangkan — menghubungkannya dengan Gemini CLI dan mengubah perintah bahasa alami Anda menjadi tindakan cloud nyata.

Memberikan Izin Cloud Run Invoker

Karena layanan Cloud Run bersifat pribadi, kita akan melakukan autentikasi menggunakan token identitas dan menetapkan izin IAM yang benar.

Kami men-deploy layanan dengan --no-allow-unauthenticated, sehingga Anda harus memberikan izin untuk memanggilnya.

Setel ID project Anda:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)

Berikan peran Cloud Run Invoker kepada diri Anda sendiri:

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=user:$(gcloud config get-value account) \
  --role='roles/run.invoker'

Hal ini memungkinkan akun Anda memanggil layanan Cloud Run dengan aman.

Membuat Token Identitas

Cloud Run memerlukan Token Identitas untuk akses yang diautentikasi.

Buat satu:

export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export ID_TOKEN=$(gcloud auth print-identity-token)

Verifikasi:

echo $PROJECT_NUMBER
echo $ID_TOKEN

Anda akan menggunakan token ini dalam konfigurasi Gemini CLI.

Mengonfigurasi Server MCP di Gemini CLI

Buka file setelan Gemini CLI:

cloudshell edit ~/.gemini/settings.json

Tambahkan konfigurasi berikut:

{
 "ide": {
   "enabled": true,
   "hasSeenNudge": true
 },
 "mcpServers": {
   "my-cloudrun-server": {
     "httpUrl": "https://gcs-mcp-server-$PROJECT_NUMBER.asia-south1.run.app/mcp",
     "headers": {
       "Authorization": "Bearer $ID_TOKEN"
     }
   }
 },
 "security": {
   "auth": {
     "selectedType": "cloud-shell"
   }
 }
}

Memvalidasi Server MCP yang dikonfigurasi di Gemini CLI

Luncurkan Gemini CLI di terminal Cloud Shell melalui perintah berikut:

gemini

Anda akan melihat output di bawah

193224319056d340.png

Di dalam Gemini CLI, jalankan:

/mcp refresh
/mcp list

Sekarang Anda akan melihat gcs-cloudrun-server Anda terdaftar. Contoh screenshot ditampilkan di bawah:

726738c48290fc30.png

7. Memanggil Operasi Google Storage melalui Bahasa Alami

Buat bucket

Create a bucket named my-ai-bucket in asia-south1 region

Anda akan diminta untuk memberikan izin guna memanggil alat create_bucket dari Server MCP.

5ab2225295285077.png

Klik Izinkan sekali, lalu bucket Anda akan berhasil dibuat di region tertentu yang Anda minta.

Mencantumkan bucket

Untuk mencantumkan bucket, masukkan perintah di bawah:

List all my GCS buckets

Menghapus bucket

Untuk menghapus bucket, masukkan perintah di bawah (ganti <your_bucket_name> dengan nama bucket Anda):

Delete the bucket <your_bucket_name>

Mendapatkan metadata bucket

Untuk mendapatkan metadata bucket, masukkan perintah di bawah (ganti <your_bucket_name> dengan nama bucket Anda):

Give me metadata of the <your_bucket_name>

8. Pembersihan

Baca seluruh bagian ini terlebih dahulu sebelum memutuskan untuk menghapus project Google Cloud, karena tindakan ini biasanya tidak dapat dibatalkan.

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, ikuti langkah-langkah berikut:

  • Di Konsol Google Cloud, buka halaman Kelola resource.
  • Dalam daftar project, pilih project yang ingin Anda hapus.
  • Klik Delete.

Pada dialog, ketik Project ID, lalu klik Shut down untuk menghapus project secara permanen.

Menghapus project akan menghentikan penagihan untuk semua resource yang digunakan dalam project tersebut, termasuk layanan Cloud Run dan image container yang disimpan di Artifact Registry.

Atau, jika Anda ingin mempertahankan project tetapi menghapus layanan yang di-deploy:

  1. Buka Cloud Run di Konsol Google Cloud.
  2. Pilih gcs-mcp-server service.
  3. Klik Hapus untuk menghapus layanan.

atau berikan perintah gcloud berikut di terminal Cloud Shell.

gcloud run services delete gcs-mcp-server --region=us-central1

9. Kesimpulan

🎉 Selamat! Anda baru saja membuat alur kerja cloud pertama yang didukung AI.

Anda telah menerapkan:

  • Server MCP berbasis Python Kustom
  • Kemampuan pemanggilan alat untuk Google Cloud Storage
  • Containerisasi menggunakan Docker
  • Deployment yang aman ke Cloud Run
  • Autentikasi berbasis identitas
  • Integrasi dengan Gemini CLI

Anda kini dapat memperluas arsitektur ini untuk mendukung layanan Google Cloud tambahan seperti BigQuery, Pub/Sub, atau Compute Engine.

Pola ini menunjukkan cara sistem AI dapat berinteraksi dengan aman dengan infrastruktur cloud melalui pemanggilan alat terstruktur.