1. Introduction
Cet atelier de programmation explore la connectivité de sortie privée et régie pour Gemini Enterprise à l'aide de la passerelle d'agent en mode agent-to-anywhere (sortie). Vous allez configurer une application Gemini Enterprise pour appeler de manière sécurisée un serveur MCP (Model Context Protocol) personnalisé hébergé sur Cloud Run en acheminant le trafic via Agent Gateway à l'aide d'interfaces Private Service Connect (PSC) pour se connecter à un point de terminaison PSC pour les API Google dans un réseau VPC.
Dans les environnements d'entreprise, accorder aux agents autonomes un accès direct au réseau risque d'entraîner une exfiltration de données et l'exécution d'outils non testés. Agent Gateway fournit un point d'application centralisé et au niveau de la plate-forme, avec un modèle Zero Trust qui inspecte de manière dynamique les charges utiles des outils MCP HTTP en flux continu. Les requêtes sortantes sont authentifiées avec une identité d'agent cryptographiquement vérifiable et autorisées par le biais d'Identity-Aware Proxy (IAP) à l'aide de stratégies d'accès unifiées (UAP) IAM avec des règles CEL (Common Expression Language). Cela permet un contrôle précis des accès à des outils et méthodes MCP spécifiques sans exposer les charges de travail de backend à l'Internet public.
Objectif de l'atelier
- Agent Gateway fonctionnant en mode sortie (agent vers n'importe quelle destination) avec validation du point de terminaison Agent Registry
- Service Cloud Run hébergeant un serveur MCP HTTP diffusable privé (
--ingress=internal) enregistré avec ses spécifications d'outil dans Agent Registry - Extension d'autorisation Identity-Aware Proxy (IAP) pour Agent Gateway
- Règles d'accès unifiées (RAU) IAM avec conditions CEL pour l'autorisation de l'outil MCP
- Application Gemini Enterprise liée à Agent Gateway et connectée à un datastores de serveur MCP personnalisé importé depuis Agent Registry
- Ressources de réseau VPC, zone Cloud DNS et point de terminaison PSC pour les API Google
- Rattachement de réseau PSC pour la sortie VPC privée Agent Gateway
- Règles de stratégie Cloud Next Generation Firewall (NGFW) pour sécuriser le trafic VPC
Fig. 1. Architecture de l'atelier de programmation
Objectifs
- Déployer un serveur MCP HTTP privé et diffusable à partir de la source sur Cloud Run et enregistrer son point de terminaison et son schéma d'outil dans Agent Registry
- Configurer Agent Gateway avec des entrées de registre conformes et router les appels d'outils de l'application Gemini Enterprise via la passerelle
- Établir une sortie VPC privée à l'aide des interfaces et des pièces jointes réseau PSC
- Déléguer l'autorisation Agent Gateway à Identity-Aware Proxy (IAP)
- Créer et associer des règles d'accès unifiées IAM à l'aide des attributs CEL
destination.agent_registry.*etdestination.is_registeredpour restreindre l'exécution des outils MCP - Valider l'application des règles et la sortie réseau à l'aide de Cloud Logging
Ce dont vous avez besoin
- Un projet Google Cloud avec facturation activée
- Une licence Gemini Enterprise active ou un essai de 30 jours
- Autorisations IAM pour provisionner les services réseau, Gemini Enterprise et les ressources Agent Platform
- Un shell compatible POSIX (
bashouzsh) avec Google Cloud CLI (gcloud),curletjqinstallés
C'est la fin de la partie "Introduction". Passons à la section Concepts.
2. Concepts
Séquence de déploiement
Cet atelier de programmation déploie d'abord l'infrastructure afin que les chemins de réseau privé et les contrôles de gouvernance soient opérationnels avant l'enregistrement et la connexion des outils MCP à Gemini Enterprise :
- Infrastructure réseau : provisionnez des sous-réseaux VPC, un point de terminaison PSC, un rattachement de réseau PSC, des règles de stratégie Cloud NGFW et des zones Cloud DNS privées.
- Agent Gateway : déployez Agent Gateway en mode sortie avec l'intégration d'Agent Registry (
registries) et la sortie VPC privée (networkAttachment). - Stratégies d'autorisation : configurez l'extension d'autorisation IAP, la stratégie d'autorisation de passerelle et la stratégie d'accès unifiée (UAP) IAM à l'aide des conditions CEL
destination.is_registeredetdestination.agent_registry.*. - Déployer et enregistrer le serveur MCP : déployez le serveur MCP math à partir de la source vers Cloud Run (
--ingress=internal), puis enregistrez les spécifications du service et de l'outil (addetsubtract) dans Agent Registry. - Application Gemini Enterprise : créez l'application Gemini Enterprise (
Engine), configurez les paramètres d'identité et d'observabilité, et associez la sortie sortante à Agent Gateway (agentGatewaySetting). - Importer un connecteur de données MCP personnalisé : créez et activez le connecteur de données
REGISTRY_MCP(:setUpDataConnector) pour associer le datastore sous-jacent du serveur MCP enregistré à l'application Gemini Enterprise. - Valider : testez les exécutions d'outils autorisées et refusées dans le chat, et vérifiez l'application des règles dans les journaux Agent Gateway, DNS, pare-feu et Cloud Run.
Sortie de données Gemini Enterprise
Gemini Enterprise achemine les requêtes d'outils de serveur MCP personnalisés vers Agent Gateway lorsque agentGatewaySetting sur Engine et use_agent_gateway_egress: true sur DataConnector sont configurés.
Fig. 2. Architecture de sortie Gemini Enterprise
L'application Gemini Enterprise organise le routage des outils dans quatre domaines clés :
- Widget (
default_search_widget_config) :- Fournit l'interface client Web. Le widget reçoit les requêtes de l'utilisateur et lance des sessions de chat avec le moteur sous-jacent.
- Assistant Core (
assistants/default_assistant/agents/default/core_assistant) :- Agent de raisonnement conversationnel racine dans le moteur. Lorsqu'il évalue une requête utilisateur, l'Assistant principal détermine si un calcul arithmétique est nécessaire, inspecte les outils disponibles et délègue l'exécution au sous-agent Agent Gateway synthétisé.
- Data Store et Data Connector :
DataStore: provisionné dans unCollectiondédié lors de l'exécution de:setUpDataConnector, il associe (dataStoreIds) les schémas d'outils du registre d'agents importés (add,subtract), les types d'arguments et les instructions de l'agent auEngineGemini Enterprise.DataConnector: gère la connexion d'actionREGISTRY_MCP(createBapConnection: true) au serveur MCP distant (instance_uri), résout la ressource de serveur MCP du registre d'agent (registry_mcp_server_name) et active la sortie de la passerelle d'agent (use_agent_gateway_egress: true).
- Identité de l'agent, Agent Registry et Agent Gateway :
- Lorsque le connecteur de données distribue l'appel d'outil sortant, il achemine le trafic vers la passerelle spécifiée dans
agentGatewaySetting. L'assistant Core génère un jeton d'identité SPIFFE qui affirme son identité :principal://agents.global.org-.../agents/default/core_assistant. - Agent Gateway s'intègre à Agent Registry à l'aide du champ
registriespour résoudre de manière dynamique les points de terminaison de destination et les schémas d'outils enregistrés. Il remplit les attributsdestination.is_registeredetdestination.agent_registry.*, puis les transmet à IAP v2 pour évaluation par rapport aux règles CEL de la stratégie d'accès unifiée (UAP) IAM avant d'autoriser le transit vers le réseau VPC.
- Lorsque le connecteur de données distribue l'appel d'outil sortant, il achemine le trafic vers la passerelle spécifiée dans
Connectivité VPC de passerelle
Agent Gateway permet la connectivité privée au réseau VPC à l'aide de deux champs YAML :
networkConfig.egress.networkAttachment: indique que le trafic IP privé doit être acheminé via le rattachement de réseau PSC vers le réseau VPC.dnsPeeringConfig.domains: résout la résolution DNS des pairs avec la zone DNS Cloud DNS du réseau VPC afin que les noms d'hôte cibles (*.run.app) soient résolus en adresse IP du point de terminaison PSC privé défini dans le réseau VPC.
Limites et exigences
- StreamableHTTP uniquement : l'ancien transport Server-Sent Events (SSE) n'est pas pris en charge. Les serveurs MCP doivent utiliser StreamableHTTP.
- Public CA TLS required: les points de terminaison MCP doivent utiliser des certificats TLS signés par une autorité de certification publiquement approuvée, même lorsqu'ils sont accessibles de manière privée via PSC.
- Remplacer la règle d'administration de l'organisation : vous devez remplacer explicitement la règle d'administration de l'organisation pour les datastores MCP personnalisés avant d'enregistrer le datastore.
La partie concernant les concepts est terminée. Passons à la section Configuration.
3. Configuration
Rôles IAM requis
Les rôles suivants sont requis pour effectuer l'atelier de programmation :
Domaine | Rôles IAM requis |
Projet et IAM |
|
Réseau et passerelle |
|
Gemini Enterprise et Registry |
|
Charges de travail et compilation |
|
Observabilité |
|
Vous pouvez également utiliser un rôle de base étendu tel que roles/owner combiné à roles/orgpolicy.policyAdmin (car roles/owner seul ne peut pas modifier les règles d'administration).
Accéder à votre projet
Cet atelier de programmation utilise un seul projet Google Cloud. Les étapes de configuration utilisent la CLI gcloud et les commandes du shell Linux.
Commencez par accéder à la ligne de commande de votre projet Google Cloud :
- Cloud Shell à l'adresse
shell.cloud.google.com, ou - Un terminal local avec
gcloudCLI installé
Définir l'ID de votre projet
gcloud config set project SET_YOUR_PROJECT_ID_HERE
Authentifier la session
# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login
Définir des variables d'environnement de shell
# 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}
Définir des domaines de confiance pour l'identité de l'agent
L'instruction if-then-else vérifie si le projet appartient à une organisation afin de définir le domaine de confiance approprié pour les identités d'agent principal.
# 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}"
Définir le projet de facturation et de quota
# 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}
Créer un répertoire local pour les fichiers de configuration
# create config folder
mkdir -p cfg
Mettre à jour gcloud cli (recommandé)
Si vous exécutez une installation autogérée du SDK Google Cloud (c'est-à-dire en dehors de Cloud Shell), mettez à jour les composants vers la dernière version.
# update gcloud cli
gcloud components update
Activer les services d'API
# 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
Règles d'administration
Les contraintes relatives aux règles d'administration gérées par défaut de Google Cloud limitent les fonctionnalités utilisées dans cet atelier de programmation :
discoveryengine.managed.disableCustomMcpServerConnector:- Limite la création de connecteurs de données qui utilisent un serveur MCP personnalisé (
custom_mcp) comme source de données (appliqué par défaut).
- Limite la création de connecteurs de données qui utilisent un serveur MCP personnalisé (
iam.managed.disableAccessPolicyBinding:- Restreint les liaisons de stratégie d'accès IAM v3 aux ressources (appliqué par défaut).
discoveryengine.managed.allowedEgressFqdns:- Restreint les domaines de sortie (noms de domaine complets
instance_uri) pour les connecteurs de données lorsque VPC Service Controls (VPC-SC) est actif ou que le projet est listé dans le paramètreenforcedProjectsde l'organisation.
- Restreint les domaines de sortie (noms de domaine complets
discoveryengine.managed.allowedDataSources:- Restreint les types de connecteurs de données autorisés (
dataSource) lorsque VPC-SC est actif ou que le projet est listé dans le paramètreenforcedProjectsde l'organisation.
- Restreint les types de connecteurs de données autorisés (
Remplacez les restrictions héritées des règles d'administration au niveau du projet en définissant explicitement enforce: false.
Désactiver une contrainte MCP personnalisée
# 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
Désactiver une contrainte de règle d'accès
# 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
Vérifier et désactiver les contraintes du connecteur de données conditionnelles
Par défaut, discoveryengine.managed.allowedEgressFqdns et discoveryengine.managed.allowedDataSources ne bloquent la création de connecteurs que si votre projet se trouve dans un périmètre VPC Service Controls (VPC-SC) ou si un administrateur de l'organisation a ajouté votre projet à enforcedProjects.
Commencez par examiner les règles en vigueur dans votre projet :
# 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~~ ces contraintes sont appliquées, définissez enforce: false sur les deux règles pour votre projet afin de vous assurer qu'elles ne bloquent pas custom_mcpla configuration du connecteur dans une organisation avec un périmètre de service VPC ou des règles.
# 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
Autorisations IAM
Attribuez les rôles IAM requis à votre compte utilisateur et au compte de service Compute Engine par défaut utilisé par Cloud Build :
- Compte utilisateur (
${USER_IDENTITY}) :- Nécessite des autorisations pour déployer et appeler des services Cloud Run (
roles/run.admin,roles/run.invoker,roles/iam.serviceAccountUser), créer des images de conteneur (roles/cloudbuild.builds.editor), gérer Gemini Enterprise (roles/discoveryengine.admin) et créer des règles d'accès unifiées (roles/iam.accessPolicyAdmin).
- Nécessite des autorisations pour déployer et appeler des services Cloud Run (
- Compte de service Compute Engine par défaut(
${PROJ_NO}-compute@developer.gserviceaccount.com) :- Utilisé par Cloud Build pour préparer le code source dans Cloud Storage (
roles/storage.admin), envoyer des images à Artifact Registry (roles/artifactregistry.writer) et écrire des journaux de compilation (roles/logging.logWriter).
- Utilisé par Cloud Build pour préparer le code source dans Cloud Storage (
Exécutez les commandes suivantes pour attribuer les liaisons de rôle :
# 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"
Vérifier les autorisations IAM
Vérifiez les six liaisons de rôle (6) sur le compte utilisateur.
# 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)"
Vérifiez les trois liaisons de rôle (3) sur le compte de service Compute par défaut.
# 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)"
Vérifier les liaisons de l'agent de service (précaution)
Dans un nouveau projet, Google Cloud provisionne automatiquement l'agent de service Agent Gateway et lui accorde le rôle roles/agentgateway.serviceAgent lorsque networkservices.googleapis.com est activé pour la première fois. Si vous réutilisez un projet existant dans lequel un nettoyage précédent a pu supprimer les liaisons d'agent de service par défaut, exécutez les commandes suivantes pour vous assurer que l'identité et la liaison de rôle sont intactes :
# 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"
La partie concernant la configuration est terminée. Passons à la section Réseau.
4. Réseau
Dans cette section, vous allez déployer un réseau VPC en mode personnalisé avec un sous-réseau /28 dédié (192.168.10.0/28) prenant en charge le rattachement de réseau PSC pour la sortie réseau Agent Gateway dans le réseau VPC.
Le point de terminaison PSC pour les API Google est déployé à l'aide d'une seule adresse IPv4 interne globale /32 (172.16.20.20) pour permettre un accès interne privé aux API et services Google. Dans cet atelier de programmation, Agent Gateway cible Cloud Run à l'aide du point de terminaison PSC en résolvant le domaine run.app. par appairage Cloud DNS.
Créer des réseaux
Créez un réseau VPC mondial.
# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom
Créez des sous-réseaux pour le rattachement de réseau PSC de l'Agent Gateway :
# 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
Créer des règles de pare-feu
Créez une stratégie de pare-feu pour autoriser tout le trafic sortant avec la journalisation activée. Il servira à surveiller le trafic sortant de l'Agent Gateway vers le réseau VPC. Cloud NGFW est compatible avec les niveaux Essentials et Standard pour la sécurité du réseau et la surveillance du trafic.
# 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
Créer un rattachement de réseau PSC
Créez un rattachement de réseau Private Service Connect (PSC) configuré pour accepter automatiquement les connexions depuis Agent Gateway. Le rattachement de réseau établit le côté consommateur du réseau VPC pour l'associer de manière sécurisée au côté producteur de l'Agent Gateway pour le trafic de sortie. Pour en savoir plus sur les exigences concernant les sous-réseaux et les spécifications des plages d'adresses IP, consultez Configurer la connectivité VPC.
# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
--region=${REGION} \
--subnets=subnet-${REGION}-agw \
--connection-preference=ACCEPT_AUTOMATIC
Vérifier le rattachement de réseau PSC
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}
Récupérez l'URI de ressource du rattachement de réseau PSC et stockez-le dans la variable d'environnement PSC_NA_URI. Cet URI sera référencé dans la configuration de l'Agent Gateway (networkConfig.egress.networkAttachment) pour provisionner l'interface PSC pour la sortie réseau dans le réseau VPC :
# 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}
Créer un point de terminaison PSC
Un point de terminaison Private Service Connect (PSC) pour les API Google est utilisé par Agent Gateway pour établir une connectivité privée au serveur MCP Cloud Run via un chemin réseau interne, sans exposer le trafic à l'Internet public. Les appels d'outils sortants quittant Agent Gateway pour accéder au réseau VPC résoudront l'URL du service Cloud Run cible (*.run.app) en cette adresse IP de point de terminaison privé.
Réservez une adresse IPv4 interne globale pour le point de terminaison PSC. L'adresse IP choisie doit être une adresse /32 qui ne chevauche aucun des sous-réseaux existants de votre réseau VPC :
# 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}
Créez un point de terminaison PSC pour les API Google à l'aide du bundle all-apis, qui inclut Cloud Run (run.app).
# 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
Valider le point de terminaison PSC
# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global
Créer une zone et des enregistrements DNS
Cloud DNS est utilisé pour permettre à Agent Gateway de communiquer de manière privée avec le serveur MCP hébergé sur Cloud Run. Lorsque Agent Gateway évalue les requêtes d'outil sortantes ciblant Cloud Run, il utilise l'appairage DNS (dnsPeeringConfig.domains) pour résoudre les requêtes DNS pour *.run.app à l'aide de votre zone Cloud DNS privée associée à votre réseau VPC. L'enregistrement DNS privé renvoie la requête avec l'adresse IP du point de terminaison PSC interne (172.16.20.20), ce qui permet aux requêtes de l'outil MCP d'être acheminées via un chemin de réseau privé.
Créez une zone gérée privée Cloud DNS pour le domaine 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}
Créez un enregistrement DNS générique A pour *.run.app. pointant vers l'adresse IP du point de terminaison PSC :
# create dns record
gcloud dns record-sets create "*.run.app." \
--zone=priv-zone-run \
--type=A \
--ttl=300 \
--rrdatas=${PSC_EP_IP}
Créez une règle Cloud DNS pour activer la journalisation des requêtes DNS. La journalisation DNS capture les demandes de résolution de domaine provenant d'Agent Gateway au sein de votre réseau VPC. Elle permet d'assurer l'auditabilité et de vérifier que les demandes d'outil *.run.app sont correctement résolues en point de terminaison PSC interne :
# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
--description="dns logging for vnet-${SLUG}" \
--networks=vnet-${SLUG} \
--enable-logging
La partie sur le réseau est terminée. Passons à la section Agent Gateway.
5. Agent Gateway
Agent Gateway spécifie registries pour les instances Agent Registry, ainsi que les champs networkConfig qui configurent les paramètres de rattachement de réseau PSC et d'appairage DNS pour la connectivité VPC privée :
registries: associe la passerelle à deux instances Agent Registry au maximum : une régionale (../locations/${REGION}) et une globale (../locations/global). Cela permet d'intégrer Agent Gateway à Agent Registry pour résoudre les déploiements régionaux (tels que les serveurs MCP Cloud Run dans${REGION}) et les ressources globales (telles que les agents Gemini Enterprise et les points de terminaison globaux) pour l'application précise des règles IAP v2. Les entrées régionales sont prioritaires sur les entrées mondiales lors de la résolution des URL de destination.networkAttachment: pointe vers le rattachement de réseau PSC (psc-na-${REGION}-agw), qui connecte Agent Gateway à votre réseau VPC pour la sortie privée.dnsPeeringConfig.domains: configurerun.app.afin que les requêtes DNS provenant d'Agent Gateway pour les services Cloud Run utilisent l'appairage DNS pour résoudre les noms d'hôte en adresse IP du point de terminaison PSC des API Google privées (172.16.20.20) configurée dans votre zone privée Cloud DNS.
Déployer Agent Gateway
Créez et importez le fichier de configuration Agent Gateway.
# 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}
Vérifier le déploiement d'Agent Gateway
Confirmez la configuration de l'Agent Registry et du réseau :
# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--format="yaml(registries,networkConfig)"
Résultat attendu :
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}
Vérifiez que le résultat affiche les détails de configuration requis :
registries: liste l'URI du registre d'agents régional (${REGION}) associé à la passerelle.egress.networkAttachment: spécifie l'URI du rattachement de réseau PSC pour la sortie VPC.dnsPeeringConfig.domains: contientrun.app.pointant verstargetNetworkpour la résolution de domaine privé.
Inspectez le rattachement de réseau PSC pour confirmer la connexion à la passerelle :
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="yaml(connectionEndpoints)"
Vérifiez qu'il existe un point de terminaison de connexion accepté :
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
Déléguer l'autorisation
Agent Gateway sécurise et régit le trafic sortant des outils à l'aide de Règles d'autorisation (networksecurity.authzPolicies) intégrées aux Règles d'accès unifiées (RAU) Identity-Aware Proxy (IAP).
Bien qu'Agent Gateway soit compatible avec les règles ALLOW et DENY de base, les environnements d'entreprise nécessitent une gouvernance centralisée axée sur l'identité. Avec les règles d'accès unifiées IAM (ou Règles d'accès), vous gérez les règles d'accès sortant à l'aide des règles d'accès IAM v3 standards.
Fig. 3. Architecture d'autorisation
Le flux d'autorisation connecte trois composants :
- Règlement sur l'autorisation des passerelles (
authzPolicy) :- Ressource régionale ciblant Agent Gateway.
- Configuré avec
policyProfile: REQUEST_AUTHZetaction: CUSTOMpour acheminer toutes les vérifications d'autorisation sortantes vers l'extension IAP Authz.
- Extension de service IAP (
authzExtension) :- Ressource régionale qui délègue l'autorisation des requêtes à Identity-Aware Proxy (
iap.googleapis.com). - Évalue les règles en mode
ENFORCEà l'aide de la versionV2des règles.
- Ressource régionale qui délègue l'autorisation des requêtes à Identity-Aware Proxy (
- Liaison et règle d'accès unifiée IAM (
accessPolicyetpolicyBinding) :- Ressources IAM v3 globales contenant des règles d'accès précises.
- Authentifie l'identité principale SPIFFE de l'agent appelant, vérifie l'autorisation universelle
iap.googleapis.com/resources.egressViaIAPet évalue les conditions CEL (Common Expression Language) par rapport aux attributs de destination.
Déployer l'extension d'autorisation
Créez une configuration d'extension d'autorisation service-extensions qui délègue les décisions d'autorisation au service IAP :
# 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}
Vérifier l'extension d'autorisation
Vérifiez que l'extension d'autorisation est active :
# 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
)"
Déployer une règle d'autorisation
Créez une configuration de règle d'autorisation network-security qui cible Agent Gateway et délègue la validation des requêtes à l'extension d'autorisation pour IAP :
# 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}
Vérifier la règle d'autorisation
Vérifiez que la règle d'autorisation est active :
# 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
)"
Créer des stratégies d'accès IAM
Agent Gateway délègue désormais les vérifications d'autorisation à IAP et résout les métadonnées de destination à partir d'Agent Registry. Définissez ensuite une règle de stratégie d'accès unifiée IAM pour régir l'exécution des outils sortants.
IAP évalue les expressions d'attribut CEL par rapport aux attributs de destination suivants du registre d'agents :
- État enregistré (
destination.is_registered) :- Valeur booléenne (
true/false) indiquant si la destination est cataloguée dans l'Agent Registry.
- Valeur booléenne (
- Nom du serveur MCP (
destination.agent_registry.mcp_server.name) :- Nom de ressource du serveur MCP canonique enregistré dans Agent Registry.
- Méthode MCP (
destination.agent_registry.mcp_server.method) :- Méthode MCP appelée (par exemple,
tools/call,tools/list,initialize).
- Méthode MCP appelée (par exemple,
- Nom de l'outil (
destination.agent_registry.mcp_server.tool.name) :- Nom de l'outil spécifique appelé (par exemple,
subtractouadd), permettant une autorisation précise au niveau de l'outil sur les serveurs MCP enregistrés.
- Nom de l'outil spécifique appelé (par exemple,
Définir une règle de stratégie d'accès IAM
Le fichier manifeste de la règle de stratégie IAM spécifie les éléments suivants :
- Comptes principaux : identité principale SPIFFE représentant l'agent assistant principal de Gemini Enterprise.
- Autorisations : autorisation universelle
iap.googleapis.com/resources.egressViaIAPrequise pour tout le trafic sortant régi par IAP. - Conditions : expression CEL (
destination.is_registered == true) garantissant que l'agent ne peut invoquer que les points de terminaison catalogués dans Agent Registry.
Créez le fichier manifeste des règles :
# 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
Déployer une stratégie d'accès IAM
Créez la stratégie d'accès IAM globale à l'aide des règles définies dans le fichier manifeste :
# 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
Vérifier la stratégie d'accès IAM
Vérifiez que la stratégie d'accès IAM a bien été créée et examinez les détails de la règle :
# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJ_ID} \
--location=global
Résultat attendu :
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}
Associer une stratégie d'accès IAM à un projet
Pour activer l'application sur toutes les passerelles d'agent de votre projet, créez une liaison de stratégie qui associe la stratégie d'accès IAM à la ressource de projet :
# 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
Vérifier la liaison de la stratégie d'accès IAM
Vérifiez que les points de liaison actifs renvoient à la bonne règle et à la bonne cible :
# show policy binding details
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
--project=${PROJ_ID} \
--location=global
Résultat attendu :
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}
La partie concernant la passerelle d'agent est terminée. Passons à la section Serveur MCP.
6. Serveur MCP
Dans cette section, vous allez créer un serveur FastMCP personnalisé exposant les outils add et subtract, et le déployer sur Cloud Run directement à partir de la source. Lors du déploiement de la source (--source), Cloud Build empaquette l'image de conteneur à l'aide des fichiers Dockerfile et uv inclus (qui installent les dépendances définies dans pyproject.toml et lancent server.py).
Une fois le service Cloud Run déployé, vous enregistrez le serveur MCP dans Agent Registry avec sa spécification d'outil (toolspec.json) afin que Gemini Enterprise puisse découvrir et appeler ses outils.
Créer une application de serveur MCP
Créez un répertoire de projet math-wizard pour le code de l'application :
# create directory for code
mkdir -p math-wizard
Écrivez le fichier manifeste du projet Python :
# 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
Certaines fonctions d'instrumentation supplémentaires sont incluses dans le code pour capturer les en-têtes HTTP entrants (mcp-session-id, x-forwarded-for, user-agent et x-cloud-trace-context) pour la validation de Cloud Logging et Cloud Trace.
Écrivez le fichier de code de l'application :
# 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
Écrivez le fichier Dockerfile pour définir les instructions de création d'image de conteneur et les commandes de démarrage :
# 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
Déployer un service sur Cloud Run
Déployez le serveur MCP à partir de la source à l'aide de Cloud Build (qui utilise le compte de service Compute par défaut du projet ${PROJ_NO}-compute@developer.gserviceaccount.com) :
# deploy cloud run service
gcloud run deploy ${MCP_NAME} \
--source math-wizard \
--region=${REGION} \
--no-invoker-iam-check \
--ingress=internal \
--quiet
Vérifier le déploiement Cloud Run
Consultez les détails du service Cloud Run pour vérifier sa configuration active :
# show cloud run service details
gcloud run services describe ${MCP_NAME} --region=${REGION}
Résultat attendu :
<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>
Enregistrer un serveur MCP dans Agent Registry
Pour permettre à Gemini Enterprise de découvrir les outils exacts disponibles sur le serveur MCP, un fichier de spécifications d'outil (toolspec.json) doit être fourni lors de l'enregistrement dans Agent Registry.
Créer une spécification d'outil MCP
# 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
Enregistrer un serveur MCP dans Agent Registry
# 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}"
Vérifier le serveur MCP dans Agent Registry
Vérifiez que le service Cloud Run déployé est répertorié en tant que serveur MCP enregistré dans la région, avec son URL de point de terminaison et les outils disponibles :
# 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
)"
Résultat attendu :
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
Affichez la spécification de configuration de service pour voir qu'elle enregistre les définitions exactes des outils, les schémas d'entrée et les annotations de comportement pour chaque outil :
# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
--location=${REGION} \
--project=${PROJ_ID} \
--format="yaml(mcpServerSpec.content.tools)"
La partie concernant le serveur MCP est terminée. Passons maintenant à la section Gemini Enterprise.
7. Gemini Enterprise
Dans cette section, vous allez créer et configurer une application Gemini Enterprise et une ressource datastore de serveur MCP personnalisé associée.
Modèle de ressources Discovery Engine
Une application Gemini Enterprise (représentée par une ressource Engine dans l'API Discovery Engine) est la couche d'orchestration centrale et l'interface conversationnelle pour les utilisateurs finaux. Il gère les sessions de chat des utilisateurs, ancre les modèles génératifs sur les données de l'entreprise et coordonne l'exécution dynamique des outils.
Les applications Gemini Enterprise interagissent avec les données et les systèmes par le biais de datastores :
- Dépôts de données de connaissances : ingérez et indexez du contenu statique (par exemple, Cloud Storage, Google Drive, BigQuery) pour la génération augmentée par récupération (RAG).
- Connecteurs de données (fournisseurs d'actions) : connectez-vous à des API tierces ou personnalisées dynamiques. Un datastore de serveur MCP personnalisé expose les outils définis par le protocole MCP (Model Context Protocol), ce qui permet au modèle d'appeler dynamiquement des fonctions externes lors d'une conversation.
Routage de sortie via Agent Gateway
Par défaut, Gemini Enterprise achemine le trafic d'exécution des connecteurs et des outils sur les réseaux publics. Toutefois, pour les charges de travail VPC privées et la gouvernance Zero Trust, le moteur peut être configuré pour acheminer le trafic sortant via Agent Gateway :
- Lorsque vous créerez le datastore de serveur MCP personnalisé plus tard dans cet atelier, vous activerez l'option Route egress through Agent Gateway (Router la sortie via Agent Gateway) dans les paramètres du datastore.
- Cela lie les appels d'outils sortants du moteur à votre Agent Gateway régional, ce qui garantit que toutes les requêtes MCP comportent le
Agent Identityde l'application, font l'objet d'une autorisation d'exécution à l'aide des stratégies d'accès unifiées (UAP) IAP et IAM, et traversent le rattachement de réseau PSC dans votre VPC privé.
Créer une application Gemini Enterprise
La méthode suivante utilise l'API discoveryengine.googleapis.com pour créer les ressources et la configuration de l'application Gemini Enterprise. Pour configurer l'application à l'aide de l'interface utilisateur de la console Google Cloud, consultez Créer une application.
# 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
Vérifier la création de l'application
# 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}"
Affichez les détails du moteur pour voir la configuration créée :
# 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}"
Notez les propriétés suivantes renseignées par le serveur dans la réponse JSON :
name: chemin d'accès canonique à la ressource (projects/${PROJ_NO}/locations/global/collections/default_collection/engines/${GE_APP_ID}).sessionConfig.sessionManagementPolicy: la valeur par défaut est"VERTEX_AI_MANAGED", qui conserve l'état des conversations multitours et des appels d'outils dans Agent Platform (anciennement Vertex AI).observabilityConfig.observabilityEnabled: la valeur par défaut esttruepour les métriques de référence (la journalisation détaillée des charges utiles d'invite et d'outil est activée lors d'une étape ultérieure).
Activer le fournisseur d'identité
Activez Google Identity en tant que fournisseur d'identité pour l'authentification des utilisateurs finaux sur votre application Gemini Enterprise.
La méthode suivante utilise l'API discoveryengine.googleapis.com pour configurer le fournisseur d'identité de l'application Gemini Enterprise. Pour configurer un fournisseur d'identité à l'aide de l'interface utilisateur de la console Google Cloud, consultez Configurer un fournisseur d'identité.
# 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
Valider le fournisseur d'identité
# 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}"
La sortie "idpType": "GSUITE" correspond au fournisseur d'identité Google.
(Facultatif) Activer la licence d'essai Gemini Enterprise
Si vous utilisez un projet auquel des licences Gemini Enterprise sont attribuées, vous pouvez ignorer cette étape. Si vous utilisez un nouveau projet sans licence, continuez et suivez ces étapes.
Créez une ressource de configuration de licence pour accorder des droits d'accès aux utilisateurs Gemini Enterprise pendant 30 jours. La licence par défaut sera alors définie sur le nouvel essai. Ainsi, tout utilisateur qui se connecte se voit automatiquement attribuer un siège :
# 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
Vérifier que la licence a été appliquée
# 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}"
Vérifiez "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" et "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}"
Vérifiez ../free_trial_gemini" et "enableLicenseAutoRegister": true.
Activer les paramètres d'observabilité
L'observabilité au niveau de l'application (moteur) Gemini Enterprise vous permet d'afficher les interactions de l'assistant principal avec les données de métriques dans l'explorateur de métriques et de corréler les traces de bout en bout dans Cloud Trace.
# 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
Vérifier les paramètres d'observabilité
# 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}'
Recherchez "sensitiveLoggingEnabled": true.
Lier à Agent Gateway
Le routage du trafic sortant de Gemini Enterprise via Agent Gateway établit une limite de gouvernance et de sécurité zéro confiance centralisée pour toutes les invocations d'outils d'agents d'IA :
- Application centralisée des règles : Agent Gateway agit comme un proxy intégré qui évalue les demandes d'outils sortantes par rapport aux règles d'autorisation et aux contrôles de gouvernance avant que le trafic ne quitte l'environnement de l'agent.
- Sortie de réseau privé : l'association de Gemini Enterprise à Agent Gateway garantit que les appels d'outils ciblant des serveurs MCP privés sur Cloud Run sont acheminés de manière sécurisée via Private Service Connect (PSC), en contournant l'Internet public.
- Auditabilité unifiée : fournit une journalisation centralisée des requêtes, des données de télémétrie et des journaux d'audit pour tous les serveurs MCP et outils externes connectés.
En configurant agentGatewaySetting dans votre application Gemini Enterprise, les appels d'outils et d'agents sortants initiés par les requêtes des utilisateurs finaux (tels que les appels vers des serveurs MCP personnalisés importés depuis Agent Registry et les agents A2A) sont automatiquement acheminés via Agent Gateway.
Corrigez le moteur agentGatewaySetting pour l'activer :
# 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
Vérifier la liaison Agent Gateway
Récupérez la configuration de l'application pour confirmer l'association agentGatewaySetting :
# 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}'
Résultat attendu :
{
"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}"
}
}
}
Créer un datastore de serveur MCP personnalisé
Dans cette section, vous allez connecter le serveur MCP à Gemini Enterprise en créant un datastore MCP personnalisé.
Avec l'API Discovery Engine, ce processus se déroule en deux étapes :
- Create (
:setUpDataConnector) : crée une ressourceCollectiondédiée (${MCP_NAME}-%timestamp-collection), associe leDataConnector(custom_mcp) et provisionne sonDataStoresous-jacent (..._mcp_data). - Activer (
PATCH .../dataConnector?updateMask=actionConfig) : active le runtime d'action du connecteur (actionState: "ACTIVE") à l'aide de la spécification de l'outil Agent Registry et associeDataStore(dataStoreIds) à votreEngineGemini 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}"
Créer un connecteur de données
# 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
Vérifier la création du connecteur de données
# 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}"
Vérifiez que le champ "registry_mcp_server_name" est renseigné avec l'UUID Agent Registry du serveur MCP :
# 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}'
Affichez l'entrée du registre du serveur MCP dans l'UI de la console Google Cloud :
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}"
Activer le connecteur de données
# 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
Vérifier les liens vers le serveur MCP personnalisé
# 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}'
Vérifiez si le datastore "dataStoreIds": "collection-math-wizard- est associé.
# 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}'
Recherchez "state": "ACTIVE" avec tous les paramètres renseignés.
Actions d'outils
Lorsque vous inspectez le datastore math-wizard-collection dans le tableau de bord Gemini Enterprise, vous remarquerez que l'onglet Actions n'est pas utilisé et que le bouton ↻ Recharger les actions personnalisées est désactivé. Ce comportement est normal.
Affichez la page d'informations sur le datastore dans l'interface utilisateur de la console Google Cloud :
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}"
Selon la façon dont vous connectez un serveur MCP personnalisé à Gemini Enterprise, la découverte et la gouvernance des outils sont gérées de deux manières :
- Workflow MCP personnalisé direct (
BYO_MCP) : lorsque vous configurez un serveur MCP personnalisé directement dans Gemini Enterprise sans Agent Registry, le catalogue d'outils est géré par le datastore lui-même (connectorModes: ["FEDERATED", "ACTIONS"]). Vous devez ouvrir l'onglet Actions, cliquer sur ↻ Recharger les actions personnalisées pour récupérer le schématools/list, puis activer ou désactiver manuellement les outils individuels (addetsubtract) dans l'UI. - Importation d'Agent Registry (workflow
REGISTRY_MCPutilisé dans cet atelier de programmation) : lorsque vous importez un serveur MCP depuis Agent Registry, Agent Registry sert de source de référence pour le point de terminaison MCP, ses métadonnées d'interface et son catalogue d'outils (connectorModes: ["FEDERATED"]). Gemini Enterprise active automatiquement les outils MCP enregistrés au moment de l'exécution via l'Agent Gateway du moteur, sans que vous ayez à recharger ou à activer manuellement les actions dans l'UI du datastore.
La partie concernant l'application Gemini Enterprise est terminée. Passons à la section Valider.
8. Valider
Dans cette section, vous allez déclencher des appels d'outils MCP en direct à partir de l'application Web Gemini Enterprise et suivre le flux de requêtes dans les journaux Agent Gateway, Cloud DNS, du pare-feu VPC et Cloud Run. Vous allez ensuite renforcer la stratégie d'accès unifiée IAM pour autoriser subtract tout en bloquant add, ce qui permet de vérifier l'application du principe de confiance zéro au niveau de la passerelle.
Accès des utilisateurs
Construisez l'URL de l'application Web Gemini Enterprise :
# 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}"
Suivez le lien pour ouvrir l'interface de chat de l'application Web Gemini Enterprise dans votre navigateur, puis cliquez sur Commencer.
Tester les requêtes d'agent dans le chat
Dans l'interface utilisateur de chat, vérifiez que le connecteur de données math-wizard-collection est activé en cliquant sur l'icône en forme de pièce de puzzle pour Connecteurs en bas de la zone de discussion. Un bouton bascule devrait s'afficher (il est coloré).
Essayez les requêtes de test suivantes :
what is 2342345 - 98234798324?
what is 72347234 + 234234?
Vérifiez que l'assistant renvoie les bonnes réponses et affiche un badge de citation d'action interactif (comme Math Calculation (8s) 🤖 Agentgateway Agent) sous chaque réponse, confirmant que l'outil a été exécuté.
Inspecter les journaux dans Cloud Logging
Vérifiez que Gemini Enterprise a routé les appels d'outils via Agent Gateway et le réseau VPC privé en inspectant les journaux dans Cloud Logging.
1. Vérifier l'autorisation Agent Gateway et IAP
Vérifiez que l'Agent Gateway a intercepté la requête, résolu la cible dans l'Agent Registry, délégué l'autorisation à IAP et autorisé l'appel d'outil :
# 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
)"
Vérifiez que le résultat contient les éléments suivants :
STATUS:200(exécution réussie) et202(établissement de la liaisonnotifications/initialized).SERVER_IP: adresse IP du point de terminaison PSC des API Google (172.16.20.20:443).MCP_METHODetTOOL: séquence du protocole MCP (notifications/initialized,tools/listettools/callavecaddousubtract).AUTHZ:ALLOWED(sortie autorisée par l'autorisation IAP).REGISTRY_MCP: ID de ressource Agent Registry résolu (agentregistry-...).
2. Vérifier le transit DNS et du pare-feu
Vérifiez que Cloud DNS a résolu le nom d'hôte en point de terminaison PSC et que le pare-feu a autorisé le trafic depuis l'interface Agent Gateway :
# 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
)"
Vérifiez les valeurs suivantes :
- DNS
QUERY_NAME&RDATA: résoutmath-wizard-...run.app.(enregistrementA,NOERROR) en172.16.20.20. - Pare-feu
SRC_IP&DEST_IP:192.168.10.2(adresse IP de l'interface PSC de l'Agent Gateway) vers172.16.20.20:443. - Pare-feu
RULE&DISPOSITION:firewallPolicy:fw-policy-...correspond àALLOWED.
3. Vérifier l'exécution de l'outil Cloud Run
Vérifiez que le conteneur Cloud Run a reçu et traité l'appel d'outil :
# 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)"
Vérifiez que textPayload affiche des entrées d'exécution d'outil (par exemple, >>> 🛠️ Tool: 'subtract' called with numbers '[x]' and '[y]').
Tester l'application du principe du moindre privilège
Dans la stratégie d'accès IAM initiale, toute méthode ou tout outil était autorisé à condition que la destination soit enregistrée (destination.is_registered == true). Dans cette étape, mettez à jour la stratégie pour appliquer le principe du moindre privilège en autorisant uniquement l'outil subtract tout en bloquant add.
Mettre à jour la stratégie d'accès IAM
Lorsque vous limitez l'exécution des outils MCP, utilisez un modèle à deux règles :
- Règle 1 (découverte et établissement de la connexion MCP) : autorise les méthodes de cycle de vie MCP sans appel d'outil (
destination.is_registered == trueetdestination.agent_registry.mcp_server.method != 'tools/call'). Étant donné que Gemini Enterprise négocie la configuration et la découverte du flux (initialize,notifications/initialized,tools/list) avant d'appeler un outil, et quedestination.agent_registry.mcp_server.tool.namen'est renseigné que pendanttools/call, la règle 1 est nécessaire pour que l'initialisation de la session et la découverte du catalogue fonctionnent. - Règle 2 (restriction au niveau de l'outil) : limite l'exécution de
tools/callde sorte que seul l'outilsubtractsoit autorisé (destination.is_registered == true,destination.agent_registry.mcp_server.method == 'tools/call'etdestination.agent_registry.mcp_server.tool.name == 'subtract').
Mettez à jour le fichier manifeste de la règle de stratégie d'accès avec les deux règles :
# 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
Appliquez les règles mises à jour à la stratégie d'accès IAM :
# 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
Vérifier la stratégie d'accès IAM
Vérifiez que la nouvelle stratégie d'accès IAM est appliquée et que seul l'outil de soustraction est autorisé :
# 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
)"
Tester un appel d'outil interdit
Revenez à l'interface utilisateur de chat de l'application Web Gemini Enterprise et essayez une autre requête de test :
what is 100 plus 20?
L'assistant tente d'appeler add, mais Agent Gateway et IAP évaluent la condition de la stratégie IAM comme false et refusent la requête de sortie avec HTTP 403 Forbidden. Dans l'UI de chat, vous remarquerez que l'assistant affiche Calculate Sum et tourne sur 🤖 Agentgateway Agent ... Working on it. lorsqu'il réessaie l'appel d'outil bloqué. Ce comportement est normal. Il confirme que l'Agent Gateway et IAP interceptent et refusent activement l'exécution d'outils non autorisés au niveau du réseau.
Réinspecter les journaux dans Cloud Logging
Affichez les entrées de journal de l'Agent Gateway et notez les nouvelles entrées 403 correspondant à l'appel d'outil add non autorisé :
# 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
)"
Résultat attendu :
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
Vérifiez que la requête supplémentaire n'a jamais atteint le backend Cloud Run :
# 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)"
La commande ne renvoie aucune nouvelle entrée, ce qui confirme que l'Agent Gateway a bien appliqué la stratégie d'accès IAM.
La partie concernant la validation est terminée. Passons à la section Nettoyage.
9. Nettoyage
Suivez ces étapes pour supprimer les ressources et les configurations créées dans cet atelier.
Supprimer les composants Gemini Enterprise
# 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"}}'
Supprimer les composants du serveur MCP
# 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}
Supprimer les règles d'accès IAM et Agent Gateway
# 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}
Supprimer les composants DNS et de pare-feu
# 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}
Supprimer les composants du réseau VPC et du PSC
# 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}
Supprimer les remplacements de règles d'administration et les fichiers locaux
# 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
Le nettoyage est terminé. Passons à la conclusion !
10. Conclusion
Félicitations ! Vous avez créé une architecture de bout en bout permettant à une application Gemini Enterprise de découvrir et d'appeler des outils de manière sécurisée sur un serveur MCP privé personnalisé :
- Serveur MCP personnalisé et Agent Registry : déployez un service FastMCP privé sur Cloud Run (
--ingress=internal) et enregistrez son point de terminaison et son schéma d'outil (addetsubtract) dans Agent Registry. - Intégration de Gemini Enterprise : vous avez provisionné une application Gemini Enterprise, lié le trafic d'outils sortant à Agent Gateway et associé le serveur MCP enregistré en tant que connecteur de données
REGISTRY_MCP. - Sortie de VPC privé et gouvernance Zero Trust : exécution routée des outils de manière privée sur PSC (
172.16.20.20) et application du principe du moindre privilège au niveau des outils à l'aide des stratégies d'accès unifiées IAP et IAM (destination.agent_registry.*).

Cosmpup pense que les ateliers de programmation sont absolument géniaux !
Et ensuite ?
- Consultez la documentation Gemini Enterprise Agent Platform pour découvrir les fonctionnalités avancées et les tutoriels.
- Configurez des garde-fous Model Armor sur Agent Gateway pour renforcer la sécurité de l'IA.
- Découvrez les Règles de gouvernance sémantique pour appliquer des règles métier et de conformité aux requêtes en langage naturel.
N'hésitez pas à nous faire part de vos commentaires, questions ou corrections en utilisant ce formulaire.
Merci !