1. Введение
В этом практическом занятии рассматривается частное, управляемое исходящее соединение для Gemini Enterprise с использованием Agent Gateway в режиме "агент-в-любом месте " (исходящий трафик). Вы настроите приложение Gemini Enterprise для безопасного вызова пользовательского сервера Model Context Protocol (MCP), размещенного на Cloud Run, путем маршрутизации трафика через Agent Gateway с использованием интерфейсов Private Service Connect (PSC) для подключения к конечной точке PSC для API Google в сети VPC.
В корпоративных средах предоставление автономным агентам прямого доступа к сети сопряжено с риском утечки данных и несанкционированного выполнения инструментов. Agent Gateway предоставляет централизованную точку обеспечения нулевого доверия на уровне платформы, которая динамически проверяет потоковые HTTP-запросы инструментов MCP. Исходящие запросы аутентифицируются с помощью криптографически проверяемого идентификатора агента и авторизуются через Identity-Aware Proxy (IAP) с использованием унифицированных политик доступа IAM (UAP) с правилами Common Expression Language (CEL). Это обеспечивает детальный контроль доступа к конкретным инструментам и методам MCP без раскрытия рабочих нагрузок бэкэнда в общедоступном интернете.
Что вы строите
- Шлюз агентов работает в режиме исходящего трафика ( агент — куда угодно ) с проверкой конечной точки реестра агентов.
- Сервис Cloud Run, размещающий частный потоковый HTTP MCP-сервер (
--ingress=internal), зарегистрированный в Agent Registry с указанием спецификаций инструмента. - Расширение авторизации Identity-Aware Proxy (IAP) для Agent Gateway
- Единые политики доступа IAM (UAP) с условиями CEL для авторизации инструментов MCP
- Приложение Gemini Enterprise, привязанное к Agent Gateway и подключенное к пользовательскому хранилищу данных сервера MCP, импортированному из Agent Registry.
- Ресурсы сети VPC, зона Cloud DNS и конечная точка PSC для API Google.
- Подключение сети PSC для исходящего трафика из частной VPC Agent Gateway
- Правила политики межсетевого экрана нового поколения (NGFW) для защиты трафика VPC
Рис. 1. Архитектура Codelab
Чему вы научитесь
- Как развернуть частный потоковый HTTP MCP-сервер из исходного кода в Cloud Run и зарегистрировать его конечную точку и схему инструментов в Agent Registry
- Как настроить Agent Gateway с использованием совместимых записей реестра и направлять вызовы инструментов Gemini Enterprise через шлюз.
- Как настроить исходящий трафик в частной виртуальной частной сети (VPC) с использованием сетевых подключений и интерфейсов PSC.
- Как делегировать авторизацию Agent Gateway прокси-серверу с поддержкой идентификации (IAP)
- Как создавать и привязывать унифицированные политики доступа IAM (UAP) с использованием атрибутов CEL
destination.agent_registry.*иdestination.is_registeredдля ограничения выполнения инструментов MCP. - Как проверить соблюдение политик и исходящий сетевой трафик с помощью облачного логирования.
Что вам нужно
- Проект Google Cloud с включенной функцией выставления счетов.
- Действующая лицензия Gemini Enterprise или 30-дневная пробная версия.
- Разрешения IAM для предоставления сетевых сервисов, ресурсов Gemini Enterprise и Agent Platform.
- POSIX-совместимая оболочка (
bashилиzsh) с установленными Google Cloud CLI (gcloud),curlиjq
На этом завершается вводная часть... далее переходим к разделу «Концепции» .
2. Концепции
Последовательность развертывания
В этом практическом занятии сначала развертывается инфраструктура, чтобы обеспечить работоспособность частных сетевых каналов и средств управления, прежде чем регистрировать и подключать инструменты MCP к Gemini Enterprise:
- Сетевая инфраструктура: создание подсетей VPC, конечной точки PSC, сетевого подключения PSC, правил политики Cloud NGFW и частных зон Cloud DNS.
- Agent Gateway: Разверните Agent Gateway в режиме исходящего трафика с интеграцией с реестром агентов (
registries) и исходящим трафиком из частной VPC (networkAttachment). - Политики авторизации: Настройте расширение авторизации IAP, политику авторизации шлюза и унифицированную политику доступа IAM (UAP), используя условия CEL
destination.is_registeredиdestination.agent_registry.*. - Развертывание и регистрация MCP-сервера: Разверните математический MCP-сервер из исходного кода в Cloud Run (
--ingress=internal) и зарегистрируйте спецификации службы и инструментов (addиsubtract) в Agent Registry. - Приложение Gemini Enterprise: Создайте приложение Gemini Enterprise (
Engine), настройте параметры идентификации и мониторинга, а также привяжите исходящий трафик к Agent Gateway (agentGatewaySetting). - Импорт пользовательского коннектора данных MCP: Создайте и активируйте коннектор данных
REGISTRY_MCP(:setUpDataConnector), чтобы связать хранилище данных зарегистрированного сервера MCP с приложением Gemini Enterprise. - Проверка: протестируйте разрешенные и запрещенные запуски инструментов в чате и проверьте соблюдение политик в Agent Gateway, DNS, брандмауэре и журналах Cloud Run.
Выход Gemini Enterprise
Gemini Enterprise перенаправляет запросы к пользовательским инструментам сервера MCP на Agent Gateway, если одновременно настроены agentGatewaySetting в Engine и use_agent_gateway_egress: true в DataConnector .
Рис. 2. Архитектура исходящего трафика Gemini Enterprise.
Приложение Gemini Enterprise организует маршрутизацию инструментов по четырем ключевым направлениям:
- Виджет (
default_search_widget_config) :- Предоставляет веб-интерфейс для клиента. Виджет получает запросы от пользователя и инициирует сеансы чата с базовым механизмом.
- Основной помощник (
assistants/default_assistant/agents/default/core_assistant) :- Основной агент, отвечающий за диалоговое мышление в рамках системы. При оценке запроса пользователя Core Assistant определяет, требуется ли арифметическое вычисление, проверяет доступные инструменты и делегирует выполнение синтезированному субагенту Agent Gateway.
- Хранилище данных и коннектор данных :
-
DataStore: Создается внутри выделеннойCollectionпри запуске:setUpDataConnectorи связывает (dataStoreIds) импортированные схемы инструментов Agent Registry (add,subtract), типы аргументов и инструкции агента с Gemini EnterpriseEngine. -
DataConnector: управляет подключением действияREGISTRY_MCP(createBapConnection: true) к удаленному MCP-серверу (instance_uri), разрешает ресурс MCP-сервера реестра агентов (registry_mcp_server_name) и включает исходящий трафик через Agent Gateway (use_agent_gateway_egress: true).
-
- Идентификация агента , Реестр агентов и Шлюз агентов :
- Когда Data Connector отправляет исходящий вызов инструмента, он направляет трафик на шлюз, указанный в
agentGatewaySetting. Core Assistant создает токен идентификации SPIFFE , подтверждающий его подлинность:principal://agents.global.org-.../agents/default/core_assistant. - Agent Gateway интегрируется с Agent Registry, используя поле
registriesдля динамического определения целевых конечных точек и зарегистрированных схем инструментов. Он заполняет атрибутыdestination.is_registeredиdestination.agent_registry.*и передает их в IAP v2 для оценки на соответствие правилам CEL унифицированной политики доступа IAM (UAP) перед разрешением передачи в сеть VPC.
- Когда Data Connector отправляет исходящий вызов инструмента, он направляет трафик на шлюз, указанный в
Подключение шлюза VPC
Agent Gateway обеспечивает подключение к частной сети VPC с помощью двух полей YAML:
-
networkConfig.egress.networkAttachment: Направляет трафик частных IP-адресов через сетевое соединение PSC в сеть VPC. -
dnsPeeringConfig.domains: Обеспечивает разрешение DNS-запросов через зону Cloud DNS сети VPC, чтобы целевые имена хостов (*.run.app) разрешались в частный IP-адрес конечной точки PSC, определенный в сети VPC.
Ограничения и требования
- Только StreamableHTTP: устаревший протокол передачи событий Server-Sent Events (SSE) не поддерживается. Серверы MCP должны использовать StreamableHTTP .
- Требуется TLS от публичного центра сертификации: конечные точки MCP должны использовать TLS-сертификаты, подписанные публично доверенным центром сертификации, даже при частном доступе через PSC.
- Переопределение политики организации: Перед регистрацией хранилища данных Custom MCP необходимо явно переопределить политику организации для него .
На этом завершается раздел, посвященный концепциям... далее переходим к разделу «Настройка» .
3. Настройка
Необходимые роли IAM
Для прохождения Codelab необходимы следующие роли:
Домен | Необходимые роли IAM |
Проект и IAM | |
Сетевые устройства и шлюзы | |
Gemini Enterprise & Registry | |
Рабочие нагрузки и сборка | |
Наблюдаемость | |
Или используйте широкую базовую роль, например, roles/owner в сочетании с roles/orgpolicy.policyAdmin (поскольку roles/owner сама по себе не может изменять политики организации).
Получите доступ к своему проекту
В этом практическом занятии используется один проект Google Cloud. Шаги настройки выполняются с помощью командной строки gcloud и команд оболочки Linux.
Для начала откройте командную строку вашего проекта Google Cloud:
- Cloud Shell доступен по адресу
shell.cloud.google.comили - Локальный терминал с установленным интерфейсом командной строки
gcloud
Укажите идентификатор вашего проекта.
gcloud config set project SET_YOUR_PROJECT_ID_HERE
Аутентификация сессии
# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login
Установка переменных среды оболочки
# 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}
Установить домены доверия идентификации агента
Оператор if-then-else проверяет, принадлежит ли проект какой-либо организации, чтобы установить правильный домен доверия для идентификаторов основного агента.
# 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}"
Настройка выставления счетов и квот проекта
# 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}
Создайте локальную директорию для файлов конфигурации.
# create config folder
mkdir -p cfg
Обновите интерфейс gcloud cli (рекомендуется).
Если вы используете самостоятельную установку Google Cloud SDK (т.е. вне Cloud Shell), обновите компоненты до последней версии.
# update gcloud cli
gcloud components update
Включить 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
Политика организации
Ограничения, установленные по умолчанию в политике управляемой организации Google Cloud, ограничивают использование функций, применяемых в этом практическом занятии:
-
discoveryengine.managed.disableCustomMcpServerConnector:- Ограничивает создание коннекторов данных, использующих пользовательский сервер MCP (
custom_mcp) в качестве источника данных (применяется по умолчанию).
- Ограничивает создание коннекторов данных, использующих пользовательский сервер MCP (
-
iam.managed.disableAccessPolicyBinding:- Ограничивает привязку политик доступа IAM v3 только ресурсами (применяется по умолчанию).
-
discoveryengine.managed.allowedEgressFqdns:- Ограничивает исходящие домены (полные доменные имена
instance_uri) для коннекторов данных, когда активна функция VPC Service Controls (VPC-SC) или проект указан в параметреenforcedProjectsорганизации.
- Ограничивает исходящие домены (полные доменные имена
-
discoveryengine.managed.allowedDataSources:- Ограничивает допустимые типы коннекторов данных (
dataSource), когда VPC-SC активен или проект указан в параметреenforcedProjectsорганизации.
- Ограничивает допустимые типы коннекторов данных (
Отмените любые унаследованные ограничения политики организации на уровне проекта, явно установив enforce: false .
Отключить пользовательское ограничение MCP
# 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
Отключить ограничение политики доступа
# 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
Проверьте и отключите ограничения условных соединителей данных.
По умолчанию параметры discoveryengine.managed.allowedEgressFqdns и discoveryengine.managed.allowedDataSources блокируют создание коннекторов только в том случае, если ваш проект находится внутри периметра VPC Service Controls (VPC SC) или если администратор организации добавил ваш проект в enforcedProjects .
Для начала изучите действующие политики вашего проекта:
# 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
~~ЕСЛИ~~ эти ограничения применяются, чтобы гарантировать, что они не блокируют настройку коннектора custom_mcp в VPC SC или организации с ограничениями по политике, установите enforce: false для обеих политик вашего проекта:
# 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
Предоставьте необходимые роли IAM вашей учетной записи пользователя и учетной записи службы Compute Engine по умолчанию, используемой Cloud Build:
- Учетная запись пользователя (
${USER_IDENTITY}):- Для развертывания и вызова служб Cloud Run (
roles/run.admin,roles/run.invoker,roles/iam.serviceAccountUser), создания образов контейнеров (roles/cloudbuild.builds.editor), управления Gemini Enterprise (roles/discoveryengine.admin) и создания унифицированных политик доступа (roles/iam.accessPolicyAdmin) требуются соответствующие разрешения.
- Для развертывания и вызова служб Cloud Run (
- Учетная запись службы Compute Engine по умолчанию (
${PROJ_NO}-compute@developer.gserviceaccount.com):- Используется Cloud Build для подготовки исходного кода в Cloud Storage (
roles/storage.admin), отправки образов в Artifact Registry (roles/artifactregistry.writer) и записи журналов сборки (roles/logging.logWriter).
- Используется Cloud Build для подготовки исходного кода в Cloud Storage (
Выполните следующие команды, чтобы назначить привязки ролей:
# 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.
Проверьте наличие шести ( 6 ) привязок ролей в учетной записи пользователя.
# 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)"
Проверьте наличие трех ( 3 ) привязок ролей для учетной записи вычислительной службы по умолчанию.
# 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)"
Проверьте привязку агента сервисной службы (в целях предосторожности).
В новом проекте Google Cloud автоматически создает агент службы Agent Gateway и предоставляет ему roles/agentgateway.serviceAgent при первом включении networkservices.googleapis.com . Если вы используете существующий проект, в котором предыдущая очистка могла удалить привязки агента службы по умолчанию, выполните следующие команды в качестве резервного варианта, чтобы гарантировать сохранность привязки идентификатора и роли:
# 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"
На этом завершается этап настройки... далее переходим к разделу «Сеть» .
4. Сеть
В этом разделе вы развернете сеть VPC в пользовательском режиме с выделенной подсетью /28 ( 192.168.10.0/28 ), поддерживающей подключение сети PSC для исходящего трафика из сети Agent Gateway в сеть VPC.
Конечная точка PSC для API Google развернута с использованием единого глобального внутреннего IPv4-адреса /32 ( 172.16.20.20 ) для поддержки частного внутреннего доступа к API и сервисам Google. В этом практическом занятии Agent Gateway обращается к Cloud Run, используя конечную точку PSC, путем разрешения домена run.app. через пиринг Cloud DNS.
Создавайте сети
Создайте глобальную сеть VPC.
# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom
Создайте подсети для сетевого подключения Agent Gateway PSC:
# 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
Создание правил брандмауэра
Создайте политику брандмауэра, разрешающую весь исходящий трафик с включенным логированием. Это будет использоваться для мониторинга трафика, исходящего из Agent Gateway в сеть VPC. Cloud NGFW поддерживает уровни Essentials и Standard для обеспечения сетевой безопасности и мониторинга трафика.
# 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
Создайте сетевое соединение Private Service Connect (PSC), настроенное на автоматический прием соединений от Agent Gateway. Сетевое соединение устанавливает связь между сетью VPC потребителя и стороной- производителем Agent Gateway для исходящего трафика. Дополнительную информацию о требованиях к подсетям и диапазонам IP-адресов см. в разделе «Настройка подключения VPC» .
# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
--region=${REGION} \
--subnets=subnet-${REGION}-agw \
--connection-preference=ACCEPT_AUTOMATIC
Проверьте подключение к сети PSC.
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}
Получите URI ресурса сетевого подключения PSC и сохраните его в переменной среды PSC_NA_URI . Этот URI будет использоваться в конфигурации Agent Gateway ( networkConfig.egress.networkAttachment ) для выделения сетевого трафика через интерфейс PSC в сеть 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}
Создать конечную точку PSC
Для установления частного соединения с сервером Cloud Run MCP по внутреннему сетевому пути без раскрытия трафика в общедоступном интернете используется конечная точка Private Service Connect (PSC) для API Google, предоставляемая Agent Gateway. Исходящие вызовы инструментов, поступающие из Agent Gateway в сеть VPC, будут преобразовывать целевой URL-адрес службы Cloud Run ( *.run.app ) в IP-адрес этой частной конечной точки.
Зарезервируйте глобальный внутренний IPv4-адрес для конечной точки PSC. Выбранный IP-адрес должен быть адресом /32 и не должен пересекаться с существующими подсетями в вашей сети 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}
Создайте конечную точку PSC для API Google, используя пакет all-apis , который включает 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
Проверьте конечную точку PSC.
# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global
Создайте зону DNS и записи.
Cloud DNS используется для обеспечения возможности частной связи Agent Gateway с сервером MCP, размещенным в Cloud Run. Когда Agent Gateway обрабатывает исходящие запросы инструментов, нацеленные на Cloud Run, он использует DNS-пиринг ( dnsPeeringConfig.domains ) для разрешения DNS-запросов для *.run.app используя вашу частную зону Cloud DNS, связанную с вашей сетью VPC. Частная DNS-запись возвращает запрос с внутренним IP-адресом конечной точки PSC ( 172.16.20.20 ), что позволяет маршрутизировать запросы инструментов MCP по частному сетевому пути.
Создайте частную зону управления Cloud DNS для домена 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}
Создайте запись DNS A с подстановочным знаком для *.run.app. , указывающую на IP-адрес конечной точки PSC:
# create dns record
gcloud dns record-sets create "*.run.app." \
--zone=priv-zone-run \
--type=A \
--ttl=300 \
--rrdatas=${PSC_EP_IP}
Создайте политику Cloud DNS для включения логирования DNS-запросов. Логирование DNS фиксирует запросы на разрешение доменов, исходящие от Agent Gateway в вашей сети VPC, обеспечивая возможность аудита и позволяя убедиться в том, что запросы к инструментам *.run.app корректно разрешаются во внутреннюю конечную точку PSC:
# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
--description="dns logging for vnet-${SLUG}" \
--networks=vnet-${SLUG} \
--enable-logging
На этом завершается раздел, посвященный сети... далее переходим к разделу «Шлюз агентов» .
5. Agent Gateway
Agent Gateway указывает registries для экземпляров Agent Registry, а также поля networkConfig , которые настраивают параметры подключения к сети PSC и DNS-пиринга для подключения к частной VPC:
-
registries: связывает шлюз с двумя экземплярами реестра агентов: одним региональным (../locations/${REGION}) и одним глобальным (../locations/global). Это позволяет интегрировать шлюз агентов с реестром агентов для разрешения как региональных развертываний (например, серверов Cloud Run MCP в${REGION}), так и глобальных ресурсов (например, агентов Gemini Enterprise и глобальных конечных точек) для детального применения политик IAP v2. Региональные записи имеют приоритет над глобальными при разрешении целевых URL-адресов. -
networkAttachment: Указывает на сетевое подключение PSC (psc-na-${REGION}-agw), соединяющее Agent Gateway с вашей сетью VPC для частного исходящего трафика. -
dnsPeeringConfig.domains: Настраиваетrun.app.таким образом, чтобы DNS-запросы, исходящие от Agent Gateway для служб Cloud Run, использовали DNS-пиринг для разрешения имен хостов на IP-адрес частной конечной точки Google API PSC (172.16.20.20), настроенный в вашей частной зоне Cloud DNS.
Разверните шлюз агентов
Создайте и импортируйте файл конфигурации 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}
Проверьте развертывание Agent Gateway.
Подтвердите конфигурацию реестра агентов и сети:
# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--format="yaml(registries,networkConfig)"
Ожидаемый результат:
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}
Убедитесь, что в выходных данных отображаются необходимые сведения о конфигурации:
-
registries: Отображает URI регионального (${REGION}) реестра агентов, связанного со шлюзом. -
egress.networkAttachment: Указывает URI подключения к сети PSC для исходящего трафика VPC. -
dnsPeeringConfig.domains: Содержитrun.app.указывающий наtargetNetworkдля разрешения частных доменов.
Проверьте сетевое подключение PSC, чтобы подтвердить подключение к шлюзу:
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="yaml(connectionEndpoints)"
Убедитесь, что существует разрешенная точка подключения:
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
Авторизация делегата
Agent Gateway обеспечивает безопасность и управление исходящим трафиком инструментов с помощью политик авторизации ( networksecurity.authzPolicies ), интегрированных с унифицированными политиками доступа (UAP) Identity-Aware Proxy (IAP) .
Хотя Agent Gateway поддерживает базовые правила ALLOW и DENY , корпоративные среды требуют централизованного управления, ориентированного на идентификацию. С помощью унифицированных политик доступа IAM (или политик доступа ) вы управляете правилами исходящего доступа, используя стандартные политики доступа IAM v3.
Рис. 3. Архитектура авторизации
Процесс авторизации связывает три компонента:
- Политика авторизации шлюза (
authzPolicy) :- Региональный ресурс, ориентированный на Agent Gateway.
- Настроено с
policyProfile: REQUEST_AUTHZиaction: CUSTOMдля перенаправления всех исходящих проверок авторизации в расширение IAP Authz Extension.
- Расширение службы IAP (
authzExtension) :- Региональный ресурс, который делегирует запросы на авторизацию прокси-серверу с поддержкой идентификации (
iap.googleapis.com). - Оценивает политики в режиме
ENFORCE, используя версию политикиV2.
- Региональный ресурс, который делегирует запросы на авторизацию прокси-серверу с поддержкой идентификации (
- Единая политика доступа и привязка IAM (
accessPolicy&policyBinding) :- Глобальные ресурсы IAM v3, содержащие детализированные правила доступа.
- Проверяет подлинность основного идентификатора SPIFFE вызывающего агента, проверяет универсальное разрешение
iap.googleapis.com/resources.egressViaIAPи оценивает условия Common Expression Language (CEL) на соответствие атрибутам назначения.
Развернуть расширение авторизации
Создайте конфигурацию расширения авторизации service-extensions , которая делегирует принятие решений об авторизации службе 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}
Проверьте расширение авторизации.
Убедитесь, что расширение авторизации активно:
# 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
)"
Развернуть политику авторизации
Создайте конфигурацию политики авторизации network-security , которая будет нацелена на Agent Gateway и делегирует проверку запросов расширению авторизации для 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}
Проверьте политику авторизации.
Убедитесь, что политика авторизации активна:
# 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
Теперь Agent Gateway делегирует проверки авторизации IAP и получает метаданные назначения из Agent Registry. Далее определите правило унифицированной политики доступа IAM для управления выполнением исходящих инструментов.
IAP оценивает выражения атрибутов CEL на основе следующих целевых атрибутов реестра агентов:
- Статус регистрации (
destination.is_registered) :- Логическое значение (
true/false), указывающее, внесено ли место назначения в каталог Agent Registry.
- Логическое значение (
- Имя MCP-сервера (
destination.agent_registry.mcp_server.name) :- Имя ресурса сервера Canonical MCP зарегистрировано в реестре агентов.
- Метод MCP (
destination.agent_registry.mcp_server.method) :- Вызываемый метод MCP (например,
tools/call,tools/list,initialize).
- Вызываемый метод MCP (например,
- Название инструмента (
destination.agent_registry.mcp_server.tool.name) :- Конкретное имя вызываемого инструмента (например,
subtractилиadd), обеспечивающее детальную авторизацию на уровне инструмента на зарегистрированных серверах MCP.
- Конкретное имя вызываемого инструмента (например,
Определите правило политики доступа IAM.
В манифесте правил политики IAM указано:
- Основные субъекты: Основной идентификатор SPIFFE, представляющий собой ключевого вспомогательного агента Gemini Enterprise.
- Разрешения: Для всего исходящего трафика, управляемого IAP, требуется универсальное разрешение
iap.googleapis.com/resources.egressViaIAP. - Условия: выражение CEL (
destination.is_registered == true), гарантирующее, что агент может вызывать только конечные точки, зарегистрированные в реестре агентов.
Создайте файл манифеста правил политики:
# 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.
Создайте глобальную политику доступа IAM, используя правила, определенные в файле манифеста:
# 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.
Убедитесь, что политика доступа IAM была успешно создана, и просмотрите сведения о правиле:
# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJ_ID} \
--location=global
Ожидаемый результат:
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 к проекту.
Чтобы активировать принудительное применение политики ко всем шлюзам агентов в вашем проекте, создайте привязку политики, которая связывает политику доступа IAM с ресурсом проекта:
# 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.
Проверьте, что активные точки привязки политики соответствуют правильной политике и целевому объекту:
# show policy binding details
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
--project=${PROJ_ID} \
--location=global
Ожидаемый результат:
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}
На этом завершается раздел, посвященный Agent Gateway... далее переходим к разделу, посвященному серверу MCP .
6. Сервер MCP
В этом разделе вы создадите собственный сервер FastMCP , предоставляющий инструменты add и subtract , и развернете его в Cloud Run непосредственно из исходного кода. Во время развертывания из исходного кода ( --source ) Cloud Build упакует образ контейнера, используя прилагаемый Dockerfile и uv (который устанавливает зависимости, определенные в pyproject.toml , и запускает server.py ).
После развертывания службы Cloud Run необходимо зарегистрировать сервер MCP в Agent Registry вместе со спецификацией инструментов ( toolspec.json ), чтобы Gemini Enterprise мог обнаруживать и запускать его инструменты.
Создание серверного приложения MCP
Создайте директорию проекта math-wizard для кода приложения:
# create directory for code
mkdir -p math-wizard
Напишите файл манифеста проекта 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
В код включены дополнительные функции инструментирования для захвата входящих HTTP-заголовков ( mcp-session-id , x-forwarded-for , user-agent и x-cloud-trace-context ) для проверки в Cloud Logging и Cloud Trace.
Напишите файл с кодом приложения:
# 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
Напишите Dockerfile , определяющий инструкции по сборке образа контейнера и команды запуска:
# 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
Разверните сервис в Cloud Run.
Разверните сервер MCP из исходного кода с помощью Cloud Build (который использует учетную запись вычислительной службы проекта по умолчанию ${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
Проверьте развертывание Cloud Run.
Проверьте сведения о службе Cloud Run, чтобы убедиться в ее активной конфигурации:
# show cloud run service details
gcloud run services describe ${MCP_NAME} --region=${REGION}
Ожидаемый результат:
<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 в реестре агентов.
Чтобы Gemini Enterprise могла определить, какие именно инструменты доступны на сервере MCP, при регистрации в реестре агентов необходимо предоставить файл с описанием инструментов ( toolspec.json ).
Создание спецификации инструмента 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
Зарегистрируйте сервер MCP в реестре агентов.
# 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 в реестре агентов.
Убедитесь, что развернутая служба Cloud Run указана в качестве зарегистрированного сервера MCP в регионе, а также ее URL-адрес конечной точки и доступные инструменты:
# 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
)"
Ожидаемый результат:
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
Ознакомьтесь со спецификацией конфигурации сервиса, чтобы убедиться, что в ней регистрируются точные определения инструментов, входные схемы и аннотации поведения для каждого инструмента:
# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
--location=${REGION} \
--project=${PROJ_ID} \
--format="yaml(mcpServerSpec.content.tools)"
На этом завершается раздел, посвященный серверу MCP... далее переходим к разделу Gemini Enterprise .
7. Gemini Enterprise
В этом разделе вы создадите и настроите приложение Gemini Enterprise и связанный с ним пользовательский ресурс хранилища данных сервера MCP .
Модель ресурсов поисковой системы
Приложение Gemini Enterprise (представленное в API Discovery Engine как ресурс Engine ) является центральным уровнем оркестрации и диалоговым интерфейсом для конечных пользователей. Оно управляет сеансами чата пользователей, основывает генеративные модели на корпоративных данных и координирует выполнение динамических инструментов.
Приложения Gemini Enterprise взаимодействуют с данными и системами через хранилища данных :
- Хранилища знаний: Загрузка и индексирование статического контента (например, Cloud Storage, Google Drive, BigQuery) для генерации данных с расширенными возможностями поиска (RAG).
- Коннекторы данных (поставщики действий): Подключаются к динамическим сторонним или пользовательским API. Пользовательское хранилище данных на сервере MCP предоставляет инструменты, определенные протоколом контекста модели (MCP), позволяя модели динамически вызывать внешние функции во время диалога.
Маршрутизация исходящего трафика через Agent Gateway
По умолчанию Gemini Enterprise направляет трафик коннекторов и выполнения инструментов через общедоступные сети. Однако для рабочих нагрузок в частных VPC и управления на основе принципа нулевого доверия механизм можно настроить на маршрутизацию исходящего трафика через Agent Gateway :
- При создании пользовательского хранилища данных сервера MCP в дальнейшем в этой лабораторной работе необходимо включить маршрутизацию исходящего трафика через Agent Gateway в настройках хранилища данных.
- Это связывает исходящие вызовы инструментов движка с вашим региональным шлюзом агентов, гарантируя, что все запросы MCP передают
Agent Identityприложения, проходят авторизацию во время выполнения с использованием IAP и унифицированных политик доступа IAM (UAP) и проходят через сетевое подключение PSC в вашу частную VPC.
Создайте корпоративное приложение Gemini.
Следующий метод использует API discoveryengine.googleapis.com для создания ресурсов и конфигурации приложения Gemini Enterprise. Инструкции по настройке с помощью пользовательского интерфейса консоли Google Cloud см. в разделе «Создание приложения» .
# 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
Подтвердите создание приложения.
# 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}"
Чтобы увидеть созданную конфигурацию, просмотрите подробные сведения о двигателе:
# 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}"
Обратите внимание на следующие свойства, заполняемые сервером в JSON-ответе:
-
name: Канонический путь к ресурсу (projects/${PROJ_NO}/locations/global/collections/default_collection/engines/${GE_APP_ID}). -
sessionConfig.sessionManagementPolicy: По умолчанию используется значение"VERTEX_AI_MANAGED", которое сохраняет состояние многоходового чата и вызова инструментов в Agent Platform (ранее известной как Vertex AI). -
observabilityConfig.observabilityEnabled: По умолчанию значение равноtrueдля базовых метрик (подробное логирование подсказок и полезной нагрузки инструмента включается на более позднем этапе).
Включить поставщика идентификации
Включите Google Identity в качестве поставщика идентификации для аутентификации конечных пользователей в вашем приложении Gemini Enterprise.
Следующий метод использует API discoveryengine.googleapis.com для настройки поставщика идентификации приложений Gemini Enterprise. Инструкции по настройке с помощью пользовательского интерфейса консоли Google Cloud см. в разделе «Настройка поставщика идентификации» .
# 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
Проверка поставщика идентификационных данных
# 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}"
Выходные данные "idpType": "GSUITE" соответствуют поставщику идентификации Google.
(Необязательно) Активируйте пробную лицензию Gemini Enterprise
Если вы используете проект, для которого назначены лицензии Gemini Enterprise, этот шаг можно пропустить. Если вы используете новый проект без лицензии, продолжайте и выполните следующие шаги.
Создайте ресурс конфигурации лицензии, чтобы предоставить пользователям Gemini Enterprise 30-дневные права доступа. Это установит лицензию по умолчанию на новый пробный период, поэтому каждому пользователю, входящему в систему, автоматически будет предоставлено право доступа:
# 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
Проверка лицензии была проведена.
# 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}"
Проверьте значения параметров "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" и "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}"
Проверьте наличие ../free_trial_gemini" и "enableLicenseAutoRegister": true .
Включить параметры мониторинга
Включение мониторинга на уровне приложения Gemini Enterprise (движка) позволяет просматривать взаимодействие основного помощника с данными метрик в Metrics Explorer и сопоставлять сквозные трассировки в 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
Проверьте настройки наблюдаемости.
# 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}'
Проверьте значение параметра "sensitiveLoggingEnabled": true .
Привязаться к Agent Gateway
Маршрутизация исходящего трафика из Gemini Enterprise через Agent Gateway устанавливает централизованную границу управления и обеспечения безопасности на основе принципа нулевого доверия для всех вызовов инструментов ИИ-агента:
- Централизованное обеспечение соблюдения политик: Agent Gateway выступает в качестве встроенного прокси-сервера, который оценивает исходящие запросы инструментов на соответствие политикам авторизации и механизмам управления до того, как трафик покинет среду агента.
- Выход из частной сети: привязка Gemini Enterprise к Agent Gateway гарантирует, что вызовы инструментов, нацеленные на частные серверы MCP в Cloud Run, будут безопасно маршрутизироваться через Private Service Connect (PSC), минуя общедоступный интернет.
- Единая система аудита: обеспечивает централизованное ведение журналов запросов, телеметрию и журналы аудита на всех подключенных серверах MCP и внешних инструментах.
Настроив agentGatewaySetting в приложении Gemini Enterprise, вы сможете автоматически направлять исходящие вызовы инструментов и агентов, инициированные запросами конечных пользователей (например, вызовы на пользовательские серверы MCP, импортированные из реестра агентов и агентов A2A), через Agent Gateway.
Внесите изменения в agentGatewaySetting движка, чтобы включить:
# 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.
Получите конфигурацию приложения, чтобы подтвердить привязку 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}'
Ожидаемый результат:
{
"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}"
}
}
}
Создайте пользовательское хранилище данных для сервера MCP.
В этом разделе вы подключите сервер MCP к Gemini Enterprise, создав собственное хранилище данных MCP.
При использовании API системы поиска это двухэтапный процесс:
- Create (
:setUpDataConnector): Creates a dedicatedCollectionresource (${MCP_NAME}-%timestamp-collection), attaches theDataConnector(custom_mcp), and provisions its backingDataStore(..._mcp_data). - Activate (
PATCH .../dataConnector?updateMask=actionConfig): Activates the connector's action runtime (actionState: "ACTIVE") using the Agent Registry tool spec and binds theDataStore(dataStoreIds) to your Gemini EnterpriseEngine.
# 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}"
Create data connector
# 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
Verify data connector creation
# 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}"
Check the "registry_mcp_server_name" field populates with the Agent Registry UUID for the MCP server:
# 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}'
View the MCP server registry entry in the Google Cloud Console UI:
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}"
Активировать коннектор данных
# 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
Verify custom MCP server linkages
# 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}'
Check for the linked data store "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}'
Check for "state": "ACTIVE" with all the parameters populated.
Действия инструмента
When you inspect the math-wizard-collection data store in the Gemini Enterprise dashboard, you will notice that the Actions tab is not used and the ↻ Reload custom actions button is disabled. This is expected behavior.
View the data store details page in the Google Cloud Console UI:
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}"
Depending on how you connect a custom MCP server to Gemini Enterprise, tool discovery and governance are handled in one of two ways:
- Direct Custom MCP (
BYO_MCPworkflow): When you configure a custom MCP server directly inside Gemini Enterprise without Agent Registry, the data store itself manages the tool catalog (connectorModes: ["FEDERATED", "ACTIONS"]). You must open the Actions tab, click ↻ Reload custom actions to fetch thetools/listschema, and manually toggle individual tools (addandsubtract) on or off in the UI. - Agent Registry Import (
REGISTRY_MCPworkflow used in this codelab): When you import an MCP server from Agent Registry , Agent Registry serves as the authoritative source of truth for the MCP endpoint, its interface metadata, and its tool catalog (connectorModes: ["FEDERATED"]). Gemini Enterprise automatically enables the registered MCP tools at runtime through the engine's Agent Gateway without requiring you to manually reload or toggle actions in the data store UI.
This concludes the Gemini Enterprise app portion... next on to the Validate section.
8. Validate
In this section you will trigger live MCP tool calls from the Gemini Enterprise web app and trace the request flow across Agent Gateway, Cloud DNS, VPC firewall, and Cloud Run logs. You will then tighten the IAM Unified Access Policy to allow subtract while blocking add , verifying zero-trust enforcement at the gateway.
Доступ пользователя
Construct the URL for the Gemini Enterprise web app:
# 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}"
Follow the link to open the Gemini Enterprise web app chat interface in your browser and click Get started .
Test agent queries in chat
In the chat UI, confirm the math-wizard-collection data connector is enabled by clicking on the puzzle piece icon for Connectors at the bottom of the chat box. You should see a toggle button that appears on (is colored in).
Try out the following test queries:
what is 2342345 - 98234798324?
what is 72347234 + 234234?
Verify that the assistant returns the correct answers and displays an interactive action citation badge (like Math Calculation (8s) 🤖 Agentgateway Agent ) beneath each response, confirming the tool was executed.
Inspect logs in Cloud Logging
Verify that Gemini Enterprise routed the tool calls through Agent Gateway and the private VPC network by inspecting the logs in Cloud Logging.
1. Verify Agent Gateway & IAP authorization
Confirm that Agent Gateway intercepted the request, resolved the target in Agent Registry, delegated authorization to IAP, and permitted the tool call:
# 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
)"
Verify that the output contains:
-
STATUS:200(successful execution) and202(notifications/initializedhandshake). -
SERVER_IP: Google APIs PSC endpoint IP (172.16.20.20:443). -
MCP_METHOD&TOOL: The MCP protocol sequence (notifications/initialized,tools/list, andtools/callwithaddorsubtract). -
AUTHZ:ALLOWED(IAP authorization permitted egress). -
REGISTRY_MCP: Resolved Agent Registry resource ID (agentregistry-...).
2. Verify DNS and firewall transit
Confirm that Cloud DNS resolved the hostname to the PSC endpoint and that the firewall permitted traffic from the Agent Gateway interface:
# 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
)"
Verify the following values:
- DNS
QUERY_NAME&RDATA: Resolvesmath-wizard-...run.app.(Arecord,NOERROR) to172.16.20.20. - Firewall
SRC_IP&DEST_IP:192.168.10.2(Agent Gateway PSC interface IP) to172.16.20.20:443. - Firewall
RULE&DISPOSITION: MatchedfirewallPolicy:fw-policy-...withALLOWED.
3. Verify Cloud Run tool execution
Confirm that the Cloud Run container received and processed the tool call:
# 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)"
Verify that textPayload displays tool execution entries (eg, >>> 🛠️ Tool: 'subtract' called with numbers '[x]' and '[y]' ).
Test least-privilege policy enforcement
In the initial IAM access policy, any method or tool was permitted as long as the destination was registered ( destination.is_registered == true ). In this step, update the policy to enforce least-privilege by allowing only the subtract tool while blocking add .
Update IAM access policy
When restricting MCP tool execution, use a two-rule pattern :
- Rule 1 (MCP discovery and handshake): Permits non-tool-call MCP lifecycle methods (
destination.is_registered == trueanddestination.agent_registry.mcp_server.method != 'tools/call'). Because Gemini Enterprise negotiates stream setup and discovery (initialize,notifications/initialized,tools/list) before invoking a tool—anddestination.agent_registry.mcp_server.tool.nameis only populated duringtools/call—Rule 1 is necessary to keep session initialization and catalog discovery working. - Rule 2 (Tool-level restriction): Restricts
tools/callexecution so only thesubtracttool is permitted (destination.is_registered == true,destination.agent_registry.mcp_server.method == 'tools/call', anddestination.agent_registry.mcp_server.tool.name == 'subtract').
Update the access policy rule manifest file with both rules:
# 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
Apply the updated rules to the IAM access policy:
# 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
Verify IAM access policy
Check the new IAM access policy is applied and only the subtract tool is allowed:
# 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
)"
Test a prohibited tool call
Return to the Gemini Enterprise web app chat UI and try another test query:
what is 100 plus 20?
The assistant attempts to invoke add , but Agent Gateway and IAP evaluate the IAM policy condition as false and deny the egress request with HTTP 403 Forbidden . In the chat UI, you will notice the assistant display Calculate Sum and spin on 🤖 Agentgateway Agent ... Working on it. as it retries the blocked tool call. This is expected behavior . It confirms that Agent Gateway and IAP are actively intercepting and denying disallowed tool execution at the network level.
Повторно проверьте журналы в Cloud Logging.
View the Agent Gateway log entries and notice the new 403 entries corresponding to the disallowed add tool call:
# 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
)"
Ожидаемый результат:
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
Check that the additional request never reached the Cloud Run backend:
# 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)"
The command returns no new entries, confirming that Agent Gateway successfully enforced the IAM access policy.
This concludes the validate portion... next on to the Cleanup section.
9. Cleanup
Follow these steps to delete the resources and configurations created in this lab.
Remove Gemini Enterprise components
# 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"}}'
Remove MCP server components
# 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}
Remove Agent Gateway and IAM access policies
# 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}
Remove DNS and firewall components
# 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}
Remove PSC and VPC network components
# 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}
Remove organization policy overrides and local files
# 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
This concludes the cleanup work... next on to the Conclusion !
10. Заключение
Congratulations! You built an end-to-end architecture enabling a Gemini Enterprise app to securely discover and invoke tools on a private custom MCP server :
- Custom MCP server & Agent Registry: Deployed a private FastMCP service on Cloud Run (
--ingress=internal) and registered its endpoint and tool schema (addandsubtract) in Agent Registry. - Gemini Enterprise integration: Provisioned a Gemini Enterprise app, bound outbound tool traffic to Agent Gateway , and attached the registered MCP server as a
REGISTRY_MCPdata connector. - Private VPC egress & zero-trust governance: Routed tool execution privately over PSC (
172.16.20.20) and enforced tool-level least privilege using IAP and IAM Unified Access Policies (destination.agent_registry.*).

Cosmpup thinks Codelabs are absolutely goated!
Что дальше?
- Check out the Gemini Enterprise Agent Platform docs for advanced features and tutorials.
- Configure Model Armor guardrails on Agent Gateway for additional AI safety and security.
- Explore Semantic Governance Policies to enforce business rules and compliance for natural language queries.
Feel free to offer comments, questions, or corrections by using this feedback form .
Спасибо!