Gemini Enterprise z bramą agentów wychodzącą do prywatnego niestandardowego serwera MCP za pomocą rejestru agentów

1. Wprowadzenie

To ćwiczenie pokazuje, jak skonfigurować prywatne, kontrolowane połączenie wychodzące dla Gemini Enterprise za pomocą Bramy agentów w trybie agent-to-anywhere (ruch wychodzący). Skonfigurujesz aplikację Gemini Enterprise, aby bezpiecznie wywoływać niestandardowy serwer protokołu kontekstu modelu (MCP) hostowany w Cloud Run, kierując ruch przez Agent Gateway przy użyciu interfejsów Private Service Connect (PSC) w celu połączenia się z punktem końcowym PSC dla interfejsów API Google w sieci VPC.

W środowiskach korporacyjnych przyznanie autonomicznym agentom bezpośredniego dostępu do sieci wiąże się z ryzykiem wydobycia danych i wykonywania niezweryfikowanych narzędzi. Brama agentów to scentralizowany punkt egzekwowania zasad zerowego zaufania na poziomie platformy, który dynamicznie sprawdza przesyłane strumieniowo ładunki narzędzi MCP HTTP. Żądania wychodzące są uwierzytelniane za pomocą kryptograficznie weryfikowalnej Agent Identity i autoryzowane przez Identity-Aware Proxy (IAP) przy użyciu ujednoliconych zasad dostępu (UAP) IAM z regułami języka CEL (Common Expression Language). Umożliwia to szczegółową kontrolę dostępu do konkretnych narzędzi i metod MCP bez udostępniania zadań backendu w internecie publicznym.

Co utworzysz

  • Brama agentów działająca w trybie ruchu wychodzącego (od agenta do dowolnego miejsca) z weryfikacją punktu końcowego Agent Registry
  • Usługa Cloud Run hostująca prywatny serwer MCP HTTP z możliwością przesyłania strumieniowego (--ingress=internal) zarejestrowany w Agent Registry ze specyfikacjami narzędzi
  • Rozszerzenie autoryzacji Identity-Aware Proxy (IAP) dla bramy agentów
  • Ujednolicone zasady dostępu (UAP) IAM z warunkami CEL na potrzeby autoryzacji narzędzia MCP
  • Aplikacja Gemini Enterprise powiązana z bramą agentów i połączona z niestandardowym magazynem danych serwera MCP zaimportowanym z Agent Registry
  • Zasoby sieci VPC, strefa Cloud DNS i punkt końcowy PSC dla interfejsów API Google
  • Przyłącze sieci PSC na potrzeby prywatnego ruchu wychodzącego z bramy agenta
  • Reguły zasad Cloud Next Generation Firewall (NGFW) do zabezpieczania ruchu VPC

figure1

Rys. 1. Architektura ćwiczeń z programowania

Czego się dowiesz

  • Jak wdrożyć prywatny serwer MCP HTTP z możliwością przesyłania strumieniowego ze źródła w Cloud Run i zarejestrować jego punkt końcowy oraz schemat narzędzia w Agent Registry
  • Jak skonfigurować bramę agentów za pomocą zgodnych wpisów w rejestrze i przekierowywać wywołania narzędzi aplikacji Gemini Enterprise przez bramę
  • Jak skonfigurować prywatny ruch wychodzący z sieci VPC za pomocą przyłączy sieci PSC i interfejsów
  • Delegowanie autoryzacji bramy agentów na Identity-Aware Proxy (IAP)
  • Jak tworzyć i wiązać ujednolicone zasady dostępu (UAP) w IAM za pomocą atrybutów CEL destination.agent_registry.* i destination.is_registered, aby ograniczyć wykonywanie narzędzia MCP
  • Jak weryfikować egzekwowanie zasad i ruch wychodzący z sieci za pomocą Cloud Logging

Wymagania

  • Projekt Google Cloud z włączonymi płatnościami
  • aktywną licencję Gemini Enterprise lub 30-dniowy okres próbny;
  • Uprawnienia IAM do udostępniania usług sieciowych, Gemini Enterprise i zasobów Agent Platform
  • Powłoka zgodna z POSIX (bash lub zsh) z zainstalowanymi narzędziami Google Cloud CLI (gcloud), curl i jq.

To koniec wprowadzenia. Przejdźmy teraz do sekcji Pojęcia.

2. Pojęcia

Sekwencja wdrażania

To ćwiczenie najpierw wdraża infrastrukturę, aby ścieżki sieci prywatnej i elementy sterujące zarządzaniem działały przed zarejestrowaniem i połączeniem narzędzi MCP z Gemini Enterprise:

  1. Infrastruktura sieciowa: udostępnij podsieci VPC, punkt końcowy PSC, przyłącze sieci PSC, reguły zasad Cloud NGFW i prywatne strefy Cloud DNS.
  2. Brama agentów: wdróż bramę agentów w trybie ruchu wychodzącego z integracją z Agent Registry (registries) i prywatnym ruchem wychodzącym z sieci VPC (networkAttachment).
  3. Zasady autoryzacji: skonfiguruj rozszerzenie autoryzacji IAP, zasadę autoryzacji bramy i zasadę ujednoliconego dostępu IAM za pomocą warunków CEL destination.is_registered i destination.agent_registry.*.
  4. Wdróż i zarejestruj serwer MCP: wdróż serwer MCP do obliczeń matematycznych ze źródła w Cloud Run (--ingress=internal) i zarejestruj specyfikacje usługi i narzędzia (add i subtract) w Agent Registry.
  5. Aplikacja Gemini Enterprise: utwórz aplikację Gemini Enterprise (Engine), skonfiguruj ustawienia tożsamości i widoczności oraz powiąż wychodzący ruch z bramą agentów (agentGatewaySetting).
  6. Importowanie niestandardowego łącznika danych MCP: utwórz i aktywuj REGISTRY_MCP łącznik danych (:setUpDataConnector), aby połączyć magazyn danych zarejestrowanego serwera MCP z aplikacją Gemini Enterprise.
  7. Weryfikacja: testuj dozwolone i niedozwolone wykonania narzędzi na czacie oraz sprawdzaj egzekwowanie zasad w logach usługi bramy agentów, DNS, zapory sieciowej i Cloud Run.

Ruch wychodzący Gemini Enterprise

Gemini Enterprise kieruje żądania narzędzi niestandardowego serwera MCP do bramy agentów, gdy skonfigurowane są zarówno agentGatewaySetting na Engine, jak i use_agent_gateway_egress: true na DataConnector.

figure2

Rys. 2. Architektura ruchu wychodzącego Gemini Enterprise

Aplikacja Gemini Enterprise porządkuje routing narzędzi w 4 głównych obszarach:

  1. Widżet (default_search_widget_config):
    • Obsługuje interfejs klienta internetowego. Widżet otrzymuje prompty od użytkownika i rozpoczyna sesje czatu z silnikiem bazowym.
  2. Podstawowy asystent (assistants/default_assistant/agents/default/core_assistant):
    • Główny konwersacyjny agent rozumowania w silniku. Podczas oceny zapytania użytkownika Asystent główny określa, czy wymagane jest obliczenie arytmetyczne, sprawdza dostępne narzędzia i przekazuje wykonanie zadania do wygenerowanego podagenta bramy agenta.
  3. Magazyn danych i Łącznik danych:
    • DataStore: jest udostępniany w ramach dedykowanego Collection podczas działania :setUpDataConnector. Łączy (dataStoreIds) zaimportowane schematy narzędzi Agent Registry (add, subtract), typy argumentów i instrukcje agenta z Engine Gemini Enterprise.
    • DataConnector: zarządza połączeniem działania REGISTRY_MCP (createBapConnection: true) ze zdalnym Serwerem MCP (instance_uri), rozwiązuje zasób Serwera MCP z Agent Registry (registry_mcp_server_name) i umożliwia ruch wychodzący z Bramy agentów (use_agent_gateway_egress: true).
  4. Agent Identity, Agent Registry i Brama agentów:
    • Gdy łącznik danych wysyła wywołanie narzędzia wychodzącego, kieruje ruch do bramy określonej w agentGatewaySetting. Centrum Asystenta tworzy token tożsamości SPIFFE potwierdzający jego tożsamość: principal://agents.global.org-.../agents/default/core_assistant.
    • Brama agentów jest zintegrowana z Agent Registry za pomocą pola registries, aby dynamicznie rozpoznawać docelowe punkty końcowe i zarejestrowane schematy narzędzi. Wypełnia atrybuty destination.is_registered i destination.agent_registry.* i przekazuje je do IAP w wersji 2 w celu oceny na podstawie reguł CEL ujednoliconych zasad dostępu (UAP) IAM przed zezwoleniem na przesyłanie danych do sieci VPC.

Połączenie z siecią VPC bramy

Brama agenta umożliwia prywatne połączenie z siecią VPC za pomocą 2 pól YAML:

  • networkConfig.egress.networkAttachment: kieruje ruch prywatnych adresów IP, aby był kierowany przez przyłącze sieci PSC do sieci VPC.
  • dnsPeeringConfig.domains: łączy rozpoznawanie nazw DNS ze strefą DNS Cloud DNS sieci VPC, dzięki czemu docelowe nazwy hostów (*.run.app) są rozpoznawane jako prywatny adres IP punktu końcowego PSC zdefiniowany w sieci VPC.

Ograniczenia i wymagania

  • Tylko StreamableHTTP: starszy transport zdarzeń wysyłanych przez serwer (SSE) nie jest obsługiwany. Serwery MCP muszą korzystać z StreamableHTTP.
  • Wymagany publiczny CA TLS: punkty końcowe MCP muszą używać certyfikatów TLS podpisanych przez publicznie zaufany urząd certyfikacji, nawet jeśli dostęp do nich jest prywatny przez PSC.
  • Zastąpienie zasad organizacji: przed zarejestrowaniem magazynu danych musisz wyraźnie zastąpić zasady organizacji dotyczące niestandardowych magazynów danych MCP.

To koniec części poświęconej koncepcjom. Przejdźmy teraz do sekcji Konfiguracja.

3. Konfiguracja

Wymagane role uprawnień

Aby ukończyć to ćwiczenie, musisz mieć te role:

Domena

Wymagane role uprawnień

Projekt i IAM

roles/orgpolicy.policyAdmin
roles/resourcemanager.projectIamAdmin
roles/iam.accessPolicyAdmin
roles/serviceusage.serviceUsageAdmin
roles/iam.serviceAccountUser

Sieć i brama

roles/networkservices.admin
roles/networksecurity.admin
roles/serviceextensions.admin
roles/compute.networkAdmin
roles/dns.admin

Gemini Enterprise i rejestr

roles/discoveryengine.admin
roles/agentregistry.admin (lub roles/apphub.admin)

Workloads & Build

roles/run.admin
roles/cloudbuild.builds.editor
roles/artifactregistry.writer
roles/storage.admin

Dostrzegalność

roles/logging.viewer
roles/logging.logWriter

Możesz też użyć szerokiego poziomu podstawowego, np. roles/owner, w połączeniu z roles/orgpolicy.policyAdmin (ponieważ sam poziom podstawowy roles/owner nie może modyfikować zasad organizacji).

Dostęp do projektu

To ćwiczenie korzysta z jednego projektu Google Cloud. Etapy konfiguracji obejmują użycie interfejsu wiersza poleceń gcloud i poleceń powłoki Linux.

Zacznij od uzyskania dostępu do wiersza poleceń projektu w chmurze Google Cloud:

Ustawianie identyfikatora projektu

gcloud config set project SET_YOUR_PROJECT_ID_HERE

Uwierzytelnianie sesji

# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login

Ustawianie zmiennych środowiskowych powłoki

# 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}

Ustawianie domen zaufania tożsamości agenta

Instrukcja if-then-else sprawdza, czy projekt należy do organizacji, aby ustawić prawidłową domenę zaufania dla tożsamości agenta głównego.

# 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}"

Ustawianie projektu rozliczeniowego i projektu limitu

# 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}

Tworzenie lokalnego katalogu plików konfiguracyjnych

# create config folder
mkdir -p cfg

Jeśli korzystasz z samodzielnie zarządzanej instalacji pakietu Google Cloud SDK (czyli poza Cloud Shell), zaktualizuj komponenty do najnowszej wersji.

# update gcloud cli
gcloud components update

Włączanie usług 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

Zasady organizacji

Domyślne zarządzane ograniczenia zasad organizacji Google Cloud ograniczają funkcje używane w tym laboratorium:

Zastąp wszelkie odziedziczone ograniczenia zasad organizacji na poziomie projektu, ustawiając wyraźnie wartość enforce: false.

Wyłączanie niestandardowego ograniczenia 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

Wyłączanie ograniczenia zasady dostępu

# 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

Sprawdzanie i wyłączanie ograniczeń warunkowego oprogramowania sprzęgającego dane

Domyślnie warunki discoveryengine.managed.allowedEgressFqdns i discoveryengine.managed.allowedDataSources blokują tworzenie oprogramowania sprzęgającego tylko wtedy, gdy Twój projekt znajduje się w granicach Ustawień usługi VPC lub gdy administrator organizacji dodał Twój projekt do enforcedProjects.

Najpierw sprawdź obowiązujące zasady w projekcie:

# 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~~ te ograniczenia są egzekwowane, aby mieć pewność, że nie blokują konfiguracji oprogramowania sprzęgającego custom_mcp w organizacji z usługą VPC SC lub ograniczeniami zasad, ustaw w obu zasadach dla projektu wartość 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

Uprawnienia

Przyznaj wymagane role uprawnień kontu użytkownika i domyślnemu kontu usługi Compute Engine używanemu przez Cloud Build:

  • Konto użytkownika (${USER_IDENTITY}):
    • Wymaga uprawnień do wdrażania i wywoływania usług Cloud Run (roles/run.admin, roles/run.invoker, roles/iam.serviceAccountUser), tworzenia obrazów kontenerów (roles/cloudbuild.builds.editor), zarządzania Gemini Enterprise (roles/discoveryengine.admin) i tworzenia ujednoliconych zasad dostępu (roles/iam.accessPolicyAdmin).
  • Domyślne konto usługi Compute Engine${PROJ_NO}-compute@developer.gserviceaccount.com:
    • Używane przez Cloud Build do przechowywania kodu źródłowego w Cloud Storage (roles/storage.admin), przesyłania obrazów do Artifact Registry (roles/artifactregistry.writer) i zapisywania dzienników kompilacji (roles/logging.logWriter).

Aby przypisać powiązania ról, uruchom te polecenia:

# 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"

Sprawdzanie uprawnień

Sprawdź, czy na koncie użytkownika jest 6 powiązań ról (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)"

Sprawdź, czy na domyślnym koncie usługi Compute są 3 powiązania ról (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)"

Weryfikowanie powiązań agenta usługi (środki ostrożności)

W nowym projekcie Google Cloud automatycznie udostępnia agenta usługi Brama agentów i przyznaje mu uprawnienia roles/agentgateway.serviceAgent, gdy po raz pierwszy włączona jest usługa networkservices.googleapis.com. Jeśli ponownie używasz istniejącego projektu, w którym wcześniejsze czyszczenie mogło spowodować usunięcie domyślnych powiązań agenta usługi, wykonaj te polecenia, aby mieć pewność, że tożsamość i powiązanie ról są nienaruszone:

# 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"

To kończy część dotyczącą konfiguracji. Przejdź do sekcji Sieć.

4. Sieć

W tej sekcji wdrożysz sieć VPC w trybie niestandardowym z dedykowaną podsiecią /28 (192.168.10.0/28) obsługującą przyłącze sieciowe usługi PSC na potrzeby ruchu wychodzącego z sieci bramy agenta do sieci VPC.

Punkt końcowy PSC dla interfejsów API Google jest wdrażany przy użyciu jednego /32globalnego wewnętrznego adresu IPv4 (172.16.20.20), aby obsługiwać prywatny dostęp wewnętrzny do interfejsów API i usług Google. W tym ćwiczeniu Agent Gateway kieruje ruch do Cloud Run przy użyciu punktu końcowego PSC, rozwiązując domenę run.app. za pomocą komunikacji równorzędnej Cloud DNS.

Tworzenie sieci

Utwórz globalną sieć VPC.

# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom

Utwórz podsieci dla przyłącza sieci PSC bramy agenta:

# 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

Utwórz reguły zapory sieciowej

Utwórz zasadę zapory sieciowej, która zezwala na cały ruch wychodzący z włączonym logowaniem. Będzie on używany do monitorowania ruchu wychodzącego z bramy agenta do sieci VPC. Cloud NGFW obsługuje poziomy Essentials i Standard w zakresie zabezpieczeń sieci i monitorowania ruchu.

# 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

Tworzenie przyłącza sieci PSC

Utwórz przyłącze sieci Private Service Connect (PSC) skonfigurowane tak, aby automatycznie akceptować połączenia z Bramy agentów. Przyłącze sieciowe tworzy po stronie sieci VPC konsumenta połączenie, które bezpiecznie łączy się z bramą agenta po stronie producenta na potrzeby wychodzącego ruchu wychodzącego. Więcej informacji o wymaganiach dotyczących podsieci i specyfikacjach zakresów adresów IP znajdziesz w artykule Konfigurowanie połączenia z siecią VPC.

# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
  --region=${REGION} \
  --subnets=subnet-${REGION}-agw \
  --connection-preference=ACCEPT_AUTOMATIC

Weryfikowanie przyłącza sieci PSC

# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}

Pobierz identyfikator URI zasobu przyłącza sieci PSC i zapisz go w zmiennej środowiskowej PSC_NA_URI. Ten URI będzie używany w konfiguracji bramy agenta (networkConfig.egress.networkAttachment) do udostępniania interfejsu PSC na potrzeby ruchu wychodzącego z sieci 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}

Tworzenie punktu końcowego PSC

Punkt końcowy Private Service Connect (PSC) dla interfejsów API Google jest używany przez Bramę agentów do nawiązywania prywatnego połączenia z serwerem MCP Cloud Run przez wewnętrzną ścieżkę sieciową bez udostępniania ruchu w internecie publicznym. Wywołania narzędzi wychodzące z Bramy agentów do sieci VPC będą rozpoznawać docelowy adres URL usługi Cloud Run (*.run.app) jako ten prywatny adres IP punktu końcowego.

Zarezerwuj globalny wewnętrzny adres IPv4 dla punktu końcowego PSC. Wybrany adres IP musi być adresem /32, który nie pokrywa się z żadną istniejącą podsiecią w sieci 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}

Utwórz punkt końcowy PSC dla interfejsów API Google za pomocą pakietu all-apis, który obejmuje 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

Weryfikowanie punktu końcowego PSC

# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global

Tworzenie strefy i rekordów DNS

Cloud DNS umożliwia bramie agenta prywatną komunikację z serwerem MCP hostowanym w Cloud Run. Gdy Brama agentów ocenia wychodzące żądania narzędzi kierowane do Cloud Run, używa połączeń równorzędnych DNS (dnsPeeringConfig.domains) do rozpoznawania zapytań DNS dotyczących *.run.app przy użyciu prywatnej strefy DNS powiązanej z siecią VPC. Prywatny rekord DNS zwraca zapytanie z wewnętrznym adresem IP punktu końcowego PSC (172.16.20.20), co umożliwia kierowanie żądań narzędzia MCP przez ścieżkę sieci prywatnej.

Utwórz prywatną zarządzaną strefę Cloud DNS dla domeny 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}

Utwórz rekord DNS z symbolem wieloznacznym A dla *.run.app. wskazujący adres IP punktu końcowego PSC:

# create dns record
gcloud dns record-sets create "*.run.app." \
  --zone=priv-zone-run \
  --type=A \
  --ttl=300 \
  --rrdatas=${PSC_EP_IP}

Utwórz zasadę Cloud DNS, aby włączyć logowanie zapytań DNS. Logowanie DNS rejestruje żądania rozpoznawania domen pochodzące z bramy agentów w sieci VPC, co zapewnia możliwość audytu i weryfikacji, czy żądania narzędzia *.run.app są prawidłowo rozpoznawane w wewnętrznym punkcie końcowym PSC:

# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
  --description="dns logging for vnet-${SLUG}" \
  --networks=vnet-${SLUG} \
  --enable-logging

To wszystko, jeśli chodzi o sieć. Przejdźmy teraz do sekcji Brama agenta.

5. Brama agentów

Brama agenta określa registries dla instancji rejestru agentów wraz z polami networkConfig, które konfigurują przyłącze sieci PSC i ustawienia połączenia równorzędnego DNS na potrzeby prywatnego połączenia VPC:

  • registries: łączy bramę z maksymalnie 2 instancjami Agent Registry: jedną regionalną (../locations/${REGION}) i jedną globalną (../locations/global). Integruje to Bramę agentów z Agent Registry, aby rozwiązywać zarówno wdrożenia regionalne (np. serwery MCP Cloud Run w ${REGION}), jak i zasoby globalne (np. agenty Gemini Enterprise i globalne punkty końcowe) na potrzeby szczegółowego egzekwowania zasad IAP w wersji 2. Podczas rozwiązywania adresów URL miejsc docelowych wpisy regionalne mają pierwszeństwo przed wpisami globalnymi.
  • networkAttachment: wskazuje przyłącze sieci PSC (psc-na-${REGION}-agw), które łączy bramę agenta z Twoją siecią VPC na potrzeby prywatnego ruchu wychodzącego.
  • dnsPeeringConfig.domains: konfiguruje run.app. tak, aby zapytania DNS pochodzące z bramy agenta dla usług Cloud Run korzystały z połączenia równorzędnego DNS w celu rozpoznawania nazw hostów na adres IP punktu końcowego PSC prywatnych interfejsów API Google (172.16.20.20) skonfigurowanego w prywatnej strefie Cloud DNS.

Wdrażanie bramy agentów

Utwórz i zaimportuj plik konfiguracji bramy agentów.

# 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}

Sprawdzanie wdrożenia bramy agentów

Potwierdź Agent Registry i konfigurację sieci:

# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
  --location=${REGION} \
  --format="yaml(registries,networkConfig)"

Oczekiwane dane wyjściowe:

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}

Sprawdź, czy w danych wyjściowych wyświetlają się wymagane szczegóły konfiguracji:

  • registries: zawiera listę regionalnych (${REGION}) identyfikatorów URI Agent Registry powiązanych z bramą.
  • egress.networkAttachment: określa identyfikator URI przyłącza sieci PSC dla ruchu wychodzącego z sieci VPC.
  • dnsPeeringConfig.domains: zawiera run.app. wskazujący targetNetwork na potrzeby rozpoznawania domeny prywatnej.

Sprawdź przyłącze sieci PSC, aby potwierdzić połączenie z bramą:

# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
  --region=${REGION} \
  --format="yaml(connectionEndpoints)"

Sprawdź, czy istnieje zaakceptowany punkt końcowy połączenia:

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

Przekazywanie autoryzacji

Brama agentów zabezpiecza i kontroluje ruch wychodzący narzędzi za pomocą zasad autoryzacji (networksecurity.authzPolicies) zintegrowanych z ujednoliconymi zasadami dostępu (UAP) Identity-Aware Proxy (IAP).

Brama agentów obsługuje podstawowe reguły wbudowane ALLOW i DENY, ale środowiska firmowe wymagają scentralizowanego zarządzania opartego na tożsamości. W przypadku ujednoliconych zasad dostępu IAM (lub zasad dostępu) regułami dostępu wychodzącego zarządzasz za pomocą standardowych zasad dostępu IAM w wersji 3.

figure3

Ilustracja 3. Architektura autoryzacji

Proces autoryzacji łączy 3 komponenty:

  1. Zasady autoryzacji bramy (authzPolicy):
    • Zasób regionalny kierowany na bramę agenta.
    • Skonfigurowano za pomocą policyProfile: REQUEST_AUTHZ i action: CUSTOM, aby kierować wszystkie wychodzące sprawdzania autoryzacji do rozszerzenia autoryzacji IAP.
  2. Rozszerzenie usługi IAP (authzExtension):
    • Zasób regionalny, który deleguje autoryzację żądań do Identity-Aware Proxy (iap.googleapis.com).
    • Ocenia zasady w trybie ENFORCE, używając wersji zasad V2.
  3. Ujednolicone zasady dostępu i powiązania IAM (accessPolicy i policyBinding):
    • Zasoby globalnych uprawnień w wersji 3 zawierające szczegółowe reguły dostępu.
    • Uwierzytelnia tożsamość podmiotu SPIFFE wywołującego agenta, weryfikuje uniwersalne uprawnienie iap.googleapis.com/resources.egressViaIAP i ocenia warunki języka CEL (Common Expression Language) na podstawie atrybutów miejsca docelowego.

Wdrażanie rozszerzenia autoryzacji

Utwórz konfigurację rozszerzenia autoryzacji service-extensions, która przekazuje decyzje o autoryzacji do usługi 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}

Weryfikacja przedłużenia autoryzacji

Sprawdź, czy rozszerzenie autoryzacji jest aktywne:

# 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
  )"

Wdrażanie zasady autoryzacji

Utwórz konfigurację zasady autoryzacji network-security, która jest kierowana na bramę agentów i przekazuje weryfikację żądań do rozszerzenia autoryzacji dla 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}

Sprawdzanie zasad autoryzacji

Sprawdź, czy zasady autoryzacji są aktywne:

# 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
  )"

Tworzenie zasad dostępu uprawnień

Brama agentów deleguje teraz sprawdzanie autoryzacji do IAP i rozwiązuje metadane miejsca docelowego z Agent Registry. Następnie zdefiniuj regułę ujednoliconych zasad dostępu IAM, która będzie regulować wykonywanie narzędzi wychodzących.

Usługa IAP ocenia wyrażenia atrybutów CEL na podstawie tych atrybutów docelowych Agent Registry:

  • Stan rejestracji (destination.is_registered):
    • Wartość logiczna (true/false) wskazująca, czy miejsce docelowe jest skatalogowane w Agent Registry.
  • Nazwa serwera MCP (destination.agent_registry.mcp_server.name):
    • Kanoniczna nazwa zasobu serwera MCP zarejestrowana w Agent Registry.
  • Metoda MCP (destination.agent_registry.mcp_server.method):
    • Wywoływana metoda MCP (np. tools/call, tools/list, initialize).
  • Nazwa narzędziadestination.agent_registry.mcp_server.tool.name:
    • Nazwa wywołanego narzędzia (np. subtract lub add), która umożliwia precyzyjną autoryzację na poziomie narzędzia na zarejestrowanych serwerach MCP.

Definiowanie reguły zasady dostępu uprawnień

Manifest reguły zasady uprawnień określa:

  • Podmioty: tożsamość podmiotu SPIFFE reprezentująca agenta głównego asystenta Gemini Enterprise.
  • Uprawnienia: uniwersalne uprawnienie iap.googleapis.com/resources.egressViaIAP wymagane w przypadku całego ruchu wychodzącego objętego ochroną IAP.
  • Warunki: wyrażenie CEL (destination.is_registered == true), które zapewnia, że agent może wywoływać tylko punkty końcowe skatalogowane w Agent Registry.

Utwórz plik manifestu reguły zasady:

# 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

Wdrażanie zasady dostępu uprawnień

Utwórz globalną zasadę dostępu uprawnień, korzystając z reguł zdefiniowanych w pliku manifestu:

# 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

Sprawdzanie zasady dostępu uprawnień

Sprawdź, czy zasada dostępu IAM została utworzona, i zbadaj szczegóły reguły:

# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
  --project=${PROJ_ID} \
  --location=global

Oczekiwane dane wyjściowe:

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}

Powiązywanie zasady dostępu uprawnień z projektem

Aby aktywować egzekwowanie we wszystkich bramach agentów w projekcie, utwórz powiązanie zasad, które dołącza zasady dostępu IAM do zasobu projektu:

# 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

Sprawdzanie powiązania zasady dostępu uprawnień

Sprawdź, czy aktywne punkty wiązania zasad są powiązane z odpowiednimi zasadami i celem:

# show policy binding details
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
  --project=${PROJ_ID} \
  --location=global

Oczekiwane dane wyjściowe:

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}

To wszystko, jeśli chodzi o bramę agenta. Przejdźmy teraz do sekcji poświęconej serwerowi MCP.

6. Serwer MCP

W tej sekcji utworzysz niestandardowy serwer FastMCP udostępniający narzędzia add i subtract, a następnie wdrożysz go w Cloud Run bezpośrednio z kodu źródłowego. Podczas wdrażania źródła (--source) Cloud Build spakuje obraz kontenera za pomocą dołączonych plików Dockerfile i uv (które instalują zależności zdefiniowane w pyproject.toml i uruchamiają server.py).

Po wdrożeniu usługi Cloud Run zarejestruj serwer MCP w Agent Registry wraz ze specyfikacją narzędzia (toolspec.json), aby Gemini Enterprise mogła wykrywać i wywoływać jego narzędzia.

Tworzenie aplikacji serwera MCP

Utwórz math-wizard katalog projektu dla kodu aplikacji:

# create directory for code
mkdir -p math-wizard

Napisz plik manifestu projektu w Pythonie:

# 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

Kod zawiera dodatkowe funkcje instrumentacji, które rejestrują przychodzące nagłówki HTTP (mcp-session-id, x-forwarded-for, user-agent i x-cloud-trace-context) na potrzeby weryfikacji Cloud Logging i Cloud Trace.

Utwórz plik kodu aplikacji:

# 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

Napisz plik Dockerfile, aby zdefiniować instrukcje kompilacji obrazu kontenera i polecenia uruchamiania:

# 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

Wdrażanie usługi w Cloud Run

Wdróż serwer MCP ze źródła za pomocą Cloud Build (która używa domyślnego konta usługi Compute w projekcie ${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

Sprawdzanie wdrożenia Cloud Run

Sprawdź szczegóły usługi Cloud Run, aby zweryfikować jej aktywną konfigurację:

# show cloud run service details
gcloud run services describe ${MCP_NAME} --region=${REGION}

Oczekiwane dane wyjściowe:

<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>

Rejestrowanie serwera MCP w Agent Registry

Aby Gemini Enterprise mogło wykryć dokładne narzędzia dostępne na serwerze MCP, podczas rejestracji w Agent Registry należy podać plik specyfikacji narzędzi (toolspec.json).

Tworzenie specyfikacji narzędzia 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

Rejestrowanie serwera MCP w 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}"

Weryfikowanie serwera MCP w rejestrze agentów

Sprawdź, czy wdrożona usługa Cloud Run jest wymieniona jako zarejestrowany serwer MCP w regionie wraz z adresem URL punktu końcowego i dostępnymi narzędziami:

# 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
  )"

Oczekiwane dane wyjściowe:

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

Wyświetl specyfikację konfiguracji usługi, aby sprawdzić, czy rejestruje ona dokładne definicje narzędzi, schematy wejściowe i adnotacje dotyczące działania każdego narzędzia:

# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
  --location=${REGION} \
  --project=${PROJ_ID} \
  --format="yaml(mcpServerSpec.content.tools)"

To wszystko, jeśli chodzi o serwer MCP. Przejdźmy teraz do sekcji Gemini Enterprise.

7. Gemini Enterprise

W tej sekcji utworzysz i skonfigurujesz aplikację Gemini Enterprise oraz połączony z nią zasób niestandardowego magazynu danych serwera MCP.

Model zasobów Discovery Engine

Aplikacja Gemini Enterprise (reprezentowana jako zasób Engine w interfejsie Discovery Engine API) to centralna warstwa orkiestracji i interfejs konwersacyjny dla użytkowników. Zarządza sesjami czatu użytkowników, opiera modele generatywne na danych przedsiębiorstwa i koordynuje dynamiczne wykonywanie narzędzi.

Aplikacje Gemini Enterprise wchodzą w interakcje z danymi i systemami za pomocą magazynów danych:

  • Magazyny danych wiedzy: pozyskiwanie i indeksowanie treści statycznych (np. Cloud Storage, Dysk Google, BigQuery) na potrzeby generowania wspomaganego wyszukiwaniem (RAG).
  • Łączniki danych (dostawcy działań): łączą się z dynamicznymi interfejsami API innych firm lub interfejsami niestandardowymi. Niestandardowy magazyn danych serwera MCP udostępnia narzędzia zdefiniowane przez protokół Model Context Protocol (MCP), co umożliwia modelowi dynamiczne wywoływanie funkcji zewnętrznych podczas rozmowy.

Routing ruchu wychodzącego przez bramę agenta

Domyślnie Gemini Enterprise kieruje ruch związany z wykonywaniem łączników i narzędzi przez sieci publiczne. W przypadku prywatnych zadań VPC i zarządzania opartego na zasadzie zerowego zaufania silnik można skonfigurować tak, aby kierował ruch wychodzący przez bramę agenta:

  • Podczas tworzenia niestandardowego magazynu danych serwera MCP w dalszej części tego laboratorium włączysz w ustawieniach magazynu danych opcję Kieruj ruch wychodzący przez bramę agenta.
  • Powoduje to powiązanie wychodzących wywołań narzędzi silnika z regionalną bramą agenta, dzięki czemu wszystkie żądania MCP zawierają Agent Identity aplikacji, podlegają autoryzacji w czasie działania przy użyciu ujednoliconych zasad dostępu IAP i IAM oraz przechodzą przez przyłącze sieci PSC do Twojego prywatnego środowiska VPC.

Tworzenie aplikacji Gemini Enterprise

Poniższa metoda korzysta z interfejsu discoveryengine.googleapis.com API do tworzenia zasobów i konfiguracji aplikacji Gemini Enterprise. Instrukcje dotyczące konfiguracji za pomocą interfejsu konsoli Google Cloud znajdziesz w sekcji Tworzenie aplikacji.

# 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

Weryfikowanie utworzenia aplikacji

# 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}"

Wyświetl szczegóły silnika, aby zobaczyć utworzoną konfigurację:

# 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}"

Zwróć uwagę na te właściwości w odpowiedzi JSON, które są wypełniane przez serwer:

  • name: kanoniczna ścieżka zasobu (projects/${PROJ_NO}/locations/global/collections/default_collection/engines/${GE_APP_ID}).
  • sessionConfig.sessionManagementPolicy: domyślnie "VERTEX_AI_MANAGED", co powoduje, że stan czatu wieloetapowego i wywołań narzędzi jest zachowywany na Agent Platform (wcześniej znanej jako Vertex AI).
  • observabilityConfig.observabilityEnabled: domyślnie true w przypadku danych podstawowych (szczegółowe rejestrowanie promptów i ładunków narzędzi zostanie włączone w późniejszym kroku).

Włączanie dostawcy tożsamości

Włącz Google Identity jako dostawcę tożsamości do uwierzytelniania użytkowników w aplikacji Gemini Enterprise.

Poniższa metoda korzysta z interfejsu discoveryengine.googleapis.com API do konfigurowania dostawcy tożsamości aplikacji Gemini Enterprise. Instrukcje dotyczące konfiguracji za pomocą interfejsu konsoli Google Cloud znajdziesz w sekcji Konfigurowanie dostawcy tożsamości.

# 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

Weryfikowanie dostawcy tożsamości

# 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}"

Dane wyjściowe "idpType": "GSUITE" odpowiadają dostawcy tożsamości Google.

Włączanie licencji próbnej Gemini Enterprise (opcjonalnie)

Jeśli używasz projektu, do którego przypisane są licencje Gemini Enterprise, możesz pominąć ten krok. Jeśli używasz nowego projektu bez licencji, przejdź dalej i wykonaj te czynności.

Utwórz zasób konfiguracji licencji, aby przyznać użytkownikom Gemini Enterprise licencje na 30 dni. Spowoduje to ustawienie nowej wersji próbnej jako domyślnej licencji, dzięki czemu każdy użytkownik logujący się na konto automatycznie otrzyma miejsce:

# 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

Sprawdzanie, czy licencja została zastosowana

# 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}"

Sprawdź "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" i "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}"

Sprawdź ../free_trial_gemini" i "enableLicenseAutoRegister": true.

Włączanie ustawień dostrzegalności

Włączenie obserwacji na poziomie aplikacji (silnika) Gemini Enterprise umożliwia wyświetlanie interakcji podstawowego asystenta z danymi o wartościach w Eksploratorze wartości oraz korelowanie kompleksowych śladów w 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

Sprawdzanie ustawień dostrzegalności

# 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}'

Sprawdź, czy jest "sensitiveLoggingEnabled": true.

Wiązanie z bramą agenta

Kierowanie ruchu wychodzącego z Gemini Enterprise przez Bramę agentów tworzy scentralizowaną granicę zarządzania i zabezpieczeń opartą na zasadzie zerowego zaufania dla wszystkich wywołań narzędzi agentów AI:

  • Centralne egzekwowanie zasad: brama agentów działa jako wbudowany serwer proxy, który ocenia wychodzące żądania narzędzi pod kątem zasad autoryzacji i kontroli zarządzania, zanim ruch opuści środowisko agenta.
  • Ruch wychodzący z sieci prywatnej: powiązanie Gemini Enterprise z Bramą agentów zapewnia, że wywołania narzędzi kierowane do prywatnych serwerów MCP w Cloud Run są bezpiecznie kierowane przez Private Service Connect (PSC), z pominięciem internetu publicznego.
  • Ujednolicona możliwość kontroli: zapewnia scentralizowane rejestrowanie żądań, telemetrię i ścieżki audytu na wszystkich połączonych serwerach MCP i narzędziach zewnętrznych.

Konfigurując agentGatewaySetting w aplikacji Gemini Enterprise, możesz automatycznie kierować wychodzące wywołania narzędzi i agentów inicjowane przez zapytania użytkowników (np. wywołania niestandardowych serwerów MCP importowanych z Agent Registry i agentów A2A) przez bramę agentów.

Zastosuj poprawkę do silnika agentGatewaySetting, aby włączyć:

# 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

Sprawdzanie powiązania bramy agenta

Pobierz konfigurację aplikacji, aby potwierdzić powiązanie 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}'

Oczekiwane dane wyjściowe:

{
  "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}"
    }
  }
}

Tworzenie magazynu danych niestandardowego serwera MCP

W tej sekcji połączysz serwer MCP z Gemini Enterprise, tworząc niestandardowy magazyn danych MCP.

W przypadku interfejsu Discovery Engine API jest to proces dwuetapowy:

  1. Utwórz (:setUpDataConnector): tworzy dedykowany zasób Collection (${MCP_NAME}-%timestamp-collection), dołącza DataConnector (custom_mcp) i udostępnia jego zasób DataStore (..._mcp_data).
  2. AktywujPATCH .../dataConnector?updateMask=actionConfig: aktywuje środowisko wykonawcze działania konektora (actionState: "ACTIVE") przy użyciu specyfikacji narzędzia Agent Registry i wiąże DataStore (dataStoreIds) z Twoją usługą Gemini Enterprise Engine.
# 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}"

Tworzenie łącznika danych

# 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

Weryfikowanie utworzenia łącznika danych

# 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}"

Sprawdź, czy pole "registry_mcp_server_name" jest wypełnione identyfikatorem UUID Agent Registry dla serwera 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}'

Wyświetl wpis rejestru serwera MCP w interfejsie konsoli 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}"

Aktywowanie łącznika danych

# 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

Weryfikowanie połączeń z niestandardowym serwerem MCP

# 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}'

Sprawdź, czy połączony magazyn danych "dataStoreIds": "collection-math-wizard-_mcp_data" jest widoczny.

# 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}'

Sprawdź, czy w przypadku parametru "state": "ACTIVE" wszystkie pola są wypełnione.

Operacje na narzędziu

Gdy sprawdzisz magazyn danych math-wizard-collection na panelu Gemini Enterprise, zauważysz, że karta Działania nie jest używana, a przycisk ↻ Ponownie załaduj działania niestandardowe jest wyłączony. Jest to prawidłowy proces.

Wyświetl stronę szczegółów magazynu danych w interfejsie konsoli 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}"

W zależności od tego, jak połączysz niestandardowy serwer MCP z Gemini Enterprise, wykrywanie narzędzi i zarządzanie nimi odbywa się na jeden z tych 2 sposobów:

  • Bezpośredni niestandardowy MCP (BYO_MCP przepływ pracy): gdy skonfigurujesz niestandardowy serwer MCP bezpośrednio w Gemini Enterprise bez Agent Registry, katalog narzędzi (connectorModes: ["FEDERATED", "ACTIONS"]) będzie zarządzany przez sam magazyn danych. Musisz otworzyć kartę Działania i kliknąć ↻ Ponownie załaduj działania niestandardowe, aby pobrać schemat tools/list, a następnie ręcznie włączyć lub wyłączyć poszczególne narzędzia (add i subtract) w interfejsie.
  • Import z Agent Registry (REGISTRY_MCP przepływ pracy używany w tym ćwiczeniu): gdy importujesz serwer MCP z Agent Registry, Agent Registry służy jako autorytatywne źródło informacji o punkcie końcowym MCP, metadanych interfejsu i katalogu narzędzi (connectorModes: ["FEDERATED"]). Gemini Enterprise automatycznie włącza zarejestrowane narzędzia MCP w czasie działania za pomocą Bramy agentów bez konieczności ręcznego ponownego wczytywania lub przełączania działań w interfejsie magazynu danych.

To kończy część dotyczącą aplikacji Gemini Enterprise. Przejdź do sekcji Sprawdzanie poprawności.

8. Weryfikuj

W tej sekcji wywołasz na żywo wywołania narzędzi MCP z aplikacji internetowej Gemini Enterprise i prześledzisz przepływ żądań w logach Agent Gateway, Cloud DNS, zapory sieci VPC i Cloud Run. Następnie zaostrzysz zasady dostępu ujednoliconego IAM, aby zezwalać na subtract i blokować add, weryfikując egzekwowanie zasady zerowego zaufania w bramie.

Dostęp użytkownika

Skonstruuj adres URL aplikacji internetowej 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}"

Kliknij link, aby otworzyć interfejs czatu aplikacji internetowej Gemini Enterprise w przeglądarce, a następnie kliknij Rozpocznij.

Testowanie zapytań do agenta na czacie

W interfejsie czatu potwierdź, że math-wizard-collection łącznik danych jest włączony. W tym celu kliknij ikonę puzzli Oprogramowanie sprzęgające u dołu okna czatu. Powinien pojawić się przycisk przełączania, który jest włączony (pokolorowany).

Wypróbuj te zapytania testowe:

what is 2342345 - 98234798324?
what is 72347234 + 234234?

Sprawdź, czy asystent zwraca prawidłowe odpowiedzi i wyświetla interaktywną odznakę cytowania działania (np. Math Calculation (8s) 🤖 Agentgateway Agent) pod każdą odpowiedzią, potwierdzając wykonanie narzędzia.

Sprawdzanie logów w Cloud Logging

Sprawdź, czy Gemini Enterprise przekierował wywołania narzędzi przez Bramę agentów i prywatną sieć VPC, przeglądając logi w Cloud Logging.

1. Weryfikowanie autoryzacji Bramy agentów i IAP

Sprawdź, czy Brama agentów przechwyciła żądanie, rozpoznała miejsce docelowe w Agent Registry, przekazała autoryzację do IAP i zezwoliła na wywołanie narzędzia:

# 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
  )"

Sprawdź, czy dane wyjściowe zawierają:

  • STATUS: 200 (udane wykonanie) i 202 (notifications/initialized handshake).
  • SERVER_IP: adres IP punktu końcowego PSC interfejsów API Google (172.16.20.20:443).
  • MCP_METHOD i TOOL: sekwencja protokołu MCP (notifications/initialized, tools/list i tools/call z add lub subtract).
  • AUTHZ: ALLOWED (autoryzacja zakupów w aplikacji zezwala na ruch wychodzący).
  • REGISTRY_MCP: identyfikator zasobu Agent Registry (agentregistry-...).

2. Sprawdzanie tranzytu DNS i zapory sieciowej

Sprawdź, czy Cloud DNS rozpoznał nazwę hosta jako punkt końcowy PSC i czy zapora sieciowa zezwoliła na ruch z interfejsu bramy agenta:

# 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
  )"

Sprawdź te wartości:

  • DNSQUERY_NAME i RDATA: rozwiązuje math-wizard-...run.app. (rekord A, NOERROR) na 172.16.20.20.
  • Zapora sieciowaSRC_IP i DEST_IP: 192.168.10.2 (adres IP interfejsu PSC bramy agenta) do 172.16.20.20:443.
  • Zapora sieciowaRULE i DISPOSITION: dopasowano firewallPolicy:fw-policy-... do ALLOWED.

3. Sprawdzanie wykonania narzędzia Cloud Run

Sprawdź, czy kontener Cloud Run otrzymał i przetworzył wywołanie narzędzia:

# 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)"

Sprawdź, czy textPayload wyświetla wpisy dotyczące wykonania narzędzia (np. >>> 🛠️ Tool: 'subtract' called with numbers '[x]' and '[y]').

Testowanie egzekwowania zasad jak najmniejszych uprawnień

W początkowej zasadzie dostępu do IAM dozwolona była dowolna metoda lub narzędzie, o ile miejsce docelowe było zarejestrowane (destination.is_registered == true). W tym kroku zaktualizuj zasadę, aby wymusić zasadę najmniejszych uprawnień, zezwalając tylko na narzędzie subtract i blokując add.

Aktualizowanie zasady dostępu uprawnień

Podczas ograniczania wykonywania narzędzia MCP używaj wzoru z 2 regułami:

  1. Reguła 1 (wykrywanie i uzgadnianie MCP): zezwala na metody cyklu życia MCP inne niż wywołania narzędzi (destination.is_registered == true i destination.agent_registry.mcp_server.method != 'tools/call'). Ponieważ Gemini Enterprise negocjuje konfigurację strumienia i wykrywanie (initialize, notifications/initialized, tools/list) przed wywołaniem narzędzia, a destination.agent_registry.mcp_server.tool.name jest wypełniane tylko podczas tools/call, reguła 1 jest niezbędna do prawidłowego działania inicjowania sesji i wykrywania katalogu.
  2. Reguła 2 (ograniczenie na poziomie narzędzia): ogranicza wykonywanie funkcji tools/call, tak aby dozwolone było tylko narzędzie subtract (destination.is_registered == true, destination.agent_registry.mcp_server.method == 'tools/call' i destination.agent_registry.mcp_server.tool.name == 'subtract').

Zaktualizuj plik manifestu reguły zasad dostępu o obie reguły:

# 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

Zastosuj zaktualizowane reguły w zasadach dostępu uprawnień:

# 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

Sprawdzanie zasady dostępu uprawnień

Sprawdź, czy nowa zasada dostępu IAM została zastosowana i czy tylko narzędzie do odejmowania jest dozwolone:

# 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
  )"

Testowanie zabronionego wywołania narzędzia

Wróć do interfejsu czatu aplikacji internetowej Gemini Enterprise i wypróbuj inne zapytanie testowe:

what is 100 plus 20?

Asystent próbuje wywołać add, ale Brama agentów i IAP oceniają warunek zasady Uprawnień jako false i odrzucają żądanie ruchu wychodzącego z HTTP 403 Forbidden. W interfejsie czatu zobaczysz, że asystent wyświetla Calculate Sum i obraca się 🤖 Agentgateway Agent ... Working on it., gdy ponawia zablokowane wywołanie narzędzia. Jest to prawidłowy proces. Potwierdza, że bramy agentów i IAP aktywnie przechwytują i odrzucają niedozwolone wykonanie narzędzi na poziomie sieci.

Ponowne sprawdzanie logów w Cloud Logging

Wyświetl wpisy logu bramy agenta i zwróć uwagę na nowe wpisy 403 odpowiadające niedozwolonemu wywołaniu narzędzia add:

# 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
  )"

Oczekiwane dane wyjściowe:

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

Sprawdź, czy dodatkowe żądanie nigdy nie dotarło do backendu 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)"

Polecenie nie zwraca żadnych nowych wpisów, co potwierdza, że Brama agentów skutecznie zastosowała zasadę dostępu IAM.

To wszystko, jeśli chodzi o weryfikację. Przejdźmy teraz do sekcji Czyszczenie.

9. Czyszczenie

Aby usunąć zasoby i konfiguracje utworzone w tym laboratorium, wykonaj te czynności.

Usuwanie komponentów 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"}}'

Usuwanie komponentów serwera 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}

Usuwanie bramy agenta i zasad dostępu IAM

# 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}

Usuwanie komponentów DNS i zapory sieciowej

# 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}

Usuwanie komponentów usługi PSC i sieci VPC

# 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}

Usuwanie zastąpień zasad organizacji i plików lokalnych

# 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

To koniec porządkowania. Przejdźmy teraz do podsumowania.

10. Podsumowanie

Gratulacje! Masz gotową architekturę kompleksową, która umożliwia aplikacji Gemini Enterprise bezpieczne wykrywanie i wywoływanie narzędzi na prywatnym niestandardowym serwerze MCP:

  • Niestandardowy serwer MCP i Agent Registry: wdrożono prywatną usługę FastMCP w Cloud Run (--ingress=internal) i zarejestrowano jej punkt końcowy oraz schemat narzędzia (add i subtract) w Agent Registry.
  • Integracja z Gemini Enterprise: udostępniono aplikację Gemini Enterprise, powiązano ruch wychodzący narzędzia z bramą agentów i dołączono zarejestrowany serwer MCP jako REGISTRY_MCP łącznik danych.
  • Prywatny ruch wychodzący z sieci VPC i zarządzanie oparte na zasadzie zerowego zaufania: prywatne wykonywanie narzędzi za pomocą PSC (172.16.20.20) i egzekwowanie zasady najmniejszych uprawnień na poziomie narzędzia za pomocą IAP i ujednoliconych zasad dostępu IAM (destination.agent_registry.*).

cosmopup

Cosmpup uważa, że Codelabs są świetne!

Co dalej?

Jeśli masz uwagi, pytania lub poprawki, możesz je przesłać za pomocą tego formularza opinii.

Dziękujemy!