1. Einführung
In diesem Codelab erfahren Sie, wie Sie mit der Google Cloud Agent Registry und dem Agent Development Kit (ADK) registrierte MCP-Server (Model Context Protocol) zur Laufzeit dynamisch erkennen und aufrufen können. So müssen Sie keine Endpunkte und Toolkonfigurationen mehr hartcodieren.
In diesem Lab werden das ADK und die Programmiersprache Python verwendet, um eine Anwendung zu erstellen. Dieselben Prinzipien können auch in anderen Programmiersprachen und mit anderen Frameworks für die Agentenentwicklung angewendet werden.
Aufgaben
- Google Cloud Agent Registry in Ihrem Projekt aktivieren und konfigurieren
- MCP-Server in Cloud Run bereitstellen und in Agent Registry registrieren
- ADK-Agenten erstellen, der den MCP-Server über eine hartcodierte URL aufruft
- KI-Agenten so ändern, dass er den MCP-Server in der Agent Registry anhand seiner Identität findet
- KI-Agenten so ändern, dass er MCP-Server zur Laufzeit mithilfe der semantischen Suche findet
Voraussetzungen
- Einen modernen Webbrowser (z. B. Chrome)
- Ein Google Cloud-Projekt mit aktivierter Abrechnung
- Ein Konto mit Berechtigungen zum Erstellen und Verwalten von Ressourcen und zum Konfigurieren von IAM-Richtlinien im Google Cloud-Projekt
2. Umgebung einrichten
In dieser Anleitung wird davon ausgegangen, dass Sie Befehle in Cloud Shell in der Google Cloud Console ausführen. Die Cloud Shell ist eine Befehlszeilenumgebung, die in Google Cloud ausgeführt wird und die erforderlichen Tools enthält. Wenn Sie die gcloud-CLI, git und Python 3 in Ihrer lokalen Umgebung installiert haben, können Sie die Befehle auch dort ausführen.
Google Cloud-Projekt erstellen
- Erstellen Sie in der Google Cloud Console auf der Projektauswahlseite ein Google Cloud-Projekt.
- Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für ein Projekt aktiviert ist.
Cloud Shell-Terminal starten
- Wählen Sie mit der Ressourcenauswahl das von Ihnen erstellte Google Cloud-Projekt aus.
- Klicken Sie oben in der Google Cloud Console auf Cloud Shell aktivieren
.
- Sobald die Verbindung mit der Cloud Shell hergestellt ist, prüfen Sie Ihre Authentifizierung:
gcloud auth list - Prüfen Sie, ob Ihr Projekt konfiguriert ist:
gcloud config get project - Wenn Ihr Projekt nicht wie erwartet festgelegt ist oder Sie eine Umgebung auf Ihrem lokalen Computer anstelle von Cloud Shell verwenden, richten Sie die Projekt-ID ein:
export GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID> gcloud config set project "${GOOGLE_CLOUD_PROJECT}"
Google Cloud-Projekt auswählen und Umgebungsvariablen festlegen
- Aktivieren Sie die erforderlichen Google Cloud APIs:
gcloud services enable \ agentregistry.googleapis.com \ aiplatform.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com \ --project="${GOOGLE_CLOUD_PROJECT}"
Python-Umgebung einrichten
- Erstellen und aktivieren Sie eine virtuelle Umgebung und installieren Sie die erforderlichen Abhängigkeiten:
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-MCP-Server erstellen und registrieren
In diesem Schritt erstellen und registrieren Sie einen Zoo-MCP-Server. Der Server stellt drei Tools bereit: list_species (listet alle im Zoo lebenden Arten auf), get_animals_by_species (listet die Tiere einer bestimmten Art auf) und get_animal_details (ruft zusätzliche Informationen zu einem bestimmten Tier ab).
Alle Dateien für diesen Schritt finden Sie auf GitHub.
MCP-Server erstellen
- Ordner und Python-Projekt für den MCP-Server einrichten
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 - Laden Sie den MCP-Servercode herunter:
curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step3/server.py -o server.py
MCP-Server in Cloud Run bereitstellen und in der Agent Registry registrieren
Als Nächstes erstellen Sie Dockerfile für den Server und stellen den Server in Cloud Run bereit.
Dockerfileerstellen: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- Erstellen Sie ein dediziertes Dienstkonto für den Server:
gcloud iam service-accounts create zoo-mcp-server-sa \ --display-name="Zoo MCP Server Service Account" - Stellen Sie den Server in der Region
us-west1bereit. Wenn die folgende Eingabeaufforderung angezeigt wird, bestätigen Sie die Erstellung eines neuen Artifact Registry-Repositorys. Diese Aufforderung wird angezeigt, wenn Sie in Ihrem Projekt kein Artifact Registry-Repository für die 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-west1haben: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)? - Registrieren Sie den MCP-Server in der Agent Registry am Standort „global“:
Mit diesen Befehlen wirdfastmcp 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.jsonmit dem Tool-Manifest generiert und die Agent Registry API aufgerufen, um den Server zu registrieren. - Prüfen Sie, ob der Agent in der Registry angezeigt wird:
Sie sehen eine YAML-Ausgabe mit den MCP-Serverinformationen, die in etwa so aussieht: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. Einfachen ADK-Agenten für die Verwendung des Zoo-MCP-Servers erstellen
In diesem Schritt erstellen Sie einen ADK-Agenten, der mithilfe der hartcodierten MCP-Server-URL des Zoos Anfragen von Nutzern zum Zoo beantwortet. Wenn Sie die URL des MCP-Servers hartcodieren, müssen Sie sie VOR der Bereitstellung des KI-Agenten kennen.
Die Quelldateien für diesen Schritt finden Sie auf GitHub.
Agentenanwendung erstellen
Erstellen Sie ein Gerüst für das ADK-Projekt und den Zoo-Agenten, der den Zoo-MCP-Server verwendet.
- Richten Sie einen Ordner und ein Projekt für den Zoo-Agenten ein:
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 - Erstellen Sie den Ordner für das Agent-Paket und laden Sie die Datei
__init__.pyherunter: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 - Erstellen Sie die Datei
.envund füllen Sie sie mit Umgebungsvariablen, die in diesem und den folgenden Schritten verwendet werden: Mit diesem Befehl werden alle Umgebungsvariablen, die für diesen Schritt und die nachfolgenden Erkennungsschritte erforderlich sind, inMCP_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/.envgeschrieben. Sie müssen die Datei also später nicht neu erstellen. In diesem Schritt werden die folgenden Variablen verwendet:GOOGLE_GENAI_USE_ENTERPRISE,GOOGLE_CLOUD_PROJECTundGOOGLE_CLOUD_LOCATION: Werden implizit vom ADK und dem Google GenAI SDK verwendet, um Gemini-Modellaufrufe über Vertex AI in Ihrem Google Cloud-Projekt und -Standort (global) weiterzuleiten. Außerdem wird hier der Standort für die Agent Registry gespeichert, in der der MCP-Server registriert ist.GOOGLE_CLOUD_PROJECT_NUMBER: Wird in diesem Schritt nicht verwendet, sondern ist hier für die Verwendung im nächsten Schritt vorab ausgefüllt.MCP_SERVER_URL: Lesen Sie direkt inzoo_agent/agent.py, um dieMcpToolsetmit der hartcodierten Cloud Run-URL des Zoo-MCP-Servers zu konfigurieren.
- Laden Sie
agent.pymit dem Code für den Zoo-KI-Agenten herunter, der eine Verbindung zum Zoo-MCP-Server herstellt: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
Funktionsweise der MCP-Serverautorisierung
Da der Cloud Run-Dienst zoo-mcp-server mit den Flags --invoker-iam-check und --no-allow-unauthenticated bereitgestellt wurde, muss jede HTTP-Anfrage an den MCP-Server ein von Google signiertes ID-Token im Authorization-Header enthalten. Das Token muss einen Aufrufer identifizieren, der die Berechtigung run.routes.invoke für den Dienst hat.
In zoo_agent/agent.py erhält die Klasse _GoogleAuthHeaders ID-Token-Anmeldedaten auf eine von zwei Arten. Zuerst wird fetch_id_token_credentials() aufgerufen, um ein ID-Token für die Dienst-URL vom Metadatenserver oder einen Dienstkontoschlüssel abzurufen. Wenn dies fehlschlägt, wird das ID-Token der Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) des Nutzers verwendet. Bei jedem Aufruf der Instanz wird das Token bei Bedarf aktualisiert und der Authorization-Header zurückgegeben:
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}"}
Der Agent übergibt eine Instanz der Klasse als header_provider-Argument an McpToolset. Das ADK ruft den Header-Anbieter auf und hängt die zurückgegebenen Header an jede Anfrage an den MCP-Server an. Da der HTTP-Client vom ADK erstellt wird, funktioniert derselbe Code unabhängig davon, welche Version des MCP Python SDK und der zugehörigen HTTP-Bibliothek installiert ist:
zoo_mcp_toolset = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=f"{MCP_SERVER_URL}/mcp",
timeout=30.0,
),
header_provider=_GoogleAuthHeaders(MCP_SERVER_URL),
)
Die angeforderte Zielgruppe ist die Dienst-URL (MCP_SERVER_URL), während die Verbindungs-URL den Pfad /mcp enthält, über den der FastMCP-Server das MCP-Protokoll bereitstellt. Das Zeitlimit von 30 Sekunden lässt Raum für Cloud Run-Kaltstarts.
KI-Agenten mit dem ADK-Playground in Ihrer lokalen Umgebung testen
Bevor Sie den Agenten testen, müssen Sie sicherstellen, dass Ihr Nutzerkonto den MCP-Server aufrufen kann.
- Nur lokales Terminal (überspringen Sie diesen Schritt in Cloud Shell): Initialisieren Sie die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten:
Folgen Sie der Anleitung, um die ADC-Initialisierung abzuschließen.gcloud auth application-default login - (Optional) Gewähren Sie Ihrem Nutzerkonto die Berechtigung, den Remote-MCP-Server aufzurufen:
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' - Führen Sie den Agenten mit dem Befehl
adk runaus: oder führen Sie die ADK-Weboberfläche mit dem Befehladk run zoo_agentadk webaus: Öffnen Sie dann die URL, die der Befehl im Browser ausgibt.Wenn Sie Cloud Shell verwenden, fügen Sie das Argumentadk web --port 8080--allow_originshinzu, damit die Weboberfläche über Cloud Shell geöffnet werden kann: Suchen Sie nach dem Ausführen des Befehls in der Cloud Shell-Symbolleiste (rechts) nach dem Symbol für die Webvorschauadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
. Klicken Sie darauf und wählen Sie Vorschau auf Port 8080 aus. In Cloud Shell wird ein neuer Browsertab mit der ADK-Weboberfläche geöffnet. - Starten Sie einen Chat mit dem KI-Agenten. Fragen Sie Gemini beispielsweise nach Tieren im Zoo:
Der Agent ruftHow many animals are in the zoo?list_speciesund dannget_animals_by_speciesfür jede Art auf, um die Antwort zu berechnen.
Über die ADK-Weboberfläche können Sie die Funktionsweise des KI-Agenten, einschließlich seiner Aufrufe an den Zoo-MCP-Server, nachvollziehen. Weitere Informationen finden Sie in der Dokumentation zur Web-UI.
5. MCP-Serverendpunkt dynamisch erkennen
In diesem Schritt ändern Sie den KI-Agenten so, dass er den in der Agent Registry registrierten Zoo-MCP-Serverendpunkt erkennt, anstatt die Endpunkt-URL hartzucodieren.
Alle Dateien für diesen Schritt finden Sie auf GitHub.
Sie verwenden die ADK-Integration mit der Agent Registry, um die URL des Servers zu finden und abzurufen. Für die Implementierung benötigen Sie die folgenden Informationen:
- Projektnummer und Standort der Agent Registry, in der Ihr MCP-Server registriert ist (
global). - Die Dienst-ID, die Sie zum Registrieren des MCP-Servers (
zoo-mcp-server) verwendet haben.
Agent für die Verwendung von Agent Registry aktualisieren
- Laden Sie die aktualisierte
agent.py-Datei von GitHub herunter, um die erste Version des Agents zu überschreiben: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.pyUmgebungsvariablen in diesem Schritt
Mit diesem Update verwendet der Agent die folgenden Umgebungsvariablen auszoo_agent/.env:GOOGLE_CLOUD_PROJECT_NUMBER: Jetzt erforderlich, um den Identitäts-URN des MCP-Servers (MCP_SERVER_URN) zu erstellen.GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISEundGOOGLE_CLOUD_LOCATION: Werden vom ADK verwendet, um den Zugriff auf Vertex AI zu konfigurieren. Der Standort wird auch verwendet, um den MCP-Server zu finden.- Nicht mehr erforderlich:
MCP_SERVER_URLwird nicht mehr verwendet, da der KI-Agent die MCP-Server-Endpunkt-URL aus der Agent Registry abruft, anstatt sie aus der Umgebung zu lesen.
So funktionieren MCP-Serveridentität und ‑erkennung in
In der Agent Registry hat jeder registrierte MCP-Server eine eindeutige Kennung, die im FeldAgentRegistrymcpServerIdals Uniform Resource Name (URN) gespeichert ist. Sie finden sie in der Ausgabe des Befehlsgcloud agent-registry mcp-servers listin Schritt 3. Der Agent rekonstruiert diese Kennung aus den Umgebungsvariablen: Der URN codiert die Projektnummer der 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}), die Projektnummer und den Standort, an dem der Server registriert ist (projects:{PROJECT_NUMBER}:locations:{LOCATION}), sowie die Dienst-ID, die Sie im Befehlgcloud agent-registry services createverwendet haben (agentregistry:services:zoo-mcp-server).Der Agent listet die registrierten MCP-Server mitregistry.list_mcp_servers()auf und gleicht diemcpServerIdjedes Servers mitMCP_SERVER_URNab. Anschließend wird die Ressourcename(projects/.../locations/.../mcpServers/...) des übereinstimmenden Servers anregistry.get_mcp_toolset()übergeben. liest die Endpunkt-URL aus der registrierten Schnittstelle (https://...run.app/mcp) des Servers und gibt einen mit dieser URL verbundenenMcpToolsetzurück: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()stellt den Toolnamen den Anzeigenamen des Servers voran, sodass der Agent die Tools alszoo_mcp_server_list_species,zoo_mcp_server_get_animals_by_speciesundzoo_mcp_server_get_animal_detailssieht. Das Präfix verhindert Namenskonflikte, wenn ein Agent Tools von mehreren MCP-Servern verwendet. In der letzten Zeile wird das Verbindungszeitlimit von der Standardeinstellung von 5 Sekunden erhöht, um Platz für Cloud Run-Kaltstarts zu schaffen.So ändert sich die Autorisierung mit
AgentRegistryAgentRegistryauthentifiziert seine eigenen API-Aufrufe, z. B.list_mcp_servers(), mit ADC. Der Header-Anbieter wird also nur für die Aufrufe an den erkannten MCP-Server benötigt. DaAgentRegistrydenMcpToolsetintern erstellt, übergeben Sie den Header-Anbieter an denAgentRegistry-Konstruktor.Im vorherigen Schritt war die Zielgruppe derMCP_SERVER_URL-Wert, den Sie im Voraus kannten. Jetzt ist die URL erst nach der Erkennung bekannt. Das ADK ruft den Header-Anbieter auf, wenn der Agent eine Anfrage an den MCP-Server sendet, nicht wennAgentRegistryerstellt wird. So kann der Agent zuerst den Anbieter erstellen und ihn an den erkannten Endpunkt binden, nachdemget_mcp_toolset()zurückgegeben wurde. Die Methodebind()ruft die Anmeldedaten auf dieselbe Weise ab wie der Konstruktor im vorherigen Schritt. Die Zielgruppe wird aus der URL des erkannten Endpunkts ohne den Pfad/mcpübernommen: Die Methodedef 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__ist dieselbe wie im vorherigen Schritt, mit dem Unterschied, dass sie einen Fehler auslöst, wenn sie vorbind()aufgerufen wird. - Führen Sie den KI-Agenten aus, um die Änderung zu testen. Führen Sie den Befehl
adk runaus: oder führen Sie die ADK-Weboberfläche mit dem Befehladk run zoo_agentadk webaus: Öffnen Sie dann die URL, die der Befehl im Browser ausgibt.Wenn Sie Cloud Shell verwenden, fügen Sie das Argumentadk web --port 8080--allow_originshinzu, damit die Weboberfläche über Cloud Shell geöffnet werden kann: Stellen Sie dem KI-Agenten dieselbe Frage wie im vorherigen Schritt. Die Antwort ist dieselbe, aber in der ADK-Weboberfläche werden die Toolaufrufe jetzt alsadk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"zoo_mcp_server_list_speciesundzoo_mcp_server_get_animals_by_speciesangezeigt.
Durch diese Änderung ist die explizite MCP-Server-URL nicht mehr erforderlich. Sie müssen jedoch die Projektnummer, den Registry-Standort und die Dienst-ID kennen, die für die Registrierung des MCP-Servers verwendet wurden. Die Erkennung erfolgt statisch während der Initialisierung des Agenten.
6. Semantische Suche für MCP-Server in der dynamischen Erkennung verwenden
In diesem Schritt verbessern Sie die dynamische Erkennung des MCP-Servers, indem Sie den genauen URN-Abgleich beim Start durch eine semantische Suche zur Laufzeit ersetzen. Bei diesem Ansatz müssen Sie weder die Projektnummer kennen, unter der der Server bereitgestellt wird, noch die genaue Identität des Servers (MCP_SERVER_URN). Außerdem wird die Toolerkennung direkt in den Standardlaufzeit-Workflow des KI-Agenten integriert, anstatt sie bei der Initialisierung zu verarbeiten.
Alle Dateien für diesen Schritt finden Sie auf GitHub.
KI-Agenten für die Verwendung der semantischen Erkennung zur Laufzeit aktualisieren
- Laden Sie die aktualisierte
agent.py-Datei von GitHub herunter, um die vorhandene Implementierung zu überschreiben: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.pyUmgebungsvariablen in diesem Schritt
Da der Agent keine MCP-Server-URN mehr erstellt, wird die erforderliche Konfiguration weiter vereinfacht:GOOGLE_CLOUD_PROJECT,GOOGLE_GENAI_USE_ENTERPRISEundGOOGLE_CLOUD_LOCATION: Werden vom ADK verwendet, um den Zugriff auf Vertex AI zu konfigurieren. Der Standort wird auch verwendet, um den MCP-Server zu finden.- Nicht mehr erforderlich:
GOOGLE_CLOUD_PROJECT_NUMBERist nicht mehr erforderlich (zusätzlich zuMCP_SERVER_URL, das bereits im vorherigen Schritt entfernt wurde).
Wechsel von der genauen Übereinstimmung zur semantischen Suche
Anstattregistry.list_mcp_servers()während der Modulinitialisierung aufzurufen und jeden Eintrag mit einem konstruiertenMCP_SERVER_URNzu vergleichen, definiertagent.pyjetzt eine Discovery-Tool-Funktiondiscover_zoo_mcp_servers, dieregistry.search_mcp_servers()mitsearch_type="SEMANTIC"aufruft: Dadurch kann der Agent die Agent Registry zur Laufzeit mit einer Beschreibung der benötigten Funktionen in natürlicher Sprache (z. B.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") durchsuchen und die gefundenen Serverressourcennamen im ADK-Sitzungsstatus (tool_context.state) speichern.Wie die dynamische Erkennung in den Agenten-Workflow eingebunden wird
Um Tools von Servern einzubinden, die zur Laufzeit erkannt werden, und den Agenten durch den Erkennungs- und Aufrufablauf zu führen, kombiniertagent.pyeine benutzerdefinierteBaseToolset-Implementierung (RegistryDiscoveredToolset) mit einem dynamischen Anweisungsanbieter (zoo_guide_instruction):- Dynamisches Toolset (
RegistryDiscoveredToolset): Erstellt eine Unterklasse vonBaseToolsetund legtself._use_invocation_cache = Falsefest, damit das ADK die verfügbaren Tools sofort neu bewertet, nachdemdiscover_zoo_mcp_serversden Sitzungsstatus aktualisiert hat, anstatt eine anfänglich leere Toolliste im Cache zu speichern. Wennget_tools()aufgerufen wird, werden die erkannten Servernamen aus dem Status gelesen, für jeden Server in einem Arbeitsthread ein authentifizierterMcpToolseterstellt und alle aktiven Tools zurückgegeben. Wenn ein Server nicht erreichbar ist, hat das keine Auswirkungen auf die anderen._build_toolset()führt blockierende E/A-Vorgänge aus, daher wird es von_tools_of()in einem Arbeitsthread ausgeführt.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] - Dynamische Agentenanweisung (
zoo_guide_instruction): Wertet den Sitzungsstatus vor jeder Modellrunde aus. Wenn noch keine Server erkannt wurden, wird_DISCOVERY_PROMPTangehängt, um den Agent anzuweisen, zuerstdiscover_zoo_mcp_serversaufzurufen. Nach erfolgreicher Erkennung wird der Prompt aktualisiert, um die aktiven MCP-Server aufzulisten. Der KI-Agent wird angewiesen, die bereitgestellten Zoo-Tools direkt zu verwenden, ohne die Erkennung noch einmal auszuführen: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." )
Autorisierung für dynamisch erkannte Server
Die semantische Suche kann mehrere Server zurückgeben und das ADK ruft einen Header-Anbieter auf, ohne ihm mitzuteilen, an welchen Server eine Anfrage gesendet wird. Daher erstellt_build_toolset()für jeden erkannten Server einen dedizierten_GoogleAuthHeadersundAgentRegistryund bindet den Anbieter an den Endpunkt dieses Servers. Der Anbieter ist derselbe wie im vorherigen Schritt, mit einem_bound-Flag, das dazu führt, dass er fehlschlägt, wenn er vorbind()verwendet wird.Aufbewahrungs- und Aktualisierungslogik
Damit die Agent Registry nicht bei jeder Runde abgefragt werden muss, aber die erkannten Endpunkte trotzdem regelmäßig aktualisiert werden, implementiertagent.pydie Zustandsspeicherung mit einer Gültigkeitsdauer (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- Aufbewahrung auf Anwendungsebene: Erkannte Servernamen und ein
discovered_at-Zeitstempel werden im Sitzungsstatus unter dem Schlüsselapp:zoo_mcp_serversgespeichert. Wenn Sie das Präfixapp:des ADK verwenden, wird der im Cache gespeicherte Erkennungseintrag auf die gesamte Anwendungsausführung angewendet. - TTL-Validierung und automatische Aktualisierung:
_fresh_discovery()prüft, ob der gespeicherte Eintrag vorhanden ist und sein AlterDISCOVERY_TTL_SECONDS(24 Stunden) nicht überschreitet. Solange der Eintrag aktuell ist, verwendetRegistryDiscoveredToolsetdie im Cache gespeichertenMcpToolset-Verbindungen (self._toolsets) wieder,zoo_guide_instructionlässt die Erkennungsaufforderung aus und jeder wiederholte Aufruf vondiscover_zoo_mcp_serversgibt sofort"already_discovered"zurück. Nach Ablauf der 24-stündigen TTL gibt_fresh_discovery()Nonezurück. Dadurch schließtRegistryDiscoveredToolset.get_tools()vorhandene MCP-Clientsitzungen (await self.close()) undzoo_guide_instructionfordert den KI-Agenten auf, eine neue Erkennung durchzuführen.
- Führen Sie den KI-Agenten aus, um den Workflow für die semantische Suche zu testen. Führen Sie den Befehl
adk runaus: oder führen Sie die ADK-Weboberfläche mit dem Befehladk run zoo_agentadk webaus: Öffnen Sie dann die URL, die der Befehl im Browser ausgibt.Wenn Sie Cloud Shell verwenden, fügen Sie das Argumentadk web --port 8080--allow_originshinzu, damit die Weboberfläche über Cloud Shell geöffnet werden kann: Wenn Sie dem Agenten eine Frage zum Zoo stellen (z. B.adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"How many animals are in the zoo?), ruft er zuerstdiscover_zoo_mcp_serversauf, stellt die Tools vom erkannten MCP-Server dynamisch bereit und ruft dann die Zoo-Tools wiezoo_mcp_server_list_speciesundzoo_mcp_server_get_animals_by_speciesauf, um Ihre Frage zu beantworten. Stellen Sie eine Folgefrage, z. B.Which is the oldest lion?. Der Agent antwortet mit den bereits bereitgestellten Zoo-Tools und ruftdiscover_zoo_mcp_serversnicht noch einmal auf, da der Discovery-Eintrag im Sitzungsstatus noch aktuell ist.
7. Bereinigen
Option 1: Projekt löschen
Wenn Sie für dieses Codelab ein dediziertes Projekt erstellt haben, können Sie weitere Kosten am einfachsten vermeiden, indem Sie das Projekt löschen:
gcloud projects delete "${GOOGLE_CLOUD_PROJECT}" --quiet
Option 2: Einzelne Ressourcen löschen
Wenn Sie ein vorhandenes Projekt verwendet haben und es behalten möchten, löschen Sie die einzelnen Ressourcen, die Sie in diesem Codelab erstellt haben:
- Löschen Sie die MCP-Serverregistrierung aus der Agent Registry. Da Sie den Server manuell registriert haben, wird die Registrierung durch das Löschen des Cloud Run-Dienstes nicht entfernt:
gcloud agent-registry services delete zoo-mcp-server \ --location=global \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Löschen Sie den Cloud Run-MCP-Serverdienst:
gcloud run services delete zoo-mcp-server \ --region=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Löschen Sie das für den MCP-Server erstellte Dienstkonto:
gcloud iam service-accounts delete \ "zoo-mcp-server-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Wenn das Artifact Registry-Repository
cloud-run-source-deployspeziell für dieses Codelab erstellt wurde, löschen Sie es, um Gebühren für die Speicherung von Container-Images zu vermeiden:gcloud artifacts repositories delete cloud-run-source-deploy \ --location=us-west1 \ --project="${GOOGLE_CLOUD_PROJECT}" \ --quiet - Optional können Sie das in Cloud Shell erstellte lokale Projektverzeichnis entfernen:
cd ~ && rm -rf adk-dynamic-discovery
8. Glückwunsch
In diesem Codelab haben Sie gelernt, wie Sie MCP-Server mit der Google Cloud Agent Registry und dem Agent Development Kit (ADK) dynamisch erkennen und verwenden:
- MCP-Server registriert: Sie haben einen sicheren MCP-Server in Cloud Run bereitgestellt und in Agent Registry registriert.
- MCP-Server anhand der Identität erkannt: Der MCP-Serverendpunkt wurde aus der Agent Registry aufgelöst, anstatt die URL hartzucodieren.
- Semantisch gefundene MCP-Server: Der KI-Agent kann MCP-Tools zur Laufzeit über die Suche in natürlicher Sprache finden und einbinden. Die Tools werden gespeichert und aktualisiert.