1. Pengantar
Dalam codelab ini, Anda akan mempelajari cara menggunakan Google Cloud Agent Registry dan Agent Development Kit (ADK) untuk menemukan dan memanggil server Model Context Protocol (MCP) terdaftar secara dinamis saat runtime, sehingga menghilangkan endpoint dan konfigurasi alat yang di-hardcode.
Lab ini menggunakan ADK dan bahasa pemrograman Python untuk membangun aplikasi. Prinsip yang sama dapat diterapkan dalam bahasa pemrograman lain dan menggunakan framework pengembangan agen lainnya.
Yang akan Anda lakukan
- Mengaktifkan dan mengonfigurasi Google Cloud Agent Registry di project Anda
- Men-deploy server MCP ke Cloud Run dan mendaftarkannya di Agent Registry
- Membangun agen ADK yang memanggil server MCP menggunakan URL hardcode
- Mengubah agen untuk menemukan server MCP di Agent Registry berdasarkan identitasnya
- Mengubah agen untuk menemukan server MCP saat runtime menggunakan penelusuran semantik
Yang Anda butuhkan
- Browser web modern (seperti Chrome)
- Project Google Cloud yang mengaktifkan penagihan
- Akun dengan izin untuk membuat dan mengelola resource serta mengonfigurasi kebijakan IAM di project Google Cloud
2. Menyiapkan lingkungan Anda
Petunjuk dalam codelab ini mengasumsikan bahwa Anda menjalankan perintah di Cloud Shell di Konsol Google Cloud. Cloud Shell adalah lingkungan command line yang berjalan di Google Cloud yang telah dilengkapi dengan alat yang diperlukan. Jika Anda telah menginstal gcloud CLI, git, dan Python 3 di lingkungan lokal, Anda juga dapat menjalankan perintah di sana.
Membuat Project Google Cloud
- Di Konsol Google Cloud, pada halaman pemilih project, buat project Google Cloud.
- Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.
Memulai terminal Cloud Shell
- Dengan menggunakan pemilih resource, pilih project Google Cloud yang Anda buat.
- Klik Activate Cloud Shell
di bagian atas Konsol Google Cloud.
- Setelah terhubung ke Cloud Shell, verifikasi autentikasi Anda:
gcloud auth list - Konfirmasi bahwa project Anda telah dikonfigurasi:
gcloud config get project - Jika project Anda tidak ditetapkan seperti yang diharapkan atau jika Anda menggunakan lingkungan di komputer lokal, bukan Cloud Shell, siapkan project ID:
export GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID> gcloud config set project "${GOOGLE_CLOUD_PROJECT}"
Memilih project Google Cloud dan menetapkan variabel lingkungan
- Aktifkan Google Cloud API yang diperlukan:
gcloud services enable \ agentregistry.googleapis.com \ aiplatform.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com \ --project="${GOOGLE_CLOUD_PROJECT}"
Menyiapkan lingkungan Python
- Buat dan aktifkan lingkungan virtual, lalu instal dependensi yang diperlukan:
mkdir -p adk-dynamic-discovery && cd adk-dynamic-discovery python3 -m venv .venv source .venv/bin/activate pip install "fastmcp<5.0.0" "google-adk[mcp,a2a,agent-identity]>=2.5.0,<3.0.0"
3. Membuat dan mendaftarkan server MCP Zoo
Pada langkah ini, Anda akan membuat dan mendaftarkan server MCP Zoo. Server ini mengekspos tiga alat: list_species ‒ mencantumkan semua spesies yang hidup di kebun binatang, get_animals_by_species ‒ mencantumkan hewan dari spesies tertentu, dan get_animal_details ‒ mendapatkan informasi tambahan tentang hewan tertentu.
Anda dapat menemukan semua file untuk langkah ini di GitHub.
Membuat server MCP
- Menyiapkan folder dan project Python untuk server MCP
mkdir mcp-on-cloudrun && cd mcp-on-cloudrun uv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13 uv add "fastmcp<5.0.0" --no-sync - Download kode server MCP:
curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step3/server.py -o server.py
Men-deploy server MCP ke Cloud Run dan mendaftarkannya di Agent Registry
Selanjutnya, Anda akan membuat Dockerfile untuk server dan men-deploy server ke Cloud Run.
- Buat
Dockerfile:cat << EOF > Dockerfile # 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 # Run the FastMCP server CMD ["uv", "run", "server.py"] EOF - Buat akun layanan yang ditetapkan untuk server:
gcloud iam service-accounts create zoo-mcp-server-sa \ --display-name="Zoo MCP Server Service Account" - Deploy server ke region
us-west1. Jika Anda melihat perintah berikut, konfirmasi pembuatan repositori Artifact Registry baru. Dialog ini akan ditampilkan jika Anda tidak memiliki repositori Artifact Registry di project untuk regiongcloud run deploy zoo-mcp-server \ --service-account=zoo-mcp-server-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --region=us-west1 \ --source=. \ --labels=dev-tutorial=codelab-dynamic-mcp-discovery \ --invoker-iam-check \ --no-allow-unauthenticatedus-west1:Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-west1] will be created. Do you want to continue (Y/n)? - Daftarkan server MCP di Agent Registry di lokasi "global":
Perintah ini menghasilkanfastmcp inspect server.py --format mcp | jq 'del(..|nulls) | del(.tools[]?._meta?)' > toolspec.json MCP_URL=$(gcloud run services describe zoo-mcp-server --region=us-west1 --format='value(status.url)') gcloud agent-registry services create zoo-mcp-server \ --display-name="zoo-mcp-server" \ --project="${GOOGLE_CLOUD_PROJECT}" \ --location=global \ --mcp-server-spec-type="tool-spec" \ --mcp-server-spec-content="toolspec.json" \ --interfaces="url=${MCP_URL}/mcp,protocolBinding=jsonrpc"toolspec.jsondengan manifes alat dan memanggil Agent Registry API untuk mendaftarkan server. - Pastikan agen muncul di registry:
Anda akan melihat output YAML dengan informasi server MCP seperti ini:gcloud agent-registry mcp-servers list \ --location=global \ --filter="display_name=zoo-mcp-server"--- attributes: agentregistry.googleapis.com/system/RuntimeReference: uri: //agentregistry.googleapis.com/projects/[PROJECT_NUMBER]/locations/global/services/zoo-mcp-server createTime: '<create time datetime in ISO 8601>' displayName: zoo-mcp-server interfaces: - protocolBinding: JSONRPC url: https://zoo-mcp-server-[PROJECT_NUMBER].us-west1.run.app/mcp mcpServerId: urn:mcp:projects-[PROJECT_NUMBER]:projects:[PROJECT_NUMBER]:locations:global:agentregistry:services:zoo-mcp-server name: projects/[PROJECT_ID]/locations/global/mcpServers/agentregistry-00000000-0000-0000-1234-56789abcdef tools: - annotations: idempotentHint: true readOnlyHint: true description: |- Returns every species in the zoo. Use it first for zoo-wide questions such as counting all animals or listing everything the zoo has. name: list_species - annotations: idempotentHint: true readOnlyHint: true description: |- 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. name: get_animals_by_species - annotations: idempotentHint: true readOnlyHint: true description: Retrieves the details of a specific animal by its name. name: get_animal_details updateTime: '<last updated datetime in ISO 8601>'
4. Membuat agen ADK dasar untuk menggunakan server MCP Zoo
Pada langkah ini, Anda akan membuat agen ADK untuk menjawab permintaan pengguna tentang kebun binatang dengan bantuan URL server MCP Kebun Binatang yang di-hardcode. Hardcode mengharuskan Anda mengetahui URL server MCP SEBELUM agen di-deploy.
Anda dapat menemukan file sumber untuk langkah ini di GitHub.
Membuat aplikasi agen
Membuat scaffold project ADK dan agen Zoo yang menggunakan server MCP Zoo.
- Siapkan folder dan project untuk agen Zoo:
mkdir ../sample-agent && cd ../sample-agent uv init --description "Example of ADK agent to showcase dynamic MCP discovery" --bare --python 3.13 uv add "google-adk[mcp,a2a,agent-identity]>=2.5.0,<3.0.0" --no-sync - Buat folder paket agen dan download file
__init__.py:mkdir zoo_agent curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step4/zoo_agent/__init__.py -o zoo_agent/__init__.py - Buat file
.envdan isi dengan variabel lingkungan yang digunakan dalam langkah ini dan langkah-langkah berikut: Perintah ini menulis semua variabel lingkungan yang diperlukan di seluruh langkah ini dan langkah penemuan berikutnya ke dalamMCP_URL=$(gcloud run services describe zoo-mcp-server --region=us-west1 --format='value(status.url)') cat << EOF > zoo_agent/.env GOOGLE_GENAI_USE_ENTERPRISE=TRUE GOOGLE_CLOUD_LOCATION=global GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT}" GOOGLE_CLOUD_PROJECT_NUMBER=$(gcloud projects describe ${GOOGLE_CLOUD_PROJECT} \ --format='value(projectNumber)') MCP_SERVER_URL="${MCP_URL}" EOFzoo_agent/.env, sehingga Anda tidak perlu membuat ulang file nanti. Pada langkah ini, variabel berikut digunakan:GOOGLE_GENAI_USE_ENTERPRISE,GOOGLE_CLOUD_PROJECT, danGOOGLE_CLOUD_LOCATION: Digunakan secara implisit oleh ADK dan Google GenAI SDK untuk merutekan panggilan model Gemini melalui Vertex AI di project dan lokasi Google Cloud Anda (global). Variabel ini juga menyimpan lokasi untuk Agent Registry tempat server MCP didaftarkan.GOOGLE_CLOUD_PROJECT_NUMBER: Tidak digunakan dalam langkah ini; nilai ini diisi otomatis di sini untuk digunakan di langkah berikutnya.MCP_SERVER_URL: Baca langsung dizoo_agent/agent.pyuntuk mengonfigurasiMcpToolsetdengan URL Cloud Run hardcode dari server MCP Kebun Binatang.
- Download
agent.pydengan kode untuk agen Zoo yang terhubung ke server MCP Zoo:curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step4/zoo_agent/agent.py -o zoo_agent/agent.py
Cara kerja otorisasi server MCP
Karena layanan Cloud Run zoo-mcp-server di-deploy dengan flag --invoker-iam-check dan --no-allow-unauthenticated, setiap permintaan HTTP ke server MCP harus menyertakan token ID yang ditandatangani Google di header Authorization. Token harus mengidentifikasi pemanggil yang memiliki izin run.routes.invoke pada layanan.
Di zoo_agent/agent.py, class _GoogleAuthHeaders mendapatkan kredensial token ID dengan salah satu dari dua cara. Pertama, fungsi ini memanggil fetch_id_token_credentials() untuk mendapatkan token ID untuk URL layanan dari server metadata atau kunci akun layanan. Jika gagal, perintah ini akan menggunakan token ID Kredensial Default Aplikasi (ADC) pengguna Anda. Setiap kali dipanggil, instance akan memperbarui token jika diperlukan dan menampilkan header Authorization:
class _GoogleAuthHeaders:
def __init__(self, audience: str):
self._request = Request()
self._id_token = False
try:
self._credentials = id_token.fetch_id_token_credentials(audience, request=self._request)
except exceptions.DefaultCredentialsError:
self._credentials, _ = google.auth.default()
self._id_token = True
if not isinstance(self._credentials, credentials.Credentials):
raise
def __call__(self, unused_context: ReadonlyContext | None = None) -> dict[str, str]:
if not self._credentials.valid or (self._id_token and not self._credentials.id_token):
self._credentials.refresh(self._request)
token = self._credentials.id_token if self._id_token else self._credentials.token
return {"Authorization": f"Bearer {token}"}
Agen meneruskan instance class ke McpToolset sebagai argumen header_provider. ADK memanggil penyedia header dan melampirkan header yang ditampilkan ke setiap permintaan ke server MCP. Karena klien HTTP dibuat oleh ADK, kode yang sama akan berfungsi, terlepas dari versi MCP Python SDK dan library HTTP-nya yang diinstal:
zoo_mcp_toolset = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=f"{MCP_SERVER_URL}/mcp",
timeout=30.0,
),
header_provider=_GoogleAuthHeaders(MCP_SERVER_URL),
)
Audiens yang diminta adalah URL layanan (MCP_SERVER_URL), sedangkan URL koneksi menyertakan jalur /mcp tempat server FastMCP menyajikan protokol MCP. Waktu tunggu 30 detik memberikan ruang untuk cold start Cloud Run.
Menguji agen menggunakan playground ADK di lingkungan lokal Anda
Sebelum menguji agen, pastikan akun pengguna Anda dapat memanggil server MCP.
- Khusus terminal lokal (lewati langkah ini di Cloud Shell): lakukan inisialisasi ADC dengan kredensial pengguna Anda:
Ikuti petunjuk untuk menyelesaikan inisialisasi ADC.gcloud auth application-default login - (Opsional) Berikan izin kepada akun pengguna Anda untuk memanggil server MCP jarak jauh:
gcloud run services add-iam-policy-binding zoo-mcp-server \ --region=us-west1 \ --project=${GOOGLE_CLOUD_PROJECT} \ --member=user:$(gcloud config get-value account) \ --role='roles/run.invoker' - Jalankan agen Anda dengan perintah
adk run: atau jalankan antarmuka Web ADK dengan perintahadk run zoo_agentadk web: lalu buka URL yang dicetak oleh perintah di browser.Jika Anda menggunakan Cloud Shell, tambahkan argumenadk web --port 8080--allow_originsuntuk mengizinkan pembukaan antarmuka Web dari Cloud Shell: Setelah menjalankan perintah, temukan ikon Web Previewadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
di toolbar Cloud Shell (sisi kanan). Klik ikon tersebut dan pilih Preview on port 8080. Cloud Shell akan membuka tab browser baru yang menampilkan antarmuka Web ADK. - Mulai chat dengan agen. Misalnya, tanyakan tentang hewan di kebun binatang:
Agen memanggilHow many animals are in the zoo?list_species, laluget_animals_by_speciesuntuk setiap spesies guna menghitung jawaban.
Antarmuka Web ADK memungkinkan Anda mempelajari cara kerja agen, termasuk panggilannya ke server MCP Kebun Binatang. Lihat dokumentasi UI Web untuk mempelajari caranya.
5. Menemukan endpoint server MCP secara dinamis
Pada langkah ini, Anda akan mengubah agen untuk menemukan endpoint server MCP Zoo yang terdaftar di Agent Registry, bukan melakukan hardcode pada URL endpoint-nya.
Anda dapat menemukan semua file untuk langkah ini di GitHub.
Anda menggunakan integrasi ADK dengan Agent Registry untuk menemukan dan mengambil URL server. Untuk menerapkannya, Anda memerlukan informasi berikut:
- Nomor project dan lokasi Agent Registry tempat server MCP Anda terdaftar (
global). - ID layanan yang Anda gunakan untuk mendaftarkan server MCP (
zoo-mcp-server).
Mengupdate agen untuk menggunakan Agent Registry
- Download file
agent.pyyang telah diupdate dari GitHub untuk mengganti versi pertama agen:curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step5/zoo_agent/agent.py -o zoo_agent/agent.pyVariabel lingkungan dalam langkah ini
Dengan update ini, agen mengandalkan variabel lingkungan berikut darizoo_agent/.env:GOOGLE_CLOUD_PROJECT_NUMBER: Sekarang diperlukan untuk membuat URN identitas server MCP (MCP_SERVER_URN).GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISE, danGOOGLE_CLOUD_LOCATION: Digunakan oleh ADK untuk mengonfigurasi akses Vertex AI. Lokasi juga digunakan untuk menemukan server MCP.- Tidak diperlukan lagi:
MCP_SERVER_URLtidak lagi digunakan karena agen mengambil URL endpoint server MCP dari Agent Registry, bukan membacanya dari lingkungan.
Cara kerja identitas dan penemuan server MCP di
Di Agent Registry, setiap server MCP yang terdaftar memiliki ID unik yang disimpan di kolomAgentRegistrymcpServerId, yang diformat sebagai Uniform Resource Name (URN). Anda dapat melihatnya di output perintahgcloud agent-registry mcp-servers listdi Langkah 3. Agen merekonstruksi ID ini dari variabel lingkungan: URN mengenkode nomor project registry (PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"] PROJECT_NUMBER = os.environ["GOOGLE_CLOUD_PROJECT_NUMBER"] LOCATION = os.environ.get("GOOGLE_CLOUD_LOCATION", "global") MCP_SERVER_URN = f"urn:mcp:projects-{PROJECT_NUMBER}:projects:{PROJECT_NUMBER}:locations:{LOCATION}:agentregistry:services:zoo-mcp-server"projects-{PROJECT_NUMBER}), nomor project dan lokasi tempat server didaftarkan (projects:{PROJECT_NUMBER}:locations:{LOCATION}), serta ID layanan yang Anda gunakan dalam perintahgcloud agent-registry services create(agentregistry:services:zoo-mcp-server).Agen mencantumkan server MCP yang terdaftar denganregistry.list_mcp_servers()dan mencocokkanmcpServerIdsetiap server denganMCP_SERVER_URN. Kemudian, class ini meneruskan resource server yang cocokname(projects/.../locations/.../mcpServers/...) keregistry.get_mcp_toolset(), yang membaca URL endpoint dari antarmuka terdaftar server (https://...run.app/mcp) dan menampilkanMcpToolsetyang terhubung ke URL tersebut:header_provider = _GoogleAuthHeaders() registry = AgentRegistry( project_id=PROJECT_ID, location=LOCATION, header_provider=header_provider, ) mcp_server_name = next( ( s["name"] for s in registry.list_mcp_servers().get("mcpServers", []) if s.get("mcpServerId") == MCP_SERVER_URN ), None, ) if not mcp_server_name: raise RuntimeError(f"MCP server '{MCP_SERVER_URN}' not found in Agent Registry.") zoo_mcp_toolset = registry.get_mcp_toolset(mcp_server_name=mcp_server_name) header_provider.bind(zoo_mcp_toolset.connection_params.url) zoo_mcp_toolset.connection_params.timeout = 30.0get_mcp_toolset()menambahkan nama tampilan server di awal nama alat, sehingga agen melihat alat sebagaizoo_mcp_server_list_species,zoo_mcp_server_get_animals_by_species, danzoo_mcp_server_get_animal_details. Awalan ini mencegah konflik nama saat agen menggunakan alat dari beberapa server MCP. Baris terakhir meningkatkan waktu tunggu koneksi dari defaultnya, yaitu 5 detik, untuk memberikan ruang bagi cold start Cloud Run.Cara perubahan otorisasi dengan
AgentRegistryAgentRegistrymengautentikasi panggilan API-nya sendiri, sepertilist_mcp_servers(), dengan ADC, sehingga penyedia header hanya diperlukan untuk panggilan ke server MCP yang ditemukan. KarenaAgentRegistrymembuatMcpToolsetsecara internal, Anda meneruskan penyedia header ke konstruktorAgentRegistry.Pada langkah sebelumnya, audiens adalah nilaiMCP_SERVER_URLyang Anda ketahui sebelumnya. Sekarang URL hanya diketahui setelah penemuan. ADK memanggil penyedia header saat agen mengirimkan permintaan ke server MCP, bukan saatAgentRegistrydibuat. Hal ini memungkinkan agen membuat penyedia terlebih dahulu dan mengikatnya ke endpoint yang ditemukan setelahget_mcp_toolset()ditampilkan. Metodebind()mendapatkan kredensial dengan cara yang sama seperti konstruktor pada langkah sebelumnya, dengan audiens yang diambil dari URL endpoint yang ditemukan tanpa jalur/mcp: Metodedef bind(self, endpoint_url: str) -> None: parsed = urlparse(endpoint_url) audience = f"{parsed.scheme}://{parsed.netloc}" try: self._credentials = id_token.fetch_id_token_credentials(audience, request=self._request) except exceptions.DefaultCredentialsError: self._credentials, _ = google.auth.default() self._id_token = True if not isinstance(self._credentials, credentials.Credentials): raise__call__sama seperti pada langkah sebelumnya, tetapi akan memunculkan error jika dipanggil sebelumbind(). - Jalankan agen Anda untuk menguji perubahan. Gunakan perintah
adk run: atau jalankan antarmuka Web ADK dengan perintahadk run zoo_agentadk web: lalu buka URL yang dicetak oleh perintah di browser.Jika Anda menggunakan Cloud Shell, tambahkan argumenadk web --port 8080--allow_originsuntuk mengizinkan pembukaan antarmuka Web dari Cloud Shell: Ajukan pertanyaan yang sama kepada agen seperti pada langkah sebelumnya. Jawabannya sama, tetapi di antarmuka Web ADK, panggilan alat kini muncul sebagaiadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"zoo_mcp_server_list_speciesdanzoo_mcp_server_get_animals_by_species.
Perubahan ini memungkinkan Anda mengabaikan kebutuhan akan URL server MCP eksplisit. Namun, Anda tetap perlu mengetahui nomor project, lokasi registry, dan ID layanan yang digunakan untuk mendaftarkan server MCP, dan penemuan dilakukan secara statis selama inisialisasi agen.
6. Menggunakan penelusuran semantik untuk server MCP dalam penemuan dinamis
Pada langkah ini, Anda akan meningkatkan penemuan dinamis server MCP dengan mengganti pencocokan URN yang sama persis saat startup dengan penelusuran semantik runtime. Pendekatan ini menghilangkan kebutuhan untuk mengetahui nomor project tempat server di-deploy atau identitas persis server (MCP_SERVER_URN), dan mengintegrasikan penemuan alat langsung ke dalam alur kerja runtime standar agen, bukan menanganinya saat inisialisasi.
Anda dapat menemukan semua file untuk langkah ini di GitHub.
Mengupdate agen untuk menggunakan penemuan semantik saat runtime
- Download file
agent.pyyang telah diupdate dari GitHub untuk menimpa implementasi yang ada:curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step6/zoo_agent/agent.py -o zoo_agent/agent.pyVariabel lingkungan dalam langkah ini
Karena agen tidak lagi membuat URN server MCP, konfigurasi yang diperlukan menjadi lebih sederhana:GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISE, danGOOGLE_CLOUD_LOCATION: Digunakan oleh ADK untuk mengonfigurasi akses Vertex AI. Lokasi juga digunakan untuk menemukan server MCP.- Tidak diperlukan lagi:
GOOGLE_CLOUD_PROJECT_NUMBERtidak diperlukan lagi (selainMCP_SERVER_URL, yang telah dihapus pada langkah sebelumnya).
Beralih dari pencocokan persis ke penelusuran semantik
Alih-alih memanggilregistry.list_mcp_servers()selama inisialisasi modul dan membandingkan setiap entri denganMCP_SERVER_URNyang dibuat,agent.pykini menentukan fungsi alat penemuandiscover_zoo_mcp_serversyang memanggilregistry.search_mcp_servers()dengansearch_type="SEMANTIC": Dengan begitu, agen dapat menelusuri Agent Registry saat runtime menggunakan deskripsi bahasa alami tentang kemampuan yang diperlukan (misalnya,def discover_zoo_mcp_servers(query: str, tool_context: ToolContext) -> dict[str, Any]: """Discovers Zoo MCP server(s) matching the query using semantic search. Args: query: Semantic description of zoo capabilities needed (e.g. 'zoo animal info') """ cached = _fresh_discovery(tool_context.state) if cached: return { "status": "already_discovered", "message": "Zoo MCP servers are already discovered.", "servers": cached["servers"], } try: response = registry.search_mcp_servers( search_string=query, search_type="SEMANTIC", page_size=5, ) except Exception as e: return { "status": "error", "message": f"Agent Registry search failed: {e}", } found_servers = response.get("mcpServers", []) if not found_servers: return { "status": "not_found", "message": f"No MCP servers found in Agent Registry at {LOCATION} matching '{query}'.", } valid_servers = [s["name"] for s in found_servers if "name" in s] tool_context.state[DISCOVERY_STATE_KEY] = { "servers": valid_servers, "discovered_at": time.time(), } return { "status": "discovered", "message": f"Successfully discovered {len(valid_servers)} Zoo MCP server(s).", "servers": valid_servers, }"zoo animals, exhibits, habitat, care, feeding schedule") dan menyimpan nama resource server yang ditemukan dalam status sesi ADK (tool_context.state).Cara penemuan dinamis diintegrasikan ke dalam alur kerja agen
Untuk memasang alat dari server yang ditemukan saat runtime dan memandu agen melalui alur penemuan, lalu pemanggilan,agent.pymenggabungkan implementasiBaseToolsetkustom (RegistryDiscoveredToolset) dengan penyedia petunjuk dinamis (zoo_guide_instruction):- Set alat dinamis (
RegistryDiscoveredToolset): Membuat subclassBaseToolsetdan menetapkanself._use_invocation_cache = Falsesehingga ADK segera mengevaluasi ulang alat yang tersedia setelahdiscover_zoo_mcp_serversmemperbarui status sesi, bukan meng-cache daftar alat yang awalnya kosong. Saatget_tools()dipanggil, fungsi ini akan membaca nama server yang ditemukan dari status, membuatMcpToolsetyang diautentikasi untuk setiap server di thread pekerja, dan menampilkan semua alat yang aktif. Kegagalan menjangkau satu server tidak akan memengaruhi server lainnya._build_toolset()menjalankan I/O pemblokiran, sehingga_tools_of()menjalankannya di thread pekerja.class RegistryDiscoveredToolset(BaseToolset): def __init__(self, agent_registry: AgentRegistry): super().__init__() self._registry = agent_registry self._toolsets: dict[str, McpToolset] = {} self._use_invocation_cache = False def _build_toolset(self, server_name: str) -> McpToolset: header_provider = _GoogleAuthHeaders() server_registry = AgentRegistry( project_id=self._registry.project_id, location=self._registry.location, header_provider=header_provider, ) toolset = server_registry.get_mcp_toolset(server_name) header_provider.bind(toolset.connection_params.url) toolset.connection_params.timeout = 30.0 return toolset async def _tools_of(self, server_name: str, ctx: ReadonlyContext) -> list[BaseTool]: try: if server_name not in self._toolsets: self._toolsets[server_name] = await asyncio.to_thread( self._build_toolset, server_name ) return await self._toolsets[server_name].get_tools_with_prefix(ctx) except Exception as e: print(f"Skipping MCP server {server_name}: {e}") return [] async def get_tools(self, readonly_context: ReadonlyContext | None = None) -> list[BaseTool]: if not readonly_context: return [] record = _fresh_discovery(readonly_context.state) if not record or not record.get("servers"): if self._toolsets: await self.close() return [] per_server = await asyncio.gather( *(self._tools_of(name, readonly_context) for name in record["servers"]) ) return [tool for tools in per_server for tool in tools] - Petunjuk agen dinamis (
zoo_guide_instruction): Mengevaluasi status sesi sebelum setiap giliran model. Jika belum ada server yang ditemukan, server akan menambahkan_DISCOVERY_PROMPTyang menginstruksikan agen untuk memanggildiscover_zoo_mcp_serversterlebih dahulu. Setelah penemuan berhasil, agen akan memperbarui perintah untuk mencantumkan server MCP yang aktif dan menginstruksikan agen untuk menggunakan alat kebun binatang yang terpasang secara langsung tanpa menjalankan penemuan lagi:def zoo_guide_instruction(ctx: ReadonlyContext) -> str: record = _fresh_discovery(ctx.state) if record is None: return _ROLE + _DISCOVERY_PROMPT return _ROLE + ( f"\nYour active Zoo MCP servers: {', '.join(record['servers'])}. " "Do not run discovery again; use the active zoo tools directly to fulfill the visitor's request." )
Otorisasi untuk server yang ditemukan secara dinamis
Penelusuran semantik dapat menampilkan beberapa server, dan ADK memanggil penyedia header tanpa memberi tahu server mana yang akan menerima permintaan. Oleh karena itu,_build_toolset()membuat_GoogleAuthHeadersdanAgentRegistrykhusus untuk setiap server yang ditemukan dan mengikat penyedia ke endpoint server tersebut. Penyedianya sama seperti pada langkah sebelumnya, dengan flag_boundyang membuatnya gagal jika digunakan sebelumbind().Logika retensi dan refresh
Untuk menghindari kueri Agent Registry di setiap giliran sekaligus tetap memperbarui endpoint yang ditemukan secara berkala,agent.pymenerapkan retensi status dengan time-to-live (TTL):DISCOVERY_STATE_KEY = "app:zoo_mcp_servers" DISCOVERY_TTL_SECONDS = 24 * 60 * 60 def _fresh_discovery(state: Any) -> dict[str, Any] | None: if not state: return None record = state.get(DISCOVERY_STATE_KEY) if not record or not record.get("servers"): return None if time.time() - record.get("discovered_at", 0) > DISCOVERY_TTL_SECONDS: return None return record- Retensi cakupan aplikasi: Nama server yang ditemukan dan stempel waktu
discovered_atdisimpan dalam status sesi di bagian kunciapp:zoo_mcp_servers. Menggunakan awalanapp:ADK akan mencakup data penemuan yang di-cache di seluruh eksekusi aplikasi. - Validasi TTL dan pemuatan ulang otomatis:
_fresh_discovery()memverifikasi bahwa data yang disimpan ada dan usianya tidak melebihiDISCOVERY_TTL_SECONDS(24 jam). Meskipun data masih baru,RegistryDiscoveredToolsetakan menggunakan kembali koneksiMcpToolsetyang di-cache (self._toolsets),zoo_guide_instructionakan menghilangkan perintah penemuan, dan panggilan berulang kediscover_zoo_mcp_serversakan segera menampilkan"already_discovered". Setelah TTL 24 jam berakhir,_fresh_discovery()akan menampilkanNone, sehinggaRegistryDiscoveredToolset.get_tools()menutup sesi klien MCP yang ada (await self.close()) danzoo_guide_instructionmeminta agen untuk melakukan penemuan baru.
- Jalankan agen Anda untuk menguji alur kerja penemuan semantik. Gunakan perintah
adk run: atau jalankan antarmuka Web ADK dengan perintahadk run zoo_agentadk web: lalu buka URL yang dicetak oleh perintah di browser.Jika Anda menggunakan Cloud Shell, tambahkan argumenadk web --port 8080--allow_originsuntuk mengizinkan pembukaan antarmuka Web dari Cloud Shell: Saat Anda mengajukan pertanyaan kepada agen tentang kebun binatang (misalnya,adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"How many animals are in the zoo?), amati bahwa agen tersebut akan memanggildiscover_zoo_mcp_serversterlebih dahulu, memasang alat secara dinamis dari server MCP yang ditemukan, lalu memanggil alat kebun binatang, sepertizoo_mcp_server_list_speciesdanzoo_mcp_server_get_animals_by_species, untuk menjawab pertanyaan Anda.Ajukan pertanyaan lanjutan, misalnyaWhich is the oldest lion?. Agen menjawab menggunakan alat kebun binatang yang sudah terpasang dan tidak memanggildiscover_zoo_mcp_serverslagi, karena data penemuan dalam status sesi masih baru.
7. Pembersihan
Opsi 1: Menghapus project
Jika Anda membuat project khusus untuk codelab ini, cara termudah untuk menghilangkan penagihan adalah dengan menghapus project:
gcloud projects delete "${GOOGLE_CLOUD_PROJECT}" --quiet
Opsi 2: Menghapus resource satu per satu
Jika Anda menggunakan project yang sudah ada dan ingin menyimpannya, hapus setiap resource yang dibuat selama codelab ini:
- Hapus pendaftaran server MCP dari Agent Registry. Karena Anda mendaftarkan server secara manual, menghapus layanan Cloud Run tidak akan menghapus pendaftaran:
gcloud agent-registry services delete zoo-mcp-server \ --location=global \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Hapus layanan server MCP Cloud Run:
gcloud run services delete zoo-mcp-server \ --region=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Hapus akun layanan yang dibuat untuk server MCP:
gcloud iam service-accounts delete \ "zoo-mcp-server-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Jika repositori Artifact Registry
cloud-run-source-deploydibuat khusus selama codelab ini, hapus repositori tersebut untuk menghindari biaya penyimpanan image container:gcloud artifacts repositories delete cloud-run-source-deploy \ --location=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Atau, hapus direktori project lokal yang dibuat di Cloud Shell:
cd ~ && rm -rf adk-dynamic-discovery
8. Selamat
Dalam codelab ini, Anda telah mempelajari cara menemukan dan menggunakan server MCP secara dinamis dengan Google Cloud Agent Registry dan Agent Development Kit (ADK):
- Mendaftarkan server MCP: Men-deploy server MCP yang aman ke Cloud Run dan mendaftarkannya di Agent Registry.
- Menemukan server MCP berdasarkan identitas: Menyelesaikan endpoint server MCP dari Registry Agen, bukan melakukan hardcode pada URL-nya.
- Menemukan server MCP secara semantik: Memungkinkan agen menemukan dan memasang alat MCP saat runtime menggunakan penelusuran bahasa alami, dengan retensi dan pembaruan.