Cloud Run'da Gemini + MCP ile doğal dili gerçek Google Cloud işlemlerine dönüştürme

1. Giriş

Bu codelab'de, Python kullanarak özel bir MCP (Model Context Protocol) sunucusu oluşturma, bunu Google Cloud Run'a dağıtma ve doğal dili kullanarak gerçek Google Cloud Storage işlemleri yürütmek için Gemini CLI ile bağlama adımları açıklanmaktadır.

Mimari Akış: Gemini CLI → Cloud Run → MCP

e149713a547f4157.png

Şunu hayal edin: Terminalinizi açıp bir yapay zeka aracına aşağıdaki gibi basit bir istem yazıyorsunuz:

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

Bulutunuz saniyeler içinde dinler ve yürütür. Karmaşık komutlar yok. Sekmeler arasında sürekli geçiş yapmanıza gerek kalmaz. Sadece basit bir dil, gerçek bulut işlemlerine dönüşüyor.

Yapacaklarınız

Gemini KSA'yı Google Cloud Storage'a bağlayan özel bir MCP sunucusu oluşturup dağıtacaksınız.

Bu kurstan sonra:

  • Python tabanlı bir MCP sunucusu oluşturma
  • Uygulamayı kapsayıcıya alma
  • Cloud Run'a dağıtma
  • IAM ve kimlik jetonlarını kullanarak güvenliğini sağlama
  • Gemini CLI ile bağlama
  • Doğal dili kullanarak canlı GCS işlemleri yürütme

Neler öğreneceksiniz?

  • MCP (Model Context Protocol) nedir ve nasıl çalışır?
  • Python kullanarak araç çağırma özellikleri oluşturma
  • Container mimarisine alınmış uygulamaları Cloud Run'a dağıtma
  • Gemini CLI, harici MCP sunucularıyla nasıl entegre olur?
  • Cloud Run hizmetlerinin kimliğini güvenli bir şekilde doğrulama
  • Yapay zeka kullanarak gerçek Google Cloud Storage işlemlerini yürütme

Gerekenler

  • Chrome web tarayıcısı
  • Gmail hesabı
  • Faturalandırmanın etkin olduğu bir Google Cloud projesi
  • Gemini CLI (Google Cloud Shell ile birlikte önceden yüklenmiş olarak gelir)
  • Python ve Google Cloud hakkında temel düzeyde bilgi sahibi olma

Bu codelab'de, kullanıcının temel Python bilgisine sahip olduğu varsayılır.

2. Başlamadan önce

Proje oluşturma

  1. Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun.
  2. Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bir projede faturalandırmanın etkin olup olmadığını kontrol etmeyi öğrenin .
  3. bq'nun önceden yüklendiği, Google Cloud'da çalışan bir komut satırı ortamı olan Cloud Shell'i kullanacaksınız. Google Cloud Console'un üst kısmından Cloud Shell'i etkinleştir'i tıklayın.

Cloud Shell&#39;i etkinleştir düğmesinin resmi

  1. Cloud Shell'e bağlandıktan sonra aşağıdaki komutu kullanarak kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını kontrol edin:
gcloud auth list
  1. gcloud komutunun projeniz hakkında bilgi sahibi olduğunu onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın.
gcloud config list project
  1. Projeniz ayarlanmamışsa ayarlamak için aşağıdaki komutu kullanın:
gcloud config set project <YOUR_PROJECT_ID>
  1. Aşağıdaki komutu kullanarak gerekli API'leri etkinleştirin. Bu işlem birkaç dakika sürebilir. Lütfen bekleyin.
gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

Yetkilendirmeniz istenirse devam etmek için Yetkilendir'i tıklayın.

5e681903144bdfbe.png

Komut başarıyla yürütüldüğünde aşağıda gösterilene benzer bir mesaj görürsünüz:

Operation "operations/..." finished successfully.

Herhangi bir API atlanırsa uygulama sırasında istediğiniz zaman etkinleştirebilirsiniz.

gcloud komutları ve kullanımı için belgelere bakın.

Python projenizi hazırlama

Bu bölümde, MCP sunucunuza ev sahipliği yapacak Python projesini oluşturacak ve bağımlılıklarını Cloud Run'a dağıtım için yapılandıracaksınız.

Proje dizinini oluşturma

Kaynak kodunuzu depolamak için mcp-on-cloudrun adlı yeni bir klasör oluşturarak başlayın:

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

requirements.txt dosyasını oluşturma

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

Dosyaya aşağıdaki içeriği ekleyin:

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

Dosyayı kaydedin.

3. MCP sunucusunu oluşturma

Bu bölümde, Google Cloud Storage işlemlerini çağrılabilir araçlar olarak kullanıma sunan MCP sunucusunu oluşturacaksınız.

Bu sunucu:

  • MCP araçlarını kaydetme
  • Google Cloud Storage'a bağlanma
  • HTTP üzerinden çalıştırma
  • Cloud Run'a dağıtılabilir olmalıdır.

Şimdi main.py içinde temel MCP mantığımızı oluşturalım.

Aşağıda, paketleri listelemek ve oluşturmaktan blob'ları yüklemek, indirmek ve yönetmeye kadar Google Cloud Storage'ı yönetmeye yönelik birden fazla aracı tanımlayan tam kod yer almaktadır.

Ana uygulama dosyasını oluşturma

mcp-on-cloudrun dizininde main.py adlı yeni bir dosya oluşturun:

touch main.py

Dosyayı Cloud Shell Düzenleyici'yi kullanarak açın:

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

main.py dosya içeriğine aşağıdaki kaynağı ekleyin:

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

Kodu ekledikten sonra dosyayı kaydedin.

Proje yapınız artık şu şekilde görünmelidir:

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

Kodu kısaca açıklayalım:

İçe Aktarma ve Kurulum:

Kod, gerekli kitaplıkları içe aktararak başlar.

  • Standart Kitaplıklar: asyncio eşzamansız yürütme, logging durum mesajları çıkışı ve os ortam değişkenleri için.
  • FastMCP: Model Context Protocol sunucusunu oluşturmak için kullanılan temel çerçeve.
  • Google Cloud Storage: GCS ile etkileşim için google.cloud.storage kitaplığı, hata işleme için de exceptions kitaplığı içe aktarılır.

İlk kullanıma hazırlama:

Sunucunun kimliğini ayıklamaya ve izlemeye yardımcı olması için günlük biçimini yapılandırırız. Ayrıca, FastMCP adlı MyEnhancedGCSMCPServer örneğini de yapılandırıyoruz. Bu nesne (mcp), sunucunun kullanıma sunduğu tüm araçları (işlevleri) kaydetmek için kullanılır. Aşağıdaki araçları tanımlıyoruz:

  • list_gcs_buckets: İlişkili Google Cloud projesindeki tüm depolama paketlerinin listesini alır.
  • create_bucket: Belirli bir ad ve konumla yeni bir paket oluşturur.
  • delete_bucket: Mevcut bir paketi siler.
  • list_objects: Belirli bir paketin içindeki tüm dosyaları (blob'lar) listeler.
  • delete_blob: Bir paketteki tek bir dosyayı siler.
  • get_bucket_metadata: Paketle ilgili teknik ayrıntıları (Konum, Depolama Sınıfı, Sürüm Oluşturma durumu, Oluşturma zamanı) döndürür.
  • get_blob_metadata: Belirli bir dosya hakkında teknik ayrıntıları (Boyut, İçerik Türü, MD5 Hash, Son Güncelleme) döndürür.

Giriş noktası:

Bu, bağlantı noktasını yapılandırır. Ayarlanmamışsa varsayılan olarak 8080 kullanılır. Ardından, sunucuyu mcp.run_async ile eşzamansız olarak başlatmak için asyncio.run() kullanılır. Son olarak, sunucuyu HTTP üzerinden çalışacak şekilde yapılandırır (host 0.0.0.0) ve gelen ağ istekleri için erişilebilir hale getirir.

4. MCP sunucusunu kapsayıcıya yerleştirme

Bu bölümde, MCP sunucunuzun Cloud Run'a dağıtılabilmesi için bir Dockerfile oluşturacaksınız.

Cloud Run için kapsayıcıya alınmış bir uygulama gerekir. Uygulamanızın nasıl oluşturulacağını ve başlatılacağını tanımlarsınız.

Dockerfile'ı oluşturma

Dockerfile adlı yeni bir dosya oluşturun:

touch Dockerfile

Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/gcs-mcp-server/Dockerfile

Docker yapılandırması ekleme

Aşağıdaki içeriği Dockerfile içine yapıştırın:

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

İçeriği ekledikten sonra dosyayı kaydedin. Proje yapınız artık şu şekilde görünmelidir:

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

5. Cloud Run'a dağıtma

Artık MCP sunucunuzu doğrudan kaynaktan dağıtabilirsiniz.

Cloud Shell'de aşağıdaki komutu çalıştırın:

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

İstendiğinde

  • Kimliği doğrulanmamış çağrılara izin verilsin mi? → Hayır

Cloud Build:

  • Container görüntüsünü oluşturma
  • Artifact Registry'ye aktarın.
  • Cloud Run'a dağıtma

Artifact Registry deposunun oluşturulabileceğini onaylamak için Y yazın.

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

Dağıtım başarılı olduktan sonra Cloud Run hizmeti URL'sini içeren bir başarı mesajı görürsünüz.

Dağıtımı Cloud Run → Servicesbölümündeki Google Cloud Console'unuzdan da doğrulayabilirsiniz.

53f95a2aa7a169d6.png

6. Gemini CLI Yapılandırması

Şimdiye kadar MCP sunucumuzu Cloud Run'da oluşturup dağıttık.

Şimdi eğlenceli kısma geçme zamanı: Gemini CLI ile bağlayıp doğal dil istemlerinizi gerçek bulut işlemlerine dönüştürme.

Cloud Run Invoker izni verme

Cloud Run hizmetimiz özel olduğundan kimlik doğrulama için kimlik jetonu kullanıp doğru IAM izinlerini atayacağız.

Hizmeti --no-allow-unauthenticated ile dağıttık. Bu nedenle, hizmeti çağırmak için izin vermeniz gerekir.

Projenizin kimliğini belirleyin:

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

Kendinize Cloud Run Çağırıcı rolünü verin:

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

Bu, hesabınızın Cloud Run hizmetini güvenli bir şekilde çağırmasına olanak tanır.

Kimlik jetonu oluşturma

Cloud Run, kimliği doğrulanmış erişim için kimlik jetonu gerektirir.

Oluşturma:

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

Doğrulayın:

echo $PROJECT_NUMBER
echo $ID_TOKEN

Bu jetonu Gemini CLI yapılandırmasında kullanacaksınız.

Gemini KSA'da MCP sunucusunu yapılandırma

Gemini CLI ayarları dosyasını açın:

cloudshell edit ~/.gemini/settings.json

Aşağıdaki yapılandırmayı ekleyin:

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

Gemini KSA'da yapılandırılan MCP sunucularını doğrulama

Aşağıdaki komutu kullanarak Cloud Shell terminalinde Gemini CLI'yı başlatın:

gemini

Aşağıdaki çıkışı görürsünüz.

193224319056d340.png

Gemini CLI'da şu komutu çalıştırın:

/mcp refresh
/mcp list

gcs-cloudrun-server'nizin kaydedildiğini göreceksiniz. Örnek ekran görüntüsü aşağıda gösterilmiştir:

726738c48290fc30.png

7. Doğal dil kullanarak Google Storage işlemlerini çağırma

Paket oluşturma

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

Bu işlem, MCP sunucusundan create_bucket aracını çağırmak için izninizi ister.

5ab2225295285077.png

Bir kez İzin Ver'i tıkladığınızda paketiniz, istediğiniz bölgede başarıyla oluşturulur.

Paketleri listeleme

Grupları listelemek için aşağıdaki istemi girin:

List all my GCS buckets

Paketi silme

Bir paketi silmek için aşağıdaki istemi girin (<your_bucket_name> yerine paketinizin adını yazın):

Delete the bucket <your_bucket_name>

Paketin meta verilerini alma

Bir paketin meta verilerini almak için aşağıdaki istemi girin (<your_bucket_name> yerine paketinizin adını yazın):

Give me metadata of the <your_bucket_name>

8. Temizleme

Bu işlem genellikle geri alınamaz olduğundan, Google Cloud projesini silmeye karar vermeden önce bu bölümün tamamını okuyun.

Bu codelab'de kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini istemiyorsanız şu adımları uygulayın:

  • Google Cloud Console'da Kaynakları yönetin sayfasına gidin.
  • Proje listesinde, silmek istediğiniz projeyi seçin.
  • Sil'i tıklayın.

İletişim kutusunda Proje kimliği'ni yazın ve ardından projeyi kalıcı olarak silmek için Kapat'ı tıklayın.

Projenin silinmesi, Cloud Run hizmetleri ve Artifact Registry'de depolanan kapsayıcı görüntüleri de dahil olmak üzere bu projede kullanılan tüm kaynaklar için faturalandırmayı durdurur.

Alternatif olarak, projeyi tutmak ancak dağıtılan hizmeti kaldırmak istiyorsanız:

  1. Google Cloud Console'da Cloud Run'a gidin.
  2. gcs-mcp-server hizmetini seçin.
  3. Hizmeti kaldırmak için Sil'i tıklayın.

veya Cloud Shell terminalinde aşağıdaki gcloud komutunu verin.

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

9. Sonuç

🎉 Tebrikler! İlk yapay zeka destekli bulut iş akışınızı oluşturdunuz.

Uyguladığınız:

  • Özel Python tabanlı bir MCP sunucusu
  • Google Cloud Storage için araç çağırma özellikleri
  • Docker kullanarak konteynerleştirme
  • Cloud Run'a güvenli dağıtım
  • Kimlik tabanlı kimlik doğrulama
  • Gemini CLI ile entegrasyon

Artık bu mimariyi BigQuery, Pub/Sub veya Compute Engine gibi ek Google Cloud hizmetlerini destekleyecek şekilde genişletebilirsiniz.

Bu kalıp, yapay zeka sistemlerinin yapılandırılmış araç çağırma yoluyla bulut altyapısıyla nasıl güvenli bir şekilde etkileşim kurabileceğini gösterir.