1. परिचय
इस कोडलैब में, आपको Google Cloud Agent Registry और एजेंट डेवलपमेंट किट (एडीके) का इस्तेमाल करने का तरीका पता चलेगा. इससे आपको रनटाइम के दौरान, रजिस्टर किए गए मॉडल कॉन्टेक्स्ट प्रोटोकॉल (एमसीपी) सर्वर को डाइनैमिक तौर पर खोजने और उन्हें शुरू करने में मदद मिलेगी. साथ ही, हार्डकोड किए गए एंडपॉइंट और टूल कॉन्फ़िगरेशन की ज़रूरत नहीं पड़ेगी.
इस लैब में, ऐप्लिकेशन बनाने के लिए एडीके और Python प्रोग्रामिंग लैंग्वेज का इस्तेमाल किया जाता है. इन सिद्धांतों को अन्य प्रोग्रामिंग भाषाओं और एजेंट डेवलपमेंट फ़्रेमवर्क में भी लागू किया जा सकता है.
आपको क्या करना होगा
- अपने प्रोजेक्ट में Google Cloud Agent Registry को चालू और कॉन्फ़िगर करना
- Cloud Run पर एमसीपी सर्वर डिप्लॉय करना और उसे एजेंट रजिस्ट्री में रजिस्टर करना
- हार्डकोड किए गए यूआरएल का इस्तेमाल करके, एमसीपी सर्वर को कॉल करने वाला ADK एजेंट बनाएं
- एजेंट को बदलें, ताकि एजेंट रजिस्ट्री में एमसीपी सर्वर को उसकी पहचान के हिसाब से खोजा जा सके
- एजेंट में बदलाव करें, ताकि वह सिमैंटिक सर्च का इस्तेमाल करके, रनटाइम के दौरान एमसीपी सर्वर खोज सके
आपको किन चीज़ों की ज़रूरत होगी
- एक मॉडर्न वेब ब्राउज़र (जैसे कि Chrome)
- बिलिंग की सुविधा वाला Google Cloud प्रोजेक्ट
- एक ऐसा खाता जिसके पास Google Cloud प्रोजेक्ट पर संसाधन बनाने और उन्हें मैनेज करने के साथ-साथ, आईएएम की नीतियां कॉन्फ़िगर करने की अनुमतियां हों
2. अपना एनवायरमेंट सेट अप करने का तरीका
इस कोडलैब में दिए गए निर्देशों के मुताबिक, Google Cloud Console में Cloud Shell में कमांड चलाए जाते हैं. Cloud Shell, Google Cloud में चलने वाला एक कमांड-लाइन एनवायरमेंट है. इसमें ज़रूरी टूल पहले से मौजूद होते हैं. अगर आपके लोकल एनवायरमेंट में gcloud सीएलआई, git, और Python 3 इंस्टॉल है, तो वहां भी कमांड चलाए जा सकते हैं.
Google Cloud प्रोजेक्ट बनाएं
- Google Cloud Console में, प्रोजेक्ट चुनने वाले पेज पर जाकर, Google Cloud प्रोजेक्ट बनाएं.
- पक्का करें कि आपके क्लाउड प्रोजेक्ट के लिए बिलिंग की सुविधा चालू हो. किसी प्रोजेक्ट के लिए बिलिंग की सुविधा चालू है या नहीं, यह देखने का तरीका जानें.
Cloud Shell टर्मिनल शुरू करना
- संसाधन पिकर का इस्तेमाल करके, वह Google Cloud प्रोजेक्ट चुनें जिसे आपने बनाया है.
- Google Cloud Console में सबसे ऊपर, Cloud Shell चालू करें
पर क्लिक करें.
- Cloud Shell से कनेक्ट होने के बाद, अपनी पुष्टि की जांच करें:
gcloud auth list - पुष्टि करें कि आपका प्रोजेक्ट कॉन्फ़िगर किया गया है:
gcloud config get project - अगर आपका प्रोजेक्ट उम्मीद के मुताबिक सेट नहीं है या Cloud Shell के बजाय अपनी लोकल मशीन पर किसी एनवायरमेंट का इस्तेमाल किया जा रहा है, तो प्रोजेक्ट आईडी सेट अप करें:
export GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID> gcloud config set project "${GOOGLE_CLOUD_PROJECT}"
कोई Google Cloud प्रोजेक्ट चुनना और एनवायरमेंट वैरिएबल सेट करना
- ज़रूरी Google Cloud API चालू करें:
gcloud services enable \ agentregistry.googleapis.com \ aiplatform.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com \ --project="${GOOGLE_CLOUD_PROJECT}"
Python एनवायरमेंट सेट अप करना
- वर्चुअल एनवायरमेंट बनाएं और उसे चालू करें. इसके बाद, ज़रूरी डिपेंडेंसी इंस्टॉल करें:
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. Zoo एमसीपी सर्वर बनाना और रजिस्टर करना
इस चरण में, Zoo MCP सर्वर को बनाया और रजिस्टर किया जाता है. सर्वर तीन टूल दिखाता है: list_species ‒ चिड़ियाघर में रहने वाली सभी प्रजातियों की सूची, get_animals_by_species ‒ किसी खास प्रजाति के जानवरों की सूची, और get_animal_details ‒ किसी खास जानवर के बारे में ज़्यादा जानकारी.
इस चरण के लिए, सभी फ़ाइलें GitHub पर देखी जा सकती हैं.
एमसीपी सर्वर बनाएं
- एमसीपी सर्वर के लिए, एक फ़ोल्डर और Python प्रोजेक्ट सेट अप करना
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 - एमसीपी सर्वर कोड डाउनलोड करें:
curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step3/server.py -o server.py
एमसीपी सर्वर को Cloud Run पर डिप्लॉय करना और एजेंट रजिस्ट्री में रजिस्टर करना
इसके बाद, आपको सर्वर के लिए Dockerfile बनाना होगा और सर्वर को Cloud Run पर डिप्लॉय करना होगा.
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- सर्वर के लिए, सेवा खाता बनाएं:
gcloud iam service-accounts create zoo-mcp-server-sa \ --display-name="Zoo MCP Server Service Account" - सर्वर को
us-west1क्षेत्र में डिप्लॉय करें. अगर आपको यह प्रॉम्प्ट दिखता है, तो Artifact Registry की नई रिपॉज़िटरी बनाने की पुष्टि करें. यह प्रॉम्प्ट तब दिखेगा, जब आपके प्रोजेक्ट मेंgcloud 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इलाके के लिए, Artifact Registry रिपॉज़िटरी मौजूद न हो: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)? - एमसीपी सर्वर को एजेंट रजिस्ट्री में "global" जगह पर रजिस्टर करें:
ये कमांड, टूल मेनिफ़ेस्ट के साथfastmcp 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.jsonजनरेट करते हैं. साथ ही, सर्वर को रजिस्टर करने के लिए, Agent Registry API को कॉल करते हैं. - पुष्टि करें कि एजेंट, रजिस्ट्री में दिख रहा है:
आपको एमसीपी सर्वर की जानकारी के साथ YAML आउटपुट दिखेगा. जैसे: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. Zoo MCP सर्वर का इस्तेमाल करने के लिए, एक बुनियादी ADK एजेंट बनाएं
इस चरण में, आपको एक ADK एजेंट बनाना होगा. यह एजेंट, हार्डकोड किए गए चिड़ियाघर के एमसीपी सर्वर यूआरएल की मदद से, चिड़ियाघर के बारे में उपयोगकर्ता के अनुरोधों का जवाब देगा. हार्डकोडेड तरीके में, एजेंट को डिप्लॉय करने से पहले आपको एमसीपी सर्वर का यूआरएल पता होना चाहिए.
इस चरण के लिए सोर्स फ़ाइलें, GitHub पर मिल सकती हैं.
एजेंट ऐप्लिकेशन बनाना
ADK प्रोजेक्ट और Zoo एजेंट का स्कैफ़ोल्ड बनाएं, जो Zoo एमसीपी सर्वर का इस्तेमाल करता है.
- 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 - एजेंट पैकेज फ़ोल्डर बनाएं और
__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 .envफ़ाइल बनाएं और उसमें इस चरण और इसके बाद के चरणों में इस्तेमाल किए जाने वाले एनवायरमेंट वैरिएबल भरें: यह कमांड, इस चरण और इसके बाद के चरणों में ज़रूरी सभी एनवायरमेंट वैरिएबल कोMCP_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में लिखता है. इससे आपको बाद में फ़ाइल को फिर से बनाने की ज़रूरत नहीं पड़ती. इस चरण में, इन वैरिएबल का इस्तेमाल किया जाता है:GOOGLE_GENAI_USE_ENTERPRISE,GOOGLE_CLOUD_PROJECT, औरGOOGLE_CLOUD_LOCATION: इनका इस्तेमाल, एडीके और Google GenAI SDK अपने-आप करते हैं. इससे आपके Google Cloud प्रोजेक्ट और जगह (global) में, Vertex AI के ज़रिए Gemini मॉडल के कॉल को रूट किया जाता है. यह एजेंट रजिस्ट्री के लिए जगह की जानकारी भी सेव करता है, जहां एमसीपी सर्वर रजिस्टर किया गया है.GOOGLE_CLOUD_PROJECT_NUMBER: इस चरण में इसका इस्तेमाल नहीं किया जाता. अगले चरण में इस्तेमाल करने के लिए, यहां इसकी जानकारी पहले से भरी होती है.MCP_SERVER_URL: Zoo एमसीपी सर्वर के हार्डकोड किए गए Cloud Run यूआरएल के साथMcpToolsetको कॉन्फ़िगर करने के लिए, सीधेzoo_agent/agent.pyमें पढ़ें.
- ज़ू एमसीपी सर्वर से कनेक्ट करने वाले ज़ू एजेंट के कोड के साथ
agent.pyडाउनलोड करें: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
एमसीपी सर्वर की अनुमति देने की प्रोसेस कैसे काम करती है
zoo-mcp-server Cloud Run सेवा को --invoker-iam-check और --no-allow-unauthenticated फ़्लैग के साथ डिप्लॉय किया गया था. इसलिए, एमसीपी सर्वर को भेजे जाने वाले हर एचटीटीपी अनुरोध के Authorization हेडर में, Google के हस्ताक्षर वाला आईडी टोकन शामिल होना चाहिए. टोकन से, सेवा पर run.routes.invoke की अनुमति रखने वाले कॉलर की पहचान होनी चाहिए.
zoo_agent/agent.py में, _GoogleAuthHeaders क्लास को आईडी टोकन क्रेडेंशियल दो में से किसी एक तरीके से मिलते हैं. सबसे पहले, यह मेटाडेटा सर्वर या सेवा खाते की कुंजी से सेवा यूआरएल के लिए आईडी टोकन पाने के लिए, fetch_id_token_credentials() को कॉल करता है. अगर यह काम नहीं करता है, तो यह आपके उपयोगकर्ता के ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल (एडीसी) के आईडी टोकन का इस्तेमाल करता है. हर बार इंस्टेंस को कॉल करने पर, यह ज़रूरत पड़ने पर टोकन को रीफ़्रेश करता है और 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}"}
एजेंट, क्लास के एक इंस्टेंस को McpToolset में header_provider आर्ग्युमेंट के तौर पर पास करता है. एडीके, हेडर उपलब्ध कराने वाली सेवा को कॉल करता है और उससे मिलने वाले हेडर को एमसीपी सर्वर को भेजे जाने वाले हर अनुरोध के साथ अटैच करता है. एचटीटीपी क्लाइंट को एडीके बनाता है. इसलिए, एमसीपी Python SDK और इसकी एचटीटीपी लाइब्रेरी का कोई भी वर्शन इंस्टॉल होने पर, एक ही कोड काम करता है:
zoo_mcp_toolset = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=f"{MCP_SERVER_URL}/mcp",
timeout=30.0,
),
header_provider=_GoogleAuthHeaders(MCP_SERVER_URL),
)
अनुरोध की गई ऑडियंस, सेवा का यूआरएल (MCP_SERVER_URL) है. वहीं, कनेक्शन यूआरएल में /mcp पाथ शामिल होता है, जहां FastMCP सर्वर, एमसीपी प्रोटोकॉल को उपलब्ध कराता है. 30 सेकंड का टाइम आउट, Cloud Run के कोल्ड स्टार्ट के लिए जगह छोड़ता है.
अपने लोकल एनवायरमेंट में ADK प्लेग्राउंड का इस्तेमाल करके, एजेंट की जांच करना
एजेंट की जांच करने से पहले, पक्का करें कि आपका उपयोगकर्ता खाता, एमसीपी सर्वर को कॉल कर सकता हो.
- सिर्फ़ लोकल टर्मिनल के लिए (Cloud Shell में यह चरण छोड़ें): अपने उपयोगकर्ता क्रेडेंशियल की मदद से एडीसी को शुरू करें:
एडीसी को शुरू करने के लिए, निर्देशों का पालन करें.gcloud auth application-default login - (ज़रूरी नहीं) अपने उपयोगकर्ता खाते को रिमोट एमसीपी सर्वर को कॉल करने की अनुमति दें:
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' adk runकमांड का इस्तेमाल करके, अपना एजेंट चलाएं: याadk run zoo_agentadk webकमांड का इस्तेमाल करके, ADK वेब इंटरफ़ेस चलाएं: इसके बाद, ब्राउज़र में वह यूआरएल खोलें जो कमांड प्रिंट करता है.अगर Cloud Shell का इस्तेमाल किया जाता है, तो Cloud Shell से वेब इंटरफ़ेस खोलने की अनुमति देने के लिए,adk web --port 8080--allow_originsआर्ग्युमेंट जोड़ें: कमांड चलाने के बाद, Cloud Shell टूलबार (दाईं ओर) में वेब की झलकadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
आइकॉन ढूंढें. इस पर क्लिक करें और पोर्ट 8080 पर झलक देखें को चुनें. Cloud Shell, एक नया ब्राउज़र टैब खोलेगा. इसमें ADK का वेब इंटरफ़ेस दिखेगा.- एजेंट से चैट करना शुरू करें. उदाहरण के लिए, उससे चिड़ियाघर में मौजूद जानवरों के बारे में पूछें:
एजेंट, जवाब का हिसाब लगाने के लिए, हर प्रजाति के लिएHow many animals are in the zoo?list_speciesऔर फिरget_animals_by_speciesको कॉल करता है.
ADK के वेब इंटरफ़ेस की मदद से, यह देखा जा सकता है कि एजेंट कैसे काम करता है. इसमें Zoo MCP सर्वर को किए गए कॉल भी शामिल हैं. इसका तरीका जानने के लिए, वेब यूज़र इंटरफ़ेस (यूआई) से जुड़ा दस्तावेज़ देखें.
5. एमसीपी सर्वर के एंडपॉइंट को डाइनैमिक तरीके से खोजें
इस चरण में, एजेंट को इस तरह बदला जाता है कि वह एजेंट रजिस्ट्री में रजिस्टर किए गए Zoo एमसीपी सर्वर के एंडपॉइंट का पता लगा सके. इसके लिए, एंडपॉइंट के यूआरएल को हार्डकोड करने की ज़रूरत नहीं पड़ती.
इस चरण के लिए, सभी फ़ाइलें GitHub पर देखी जा सकती हैं.
सर्वर का यूआरएल ढूंढने और उसे वापस पाने के लिए, एजेंट रजिस्ट्री के साथ ADK इंटिग्रेशन का इस्तेमाल किया जाता है. इसे लागू करने के लिए, आपको यह जानकारी देनी होगी:
- एजेंट रजिस्ट्री का प्रोजेक्ट नंबर और जगह की जानकारी, जहां आपका एमसीपी सर्वर रजिस्टर (
global) है. - वह सेवा आईडी जिसका इस्तेमाल आपने एमसीपी सर्वर (
zoo-mcp-server) को रजिस्टर करने के लिए किया था.
एजेंट रजिस्ट्री का इस्तेमाल करने के लिए, एजेंट को अपडेट करना
- एजेंट के पहले वर्शन को बदलने के लिए, GitHub से अपडेट की गई
agent.pyफ़ाइल डाउनलोड करें: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.pyइस चरण में एनवायरमेंट वैरिएबल
इस अपडेट के बाद, एजेंटzoo_agent/.envके इन एनवायरमेंट वैरिएबल पर निर्भर करता है:GOOGLE_CLOUD_PROJECT_NUMBER: अब एमसीपी सर्वर की पहचान यूआरएन (MCP_SERVER_URN) बनाने के लिए ज़रूरी है.GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISE, औरGOOGLE_CLOUD_LOCATION: इनका इस्तेमाल, ADK करता है. इससे Vertex AI के ऐक्सेस को कॉन्फ़िगर किया जाता है. जगह की जानकारी का इस्तेमाल, एमसीपी सर्वर का पता लगाने के लिए भी किया जाता है.- अब ज़रूरी नहीं है:
MCP_SERVER_URLका इस्तेमाल अब नहीं किया जाता. इसकी वजह यह है कि एजेंट, एमसीपी सर्वर के एंडपॉइंट यूआरएल को एनवायरमेंट से पढ़ने के बजाय, एजेंट रजिस्ट्री से फ़ेच करता है.
एजेंट रजिस्ट्री में, रजिस्टर किए गए हर एमसीपी सर्वर का एक यूनीक आइडेंटिफ़ायर होता है. यह आइडेंटिफ़ायर, सर्वर केAgentRegistryमें एमसीपी सर्वर की पहचान और उसे खोजने की सुविधा कैसे काम करती हैmcpServerIdफ़ील्ड में सेव होता है. इसे यूनिफ़ॉर्म रिसॉर्स नेम (यूआरएन) के तौर पर फ़ॉर्मैट किया जाता है. इसे तीसरे चरण में,gcloud agent-registry mcp-servers listकमांड के आउटपुट में देखा जा सकता है. एजेंट, एनवायरमेंट वैरिएबल से इस आइडेंटिफ़ायर को फिर से बनाता है: यूआरएन, रजिस्ट्री के प्रोजेक्ट नंबर (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}), सर्वर के रजिस्टर होने की जगह और प्रोजेक्ट नंबर (projects:{PROJECT_NUMBER}:locations:{LOCATION}), औरgcloud agent-registry services createकमांड (agentregistry:services:zoo-mcp-server) में इस्तेमाल किए गए सेवा आईडी को एन्कोड करता है. एजेंट,registry.list_mcp_servers()के साथ रजिस्टर किए गए एमसीपी सर्वर की सूची बनाता है और हर सर्वर केmcpServerIdकोMCP_SERVER_URNसे मैच करता है. इसके बाद, यह मैच होने वाले सर्वर के संसाधनname(projects/.../locations/.../mcpServers/...) कोregistry.get_mcp_toolset()को पास करता है. यह सर्वर के रजिस्टर किए गए इंटरफ़ेस (https://...run.app/mcp) से एंडपॉइंट यूआरएल को पढ़ता है और उस यूआरएल से कनेक्ट किया गयाMcpToolsetदिखाता है: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(), टूल के नामों के आगे सर्वर का डिसप्ले नेम जोड़ता है. इससे एजेंट को टूल,zoo_mcp_server_list_species,zoo_mcp_server_get_animals_by_species, औरzoo_mcp_server_get_animal_detailsके तौर पर दिखते हैं. प्रीफ़िक्स की मदद से, एजेंट को एक से ज़्यादा एमसीपी सर्वर के टूल इस्तेमाल करने पर, नाम से जुड़ी गड़बड़ियों से बचने में मदद मिलती है. आखिरी लाइन, कनेक्शन के टाइम आउट को डिफ़ॉल्ट रूप से पांच सेकंड से बढ़ा देती है, ताकि Cloud Run को कोल्ड स्टार्ट के लिए जगह मिल सके.AgentRegistryके साथ अनुमति देने की प्रोसेस में क्या बदलाव होता हैAgentRegistry, एडीसी की मदद से अपने एपीआई कॉल की पुष्टि करता है. जैसे,list_mcp_servers(). इसलिए, हेडर प्रोवाइडर की ज़रूरत सिर्फ़ खोजे गए एमसीपी सर्वर को किए जाने वाले कॉल के लिए होती है.AgentRegistry,McpToolsetको इंटरनल तौर पर बनाता है. इसलिए, आपको हेडर प्रोवाइडर कोAgentRegistryकंस्ट्रक्टर को पास करना होगा. पिछले चरण में, ऑडियंसMCP_SERVER_URLवैल्यू थी, जिसके बारे में आपको पहले से पता था. अब यूआरएल का पता, खोज के बाद ही चलता है. ADK, हेडर प्रोवाइडर को तब कॉल करता है, जब एजेंट, एमसीपी सर्वर को अनुरोध भेजता है. यहAgentRegistryबनाए जाने पर कॉल नहीं करता. इससे एजेंट को पहले प्रोवाइडर बनाने औरget_mcp_toolset()के वापस आने के बाद, उसे खोजे गए एंडपॉइंट से बाइंड करने की अनुमति मिलती है.bind()तरीके से क्रेडेंशियल उसी तरह मिलते हैं जिस तरह पिछले चरण में कंस्ट्रक्टर को मिले थे. इसमें ऑडियंस को खोजे गए एंडपॉइंट यूआरएल से लिया जाता है. इसमें/mcpपाथ शामिल नहीं होता:def 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__तरीका, पिछले चरण की तरह ही है. हालांकि, अगर इसेbind()से पहले कॉल किया जाता है, तो गड़बड़ी होती है. - बदलाव की जांच करने के लिए, अपने एजेंट को चलाएं.
adk runनिर्देश का इस्तेमाल करें: याadk run zoo_agentadk webकमांड का इस्तेमाल करके, ADK वेब इंटरफ़ेस चलाएं: इसके बाद, ब्राउज़र में वह यूआरएल खोलें जो कमांड प्रिंट करता है.अगर Cloud Shell का इस्तेमाल किया जाता है, तो Cloud Shell से वेब इंटरफ़ेस खोलने की अनुमति देने के लिए,adk web --port 8080--allow_originsआर्ग्युमेंट जोड़ें: एजेंट से वही सवाल पूछें जो आपने पिछले चरण में पूछा था. जवाब वही है, लेकिन ADK के वेब इंटरफ़ेस में टूल कॉल अबadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"zoo_mcp_server_list_speciesऔरzoo_mcp_server_get_animals_by_speciesके तौर पर दिखते हैं.
इस बदलाव की वजह से, आपको एमसीपी सर्वर का यूआरएल डालने की ज़रूरत नहीं पड़ती. हालांकि, आपको अब भी प्रोजेक्ट नंबर, रजिस्ट्री की जगह, और एमसीपी सर्वर को रजिस्टर करने के लिए इस्तेमाल किए गए सेवा आईडी की जानकारी होनी चाहिए. साथ ही, एजेंट को शुरू करने के दौरान, स्टैटिक तरीके से खोज की जाती है.
6. डाइनैमिक डिस्कवरी में एमसीपी सर्वर के लिए सिमैंटिक सर्च का इस्तेमाल करना
इस चरण में, एमसीपी सर्वर की डाइनैमिक डिस्कवरी को बेहतर बनाया जाता है. इसके लिए, स्टार्टअप के समय एग्ज़ैक्ट यूआरएन मैचिंग को रनटाइम सिमैंटिक सर्च से बदल दिया जाता है. इस तरीके से, उस प्रोजेक्ट नंबर को जानने की ज़रूरत नहीं पड़ती जहां सर्वर को डिप्लॉय किया गया है या सर्वर की सटीक पहचान (MCP_SERVER_URN) की ज़रूरत नहीं पड़ती. साथ ही, टूल की खोज को सीधे एजेंट के स्टैंडर्ड रनटाइम वर्कफ़्लो में इंटिग्रेट किया जाता है. इसके लिए, उसे शुरू करने के दौरान मैनेज करने की ज़रूरत नहीं पड़ती.
इस चरण के लिए, सभी फ़ाइलें GitHub पर देखी जा सकती हैं.
रनटाइम के दौरान सिमैंटिक डिस्कवरी का इस्तेमाल करने के लिए, एजेंट को अपडेट करें
- मौजूदा सेटअप को ओवरराइट करने के लिए, GitHub से अपडेट की गई
agent.pyफ़ाइल डाउनलोड करें: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.pyइस चरण में एनवायरमेंट वैरिएबल
एजेंट अब एमसीपी सर्वर यूआरएन नहीं बनाता है. इसलिए, ज़रूरी कॉन्फ़िगरेशन को और आसान बना दिया गया है:GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISE, औरGOOGLE_CLOUD_LOCATION: इनका इस्तेमाल, ADK करता है. इससे Vertex AI के ऐक्सेस को कॉन्फ़िगर किया जाता है. जगह की जानकारी का इस्तेमाल, एमसीपी सर्वर का पता लगाने के लिए भी किया जाता है.- की अब ज़रूरत नहीं है:
GOOGLE_CLOUD_PROJECT_NUMBERकी अब ज़रूरत नहीं है. इसके अलावा,MCP_SERVER_URLको पिछले चरण में ही हटा दिया गया था.
एग्ज़ैक्ट मैच से सिमैंटिक सर्च पर स्विच करना
मॉड्यूल शुरू करने के दौरानregistry.list_mcp_servers()को कॉल करने और हर एंट्री की तुलना, बनाए गएMCP_SERVER_URNसे करने के बजाय,agent.pyअब डिस्कवरी टूल फ़ंक्शनdiscover_zoo_mcp_serversको तय करता है. यह फ़ंक्शन,search_type="SEMANTIC"के साथregistry.search_mcp_servers()को कॉल करता है: इससे एजेंट, रनटाइम के दौरान Agent Registry में खोज कर सकता है. इसके लिए, वह अपनी ज़रूरत के हिसाब से क्षमताओं का ब्यौरा नैचुरल लैंग्वेज में देता है. उदाहरण के लिए,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". इसके बाद, वह खोजे गए सर्वर रिसॉर्स के नामों को ADK सेशन स्टेट (tool_context.state) में सेव करता है.एजेंट के वर्कफ़्लो में डाइनैमिक डिस्कवरी को कैसे इंटिग्रेट किया जाता है
रनटाइम के दौरान खोजे गए सर्वर से टूल माउंट करने और एजेंट को खोज के बाद शुरू करने के फ़्लो के बारे में बताने के लिए,agent.pyकस्टमBaseToolsetलागू करने (RegistryDiscoveredToolset) को डाइनैमिक निर्देश देने वाले प्रोवाइडर (zoo_guide_instruction) के साथ जोड़ता है:- डाइनैमिक टूलसेट (
RegistryDiscoveredToolset):BaseToolsetको सबक्लास करता है औरself._use_invocation_cache = Falseको सेट करता है, ताकि ADK उपलब्ध टूल का फिर से आकलन कर सके. ऐसाdiscover_zoo_mcp_serversके सेशन की स्थिति को अपडेट करने के तुरंत बाद होता है. इससे, शुरुआत में खाली टूल की सूची को कैश मेमोरी में सेव करने की ज़रूरत नहीं पड़ती.get_tools()को कॉल करने पर, यह स्टेट से खोजे गए सर्वर के नाम पढ़ता है. साथ ही, वर्कर थ्रेड में हर सर्वर के लिए, पुष्टि किया गयाMcpToolsetबनाता है और सभी चालू टूल दिखाता है. एक सर्वर के काम न करने पर, दूसरे सर्वर पर कोई असर नहीं पड़ता._build_toolset(), I/O को ब्लॉक करता है. इसलिए,_tools_of()इसे वर्कर थ्रेड में चलाता है.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] - डाइनैमिक एजेंट के लिए निर्देश (
zoo_guide_instruction): मॉडल के हर टर्न से पहले, सेशन की स्थिति का आकलन करता है. जब तक कोई सर्वर नहीं मिलता, तब तक यह_DISCOVERY_PROMPTको जोड़ता है. इससे एजेंट को सबसे पहलेdiscover_zoo_mcp_serversको कॉल करने का निर्देश मिलता है. खोज पूरी होने के बाद, यह प्रॉम्प्ट को अपडेट करता है, ताकि चालू एमसीपी सर्वर की सूची बनाई जा सके. साथ ही, यह एजेंट को निर्देश देता है कि वह खोज को फिर से चलाए बिना, माउंट किए गए चिड़ियाघर के टूल का सीधे इस्तेमाल करे: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." )
डाइनैमिक तरीके से खोजे गए सर्वर के लिए अनुमति
सिमैंटिक सर्च से कई सर्वर मिल सकते हैं. साथ ही, एडीके किसी हेडर प्रोवाइडर को यह बताए बिना कॉल करता है कि अनुरोध किस सर्वर पर भेजा गया है. इसलिए,_build_toolset()हर सर्वर के लिए एक खास_GoogleAuthHeadersऔरAgentRegistryबनाता है. साथ ही, सेवा देने वाली कंपनी को उस सर्वर के एंडपॉइंट से जोड़ता है. प्रोवाइडर वही है जो पिछले चरण में था. इसमें_boundफ़्लैग है. इसकी वजह से,bind()से पहले इस्तेमाल किए जाने पर यह काम नहीं करता.डेटा को सेव रखने और रीफ़्रेश करने का लॉजिक
खोजे गए एंडपॉइंट को समय-समय पर रीफ़्रेश करते हुए, हर बार एजेंट रजिस्ट्री से क्वेरी करने से बचने के लिए,agent.pyटाइम-टू-लिव (टीटीएल) के साथ स्टेट रिटेंशन लागू करता है: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- ऐप्लिकेशन के दायरे में निजी डेटा का रखरखाव: खोजे गए सर्वर के नाम और
discovered_atटाइमस्टैंप कोapp:zoo_mcp_serversकुंजी के तहत सेशन की स्थिति में सेव किया जाता है. ADK केapp:प्रीफ़िक्स का इस्तेमाल करने से, ऐप्लिकेशन के चलने के दौरान कैश मेमोरी में सेव किए गए डिस्कवरी रिकॉर्ड को स्कोप किया जाता है. - टीटीएल की पुष्टि और अपने-आप रीफ़्रेश होने की सुविधा:
_fresh_discovery()पुष्टि करता है कि सेव किया गया रिकॉर्ड मौजूद है और उसकी उम्रDISCOVERY_TTL_SECONDS(24 घंटे) से ज़्यादा नहीं है. जब तक रिकॉर्ड नया है, तब तकRegistryDiscoveredToolset, कैश मेमोरी में सेव किए गएMcpToolsetकनेक्शन (self._toolsets) का फिर से इस्तेमाल करता है. साथ ही,zoo_guide_instruction, डिस्कवरी प्रॉम्प्ट को हटा देता है औरdiscover_zoo_mcp_serversको किया गया कोई भी रिपीट कॉल, तुरंत"already_discovered"दिखाता है. 24 घंटे का टीटीएल खत्म होने के बाद,_fresh_discovery()Noneदिखाता है. इससेRegistryDiscoveredToolset.get_tools(), मौजूदा एमसीपी क्लाइंट सेशन (await self.close()) बंद कर देता है औरzoo_guide_instruction, एजेंट को फिर से डिस्कवरी करने के लिए कहता है.
- सेमैंटिक डिस्कवरी वर्कफ़्लो को टेस्ट करने के लिए, अपना एजेंट चलाएं.
adk runनिर्देश का इस्तेमाल करें: याadk run zoo_agentadk webकमांड का इस्तेमाल करके, ADK वेब इंटरफ़ेस चलाएं: इसके बाद, ब्राउज़र में वह यूआरएल खोलें जो कमांड प्रिंट करता है.अगर Cloud Shell का इस्तेमाल किया जाता है, तो Cloud Shell से वेब इंटरफ़ेस खोलने की अनुमति देने के लिए,adk web --port 8080--allow_originsआर्ग्युमेंट जोड़ें: जब एजेंट से चिड़ियाघर के बारे में कोई सवाल पूछा जाता है (उदाहरण के लिए,adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"How many animals are in the zoo?), तो देखें कि वह सबसे पहलेdiscover_zoo_mcp_serversको कॉल करता है. इसके बाद, खोजे गए एमसीपी सर्वर से टूल को डाइनैमिक तौर पर माउंट करता है. इसके बाद, आपके सवाल का जवाब देने के लिए, चिड़ियाघर के टूल, जैसे किzoo_mcp_server_list_speciesऔरzoo_mcp_server_get_animals_by_speciesको कॉल करता है.कोई फ़ॉलो-अप सवाल पूछें, जैसे किWhich is the oldest lion?. एजेंट, पहले से माउंट किए गए चिड़ियाघर के टूल का इस्तेमाल करके जवाब देता है. साथ ही,discover_zoo_mcp_serversको फिर से कॉल नहीं करता, क्योंकि सेशन की स्थिति में खोज का रिकॉर्ड अब भी नया है.
7. व्यवस्थित करें
पहला विकल्प: प्रोजेक्ट मिटाना
अगर आपने इस कोडलैब के लिए कोई खास प्रोजेक्ट बनाया है, तो बिलिंग को खत्म करने का सबसे आसान तरीका है कि प्रोजेक्ट को मिटा दें:
gcloud projects delete "${GOOGLE_CLOUD_PROJECT}" --quiet
दूसरा विकल्प: एक-एक करके संसाधन मिटाना
अगर आपने किसी मौजूदा प्रोजेक्ट का इस्तेमाल किया है और आपको उसे बनाए रखना है, तो इस कोडलैब के दौरान बनाए गए अलग-अलग संसाधनों को मिटा दें:
- एजेंट रजिस्ट्री से एमसीपी सर्वर का रजिस्ट्रेशन मिटाएं. सर्वर को मैन्युअल तरीके से रजिस्टर करने की वजह से, Cloud Run सेवा को मिटाने पर रजिस्ट्रेशन नहीं हटता:
gcloud agent-registry services delete zoo-mcp-server \ --location=global \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Cloud Run एमसीपी सर्वर की सेवा मिटाएं:
gcloud run services delete zoo-mcp-server \ --region=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - एमसीपी सर्वर के लिए बनाया गया सेवा खाता मिटाएं:
gcloud iam service-accounts delete \ "zoo-mcp-server-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - अगर
cloud-run-source-deployArtifact Registry रिपॉज़िटरी को खास तौर पर इस कोडलैब के दौरान बनाया गया था, तो कंटेनर इमेज के स्टोरेज शुल्क से बचने के लिए इसे मिटा दें:gcloud artifacts repositories delete cloud-run-source-deploy \ --location=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - इसके अलावा, Cloud Shell में बनाई गई लोकल प्रोजेक्ट डायरेक्ट्री को हटाया जा सकता है:
cd ~ && rm -rf adk-dynamic-discovery
8. बधाई हो
इस कोडलैब में, आपने Google Cloud Agent Registry और Agent Development Kit (ADK) की मदद से, एमसीपी सर्वर को डाइनैमिक तौर पर खोजने और इस्तेमाल करने का तरीका सीखा:
- एमसीपी सर्वर को रजिस्टर करना: Cloud Run पर एक सुरक्षित एमसीपी सर्वर को डिप्लॉय किया और उसे एजेंट रजिस्ट्री में रजिस्टर किया.
- आइडेंटिटी के हिसाब से एमसीपी सर्वर का पता लगाया गया: एजेंट रजिस्ट्री से एमसीपी सर्वर एंडपॉइंट को रिज़ॉल्व किया गया. इसके लिए, उसके यूआरएल को हार्डकोड नहीं किया गया.
- एमसीपी सर्वर को सिमैंटिक तरीके से खोजना: एजेंट को रनटाइम के दौरान, बोलचाल की भाषा में क्वेरी पूछने की सुविधा का इस्तेमाल करके, एमसीपी टूल ढूंढने और माउंट करने की अनुमति दें. साथ ही, डेटा को सेव रखने और रीफ़्रेश करने की सुविधा दें.