1. Giriş
Genel Bakış
Bu laboratuvarda, Model Context Protocol (MCP) sunucusu oluşturup dağıtacaksınız. MCP sunucuları, LLM'lerin harici araçlara ve hizmetlere erişmesini sağlamak için kullanışlıdır. Bu hizmeti, Cloud Run'da birden fazla istemciden erişilebilen güvenli ve üretime hazır bir hizmet olarak yapılandıracaksınız. Ardından, Gemini CLI'dan uzak MCP sunucusuna bağlanacaksınız.
Yapacaklarınız
get_animals_by_species
ve get_animal_details
olmak üzere iki araca sahip bir hayvanat bahçesi MCP sunucusu oluşturmak için FastMCP'yi kullanacağız. FastMCP, MCP sunucuları ve istemcileri oluşturmak için hızlı ve Pythonic bir yol sağlar.
Neler öğreneceksiniz?
- MCP sunucusunu Cloud Run'a dağıtın.
- Tüm istekler için kimlik doğrulama gerektirerek sunucunuzun uç noktasını güvenli hale getirin. Böylece, yalnızca yetkili istemciler ve aracılar sunucunuzla iletişim kurabilir.
- Gemini KSA'dan güvenli MCP sunucusu uç noktanıza bağlanma
2. Proje Ayarları
- Google Hesabınız yoksa Google Hesabı oluşturmanız gerekir.
- İş veya okul hesabı yerine kişisel hesap kullanıyorsanız. İş ve okul hesaplarında, bu laboratuvar için gereken API'leri etkinleştirmenizi engelleyen kısıtlamalar olabilir.
- Google Cloud Console'da oturum açın.
- Cloud Console'da faturalandırmayı etkinleştirin.
- Bu laboratuvarı tamamlamak için 1 ABD dolarından daha az tutarda bulut kaynağı kullanmanız gerekir.
- Daha fazla ödeme alınmaması için bu laboratuvarın sonundaki adımları uygulayarak kaynakları silebilirsiniz.
- Yeni kullanıcılar 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.
- Yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanmayı seçin.
3. Cloud Shell Düzenleyici'yi açma
- Doğrudan Cloud Shell Düzenleyici'ye gitmek için bu bağlantıyı tıklayın.
- Bugün herhangi bir noktada yetkilendirmeniz istenirse devam etmek için Yetkilendir'i tıklayın.
- Terminal ekranın alt kısmında görünmüyorsa açın:
- Görünüm'ü tıklayın.
- Terminal'i tıklayın.
- Terminalde şu komutla projenizi ayarlayın:
- Biçim:
gcloud config set project [PROJECT_ID]
- Örnek:
gcloud config set project lab-project-id-example
- Proje kimliğinizi hatırlamıyorsanız:
- Tüm proje kimliklerinizi şu komutla listeleyebilirsiniz:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- Tüm proje kimliklerinizi şu komutla listeleyebilirsiniz:
- Biçim:
- Şu mesajı görmeniz gerekir:
Updated property [core/project].
WARNING
simgesini görüyorsanız veDo you want to continue (Y/n)?
soruluyorsa proje kimliğini yanlış girmiş olabilirsiniz.n
tuşuna,Enter
tuşuna basın vegcloud config set project
komutunu tekrar çalıştırmayı deneyin.
4. API'leri etkinleştir
Terminalde API'leri etkinleştirin:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
Yetkilendirmeniz istenirse devam etmek için Yetkilendir'i tıklayın.
Bu komutun tamamlanması birkaç dakika sürebilir ancak sonunda aşağıdakine benzer bir başarılı mesajı oluşturması gerekir:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
5. Python projenizi hazırlama
- Dağıtım için kaynak kodunu depolamak üzere
mcp-on-cloudrun
adlı bir klasör oluşturun:mkdir mcp-on-cloudrun && cd mcp-on-cloudrun
uv
aracıylapyproject.toml
dosyası oluşturmak için Python projesi oluşturun:uv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13
uv init
komutu, projeniz için birpyproject.toml
dosyası oluşturur.Dosyanın içeriğini görüntülemek için aşağıdakileri çalıştırın: Çıkış şu şekilde görünmelidir:cat pyproject.toml
[project] name = "mcp-on-cloudrun" version = "0.1.0" description = "Example of deploying an MCP server on Cloud Run" requires-python = ">=3.13" dependencies = []
6. Hayvanat bahçesi MCP sunucusunu oluşturma
MCP ile LLM kullanımını iyileştirmek için değerli bağlam sağlamak üzere FastMCP ile bir zoo MCP sunucusu oluşturun. FastMCP, Model Context Protocol ile çalışmak için kullanılan standart bir çerçevedir. FastMCP, Python ile MCP sunucuları ve istemcileri oluşturmak için hızlı bir yöntem sunar. Bu MCP sunucusu, kurgusal bir hayvanat bahçesindeki hayvanlar hakkında veri sağlar. Verileri basitlik için bellekte saklarız. Üretim MCP sunucusu için verileri veritabanları veya API'ler gibi kaynaklardan sağlamak isteyebilirsiniz.
pyproject.toml
dosyasına bağımlılık olarak FastMCP'yi eklemek için aşağıdaki komutu çalıştırın: Bu işlem, projenize biruv add fastmcp==2.11.1 --no-sync
uv.lock
dosyası ekler.- MCP sunucusu kaynak kodu için yeni bir
server.py
dosyası oluşturup açın:cloudshell edit server.py
cloudshell edit
komutu,server.py
dosyasını terminalin üzerindeki düzenleyicide açar. server.py
dosyasına aşağıdaki hayvanat bahçesi MCP sunucusu kaynak kodunu ekleyin:import asyncio import logging import os from typing import List, Dict, Any from fastmcp import FastMCP logger = logging.getLogger(__name__) logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO) mcp = FastMCP("Zoo Animal MCP Server 🦁🐧🐻") # Dictionary of animals at the zoo ZOO_ANIMALS = [ { "species": "lion", "name": "Leo", "age": 7, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "Nala", "age": 6, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "Simba", "age": 3, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "King", "age": 8, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "penguin", "name": "Waddles", "age": 2, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Pip", "age": 4, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Skipper", "age": 5, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Chilly", "age": 3, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Pingu", "age": 6, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Noot", "age": 1, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "elephant", "name": "Ellie", "age": 15, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Peanut", "age": 12, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Dumbo", "age": 5, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Trunkers", "age": 10, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "bear", "name": "Smokey", "age": 10, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Grizzly", "age": 8, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Barnaby", "age": 6, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Bruin", "age": 12, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "giraffe", "name": "Gerald", "age": 4, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Longneck", "age": 5, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Patches", "age": 3, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Stretch", "age": 6, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Speedy", "age": 2, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Dash", "age": 3, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Gazelle", "age": 4, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Swift", "age": 5, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "polar bear", "name": "Snowflake", "age": 7, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "polar bear", "name": "Blizzard", "age": 5, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "polar bear", "name": "Iceberg", "age": 9, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "walrus", "name": "Wally", "age": 10, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Tusker", "age": 12, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Moby", "age": 8, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Flippers", "age": 9, "enclosure": "The Walrus Cove", "trail": "Polar Path" } ] @mcp.tool() def get_animals_by_species(species: str) -> List[Dict[str, Any]]: """ Retrieves all animals of a specific species from the zoo. Can also be used to collect the base data for aggregate queries of animals of a specific species - like counting the number of penguins or finding the oldest lion. Args: species: The species of the animal (e.g., 'lion', 'penguin'). Returns: A list of dictionaries, where each dictionary represents an animal and contains details like name, age, enclosure, and trail. """ logger.info(f">>> 🛠️ Tool: 'get_animals_by_species' called for '{species}'") return [animal for animal in ZOO_ANIMALS if animal["species"].lower() == species.lower()] @mcp.tool() def get_animal_details(name: str) -> Dict[str, Any]: """ Retrieves the details of a specific animal by its name. Args: name: The name of the animal. Returns: A dictionary with the animal's details (species, name, age, enclosure, trail) or an empty dictionary if the animal is not found. """ logger.info(f">>> 🛠️ Tool: 'get_animal_details' called for '{name}'") for animal in ZOO_ANIMALS: if animal["name"].lower() == name.lower(): return animal return {} if __name__ == "__main__": logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}") asyncio.run( mcp.run_async( transport="http", host="0.0.0.0", port=os.getenv("PORT", 8080), ) )
Kodunuz tamamlandı. MCP sunucusunu Cloud Run'a dağıtma zamanı geldi.
7. Cloud Run'a dağıtma
Şimdi doğrudan kaynak kodundan Cloud Run'a bir MCP sunucusu dağıtın.
- Cloud Run'a dağıtmak için yeni bir
Dockerfile
oluşturup açın:cloudshell edit Dockerfile
server.py
dosyasını çalıştırmak içinuv
aracını kullanmak üzere Dockerfile'a aşağıdaki kodu ekleyin:# Use the official Python image FROM python:3.13-slim # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Install the project into /app COPY . /app WORKDIR /app # Allow statements and log messages to immediately appear in the logs ENV PYTHONUNBUFFERED=1 # Install dependencies RUN uv sync EXPOSE $PORT # Run the FastMCP server CMD ["uv", "run", "server.py"]
- Uygulamayı Cloud Run'a dağıtmak için
gcloud
komutunu çalıştırın. Kimlik doğrulama gerektirmek içingcloud run deploy zoo-mcp-server \ --no-allow-unauthenticated \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp
--no-allow-unauthenticated
işaretini kullanın. Bu işlem, güvenlik nedeniyle önemlidir. Kimlik doğrulama gerektirmiyorsanız herkes MCP sunucunuzu arayabilir ve sisteminizde hasara neden olabilir. - Yeni bir Artifact Registry deposunun oluşturulduğunu onaylayın. Kaynak koddan Cloud Run'a ilk kez dağıtım yaptığınız için şunları görürsünüz:
Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [europe-west1] will be created. Do you want to continue (Y/n)?
Y
yazıpEnter
tuşuna basın. Bu işlem, dağıtımınız için bir Artifact Registry deposu oluşturur. Bu, Cloud Run hizmeti için MCP sunucusu Docker kapsayıcısının depolanması için gereklidir. - Birkaç dakika sonra şuna benzer bir mesaj görürsünüz:
Service [zoo-mcp-server] revision [zoo-mcp-server-12345-abc] has been deployed and is serving 100 percent of traffic.
MCP sunucunuzu dağıtmış olmanız gerekir. Artık kullanabilirsiniz.
8. Uzak MCP sunucusunu Gemini CLI'ya ekleme
Uzak bir MCP sunucusunu başarıyla dağıttığınıza göre artık Google Code Assist veya Gemini CLI gibi çeşitli uygulamaları kullanarak bu sunucuya bağlanabilirsiniz. Bu bölümde, Gemini CLI'yı kullanarak yeni uzak MCP sunucunuza bağlantı oluşturacağız.
- Kullanıcı hesabınıza, uzaktaki MCP sunucusunu çağırma izni verme
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member=user:$(gcloud config get-value account) \ --role='roles/run.invoker'
- Google Cloud kimlik bilgilerinizi ve proje numaranızı, Gemini Ayarları dosyasında kullanmak üzere ortam değişkenlerine kaydedin:
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token)
- Gemini CLI ayarlar dosyanızı açın.
cloudshell edit ~/.gemini/settings.json
- Cloud Run MCP sunucusunu eklemek için Gemini CLI ayarları dosyanızı değiştirme
{ "mcpServers": { "zoo-remote": { "httpUrl": "https://zoo-mcp-server-$PROJECT_NUMBER.europe-west1.run.app/mcp/", "headers": { "Authorization": "Bearer $ID_TOKEN" } } }, "selectedAuthType": "cloud-shell", "hasSeenIdeIntegrationNudge": true }
- Cloud Shell'de Gemini CLI'yı başlatma
Bazı varsayılan ayarları kabul etmek içingemini
Enter
tuşuna basmanız gerekebilir. - Gemini'ın, bağlamı dahilinde kullanabileceği MCP araçlarını listelemesini sağlama
/mcp
- Gemini'dan hayvanat bahçesinde bir şey bulmasını isteme
Gemini CLI,Where can I find penguins?
zoo-remote
MCP sunucusunu kullanması gerektiğini bilir ve MCP'nin yürütülmesine izin vermek isteyip istemediğinizi sorar. - Aşağı ok tuşunu kullanın, ardından seçmek için
Enter
tuşuna basın.Yes, always allow all tools from server "zoo-remote"
Çıktıda doğru yanıt ve MCP sunucusunun kullanıldığını gösteren bir görüntüleme kutusu yer almalıdır.
Başardınız. Cloud Run'a uzaktan MCP sunucusu dağıtma ve Gemini CLI kullanarak bu sunucuyu test etme işlemlerini başarıyla tamamladınız.
Oturumunuzu sonlandırmaya hazır olduğunuzda /quit
yazıp Enter
tuşuna basarak Gemini CLI'dan çıkın.
Hata ayıklama
Şuna benzer bir hata görürseniz:
🔍 Attempting OAuth discovery for 'zoo-remote'... ❌ 'zoo-remote' requires authentication but no OAuth configuration found Error connecting to MCP server 'zoo-remote': MCP server 'zoo-remote' requires authentication. Please configure OAuth or check server settings.
Kimlik jetonunun zaman aşımına uğramış olması ve ID_TOKEN
ayarının tekrar yapılması gerekiyor olabilir.
/quit
yazıpEnter
tuşuna basarak Gemini CLI'dan çıkın.- Terminalinizde projenizi ayarlama
gcloud config set project [PROJECT_ID]
- Yukarıdaki 2. adımdan yeniden başlatın.
9. (İsteğe bağlı) Sunucu günlüklerinde araç çağrılarını doğrulama
Cloud Run MCP sunucunuzun çağrıldığını doğrulamak için hizmet günlüklerini kontrol edin.
gcloud run services logs read zoo-mcp-server --region europe-west1 --limit=5
Bir araç çağrısı yapıldığını onaylayan bir çıkış günlüğü görmeniz gerekir. 🛠️
2025-08-05 19:50:31 INFO: 169.254.169.126:39444 - "POST /mcp/ HTTP/1.1" 200 OK 2025-08-05 19:50:31 [INFO]: Processing request of type CallToolRequest 2025-08-05 19:50:31 [INFO]: >>> 🛠️ Tool: 'get_animals_by_species' called for 'penguin'
10. (İsteğe bağlı) Sunucuya MCP istemi ekleme
Bir MCP istemi, uzun bir istem için kısa bir sürüm oluşturarak sık kullandığınız istemlerde iş akışınızı hızlandırabilir.
Gemini CLI, MCP istemlerini otomatik olarak özel eğik çizgi komutlarına dönüştürür. Böylece, /prompt_name
yazarak bir MCP istemi çağırabilirsiniz. Burada prompt_name
, MCP isteminizin adıdır.
Gemini CLI'ya /find animal
yazarak hayvanat bahçesindeki bir hayvanı hızlıca bulabilmek için MCP istemi oluşturun.
- Bu kodu,
server.py
dosyanızda ana korumanın (if __name__ == "__main__":
) üstüne ekleyin.@mcp.prompt() def find(animal: str) -> str: """ Find which exhibit and trail a specific animal might be located. """ return ( f"Please find the exhibit and trail information for {animal} in the zoo. " f"Respond with '[animal] can be found in the [exhibit] on the [trail].'" f"Example: Penguins can be found in The Arctic Exhibit on the Polar Path." )
- Uygulamanızı Cloud Run'a yeniden dağıtma
gcloud run deploy zoo-mcp-server \ --no-allow-unauthenticated \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp
- Uzak MCP sunucunuz için ID_TOKEN'ınızı yenileyin
export ID_TOKEN=$(gcloud auth print-identity-token)
- Uygulamanızın yeni sürümü dağıtıldıktan sonra Gemini CLI'yı başlatın.
gemini
- İstemde, oluşturduğunuz yeni özel komutu kullanın:
/find --animal="lions"
Gemini CLI'nın get_animals_by_species
aracını çağırdığını ve yanıtı MCP isteminde belirtildiği şekilde biçimlendirdiğini görmelisiniz.
╭───────────────────────────╮ │ > /find --animal="lion" │ ╰───────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✔ get_animals_by_species (zoo-remote MCP Server) get_animals_by_species (zoo-remote MCP Server) │ │ │ │ [{"species":"lion","name":"Leo","age":7,"enclosure":"The Big Cat │ │ Plains","trail":"Savannah │ │ Heights"},{"species":"lion","name":"Nala","age":6,"enclosure":"The Big Cat │ │ Plains","trail":"Savannah │ │ Heights"},{"species":"lion","name":"Simba","age":3,"enclosure":"The Big Cat │ │ Plains","trail":"Savannah │ │ Heights"},{"species":"lion","name":"King","age":8,"enclosure":"The Big Cat │ │ Plains","trail":"Savannah Heights"}] │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ Lions can be found in The Big Cat Plains on the Savannah Heights.
Kendinizi Test Edeceğiniz Ek Hedefler
Ek bir zorluk için, hayvanat bahçesindeki belirli hayvan türleri hakkında eğlenceli bilgiler döndüren bir istem oluşturmak üzere aynı adımları uygulayıp uygulayamayacağınızı görün.
Öğrendiklerinizi test etmek için daha da ileri giderek sık kullanacağınız bir araç fikri geliştirin ve ikinci bir uzak MCP sunucusu dağıtın. Ardından, çalışıp çalışmadığını görmek için Gemini KSA ayarlarınıza ekleyin.
11. Sonuç
Tebrikler! Güvenli bir uzak MCP sunucusunu başarıyla dağıtıp bağladınız.
Sonraki laboratuvara geçin.
Bu laboratuvar, üç bölümlük bir serinin ilk laboratuvarıdır. İkinci laboratuvarda, ADK aracısı ile oluşturduğunuz MCP sunucusunu kullanacaksınız.
ADK aracısıyla Cloud Run'da MCP sunucusu kullanma
(İsteğe bağlı) Temizleme
Bir sonraki laboratuvara devam etmeyecekseniz ve oluşturduğunuz öğeleri temizlemek istiyorsanız ek ücret ödememek için Cloud projenizi silebilirsiniz.
Cloud Run, hizmet kullanılmadığında ücret almaz ancak container görüntüsünü Artifact Registry'de depoladığınız için ücretlendirilebilirsiniz. Cloud projenizi sildiğinizde, bu projede kullanılan tüm kaynaklar için faturalandırma durdurulur.
İsterseniz projeyi silebilirsiniz:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Ayrıca gereksiz kaynakları cloudshell diskinizden de silebilirsiniz. Şunları yapabilirsiniz:
- Codelab proje dizinini silin:
rm -rf ~/mcp-on-cloudrun
- Uyarı! Bu işlem geri alınamaz. Yer açmak için Cloud Shell'inizdeki her şeyi silmek istiyorsanız tüm ana dizininizi silebilirsiniz. Saklamak istediğiniz her şeyin başka bir yere kaydedildiğinden emin olun.
sudo rm -rf $HOME