1. Einführung
In diesem Codelab wird die private, verwaltete Egress-Konnektivität für Gemini Enterprise mit dem KI-Agenten-Gateway im agent-to-anywhere-Modus (Egress) untersucht. Sie konfigurieren eine Gemini Enterprise-App, um einen benutzerdefinierten Model Context Protocol (MCP)-Server, der in Cloud Run gehostet wird, sicher aufzurufen. Dazu leiten Sie Traffic über Agent Gateway mithilfe von Private Service Connect (PSC)-Schnittstellen weiter, um eine Verbindung zu einem PSC-Endpunkt für Google APIs in einem VPC-Netzwerk herzustellen.
In Unternehmensumgebungen birgt die Gewährung von direktem Netzwerkzugriff für autonome Agents das Risiko von Daten-Exfiltration und der Ausführung nicht geprüfter Tools. Agent Gateway bietet einen zentralen Zero-Trust-Durchsetzungspunkt auf Plattformebene, der streamfähige HTTP-MCP-Tool-Nutzlasten dynamisch prüft. Ausgehende Anfragen werden mit einer kryptografisch überprüfbaren Agent Identity authentifiziert und über Identity-Aware Proxy (IAP) mithilfe von IAM Unified Access Policies (UAP) mit CEL-Regeln (Common Expression Language) autorisiert. So lässt sich die Zugriffssteuerung auf bestimmte MCP-Tools und -Methoden detailliert steuern, ohne Backend-Arbeitslasten im öffentlichen Internet offenzulegen.
Was Sie erstellen
- Agent Gateway im Modus „Ausgehender Traffic“ (Agent zu beliebigem Ziel) mit Endpunktprüfung der Agent Registry
- Cloud Run-Dienst, der einen privaten streamfähigen HTTP-MCP-Server (
--ingress=internal) hostet, der mit seinen Tool-Spezifikationen in Agent Registry registriert ist - IAP-Autorisierungserweiterung (Identity-Aware Proxy) für Agent Gateway
- IAM Unified Access Policies (UAP) mit CEL-Bedingungen für die Autorisierung von MCP-Tools
- Gemini Enterprise-App, die an das Agent Gateway gebunden und mit einem benutzerdefinierten MCP-Server-Datenspeicher verbunden ist, der aus der Agent Registry importiert wurde
- VPC-Netzwerkressourcen, Cloud DNS-Zone und PSC-Endpunkt für Google APIs
- PSC-Netzwerk-Anhang für ausgehenden privaten VPC-Traffic des Agent Gateway
- Cloud Next Generation Firewall (NGFW)-Richtlinienregeln zum Sichern des VPC-Traffics
Abbildung 1. Codelab-Architektur
Lerninhalte
- So stellen Sie einen privaten streamfähigen HTTP-MCP-Server aus dem Quellcode in Cloud Run bereit und registrieren seinen Endpunkt und sein Tool-Schema in Agent Registry
- Agent Gateway mit konformen Registrierungseinträgen konfigurieren und Tool-Aufrufe der Gemini Enterprise App über das Gateway weiterleiten
- Privaten VPC-Ausgang mit PSC-Netzwerk-Attachments und ‑Schnittstellen einrichten
- Agent Gateway-Autorisierung an Identity-Aware Proxy (IAP) delegieren
- IAM Unified Access Policies (UAP) mit
destination.agent_registry.*- unddestination.is_registered-CEL-Attributen erstellen und binden, um die Ausführung von MCP-Tools einzuschränken - Richtliniendurchsetzung und Netzwerk-Egress mit Cloud Logging validieren
Voraussetzungen
- Ein Google Cloud-Projekt mit aktivierter Abrechnungsfunktion
- Eine aktive Gemini Enterprise-Lizenz oder ein 30‑tägiger Testzeitraum
- IAM-Berechtigungen zum Bereitstellen von Netzwerkdiensten, Gemini Enterprise- und Agent Platform-Ressourcen
- Eine POSIX-kompatible Shell (
bashoderzsh) mit installierter Google Cloud CLI (gcloud),curlundjq
Damit sind wir mit der Einführung fertig. Als Nächstes folgt der Abschnitt Konzepte.
2. Konzepte
Bereitstellungsreihenfolge
In diesem Codelab wird die Infrastruktur zuerst bereitgestellt, damit private Netzwerkpfade und Governance-Kontrollen betriebsbereit sind, bevor MCP-Tools registriert und mit Gemini Enterprise verbunden werden:
- Netzwerkinfrastruktur:Stellen Sie VPC-Subnetze, einen PSC-Endpunkt, einen PSC-Netzwerkanhang, Cloud NGFW-Richtlinienregeln und private Cloud DNS-Zonen bereit.
- Agent Gateway:Stellen Sie Agent Gateway im Egress-Modus mit Agent Registry-Integration (
registries) und privatem VPC-Egress (networkAttachment) bereit. - Autorisierungsrichtlinien:Konfigurieren Sie die IAP-Autorisierungserweiterung, die Gateway-Autorisierungsrichtlinie und die einheitliche IAM-Zugriffsrichtlinie (Unified Access Policy, UAP) mit
destination.is_registered- unddestination.agent_registry.*-CEL-Bedingungen. - MCP-Server bereitstellen und registrieren:Stellen Sie den Math-MCP-Server aus der Quelle in Cloud Run (
--ingress=internal) bereit und registrieren Sie die Dienst- und Tool-Spezifikationen (addundsubtract) in der Agent Registry. - Gemini Enterprise-App:Erstellen Sie die Gemini Enterprise-App (
Engine), konfigurieren Sie die Identitäts- und Observability-Einstellungen und binden Sie den ausgehenden Egress an das Agent Gateway (agentGatewaySetting). - Benutzerdefinierten MCP-Daten-Connector importieren:Erstellen und aktivieren Sie den
REGISTRY_MCP-Daten-Connector (:setUpDataConnector), um den zugrunde liegenden Datenspeicher des registrierten MCP-Servers mit der Gemini Enterprise App zu verknüpfen. - Validieren:Testen Sie zulässige und abgelehnte Tool-Ausführungen im Chat und prüfen Sie die Richtliniendurchsetzung in den Protokollen von Agent Gateway, DNS, Firewall und Cloud Run.
Gemini Enterprise-Ausgang
Gemini Enterprise leitet Toolanfragen für benutzerdefinierte MCP-Server an das Agent Gateway weiter, wenn sowohl agentGatewaySetting auf dem Engine als auch use_agent_gateway_egress: true auf dem DataConnector konfiguriert sind.
Abbildung 2. Gemini Enterprise-Architektur für den Datenexport
Die Gemini Enterprise App organisiert das Tool-Routing in vier wichtigen Bereichen:
- Widget (
default_search_widget_config):- Stellt die Weboberfläche des Clients bereit. Das Widget empfängt Prompts vom Nutzer und startet Chatsitzungen mit der zugrunde liegenden Engine.
- Core Assistant (
assistants/default_assistant/agents/default/core_assistant):- Der konversationelle Reasoning-Root-Agent in der Engine. Bei der Auswertung einer Nutzeranfrage ermittelt der Core Assistant, ob eine arithmetische Berechnung erforderlich ist, prüft die verfügbaren Tools und delegiert die Ausführung an den synthetisierten Agent Gateway-Unter-Agent.
- Datenspeicher und Daten-Connector:
DataStore: Wird in einem dediziertenCollectionbereitgestellt, wenn:setUpDataConnectorausgeführt wird. Es verknüpft (dataStoreIds) die importierten Tool-Schemas der Agent Registry (add,subtract), Argumenttypen und Agent-Anweisungen mit dem Gemini Enterprise-Engine.DataConnector: Verwaltet dieREGISTRY_MCP-Aktionsverbindung (createBapConnection: true) zum Remote-MCP-Server (instance_uri), löst die MCP-Serverressource der Agent Registry (registry_mcp_server_name) auf und ermöglicht den Agent Gateway-Ausgang (use_agent_gateway_egress: true).
- Agent Identity, Agent Registry und Agent Gateway:
- Wenn der Data Connector den ausgehenden Tool-Aufruf sendet, wird der Traffic an das in
agentGatewaySettingangegebene Gateway weitergeleitet. Der Gacklaxiekern-Assistent erstellt ein SPIFFE-Identitätstoken, das seine Identität bestätigt:principal://agents.global.org-.../agents/default/core_assistant. - Agent Gateway wird über das Feld
registriesin Agent Registry eingebunden, um Zielendpunkte und registrierte Tool-Schemas dynamisch aufzulösen. Sie füllt die Attributedestination.is_registeredunddestination.agent_registry.*aus und übergibt sie an IAP v2, damit sie anhand der CEL-Regeln der IAM Unified Access Policy (UAP) ausgewertet werden, bevor der Transit in das VPC-Netzwerk zugelassen wird.
- Wenn der Data Connector den ausgehenden Tool-Aufruf sendet, wird der Traffic an das in
VPC-Verbindung des Gateways
Agent Gateway ermöglicht private VPC-Netzwerkverbindungen über zwei YAML-Felder:
networkConfig.egress.networkAttachment:Leitet privaten IP-Traffic über die PSC-Netzwerkverbindung in das VPC-Netzwerk weiter.dnsPeeringConfig.domains:Die DNS-Auflösung wird mit der Cloud DNS-Zone des VPC-Netzwerks durchgeführt, sodass Ziel-Hostnamen (*.run.app) in die private PSC-Endpunkt-IP-Adresse aufgelöst werden, die im VPC-Netzwerk definiert ist.
Beschränkungen und Anforderungen
- Nur StreamableHTTP:Der alte SSE-Transport (Server-Sent Events) wird nicht unterstützt. MCP-Server müssen StreamableHTTP verwenden.
- Öffentliche CA-TLS erforderlich:Für MCP-Endpunkte müssen TLS-Zertifikate verwendet werden, die von einer öffentlich vertrauenswürdigen CA signiert wurden, auch wenn privat über PSC darauf zugegriffen wird.
- Überschreiben der Organisationsrichtlinie:Sie müssen die Organisationsrichtlinie für benutzerdefinierte MCP-Datenspeicher explizit überschreiben, bevor Sie den Datenspeicher registrieren.
Damit sind wir mit den Konzepten fertig. Weiter geht es mit dem Abschnitt Einrichtung.
3. Einrichtung
Erforderliche IAM-Rollen
Für dieses Codelab sind die folgenden Rollen erforderlich:
Domain | Erforderliche IAM-Rollen |
Projekt und IAM |
|
Netzwerk und Gateway |
|
Gemini Enterprise und Registry |
|
Workloads und Entwicklung |
|
Beobachtbarkeit |
|
Oder Sie verwenden eine allgemeine einfache Rolle wie roles/owner in Kombination mit roles/orgpolicy.policyAdmin, da mit roles/owner allein keine Organisationsrichtlinien geändert werden können.
Auf Ihr Projekt zugreifen
In diesem Codelab wird ein einzelnes Google Cloud-Projekt verwendet. Bei den Konfigurationsschritten werden die gcloud-Befehlszeile und Linux-Shell-Befehle verwendet.
Rufen Sie zuerst die Befehlszeile Ihres Google Cloud-Projekts auf:
- Cloud Shell unter
shell.cloud.google.comoder - Ein lokales Terminal mit
gcloudCLI installiert
Projekt-ID festlegen
gcloud config set project SET_YOUR_PROJECT_ID_HERE
Sitzung authentifizieren
# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login
Shell-Umgebungsvariablen festlegen
# set custom var for slug (eg, "foo") and region preference
export SLUG="foo"
export REGION="us-central1"
echo ${SLUG}
echo ${REGION}
# create project vars (automatic)
export PROJ_ID=$(gcloud config list --format="value(core.project)")
export PROJ_NO=$(gcloud projects describe ${PROJ_ID} --format="value(projectNumber)")
export ORG_ID=$(gcloud projects get-ancestors ${PROJ_ID} --format="value(id)" | tail -n 1)
export USER_IDENTITY=$(gcloud config get-value account)
echo ${PROJ_ID}
echo ${PROJ_NO}
echo ${ORG_ID}
echo ${USER_IDENTITY}
# create resource vars for agent platform (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-ata"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export UAP_POLICY_NAME="uap-policy-${SLUG}"
export UAP_BINDING_NAME="uap-binding-${SLUG}"
export MCP_NAME="math-wizard"
export MCP_URL="https://${MCP_NAME}-${PROJ_NO}.${REGION}.run.app/mcp"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${UAP_POLICY_NAME}
echo ${UAP_BINDING_NAME}
echo ${MCP_NAME}
echo ${MCP_URL}
# create resource vars for gemini enterprise (automatic)
export GE_APP_DISPLAY_NAME="Codelab app"
export GE_APP_ORG_NAME="${SLUG}, Inc."
export GE_LOCATION="global"
export GE_APP_NAME="app-${SLUG}-${GE_LOCATION}"
export GE_APP_INIT="${GE_APP_NAME}_$(date +%s)"
echo ${GE_APP_DISPLAY_NAME}
echo ${GE_APP_ORG_NAME}
echo ${GE_LOCATION}
echo ${GE_APP_NAME}
echo ${GE_APP_INIT}
Vertrauenswürdige Domains für die Identität von KI‑Agenten festlegen
Mit der if-then-else-Anweisung wird geprüft, ob das Projekt zu einer Organisation gehört, um die richtige Vertrauensdomäne für die Identitäten des Haupt-Agents festzulegen.
# set var for trust domain
if [[ -n "${ORG_ID}" ]]; then
export TRUST_DOMAIN="agents.global.org-${ORG_ID}.system.id.goog"
else
export TRUST_DOMAIN="agents.global.proj-${PROJ_NO}.system.id.goog"
fi
echo "trust domain: ${TRUST_DOMAIN}"
Abrechnungs- und Kontingentprojekt festlegen
# set cli quota project
gcloud config set billing/quota_project ${PROJ_ID}
# set api quota project
gcloud auth application-default set-quota-project ${PROJ_ID}
Lokales Verzeichnis für Konfigurationsdateien erstellen
# create config folder
mkdir -p cfg
Update gcloud cli (empfohlen)
Wenn Sie eine selbstverwaltete Installation des Google Cloud SDK ausführen (d. h. außerhalb von Cloud Shell), aktualisieren Sie die Komponenten auf die neueste Version.
# update gcloud cli
gcloud components update
API-Dienste aktivieren
# enable google apis (part 1)
gcloud services enable \
agentregistry.googleapis.com \
agentidentity.googleapis.com \
aiplatform.googleapis.com \
apphub.googleapis.com \
apptopology.googleapis.com \
cloudapiregistry.googleapis.com \
cloudtrace.googleapis.com \
compute.googleapis.com \
dataform.googleapis.com \
iam.googleapis.com \
iap.googleapis.com \
logging.googleapis.com \
modelarmor.googleapis.com \
monitoring.googleapis.com \
networksecurity.googleapis.com \
networkservices.googleapis.com \
notebooks.googleapis.com \
observability.googleapis.com
# enable google apis (part 2)
gcloud services enable \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
discoveryengine.googleapis.com \
dns.googleapis.com \
orgpolicy.googleapis.com \
run.googleapis.com \
saasservicemgmt.googleapis.com \
securitycenter.googleapis.com \
storage.googleapis.com \
telemetry.googleapis.com \
texttospeech.googleapis.com
Organisationsrichtlinien
Die standardmäßigen Einschränkungen für verwaltete Organisationsrichtlinien für Google Cloud schränken die in diesem Codelab verwendeten Funktionen ein:
discoveryengine.managed.disableCustomMcpServerConnector:- Schränkt das Erstellen von Datenconnectors ein, die einen benutzerdefinierten MCP-Server (
custom_mcp) als Datenquelle verwenden (wird standardmäßig erzwungen).
- Schränkt das Erstellen von Datenconnectors ein, die einen benutzerdefinierten MCP-Server (
iam.managed.disableAccessPolicyBinding:- Beschränkt IAM v3-Zugriffsrichtlinienbindungen auf Ressourcen (wird standardmäßig erzwungen).
discoveryengine.managed.allowedEgressFqdns:- Beschränkt ausgehende Egress-Domains (
instance_uri-FQDNs) für Daten-Connectors, wenn VPC Service Controls (VPC-SC) aktiv ist oder das Projekt imenforcedProjects-Parameter der Organisation aufgeführt ist.
- Beschränkt ausgehende Egress-Domains (
discoveryengine.managed.allowedDataSources:- Beschränkt die zulässigen Dataconnector-Typen (
dataSource), wenn VPC-SC aktiv ist oder das Projekt im ParameterenforcedProjectsder Organisation aufgeführt ist.
- Beschränkt die zulässigen Dataconnector-Typen (
Überschreiben Sie alle geerbten Einschränkungen für Organisationsrichtlinien auf Projektebene, indem Sie enforce: false explizit festlegen.
Benutzerdefinierte MCP-Einschränkung deaktivieren
# disable data connector constraint (allow custom mcp servers)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.disableCustomMcpServerConnector
spec:
rules:
- enforce: false
EOF
# verify org policy constraint on project
gcloud org-policies describe discoveryengine.managed.disableCustomMcpServerConnector \
--project=${PROJ_ID} --effective
Einschränkung für Zugriffsrichtlinie deaktivieren
# disable iam v3 constraint (allow v3 access policies)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/iam.managed.disableAccessPolicyBinding
spec:
rules:
- enforce: false
EOF
# verify org policy constraint on project
gcloud org-policies describe iam.managed.disableAccessPolicyBinding \
--project=${PROJ_ID} --effective
Bedingte Einschränkungen für Daten-Connectors prüfen und deaktivieren
Standardmäßig wird die Connector-Erstellung durch discoveryengine.managed.allowedEgressFqdns und discoveryengine.managed.allowedDataSources nur blockiert, wenn sich Ihr Projekt in einem VPC Service Controls-Perimeter (VPC SC) befindet oder wenn ein Organisationsadministrator Ihr Projekt zu enforcedProjects hinzugefügt hat.
Sehen Sie sich zuerst die geltenden Richtlinien für Ihr Projekt an:
# check effective egress fqdn constraint on project
gcloud org-policies describe discoveryengine.managed.allowedEgressFqdns \
--project=${PROJ_ID} --effective
# check effective data source constraint on project
gcloud org-policies describe discoveryengine.managed.allowedDataSources \
--project=${PROJ_ID} --effective
~~IF~~ diese Einschränkungen erzwungen werden, legen Sie enforce: false für beide Richtlinien für Ihr Projekt fest, damit sie die Einrichtung des custom_mcp-Connectors in einer VPC SC oder einer organisationsrichtlinienbeschränkten Organisation nicht blockieren:
# disable egress fqdn constraint on project
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.allowedEgressFqdns
spec:
rules:
- enforce: false
EOF
# disable allowed data sources constraint on project
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.allowedDataSources
spec:
rules:
- enforce: false
EOF
# verify both constraints are disabled on project
gcloud org-policies describe discoveryengine.managed.allowedEgressFqdns \
--project=${PROJ_ID} --effective
gcloud org-policies describe discoveryengine.managed.allowedDataSources \
--project=${PROJ_ID} --effective
IAM-Berechtigungen
Weisen Sie Ihrem Nutzerkonto und dem von Cloud Build verwendeten Compute Engine-Standarddienstkonto die erforderlichen IAM-Rollen zu:
- Nutzerkonto (
${USER_IDENTITY})- :
- Erfordert Berechtigungen zum Bereitstellen und Aufrufen von Cloud Run-Diensten (
roles/run.admin,roles/run.invoker,roles/iam.serviceAccountUser), zum Erstellen von Container-Images (roles/cloudbuild.builds.editor), zum Verwalten von Gemini Enterprise (roles/discoveryengine.admin) und zum Erstellen von Unified Access Policies (roles/iam.accessPolicyAdmin).
- Erfordert Berechtigungen zum Bereitstellen und Aufrufen von Cloud Run-Diensten (
- Standardmäßiges Compute Engine-Dienstkonto(
${PROJ_NO}-compute@developer.gserviceaccount.com)- :
- Wird von Cloud Build verwendet, um Quellcode in Cloud Storage (
roles/storage.admin) bereitzustellen, Images in Artifact Registry (roles/artifactregistry.writer) zu übertragen und Build-Logs zu schreiben (roles/logging.logWriter).
- Wird von Cloud Build verwendet, um Quellcode in Cloud Storage (
Führen Sie die folgenden Befehle aus, um die Rollenbindungen zuzuweisen:
# grant roles to user account
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/run.invoker"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/discoveryengine.admin"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/iam.accessPolicyAdmin"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="user:${USER_IDENTITY}" \
--role="roles/cloudbuild.builds.editor"
# grant roles to default compute (cloud build) service account
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
--role="roles/storage.admin"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
--role="roles/artifactregistry.writer"
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
--role="roles/logging.logWriter"
IAM-Berechtigungen überprüfen
Prüfen Sie, ob für das Nutzerkonto die sechs Rollenbindungen (6) vorhanden sind.
# show iam policy on project for user account
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.members:${USER_IDENTITY}" \
--format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"
Prüfen Sie, ob die drei (3) Rollenbindungen für das Standarddienstkonto für Compute Engine vorhanden sind.
# show iam policy on project for default compute service account
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.members:${PROJ_NO}-compute@developer.gserviceaccount.com" \
--format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"
Bindungen des Dienst-Agents prüfen (Vorsichtsmaßnahme)
In einem neuen Projekt stellt Google Cloud automatisch den Agent Gateway-Dienst-Agent bereit und gewährt ihm roles/agentgateway.serviceAgent, wenn networkservices.googleapis.com zum ersten Mal aktiviert wird. Wenn Sie ein vorhandenes Projekt wiederverwenden, in dem durch vorherige Bereinigungen möglicherweise Standardbindungen für Dienst-Agents entfernt wurden, führen Sie die folgenden Befehle als Fail-Safe aus, um sicherzustellen, dass die Identitäts- und Rollenbindung intakt sind:
# ensure network services service account has been created
gcloud beta services identity create \
--service=networkservices.googleapis.com \
--project="${PROJ_ID}"
# ensure network services service account has service agent roles applied
gcloud projects add-iam-policy-binding "${PROJ_ID}" \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-agentgateway.iam.gserviceaccount.com" \
--role="roles/agentgateway.serviceAgent"
Das war der Einrichtungsteil. Weiter geht es mit dem Abschnitt Netzwerk.
4. Netzwerk
In diesem Abschnitt stellen Sie ein VPC-Netzwerk im benutzerdefinierten Modus mit einem dedizierten /28-Subnetz (192.168.10.0/28) bereit, das die Netzwerk-Attachment für Private Service Connect (PSC) für den Netzwerk-Egress von Agent Gateway in das VPC-Netzwerk unterstützt.
Der PSC-Endpunkt für Google APIs wird mit einer einzelnen /32globalen internen IPv4-Adresse (172.16.20.20) bereitgestellt, um den privaten internen Zugriff auf Google APIs und Google-Dienste zu unterstützen. In diesem Codelab wird Cloud Run über den PSC-Endpunkt als Ziel für das Agent Gateway verwendet. Dazu wird die run.app.-Domain über Cloud DNS-Peering aufgelöst.
Netzwerke erstellen
Globales VPC-Netzwerk erstellen
# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom
Subnetze für die PSC-Netzwerkverbindung des Agent Gateway erstellen:
# create subnet for agent gateway psc na
gcloud compute networks subnets create subnet-${REGION}-agw \
--network=vnet-${SLUG} \
--range=192.168.10.0/28 \
--region=${REGION} \
--enable-private-ip-google-access
Firewallregeln erstellen
Erstellen Sie eine Firewallrichtlinie, die den gesamten ausgehenden Traffic mit aktiviertem Logging zulässt. Damit wird der Traffic überwacht, der vom Agent Gateway zum VPC-Netzwerk übertragen wird. Cloud NGFW unterstützt sowohl die Essentials- als auch die Standardstufe für Netzwerksicherheit und Traffic-Monitoring.
# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG} --global
# create fw policy rule
gcloud compute network-firewall-policies rules create 1001 \
--description="allow all out and log" \
--firewall-policy=fw-policy-${SLUG} \
--global-firewall-policy \
--action=allow \
--direction=EGRESS \
--layer4-configs=all \
--dest-ip-ranges=0.0.0.0/0 \
--enable-logging
# bind fw policy to network
gcloud compute network-firewall-policies associations create \
--name=fw-policy-bind-${SLUG} \
--firewall-policy=fw-policy-${SLUG} \
--network=vnet-${SLUG} \
--global-firewall-policy
PSC-Netzwerkanhang erstellen
Erstellen Sie einen Private Service Connect-Netzwerkanhang (PSC), der so konfiguriert ist, dass Verbindungen von Agent Gateway automatisch akzeptiert werden. Der Netzwerkanhang stellt die Nutzer-VPC-Netzwerkseite der Verbindung her, um eine sichere Verbindung mit der Produzenten-Seite des Agent Gateway für ausgehenden Traffic herzustellen. Weitere Informationen zu Subnetzanforderungen und IP-Bereichsspezifikationen finden Sie unter VPC-Verbindung konfigurieren.
# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
--region=${REGION} \
--subnets=subnet-${REGION}-agw \
--connection-preference=ACCEPT_AUTOMATIC
PSC-Netzwerkanhang prüfen
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}
Rufen Sie den Ressourcen-URI der PSC-Netzwerkverbindung ab und speichern Sie ihn in der Umgebungsvariable PSC_NA_URI. Auf diesen URI wird in der Agent Gateway-Konfiguration (networkConfig.egress.networkAttachment) verwiesen, um die PSC-Schnittstelle für den Netzwerkausgang in das VPC-Netzwerk bereitzustellen:
# fetch psc network attachment uri
export PSC_NA_URI=$(gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="value(selfLink.scope(v1))")
echo ${PSC_NA_URI}
PSC-Endpunkt erstellen
Ein Private Service Connect-Endpunkt (PSC) für Google APIs wird für Agent Gateway verwendet, um eine private Verbindung zum Cloud Run-MCP-Server über einen internen Netzwerkpfad herzustellen, ohne Traffic im öffentlichen Internet verfügbar zu machen. Bei ausgehenden Tool-Aufrufen, die von Agent Gateway in das VPC-Netzwerk geleitet werden, wird die Ziel-Cloud Run-Dienst-URL (*.run.app) in diese private Endpunkt-IP-Adresse aufgelöst.
Reservieren Sie eine globale interne IPv4-Adresse für den PSC-Endpunkt. Die ausgewählte IP-Adresse muss eine /32-Adresse sein, die sich nicht mit vorhandenen Subnetzen in Ihrem VPC-Netzwerk überschneidet:
# set env var for psc ep ip address
export PSC_EP_IP="172.16.20.20"
echo ${PSC_EP_IP}
# reserve internal global ipv4 address
gcloud compute addresses create ip-psc2gapis \
--global \
--purpose=PRIVATE_SERVICE_CONNECT \
--addresses=${PSC_EP_IP} \
--network=vnet-${SLUG}
Erstellen Sie einen PSC-Endpunkt für Google APIs mit dem all-apis-Bundle, das Cloud Run (run.app) enthält.
# create psc endpoint for google apis
gcloud compute forwarding-rules create psc2gapis \
--global \
--network=vnet-${SLUG} \
--address=ip-psc2gapis \
--target-google-apis-bundle=all-apis
PSC-Endpunkt prüfen
# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global
DNS-Zone und ‑Einträge erstellen
Cloud DNS wird verwendet, damit das Agent Gateway privat mit dem in Cloud Run gehosteten MCP-Server kommunizieren kann. Wenn Agent Gateway ausgehende Tool-Anfragen an Cloud Run auswertet, wird DNS-Peering (dnsPeeringConfig.domains) verwendet, um DNS-Abfragen für *.run.app mit Ihrer privaten Cloud DNS-Zone aufzulösen, die Ihrem VPC-Netzwerk zugeordnet ist. Der private DNS-Eintrag gibt die Anfrage mit der internen PSC-Endpunkt-IP-Adresse (172.16.20.20) zurück, sodass MCP-Toolanfragen über einen privaten Netzwerkpfad weitergeleitet werden können.
Erstellen Sie eine private, von Cloud DNS verwaltete Zone für die Domain run.app.:
# create private dns zone
gcloud dns managed-zones create priv-zone-run \
--description="private zone for run.app" \
--dns-name="run.app." \
--visibility=private \
--networks=vnet-${SLUG}
Erstellen Sie einen Platzhalter-DNS-Eintrag vom Typ A für *.run.app., der auf die IP-Adresse des PSC-Endpunkts verweist:
# create dns record
gcloud dns record-sets create "*.run.app." \
--zone=priv-zone-run \
--type=A \
--ttl=300 \
--rrdatas=${PSC_EP_IP}
Erstellen Sie eine Cloud DNS-Richtlinie, um das Logging von DNS-Abfragen zu aktivieren. Beim DNS-Logging werden Domainauflösungsanfragen erfasst, die vom Agent Gateway in Ihrem VPC-Netzwerk stammen. So können Sie prüfen, ob *.run.app-Toolanfragen korrekt zum internen PSC-Endpunkt aufgelöst werden:
# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
--description="dns logging for vnet-${SLUG}" \
--networks=vnet-${SLUG} \
--enable-logging
Damit ist der Netzwerkteil abgeschlossen. Fahren Sie mit dem Abschnitt Agent Gateway fort.
5. Agent Gateway
Agent Gateway gibt registries für Agent Registry-Instanzen zusammen mit den Feldern networkConfig an, die den PSC-Netzwerkanhang und die DNS-Peering-Einstellungen für private VPC-Verbindungen konfigurieren:
registries:Ordnet das Gateway bis zu zwei Agent Registry-Instanzen zu: einer regionalen (../locations/${REGION}) und einer globalen (../locations/global). Dadurch wird Agent Gateway in Agent Registry eingebunden, um sowohl regionale Bereitstellungen (z. B. Cloud Run-MCP-Server in${REGION}) als auch globale Ressourcen (z. B. Gemini Enterprise-Agents und globale Endpunkte) für die detaillierte IAP v2-Richtlinienerzwingung aufzulösen. Regionale Einträge haben Vorrang vor globalen Einträgen, wenn Ziel-URLs aufgelöst werden.networkAttachment:Verweist auf den PSC-Netzwerkanhang (psc-na-${REGION}-agw), der das Agent Gateway für den privaten ausgehenden Traffic mit Ihrem VPC-Netzwerk verbindet.dnsPeeringConfig.domains:Konfiguriertrun.app.so, dass DNS-Anfragen, die von Agent Gateway für Cloud Run-Dienste stammen, DNS-Peering verwenden, um Hostnamen in die private Google APIs PSC-Endpunkt-IP-Adresse (172.16.20.20) aufzulösen, die in Ihrer privaten Cloud DNS-Zone konfiguriert ist.
KI-Agenten-Gateway bereitstellen
Konfigurationsdatei für das Agent Gateway erstellen und importieren
# create agent gateway config file
cat > cfg/${AGW_NAME}-networkConfig.yaml << EOF
name: ${AGW_NAME}
protocols:
- MCP
googleManaged:
governedAccessPath: AGENT_TO_ANYWHERE
registries:
- "//agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}"
networkConfig:
egress:
networkAttachment: ${PSC_NA_URI}
dnsPeeringConfig:
domains:
- run.app.
targetProject: ${PROJ_ID}
targetNetwork: projects/${PROJ_ID}/global/networks/vnet-${SLUG}
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
--source="cfg/${AGW_NAME}-networkConfig.yaml" \
--location=${REGION}
Agent Gateway-Bereitstellung überprüfen
Bestätigen Sie die Agent-Registrierung und die Netzwerkkonfiguration:
# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--format="yaml(registries,networkConfig)"
Erwartete Ausgabe:
networkConfig:
dnsPeeringConfig:
domains:
- run.app.
targetNetwork: projects/${PROJ_ID}/global/networks/vnet-${SLUG}
targetProject: ${PROJ_ID}
egress:
networkAttachment: projects/${PROJ_ID}/regions/${REGION}/networkAttachments/psc-na-${REGION}-agw
registries:
- //agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}
Prüfen Sie, ob in der Ausgabe die erforderlichen Konfigurationsdetails angezeigt werden:
registries:Listet den regionalen (${REGION}) Agent Registry-URI auf, der dem Gateway zugeordnet ist.egress.networkAttachment:Gibt den URI des PSC-Netzwerk-Attachments für VPC-Ausgang an.dnsPeeringConfig.domains:Enthältrun.app., die auftargetNetworkfür die Auflösung privater Domains verweisen.
Prüfen Sie die PSC-Netzwerkverbindung, um die Gateway-Verbindung zu bestätigen:
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="yaml(connectionEndpoints)"
Prüfen Sie, ob ein akzeptierter Verbindungsendpunkt vorhanden ist:
connectionEndpoints:
- ipAddress: 192.168.10.2
projectIdOrNum: '<AGW_TENANT_PROJ_NO>'
status: ACCEPTED
subnetwork: https://www.googleapis.com/compute/v1/projects/${PROJ_ID}/regions/${REGION}/subnetworks/subnet-${REGION}-agw
Autorisierung delegieren
Agent Gateway schützt und steuert ausgehenden Tool-Traffic mithilfe von Autorisierungsrichtlinien (networksecurity.authzPolicies), die in Identity-Aware Proxy (IAP) Unified Access Policies (UAP) eingebunden sind.
Agent Gateway unterstützt zwar grundlegende Inline-ALLOW- und DENY-Regeln, in Unternehmensumgebungen ist jedoch eine zentrale, identitätsbezogene Verwaltung erforderlich. Mit IAM Unified Access Policies (oder Zugriffsrichtlinien) verwalten Sie Regeln für den ausgehenden Zugriff mit standardmäßigen IAM v3-Zugriffsrichtlinien.
Abbildung 3. Autorisierungsarchitektur
Der Autorisierungsablauf verbindet drei Komponenten:
- Gateway Authorization Policy (
authzPolicy):- Eine regionale Ressource, die auf das Agent Gateway ausgerichtet ist.
- Mit
policyProfile: REQUEST_AUTHZundaction: CUSTOMkonfiguriert, um alle ausgehenden Autorisierungsprüfungen an die IAP Authz Extension weiterzuleiten.
- IAP Service Extension (
authzExtension):- Eine regionale Ressource, die die Autorisierung von Anfragen an Identity-Aware Proxy (
iap.googleapis.com) delegiert. - Bewertet Richtlinien im
ENFORCE-Modus mit RichtlinienversionV2.
- Eine regionale Ressource, die die Autorisierung von Anfragen an Identity-Aware Proxy (
- IAM Unified Access Policy and Binding (
accessPolicy&policyBinding):- Globale IAM v3-Ressourcen mit detaillierten Zugriffsregeln.
- Authentifiziert die SPIFFE-Hauptidentität des aufrufenden Agents, prüft die universelle Berechtigung
iap.googleapis.com/resources.egressViaIAPund wertet CEL-Bedingungen (Common Expression Language) anhand von Zielattributen aus.
Autorisierungserweiterung bereitstellen
Erstellen Sie eine service-extensions-Autorisierungserweiterungskonfiguration, die Autorisierungsentscheidungen an den IAP-Dienst delegiert:
# create authz extension config file
cat > cfg/${AGW_NAME}-svc-ext-authz-iap.yaml << EOF
name: ${AGW_NAME}-svc-ext-authz-iap
service: iap.googleapis.com
failOpen: false
timeout: 1s
metadata:
iapPolicyVersion: "V2"
EOF
# import iap authz extension (create authz extension)
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-iap \
--source=cfg/${AGW_NAME}-svc-ext-authz-iap.yaml \
--location=${REGION}
Autorisierungserweiterung überprüfen
Prüfen Sie, ob die Autorisierungserweiterung aktiv ist:
# list authz extensions
gcloud service-extensions authz-extensions list \
--location=${REGION} \
--format="table(
name.basename():label=NAME,
createTime.date(tz=LOCAL):label=CREATED,
updateTime.date(tz=LOCAL):label=MODIFIED,
service:label=SERVICE,
metadata:label=METADATA,
timeout:label=TIMEOUT
)"
Autorisierungsrichtlinie bereitstellen
Erstellen Sie eine network-security-Autorisierungsrichtlinienkonfiguration, die auf das Agent Gateway ausgerichtet ist und die Anfrageüberprüfung an die Autorisierungserweiterung für IAP delegiert:
# create authz policy config file
cat > cfg/${AGW_NAME}-authz-policy-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-iap
target:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
authzExtension:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap"
EOF
# import authz policy config file (create authz policy)
gcloud network-security authz-policies import ${AGW_NAME}-authz-policy-iap \
--source=cfg/${AGW_NAME}-authz-policy-iap.yaml \
--location=${REGION}
Autorisierungsrichtlinie prüfen
Prüfen Sie, ob die Autorisierungsrichtlinie aktiv ist:
# list authz policies
gcloud network-security authz-policies list \
--location=${REGION} \
--format="table(
name.basename():label=NAME,
action:label=ACTION,
customProvider.list().sub('\W.*', ''):label=CUSTOM_PROVIDER_TYPE,
policyProfile:label=POLICY_PROFILE,
customProvider.authzExtension.resources[0].basename():label=CUSTOM_PROVIDER_RESOURCE
)"
IAM-Zugriffsrichtlinien erstellen
Agent Gateway delegiert Autorisierungsprüfungen jetzt an IAP und löst Zielmetadaten aus Agent Registry auf. Definieren Sie als Nächstes eine IAM Unified Access Policy-Regel, um die Ausführung ausgehender Tools zu steuern.
IAP wertet CEL-Attributausdrücke anhand der folgenden Zielattribute der Agent Registry aus:
- Registrierter Status (
destination.is_registered):- Boolescher Wert (
true/false), der angibt, ob das Ziel in der Agent Registry katalogisiert ist.
- Boolescher Wert (
- Name des MCP-Servers (
destination.agent_registry.mcp_server.name):- Der kanonische MCP-Server-Ressourcenname, der in Agent Registry registriert ist.
- MCP-Methode (
destination.agent_registry.mcp_server.method):- Die aufgerufene MCP-Methode, z. B.
tools/call,tools/listoderinitialize.
- Die aufgerufene MCP-Methode, z. B.
- Name des Tools (
destination.agent_registry.mcp_server.tool.name):- Der Name des aufgerufenen Tools, z. B.
subtractoderadd. Dies ermöglicht eine detaillierte Autorisierung auf Tool-Ebene auf registrierten MCP-Servern.
- Der Name des aufgerufenen Tools, z. B.
IAM-Zugriffsrichtlinienregel definieren
Das Manifest der IAM-Richtlinienregel gibt Folgendes an:
- Principals:Die SPIFFE-Hauptidentität, die den Gemini Enterprise-Kernassistenten-Agenten repräsentiert.
- Berechtigungen:Die universelle Berechtigung
iap.googleapis.com/resources.egressViaIAP, die für den gesamten ausgehenden Traffic, der von IAP verwaltet wird, erforderlich ist. - Bedingungen:Ein CEL-Ausdruck (
destination.is_registered == true), der dafür sorgt, dass der Agent nur Endpunkte aufrufen kann, die in der Agent Registry katalogisiert sind.
Manifestdatei für die Richtlinienregel erstellen:
# create access policy rule file
cat > cfg/${UAP_POLICY_NAME}-rules.json << EOF
[
{
"description": "allow ge assistant to any registered service",
"effect": "ALLOW",
"principals": [
"principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_INIT}/assistants/default_assistant/agents/default/core_assistant"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true"
}
}
}
]
EOF
IAM-Zugriffsrichtlinie bereitstellen
Erstellen Sie die globale IAM-Zugriffsrichtlinie anhand der in der Manifestdatei definierten Regeln:
# create iam access policy
gcloud iam access-policies create ${UAP_POLICY_NAME} \
--details-rules=cfg/${UAP_POLICY_NAME}-rules.json \
--project=${PROJ_ID} \
--location=global
IAM-Zugriffsrichtlinie überprüfen
Prüfen Sie, ob die IAM-Zugriffsrichtlinie erfolgreich erstellt wurde, und sehen Sie sich die Regeldetails an:
# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJ_ID} \
--location=global
Erwartete Ausgabe:
details:
rules:
- conditions:
iap.googleapis.com:
expression: destination.is_registered == true
description: allow ge assistant to any registered service
effect: ALLOW
operation:
permissions:
- iap.googleapis.com/resources.egressViaIAP
principals:
- principal://agents.global.org-${ORG_ID}.system.id.goog/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_INIT}/assistants/default_assistant/agents/default/core_assistant
name: projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}
IAM-Zugriffsrichtlinie an Projekt binden
Wenn Sie die Erzwingung für alle Agent Gateways in Ihrem Projekt aktivieren möchten, erstellen Sie eine Richtlinienbindung, mit der die IAM-Zugriffsrichtlinie an die Projektressource angehängt wird:
# bind iam access policy to project resource
gcloud iam policy-bindings create ${UAP_BINDING_NAME} \
--policy="projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}" \
--target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJ_ID}" \
--project=${PROJ_ID} \
--location=global
IAM-Richtlinienbindung für den Zugriff prüfen
Prüfen Sie, ob die aktiven Richtlinienbindungspunkte auf die richtige Richtlinie und das richtige Ziel verweisen:
# show policy binding details
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
--project=${PROJ_ID} \
--location=global
Erwartete Ausgabe:
name: projects/${PROJ_ID}/locations/global/policyBindings/${UAP_BINDING_NAME}
policy: projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}
policyKind: ACCESS
target:
resource: //cloudresourcemanager.googleapis.com/projects/${PROJ_ID}
Damit ist der Abschnitt zum Agent Gateway abgeschlossen. Als Nächstes folgt der Abschnitt zum MCP-Server.
6. MCP-Server
In diesem Abschnitt erstellen Sie einen benutzerdefinierten FastMCP-Server, der die Tools add und subtract bereitstellt, und stellen ihn direkt aus der Quelle in Cloud Run bereit. Während der Quellcodebereitstellung (--source) verpackt Cloud Build das Container-Image mit dem enthaltenen Dockerfile und uv (wodurch die in pyproject.toml definierten Abhängigkeiten installiert und server.py gestartet wird).
Sobald der Cloud Run-Dienst bereitgestellt wurde, registrieren Sie den MCP-Server in der Agent Registry zusammen mit der zugehörigen Tool-Spezifikation (toolspec.json), damit Gemini Enterprise die Tools erkennen und aufrufen kann.
MCP-Serveranwendung erstellen
Erstellen Sie ein math-wizard-Projektverzeichnis für den Anwendungscode:
# create directory for code
mkdir -p math-wizard
Manifestdatei für das Python-Projekt schreiben:
# create python project manifest file
cat > math-wizard/pyproject.toml << 'EOF'
[project]
name = "math-wizard"
version = "0.1.0"
description = "math wizard mcp server"
requires-python = ">=3.12"
dependencies = [
"fastmcp==2.13.1",
]
EOF
Einige zusätzliche Instrumentierungsfunktionen sind im Code enthalten, um eingehende HTTP-Header (mcp-session-id, x-forwarded-for, user-agent und x-cloud-trace-context) für die Cloud Logging- und Cloud Trace-Validierung zu erfassen.
Schreiben Sie die Anwendungscode-Datei:
# create mcp server application code
cat > math-wizard/server.py << 'EOF'
import asyncio
import json
import logging
import os
from fastmcp import FastMCP
from fastmcp.server.dependencies import get_http_headers
from mcp.types import ToolAnnotations
logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
mcp = FastMCP("math wizard mcp server")
def log_network_context(tool_name: str, a: int, b: int) -> None:
headers = get_http_headers()
print(json.dumps({
"severity": "INFO",
"message": f">>> 🛠️ Tool: '{tool_name}' called with numbers '{a}' and '{b}'",
"tool": tool_name,
"mcp_session_id": headers.get("mcp-session-id"),
"x_forwarded_for": headers.get("x-forwarded-for"),
"user_agent": headers.get("user-agent"),
"trace_header": headers.get("x-cloud-trace-context"),
}), flush=True)
@mcp.tool(
annotations=ToolAnnotations(
readOnlyHint=True,
)
)
def add(a: int, b: int) -> int:
"""Use this to add two numbers together.
Args:
a: The first number.
b: The second number.
Returns:
The sum of the two numbers.
"""
logger.info(f">>> 🛠️ Tool: 'add' called with numbers '{a}' and '{b}'")
log_network_context("add", a, b)
return a + b
@mcp.tool(
annotations=ToolAnnotations(
readOnlyHint=True,
)
)
def subtract(a: int, b: int) -> int:
"""Use this to subtract two numbers.
Args:
a: The first number.
b: The second number.
Returns:
The difference of the two numbers.
"""
logger.info(f">>> 🛠️ Tool: 'subtract' called with numbers '{a}' and '{b}'")
log_network_context("subtract", a, b)
return a - b
if __name__ == "__main__":
logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}")
asyncio.run(
mcp.run_async(
transport="streamable-http",
host="0.0.0.0",
port=int(os.getenv("PORT", 8080)),
)
)
EOF
Schreiben Sie die Dockerfile, um Anleitungen zum Erstellen von Container-Images und Startbefehle zu definieren:
# create dockerfile
cat > math-wizard/Dockerfile << 'EOF'
# use official python 3.12 image
FROM python:3.12-slim
# install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# install the project into /app
COPY . /app
WORKDIR /app
# allow statements and log messages to immediately appear in the logs
ENV PYTHONUNBUFFERED=1
# install dependencies
RUN uv sync
EXPOSE 8080
# run the mcp server
CMD ["uv", "run", "server.py"]
EOF
Dienst in Cloud Run bereitstellen
Stellen Sie den MCP-Server aus der Quelle mit Cloud Build bereit (dabei wird das Compute-Standarddienstkonto des Projekts ${PROJ_NO}-compute@developer.gserviceaccount.com verwendet):
# deploy cloud run service
gcloud run deploy ${MCP_NAME} \
--source math-wizard \
--region=${REGION} \
--no-invoker-iam-check \
--ingress=internal \
--quiet
Cloud Run-Bereitstellung prüfen
Prüfen Sie die Details des Cloud Run-Dienstes, um die aktive Konfiguration zu ermitteln:
# show cloud run service details
gcloud run services describe ${MCP_NAME} --region=${REGION}
Erwartete Ausgabe:
<snip>
✔ Service math-wizard in region ${REGION}
URL: https://math-wizard-${PROJ_NO}.${REGION}.run.app
Ingress: internal
Traffic:
100% LATEST (currently math-wizard-00001-<id>)
</snip>
MCP-Server in Agent Registry registrieren
Damit Gemini Enterprise die genauen Tools erkennen kann, die auf dem MCP-Server verfügbar sind, muss bei der Registrierung in Agent Registry eine Tool-Spezifikationsdatei (toolspec.json) angegeben werden.
MCP-Tool-Spezifikation erstellen
# create tool spec file
cat > cfg/toolspec.json << 'EOF'
{
"tools": [
{
"name": "add",
"description": "Use this to add two numbers together.",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "integer", "description": "The first number." },
"b": { "type": "integer", "description": "The second number." }
},
"required": ["a", "b"]
},
"isReadOnly": true,
"isDestructive": false,
"isIdempotent": true,
"isOpenWorld": false
},
{
"name": "subtract",
"description": "Use this to subtract two numbers.",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "integer", "description": "The first number." },
"b": { "type": "integer", "description": "The second number." }
},
"required": ["a", "b"]
},
"isReadOnly": true,
"isDestructive": false,
"isIdempotent": true,
"isOpenWorld": false
}
]
}
EOF
MCP-Server in Agent Registry registrieren
# register mcp server in agent registry
gcloud agent-registry services create ${MCP_NAME} \
--project=${PROJ_ID} \
--location=${REGION} \
--display-name="${MCP_NAME}-${PROJ_NO}.${REGION}.run.app" \
--description="MANDATORY MATH & ARITHMETIC AGENT: You MUST ALWAYS invoke \
this tool for ANY mathematical calculation, addition (+), subtraction (-), \
sum, difference, or arithmetic question (including simple questions like \
'what is 67 + 345?'). NEVER compute arithmetic yourself and NEVER transfer \
math queries to file_and_coding_agent / code interpreter. Always delegate \
every math question to this tool." \
--mcp-server-spec-type=tool-spec \
--mcp-server-spec-content=cfg/toolspec.json \
--interfaces=protocolBinding=JSONRPC,url="${MCP_URL}"
MCP-Server in Agent Registry überprüfen
Prüfen Sie, ob der bereitgestellte Cloud Run-Dienst in der Region als registrierter MCP-Server mit seiner Endpunkt-URL und den verfügbaren Tools aufgeführt ist:
# list registered mcp servers in agent registry
gcloud agent-registry mcp-servers list \
--location=${REGION} \
--project=${PROJ_ID} \
--format="table(
name.basename():label=REGISTRY_ID,
displayName:label=DISPLAY_NAME,
interfaces[0].url:label=ENDPOINT_URL,
tools[].name.list():label=TOOLS
)"
Erwartete Ausgabe:
REGISTRY_ID DISPLAY_NAME ENDPOINT_URL TOOLS
agentregistry-00000000-0000-0000-0012-3456789abcde math-wizard-${PROJ_NO}.${REGION}.run.app https://math-wizard-${PROJ_NO}.${REGION}.run.app/mcp add,subtract
Sehen Sie sich die Dienstkonfigurationsspezifikation an, um zu sehen, dass sie die genauen Tool-Definitionen, Eingabeschemas und Verhaltensanmerkungen für jedes Tool registriert:
# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
--location=${REGION} \
--project=${PROJ_ID} \
--format="yaml(mcpServerSpec.content.tools)"
Damit ist der Teil zum MCP-Server abgeschlossen. Weiter geht es mit dem Abschnitt zu Gemini Enterprise.
7. Gemini Enterprise
In diesem Abschnitt erstellen und konfigurieren Sie eine Gemini Enterprise-App und eine verknüpfte benutzerdefinierte MCP-Server-Datenspeicher-Ressource.
Discovery Engine-Ressourcenmodell
Eine Gemini Enterprise-App (in der Discovery Engine API als Engine-Ressource dargestellt) ist die zentrale Orchestrierungsebene und Konversationsschnittstelle für Endnutzer. Sie verwaltet Nutzer-Chatsitzungen, stützt generative Modelle auf Unternehmensdaten und koordiniert die dynamische Ausführung von Tools.
Gemini Enterprise-Apps interagieren über Datenspeicher mit Daten und Systemen:
- Wissensdatenspeicher:Statische Inhalte (z. B. Cloud Storage, Google Drive, BigQuery) für Retrieval Augmented Generation (RAG) aufnehmen und indexieren.
- Daten-Connectors (Aktionsanbieter): Sie können eine Verbindung zu dynamischen Drittanbieter- oder benutzerdefinierten APIs herstellen. Ein benutzerdefinierter MCP-Server-Datenspeicher stellt Tools bereit, die durch das Model Context Protocol (MCP) definiert werden. So kann das Modell während einer Unterhaltung dynamisch externe Funktionen aufrufen.
Routing für ausgehenden Traffic über Agent Gateway
Standardmäßig leitet Gemini Enterprise Connector- und Tool-Ausführungstraffic über öffentliche Netzwerke weiter. Für private VPC-Arbeitslasten und Zero-Trust-Governance kann die Engine jedoch so konfiguriert werden, dass der ausgehende Traffic über das Agent Gateway geleitet wird:
- Wenn Sie den benutzerdefinierten MCP-Server-Datenspeicher später in diesem Lab erstellen, aktivieren Sie in den Datenspeichereinstellungen die Option Route egress through Agent Gateway (Ausgang über Agent Gateway weiterleiten).
- Dadurch werden die ausgehenden Tool-Aufrufe der Engine an Ihr regionales Agent Gateway gebunden. So wird sichergestellt, dass alle MCP-Anfragen die
Agent Identityder App enthalten, die Laufzeitautorisierung über IAP und IAM Unified Access Policies (UAP) erfolgt und die PSC-Netzwerkverbindung in Ihre private VPC führt.
Gemini Enterprise-App erstellen
Bei der folgenden Methode wird die discoveryengine.googleapis.com API verwendet, um die Ressourcen und Konfiguration der Gemini Enterprise-App zu erstellen. Eine Anleitung zur Konfiguration über die Google Cloud Console-UI finden Sie unter App erstellen.
# create engine (ge app)
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines?engineId=${GE_APP_INIT}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"displayName": "${GE_APP_DISPLAY_NAME}",
"dataStoreIds": [],
"solutionType": "SOLUTION_TYPE_SEARCH",
"industryVertical": "GENERIC",
"appType": "APP_TYPE_INTRANET",
"searchEngineConfig": {
"searchTier": "SEARCH_TIER_ENTERPRISE",
"searchAddOns": [
"SEARCH_ADD_ON_LLM"
]
},
"commonConfig": {
"companyName": "${GE_APP_ORG_NAME}"
}
}
EOF
App-Erstellung bestätigen
# fetch engine (ge app) id
export GE_APP_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" -H "X-Goog-User-Project: ${PROJ_ID}" \
| jq -r --arg name "${GE_APP_DISPLAY_NAME}" '.engines[] | select(.displayName==$name) | .name | split("/") | last')
echo "engine (ge app) id: ${GE_APP_ID}"
So rufen Sie die erstellte Konfiguration auf:
# get engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Beachten Sie die folgenden serverseitig ausgefüllten Attribute in der JSON-Antwort:
name: Kanonischer Ressourcenpfad (projects/${PROJ_NO}/locations/global/collections/default_collection/engines/${GE_APP_ID}).sessionConfig.sessionManagementPolicy: Standardmäßig wird"VERTEX_AI_MANAGED"verwendet, wodurch der Status von Multi-Turn-Chats und Tool-Aufrufen in der Agent Platform (früher Vertex AI) beibehalten wird.observabilityConfig.observabilityEnabled: Der Standardwert für Basismesswerte isttrue. Das detaillierte Logging von Prompts und Tool-Nutzlasten wird in einem späteren Schritt aktiviert.
Identitätsanbieter aktivieren
Aktivieren Sie Google Identity als Identitätsanbieter für die Endnutzerauthentifizierung in Ihrer Gemini Enterprise-App.
Bei der folgenden Methode wird die discoveryengine.googleapis.com API verwendet, um den Identitätsanbieter der Gemini Enterprise-App zu konfigurieren. Eine Anleitung zur Konfiguration über die Google Cloud Console-Benutzeroberfläche finden Sie unter Identitätsanbieter konfigurieren.
# set identity provider
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"idpConfig": {
"idpType": "GSUITE"
}
}
EOF
Identitätsanbieter bestätigen
# show identity provider
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Die Ausgabe "idpType": "GSUITE" entspricht dem Google-Identitätsanbieter.
(Optional) Gemini Enterprise-Testlizenz aktivieren
Wenn Sie ein Projekt mit zugewiesenen Gemini Enterprise-Lizenzen verwenden, können Sie diesen Schritt überspringen. Wenn Sie ein neues Projekt ohne Lizenz verwenden, fahren Sie mit den folgenden Schritten fort.
Erstellen Sie eine Lizenzkonfigurationsressource, um Gemini Enterprise-Nutzerplätze für 30 Tage zu autorisieren. Dadurch wird die Standardlizenz auf den neuen Testzeitraum festgelegt, sodass jeder Nutzer, der sich anmeldet, automatisch einen Arbeitsplatz erhält:
# configure free trial subscription
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs?licenseConfigId=free_trial_gemini" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"subscriptionTier": "SUBSCRIPTION_TIER_SEARCH_AND_ASSISTANT",
"freeTrial": true
}
EOF
Prüfen, ob die Lizenz angewendet wurde
# show license config
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs/free_trial_gemini" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Prüfen Sie "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" und "freeTrial": true.
# verify auto-registration enabled on default user store
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/userStores/default_user_store" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Prüfen Sie ../free_trial_gemini" und "enableLicenseAutoRegister": true.
Einstellungen für die Beobachtbarkeit aktivieren
Wenn Sie Beobachtbarkeit auf Ebene der Gemini Enterprise App (Engine) aktivieren, können Sie die Interaktionen des Hauptassistenten mit Messwertdaten im Metrics Explorer ansehen und End-to-End-Traces in Cloud Trace korrelieren.
# set observability on engine (ge app)
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}?updateMask=observabilityConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"observabilityConfig": {
"observabilityEnabled": true,
"sensitiveLoggingEnabled": true
}
}
EOF
Einstellungen für Beobachtbarkeit überprüfen
# verify observability is enabled on engine (ge app)
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{observabilityConfig: .observabilityConfig}'
Suchen Sie nach "sensitiveLoggingEnabled": true.
An Agent Gateway binden
Wenn ausgehender Traffic von Gemini Enterprise über Agent Gateway weitergeleitet wird, wird eine zentrale Zero-Trust-Grenze für Governance und Sicherheit für alle Tool-Aufrufe von KI-Agenten eingerichtet:
- Zentrale Richtliniendurchsetzung:Agent Gateway fungiert als Inline-Proxy, der ausgehende Toolanfragen anhand von Autorisierungsrichtlinien und Governance-Kontrollen auswertet, bevor der Traffic die Agent-Umgebung verlässt.
- Ausgehender Traffic aus dem privaten Netzwerk:Durch die Bindung von Gemini Enterprise an das Agent Gateway werden Tool-Aufrufe, die auf private MCP-Server in Cloud Run ausgerichtet sind, sicher über Private Service Connect (PSC) geleitet und das öffentliche Internet wird umgangen.
- Einheitliche Prüfbarkeit: Bietet eine zentrale Protokollierung von Anfragen, Telemetrie und Prüfpfaden für alle verbundenen MCP-Server und externen Tools.
Wenn Sie agentGatewaySetting in Ihrer Gemini Enterprise-App konfigurieren, werden ausgehende Tool- und Agent-Aufrufe, die durch Endnutzeranfragen initiiert werden (z. B. Aufrufe benutzerdefinierter MCP-Server, die aus der Agent Registry importiert wurden, und A2A-Agents), automatisch über das Agent Gateway weitergeleitet.
Patchen Sie die Engine agentGatewaySetting, um Folgendes zu aktivieren:
# bind engine (ge app) to agent gateway
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}?updateMask=agentGatewaySetting.defaultEgressAgentGateway.name" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"agentGatewaySetting": {
"defaultEgressAgentGateway": {
"name": "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
}
}
}
EOF
Agent-Gateway-Bindung überprüfen
Rufen Sie die App-Konfiguration ab, um die agentGatewaySetting-Bindung zu bestätigen:
# verify engine (ge app) agent gateway configuration
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name: .name, displayName: .displayName, agentGatewaySetting: .agentGatewaySetting}'
Erwartete Ausgabe:
{
"name": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}",
"displayName": "${GE_APP_DISPLAY_NAME}",
"agentGatewaySetting": {
"defaultEgressAgentGateway": {
"name": "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
}
}
}
Benutzerdefinierten MCP-Server-Datenspeicher erstellen
In diesem Abschnitt verbinden Sie den MCP-Server mit Gemini Enterprise, indem Sie einen benutzerdefinierten MCP-Datenspeicher erstellen.
Mit der Discovery Engine API ist dies ein zweistufiger Prozess:
- Erstellen (
:setUpDataConnector): Erstellt eine dedizierteCollection-Ressource (${MCP_NAME}-%timestamp-collection), hängt dieDataConnector(custom_mcp) an und stellt die zugrunde liegendeDataStore(..._mcp_data) bereit. - Aktivieren (
PATCH .../dataConnector?updateMask=actionConfig): Aktiviert die Aktionslaufzeit des Connectors (actionState: "ACTIVE") mithilfe der Tool-Spezifikation der Agent Registry und bindet dieDataStore(dataStoreIds) an IhreEnginevon Gemini Enterprise.
# fetch mcp server agent registry resource name
export MCP_REGISTRY_URI=$(gcloud agent-registry mcp-servers list \
--location=${REGION} \
--project=${PROJ_ID} \
--filter="displayName:${MCP_NAME}" \
--format="value(name)")
echo "mcp registry name: ${MCP_REGISTRY_URI}"
echo "mcp url: ${MCP_URL}"
Daten-Connector erstellen
# create custom mcp data connector from agent registry and link to engine
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}:setUpDataConnector" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"collectionId": "${MCP_NAME}-$(date +%s)-collection",
"collectionDisplayName": "${MCP_NAME}-collection",
"dataConnector": {
"dataSource": "custom_mcp",
"dataSourceVersion": 1,
"params": {
"oauth_access_token": "unused"
},
"refreshInterval": "86400s",
"entities": [
{
"entityName": "mcp_data"
}
],
"connectorModes": [
"FEDERATED"
],
"actionConfig": {
"isActionConfigured": true,
"createBapConnection": true,
"actionParams": {
"auth_type": "NO_AUTH",
"instance_uri": "${MCP_URL}",
"mcp_server_source": "REGISTRY_MCP",
"registry_mcp_server_name": "${MCP_REGISTRY_URI}",
"mcp_agent_instructions": "MANDATORY MATH & ARITHMETIC AGENT: Always invoke this tool for any mathematical calculation, addition (+), subtraction (-), sum, or difference.",
"use_agent_gateway_egress": true,
"agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
}
}
}
}
EOF
Erstellung des Daten-Connectors prüfen
# fetch collection id
export GE_COLLECTION_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq -r --arg dname "${MCP_NAME}-collection" '.collections[] | select(.displayName == $dname) | .name | split("/") | last' | head -n 1)
echo "ge collection id: ${GE_COLLECTION_ID}"
Prüfen Sie, ob das Feld "registry_mcp_server_name" mit der Agent Registry-UUID für den MCP-Server ausgefüllt wird:
# show data connector details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/dataConnector" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name, state, actionState, connectorModes, bapConfig, registry_mcp_server_name: .actionConfig.actionParams.registry_mcp_server_name}'
So rufen Sie den MCP-Serverregistrierungseintrag in der Google Cloud Console auf:
echo "mcp server registry page url: https://console.cloud.google.com/agent-platform/agent-registry/mcp-servers/${REGION}/${MCP_REGISTRY_URI##*/}/overview?project=${PROJ_ID}"
Daten-Connector aktivieren
# activate and bind data connector
curl -s -X PATCH "https://discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector?updateMask=actionConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"name": "projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector",
"actionConfig": {
"isActionConfigured": true,
"createBapConnection": true,
"actionParams": {
"auth_type": "NO_AUTH",
"instance_uri": "${MCP_URL}",
"mcp_server_source": "REGISTRY_MCP",
"registry_mcp_server_name": "${MCP_REGISTRY_URI}",
"mcp_agent_instructions": "MANDATORY MATH & ARITHMETIC AGENT: Always invoke this tool for any mathematical calculation, addition (+), subtraction (-), sum, or difference.",
"use_agent_gateway_egress": true,
"agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
}
}
}
EOF
Verknüpfungen mit benutzerdefinierten MCP-Servern überprüfen
# show engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name: .name, dataStoreIds: .dataStoreIds, agentGatewaySetting: .agentGatewaySetting}'
Suchen Sie nach dem verknüpften Datenspeicher "dataStoreIds": "collection-math-wizard-.
# show collection details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq --arg app "${GE_APP_ID}" '.collections[] | select(.dataConnector.actionConfig.actionParams.agent_gateway_engine // "" | endswith($app)) | .dataConnector | {name: .name, state: .state, actionState: .actionState, connectorModes: .connectorModes, actionParams: .actionConfig.actionParams}'
Suchen Sie nach "state": "ACTIVE" mit allen ausgefüllten Parametern.
Tool-Aktionen
Wenn Sie den math-wizard-collection-Datenspeicher im Gemini Enterprise-Dashboard untersuchen, werden Sie feststellen, dass der Tab Aktionen nicht verwendet wird und die Schaltfläche Benutzerdefinierte Aktionen ↻ neu laden deaktiviert ist. Das ist ganz normal.
So rufen Sie die Seite mit den Datenspeicherdetails in der Google Cloud Console-UI auf:
echo "data store details page url: https://console.cloud.google.com/gemini-enterprise/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/connector/details?project=${PROJ_ID}"
Je nachdem, wie Sie einen benutzerdefinierten MCP-Server mit Gemini Enterprise verbinden, werden die Tool-Erkennung und ‑Verwaltung auf eine von zwei Arten gehandhabt:
- Direkter benutzerdefinierter MCP (
BYO_MCP-Workflow): Wenn Sie einen benutzerdefinierten MCP-Server direkt in Gemini Enterprise ohne Agent Registry konfigurieren, wird der Toolkatalog (connectorModes: ["FEDERATED", "ACTIONS"]) vom Datenspeicher selbst verwaltet. Sie müssen den Tab Aktionen öffnen, auf ↻ Benutzerdefinierte Aktionen neu laden klicken, um dastools/list-Schema abzurufen, und einzelne Tools (addundsubtract) manuell in der Benutzeroberfläche aktivieren oder deaktivieren. - Agent Registry Import (
REGISTRY_MCP-Workflow, der in diesem Codelab verwendet wird): Wenn Sie einen MCP-Server aus der Agent Registry importieren, dient die Agent Registry als maßgebliche Quelle für den MCP-Endpunkt, seine Schnittstellenmetadaten und seinen Toolkatalog (connectorModes: ["FEDERATED"]). Gemini Enterprise aktiviert die registrierten MCP-Tools automatisch zur Laufzeit über das Agent Gateway der Engine, ohne dass Sie Aktionen in der Benutzeroberfläche des Datenspeichers manuell neu laden oder ein- bzw. ausschalten müssen.
Damit ist der Teil zur Gemini Enterprise-App abgeschlossen. Weiter geht es mit dem Abschnitt Validieren.
8. Validieren
In diesem Abschnitt lösen Sie Live-MCP-Tool-Aufrufe über die Gemini Enterprise-Web-App aus und verfolgen den Anfragefluss über Agent Gateway, Cloud DNS, VPC-Firewall und Cloud Run-Logs. Anschließend verschärfen Sie die IAM Unified Access Policy, um subtract zuzulassen und add zu blockieren. So wird die Zero-Trust-Durchsetzung am Gateway überprüft.
Nutzerzugriff
Erstellen Sie die URL für die Gemini Enterprise-Webanwendung:
# fetch app user url
export GE_WIDGET_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/widgetConfigs/default_search_widget_config" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
| jq -r '.configId')
export GE_APP_USER_URL="https://vertexaisearch.cloud.google.com/home/cid/${GE_WIDGET_ID}"
echo "app user url: ${GE_APP_USER_URL}"
Folgen Sie dem Link, um die Gemini Enterprise-Webanwendung in Ihrem Browser zu öffnen, und klicken Sie auf Erste Schritte.
Agent-Anfragen im Chat testen
Prüfen Sie in der Chat-Benutzeroberfläche, ob der math-wizard-collection-Daten-Connector aktiviert ist. Klicken Sie dazu unten im Chatfeld auf das Puzzlesymbol für Connectors. Es sollte ein Ein/Aus-Schalter angezeigt werden, der aktiviert ist (farbig dargestellt).
Probieren Sie die folgenden Testabfragen aus:
what is 2342345 - 98234798324?
what is 72347234 + 234234?
Prüfen Sie, ob der Assistent die richtigen Antworten zurückgibt und unter jeder Antwort ein interaktives Badge für die Aktionsquelle (z. B. Math Calculation (8s) 🤖 Agentgateway Agent) angezeigt wird, um zu bestätigen, dass das Tool ausgeführt wurde.
Logs in Cloud Logging ansehen
Prüfen Sie in Cloud Logging, ob Gemini Enterprise die Tool-Aufrufe über Agent Gateway und das private VPC-Netzwerk weitergeleitet hat.
1. Agent Gateway- und IAP-Autorisierung überprüfen
Prüfen Sie, ob Agent Gateway die Anfrage abgefangen, das Ziel in der Agent Registry aufgelöst, die Autorisierung an IAP delegiert und den Tool-Aufruf zugelassen hat:
# show agent gateway logs
gcloud logging read 'resource.type="networkservices.googleapis.com/Gateway"' \
--project=${PROJ_ID} \
--limit=5 \
--format="table( \
timestamp.date(tz=LOCAL):label=TIMESTAMP, \
httpRequest.status:label=STATUS, \
httpRequest.serverIp:label=SERVER_IP, \
jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD, \
jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL, \
jsonPayload.authzPolicyInfo.result:label=AUTHZ, \
jsonPayload.agentGatewayInfo.agentRegistryResource.basename():label=REGISTRY_MCP
)"
Prüfen Sie, ob die Ausgabe Folgendes enthält:
STATUS:200(erfolgreiche Ausführung) und202(notifications/initialized-Handshake).SERVER_IP: Google APIs PSC-Endpunkt-IP (172.16.20.20:443).MCP_METHODundTOOL: Die MCP-Protokollsequenz (notifications/initialized,tools/listundtools/callmitaddodersubtract).AUTHZ:ALLOWED(IAP-Autorisierung für Egress zulässig).REGISTRY_MCP: Aufgelöste Ressourcen-ID der Agent Registry (agentregistry-...).
2. DNS- und Firewall-Transit überprüfen
Prüfen Sie, ob Cloud DNS den Hostnamen in den PSC-Endpunkt aufgelöst hat und ob die Firewall Traffic von der Agent Gateway-Schnittstelle zugelassen hat:
# show dns logs
gcloud logging read 'resource.type="dns_query"' \
--project=${PROJ_ID} \
--limit=5 \
--format="table( \
timestamp.date(tz=LOCAL):label=TIMESTAMP, \
jsonPayload.queryName:label=QUERY_NAME, \
jsonPayload.queryType:label=TYPE, \
jsonPayload.responseCode:label=RCODE, \
jsonPayload.rdata:label=RDATA
)"
# show firewall logs
gcloud logging read 'logName:"compute.googleapis.com%2Ffirewall"' \
--project=${PROJ_ID} \
--limit=5 \
--format="table( \
timestamp.date(tz=LOCAL):label=TIMESTAMP, \
jsonPayload.connection.src_ip:label=SRC_IP, \
jsonPayload.connection.dest_ip:label=DEST_IP, \
jsonPayload.connection.dest_port:label=PORT, \
jsonPayload.rule_details.reference.basename():label=RULE, \
jsonPayload.disposition:label=DISPOSITION
)"
Prüfen Sie die folgenden Werte:
- DNS
QUERY_NAME&RDATA: Löstmath-wizard-...run.app.(A-Eintrag,NOERROR) in172.16.20.20auf. - Firewall
SRC_IP&DEST_IP:192.168.10.2(IP der Agent Gateway PSC-Schnittstelle) bis172.16.20.20:443. - Firewall
RULE&DISPOSITION: Abgleich vonfirewallPolicy:fw-policy-...mitALLOWED.
3. Ausführung des Cloud Run-Tools überprüfen
Prüfen Sie, ob der Cloud Run-Container den Toolaufruf empfangen und verarbeitet hat:
# show cloud run logs
gcloud logging read 'resource.type="cloud_run_revision"
AND textPayload:"Tool:"' \
--project=${PROJ_ID} \
--limit=5 \
--format="value(timestamp.date(tz=LOCAL), textPayload)"
Prüfen Sie, ob textPayload Einträge zur Toolausführung enthält (z. B. >>> 🛠️ Tool: 'subtract' called with numbers '[x]' and '[y]').
Erzwingung der Richtlinie für die geringsten Berechtigungen testen
In der ursprünglichen IAM-Zugriffsrichtlinie war jede Methode oder jedes Tool zulässig, sofern das Ziel registriert war (destination.is_registered == true). In diesem Schritt aktualisieren Sie die Richtlinie, um das Prinzip der geringsten Berechtigung zu erzwingen. Dazu lassen Sie nur das Tool subtract zu und blockieren add.
IAM-Zugriffsrichtlinie aktualisieren
Wenn Sie die Ausführung von MCP-Tools einschränken, verwenden Sie ein Muster mit zwei Regeln:
- Regel 1 (MCP-Erkennung und ‑Handshake): Erlaubt MCP-Lifecycle-Methoden ohne Toolaufruf (
destination.is_registered == trueunddestination.agent_registry.mcp_server.method != 'tools/call'). Da Gemini Enterprise die Stream-Einrichtung und ‑Erkennung (initialize,notifications/initialized,tools/list) vor dem Aufrufen eines Tools aushandelt unddestination.agent_registry.mcp_server.tool.nameerst währendtools/callausgefüllt wird, ist Regel 1 erforderlich, damit die Sitzungsinitialisierung und die Katalogerkennung funktionieren. - Regel 2 (Einschränkung auf Tool-Ebene): Beschränkt die Ausführung von
tools/call, sodass nur das Toolsubtractzulässig ist (destination.is_registered == true,destination.agent_registry.mcp_server.method == 'tools/call'unddestination.agent_registry.mcp_server.tool.name == 'subtract').
Aktualisieren Sie die Manifestdatei der Zugriffsrichtlinienregel mit beiden Regeln:
# create access policy rule file (update: allow subtract only)
cat > cfg/${UAP_POLICY_NAME}-rule-update.json << EOF
[
{
"description": "allow ge assistant to any registered endpoint to perform mcp discovery and handshake",
"effect": "ALLOW",
"principals": [
"principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_ID}/assistants/default_assistant/agents/default/core_assistant"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.mcp_server.method != 'tools/call'"
}
}
},
{
"description": "allow ge assistant to any registered mcp server with tool call subtract",
"effect": "ALLOW",
"principals": [
"principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_ID}/assistants/default_assistant/agents/default/core_assistant"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.mcp_server.method == 'tools/call' && \
destination.agent_registry.mcp_server.tool.name == 'subtract'"
}
}
}
]
EOF
Wenden Sie die aktualisierten Regeln auf die IAM-Zugriffsrichtlinie an:
# update iam access policy
gcloud iam access-policies update ${UAP_POLICY_NAME} \
--details-rules=cfg/${UAP_POLICY_NAME}-rule-update.json \
--project=${PROJ_ID} \
--location=global
IAM-Zugriffsrichtlinie überprüfen
Prüfen Sie, ob die neue IAM-Zugriffsrichtlinie angewendet wird und nur das Tool zum Entfernen von Objekten zulässig ist:
# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJ_ID} \
--location=global \
--flatten="details.rules[]" \
--format="table( \
details.rules.principals[0].scope(engines).sub('assistants/default_assistant/agents/default', '...'):label=PRINCIPAL, \
details.rules.effect:label=EFFECT, \
details.rules.conditions.'iap.googleapis.com'.expression.sub('\s*&&\s*', '\n&& ').sub('\s*\|\|\s*', '\n|| '):label=EXPRESSION
)"
Unzulässigen Tool-Aufruf testen
Kehren Sie zur Chat-Benutzeroberfläche der Gemini Enterprise Web-App zurück und versuchen Sie es mit einer anderen Testanfrage:
what is 100 plus 20?
Der Assistent versucht, add aufzurufen, aber Agent Gateway und IAP bewerten die IAM-Richtlinienbedingung als false und lehnen die Egress-Anfrage mit HTTP 403 Forbidden ab. In der Chat-Benutzeroberfläche wird angezeigt, dass der Assistent Calculate Sum anzeigt und 🤖 Agentgateway Agent ... Working on it. ausführt, während er den blockierten Tool-Aufruf wiederholt. Das ist ganz normal. Es wird bestätigt, dass Agent Gateway und IAP unzulässige Tool-Ausführungen auf Netzwerkebene aktiv abfangen und ablehnen.
Logs in Cloud Logging noch einmal prüfen
Sehen Sie sich die Logeinträge für das Agent Gateway an. Beachten Sie die neuen 403-Einträge, die dem unzulässigen add-Tool-Aufruf entsprechen:
# show agent gateway logs
gcloud logging read 'resource.type="networkservices.googleapis.com/Gateway"' \
--project=${PROJ_ID} \
--limit=5 \
--format="table( \
timestamp.date(tz=LOCAL):label=TIMESTAMP, \
httpRequest.status:label=STATUS, \
httpRequest.serverIp:label=SERVER_IP, \
jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD, \
jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL, \
jsonPayload.authzPolicyInfo.result:label=AUTHZ, \
jsonPayload.agentGatewayInfo.agentRegistryResource.basename():label=REGISTRY_MCP
)"
Erwartete Ausgabe:
TIMESTAMP STATUS SERVER_IP MCP_METHOD TOOL AUTHZ REGISTRY_MCP
YYYY-MM-DDTHH:MM:SS 403 tools/call add DENIED agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS 403
YYYY-MM-DDTHH:MM:SS 202 172.16.20.20:443 notifications/initialized ALLOWED agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS 172.16.20.20:443 ALLOWED agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS 200 172.16.20.20:443 initialize ALLOWED agentregistry-00000000-0000-0000-0012-3456789abcde
Prüfen Sie, ob die zusätzliche Anfrage das Cloud Run-Backend nie erreicht hat:
# show cloud run logs
gcloud logging read 'resource.type="cloud_run_revision"
AND textPayload:"Tool:"' \
--project=${PROJ_ID} \
--limit=5 \
--format="value(timestamp.date(tz=LOCAL), textPayload)"
Der Befehl gibt keine neuen Einträge zurück. Das bestätigt, dass das Agent Gateway die IAM-Zugriffsrichtlinie erfolgreich durchgesetzt hat.
Damit ist der Validierungsteil abgeschlossen. Weiter geht es mit dem Abschnitt Bereinigen.
9. Bereinigen
Führen Sie die folgenden Schritte aus, um die in diesem Lab erstellten Ressourcen und Konfigurationen zu löschen.
Gemini Enterprise-Komponenten entfernen
# delete gemini enterprise engine (app)
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
# delete custom mcp collection, data connector, and backing data store
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
# reset identity provider configuration
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d '{"idpConfig":{"idpType":"IDP_TYPE_UNSPECIFIED"}}'
MCP-Serverkomponenten entfernen
# delete agent registry service
gcloud -q agent-registry services delete ${MCP_NAME} \
--location=${REGION} \
--project=${PROJ_ID}
# delete cloud run service, source-deploy artifact registry repo, and staging bucket
gcloud -q run services delete ${MCP_NAME} \
--region=${REGION} \
--project=${PROJ_ID}
gcloud -q artifacts repositories delete cloud-run-source-deploy \
--location=${REGION} \
--project=${PROJ_ID}
gcloud -q storage rm --recursive gs://run-sources-${PROJ_ID}-${REGION} \
--project=${PROJ_ID}
Agent Gateway und IAM-Zugriffsrichtlinien entfernen
# delete gateway authorization policy, iap extension, and agent gateway
gcloud -q network-security authz-policies delete ${AGW_NAME}-authz-policy-iap \
--location=${REGION} \
--project=${PROJ_ID}
gcloud -q service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
--location=${REGION} \
--project=${PROJ_ID}
gcloud -q network-services agent-gateways delete ${AGW_NAME} \
--location=${REGION} \
--project=${PROJ_ID}
# delete iam policy binding and access policy
gcloud -q iam policy-bindings delete ${UAP_BINDING_NAME} \
--location=global \
--project=${PROJ_ID}
gcloud -q iam access-policies delete ${UAP_POLICY_NAME} \
--location=global \
--project=${PROJ_ID}
DNS- und Firewallkomponenten entfernen
# delete dns record set, managed zone, and policy
gcloud -q dns record-sets delete "*.run.app." \
--type=A \
--zone=priv-zone-run \
--project=${PROJ_ID}
gcloud -q dns managed-zones delete priv-zone-run \
--project=${PROJ_ID}
gcloud -q dns policies update dns-policy-${SLUG} \
--networks="" \
--project=${PROJ_ID}
gcloud -q dns policies delete dns-policy-${SLUG} \
--project=${PROJ_ID}
# delete firewall policy association, rule, and policy
gcloud -q compute network-firewall-policies associations delete \
--name=fw-policy-bind-${SLUG} \
--firewall-policy=fw-policy-${SLUG} \
--global-firewall-policy \
--project=${PROJ_ID}
gcloud -q compute network-firewall-policies rules delete 1001 \
--firewall-policy=fw-policy-${SLUG} \
--global-firewall-policy \
--project=${PROJ_ID}
gcloud -q compute network-firewall-policies delete fw-policy-${SLUG} \
--global \
--project=${PROJ_ID}
PSC- und VPC-Netzwerkkomponenten entfernen
# delete psc forwarding rule and internal ip address
gcloud -q compute forwarding-rules delete psc2gapis \
--global \
--project=${PROJ_ID}
gcloud -q compute addresses delete ip-psc2gapis \
--global \
--project=${PROJ_ID}
# delete psc network attachment, subnet, and vpc network
gcloud -q compute network-attachments delete psc-na-${REGION}-agw \
--region=${REGION} \
--project=${PROJ_ID}
gcloud -q compute networks subnets delete subnet-${REGION}-agw \
--region=${REGION} \
--project=${PROJ_ID}
gcloud -q compute networks delete vnet-${SLUG} \
--project=${PROJ_ID}
Überschreibungen von Organisationsrichtlinien und lokale Dateien entfernen
# delete project-level organization policy overrides
gcloud -q org-policies delete discoveryengine.managed.disableCustomMcpServerConnector --project=${PROJ_ID}
gcloud -q org-policies delete iam.managed.disableAccessPolicyBinding --project=${PROJ_ID}
# remove local project files
rm -rf cfg math-wizard
Damit ist die Bereinigung abgeschlossen. Weiter geht es mit dem Fazit.
10. Fazit
Glückwunsch! Sie haben eine End-to-End-Architektur erstellt, die es einer Gemini Enterprise-App ermöglicht, Tools auf einem privaten benutzerdefinierten MCP-Server sicher zu erkennen und aufzurufen:
- Benutzerdefinierter MCP-Server und Agent Registry:Ein privater FastMCP-Dienst wurde in Cloud Run (
--ingress=internal) bereitgestellt und sein Endpunkt und sein Tool-Schema (addundsubtract) wurden in Agent Registry registriert. - Gemini Enterprise-Integration:Sie haben eine Gemini Enterprise-App bereitgestellt, ausgehenden Tool-Traffic an das Agent Gateway gebunden und den registrierten MCP-Server als
REGISTRY_MCP-Daten-Connector angehängt. - Privater VPC-Ausgang und Zero-Trust-Governance:Die Ausführung von Tools wird privat über PSC (
172.16.20.20) weitergeleitet und das Tool-Level-Prinzip der geringsten Berechtigung wird mit IAP und IAM Unified Access Policies (destination.agent_registry.*) erzwungen.

Cosmpup findet Codelabs einfach nur genial!
Wie geht es weiter?
- In der Dokumentation zur Gemini Enterprise Agent Platform finden Sie Informationen zu erweiterten Funktionen und Tutorials.
- Model Armor-Schutzmaßnahmen in Agent Gateway konfigurieren, um die KI-Sicherheit zu erhöhen.
- Semantische Governance-Richtlinien können verwendet werden, um Geschäftsregeln und Compliance für Anfragen in natürlicher Sprache zu erzwingen.
Wenn Sie Kommentare, Fragen oder Korrekturen haben, können Sie dieses Feedbackformular verwenden.
Vielen Dank!