‫Gemini Enterprise با «درگاه عامل» خروجی VPC با ترافیک کامل و نشانی IP ایستا Cloud NAT به سرور MCP خارجی

۱. مقدمه

این Codelab اتصال‌پذیری خروجی IP ایستا را برای Gemini Enterprise بااستفاده از دروازه عامل در حالت عامل به هرجا (خروجی) بررسی می‌کند. بااستفاده از پیکربندی الگوی اتصال، برنامه Gemini Enterprise را پیکربندی می‌کنید تا با مسیریابی همه ترافیک خروجی ازطریق «دروازه عامل»، سرور سفارشی پروتکل بافتار مدل (MCP) را که با فهرست مجاز IP منبع دقیق و اصالت‌سنجی OAuth 2.0 محافظت می‌شود فراخوانی کند. پیوست شبکه Private Service Connect (PSC) «دروازه عامل» را به شبکه VPC متصل می‌کند و Cloud NAT نشانی IP خارجی پایداری را برای ترافیک خروجی اینترنت فراهم می‌کند.

به‌طور پیش‌فرض، اتصالات خروجی از Gemini Enterprise به نقاط پایانی اینترنت عمومی از استخرهای نشانی IP مشترک و پویای Google منشأ می‌گیرد که نمی‌تواند به یک قانون فهرست مجاز IP متعلق به مشتری واحد سنجاق شود. جفت کردن «درگاه عامل» با AgentConnectivityTemplate در حالت ALL_TRAFFIC همه ترافیک خروجی عامل را به شبکه VPC مسیریابی می‌کند، جایی که Cloud NAT اتصالات اینترنتی را به نشانی IPv4 خارجی ایستا و رزروشده‌ای که تحت کنترل شما است ترجمه می‌کند و درعین‌حال حاکمیت ابزار متمرکز MCP را ازطریق ثبت عامل و پراکسی آگاه از هویت (IAP) حفظ می‌کند.

آنچه می‌سازید

  • «الگوی اتصال عامل» (vpcEgress: ALL_TRAFFIC) و «دروازه عامل» که در حالت خروجی (عامل به هرجا) با درستی‌سنجی نقطه پایانی «ثبت عامل» کار می‌کند
  • شبکه VPC، پیوست شبکه PSC،‏ Cloud Router، و درگاه Cloud NAT که به نشانی IPv4 خارجی ثابت رزروشده‌ای مقید است
  • سرور منبع MCP HTTP جاری‌شدنی خارجی (mcp-sprockets) که با Caddy TLS پیش‌کار شده است، با قوانین دیوار آتش به‌شدت به IP استاتیک Cloud NAT محدود شده است، و کدهای حامل Google OAuth 2.0 واگذارشده توسط کاربر را دربرابر https://oauth2.googleapis.com/tokeninfo درستی‌سنجی می‌کند
  • صفحه کسب رضایت Google Auth Platform OAuth 2.0 و اعتبارنامه‌های کارخواه Web application OAuth 2.0 (accounts.google.com و oauth2.googleapis.com/token)
  • ورودی کاتالوگ سرور MCP «ثبت‌کننده کارگزار» و مشخصات ابزار (toolspec.json)
  • افزونه مجوز Identity-Aware Proxy (IAP) و خط‌مشی مجوز «دروازه» برای «دروازه عامل»
  • برنامه Gemini Enterprise به «درگاه عامل» متصل است و به مخزن داده سرور MCP سفارشی OAuth 2.0 متصل است که از «ثبت عامل» وارد شده است

figure1

شکل ۱. معماری Codelab

آنچه یاد می‌گیرید

  • نحوه پیکربندی AgentConnectivityTemplate با vpcEgress: ALL_TRAFFIC برای هدایت همه ترافیک خروجی «درگاه عامل» به شبکه VPC
  • نحوه رزرو کردن نشانی IPv4 خارجی ثابت و ملزم کردن آن به Cloud NAT در زیرشبکه پیوست شبکه PSC
  • نحوه استقرار سرور منبع MCP HTTP جاری‌شدنی خارجی که نشان‌های حامل Google OAuth 2.0 را تأیید می‌کند (oauth2.googleapis.com/tokeninfo) و فایروال ورودی آن را به‌طور دقیق به IP استاتیک Cloud NAT محدود می‌کند (${NAT_EXT_IP}/32)
  • نحوه پیکربندی کردن اعتبارنامه‌های کارخواه Google Identity OAuth 2.0 و ثبت سرور MCP و طرحواره ابزار آن در «ثبت عامل»
  • نحوه متصل کردن سرور MCP ثبت‌شده OAuth 2.0 به Gemini Enterprise و مسیریابی تماس‌های ابزار واگذارشده کاربر ازطریق «دروازه نماینده»
  • نحوه اعتبارسنجی ترجمه IP ایستا، درستی‌سنجی هویت کاربر نهایی OAuth 2.0 (authenticated_user)، و اجرای خط‌مشی دروازه بااستفاده از دستورات CLI و Cloud Logging

آنچه نیاز دارید

  • پروژه Google Cloud با صورت‌حساب فعال
  • پروانه Gemini Enterprise فعال یا دوره آزمایشی ۳۰ روزه
  • اجازه‌های IAM برای آماده‌سازی منابع سرویس‌های شبکه، «خط‌مشی‌های سازمان»، «Gemini Enterprise»، و «پلاتفرم عامل»
  • پوسته سازگار با POSIX (bash یا zsh) با Google Cloud CLI (gcloud)، curl، و jq نصب‌شده

این بخش معرفی را به پایان می‌رساند… در ادامه به بخش مفاهیم می‌پردازیم.

۲. مفاهیم

توالی استقرار

این Codelab ابتدا زیرساخت شبکه و حکمرانی را مستقر می‌کند تا مسیرهای خروجی IP ایستا و کنترل‌های دروازه قبل‌از ثبت و اتصال ابزارهای MCP با Gemini Enterprise عملیاتی شوند:

  1. زیرساخت شبکه: نشانی‌های IPv4 خارجی ایستا را رزرو کنید و زیرشبکه پیوست PSC، پیوست شبکه PSC،‏ Cloud Router، دروازه Cloud NAT، و قوانین فایروال شبکه MCP خارجی را آماده کنید.
  2. الگوی اتصال عامل و درگاه عامل: AgentConnectivityTemplate (vpcEgress: ALL_TRAFFIC) و AgentGateway منطقه‌ای را در حالت خروجی (AGENT_TO_ANYWHERE) با یکپارچه‌سازی «ثبت عامل» (registries) مستقر کنید.
  3. خط‌مشی‌های مجوز: افزونه مجوز IAP (AuthzExtension)، خط‌مشی مجوز «دروازه» (AuthzPolicy)، و «خط‌مشی دسترسی یکپارچه IAM v3» (AccessPolicy و PolicyBinding) را پیکربندی کنید.
  4. استقرار و ثبت سرور MCP: سرور منبع mcp-sprockets OAuth 2.0 خارجی را در پشت Caddy TLS مستقر کنید، اجرای tokeninfo Google OAuth 2.0 آن را تأیید کنید، دیوار آتش ورودی آن را به‌طور دقیق به IP استاتیک Cloud NAT (${NAT_EXT_IP}/32) محدود کنید، و مشخصات سرویس و ابزار (get_sprockets و get_sprocket_by_id) را در «ثبت عامل» ثبت کنید.
  5. برنامه Gemini Enterprise و کارخواه OAuth 2.0: ارائه‌دهنده هویت Google، پروانه آزمایشی، و صفحه موافقت OAuth 2.0 و اطلاعات اعتباری کارخواه «برنامه وب» (OAUTH_CLIENT_ID و OAUTH_CLIENT_SECRET) را پیکربندی کنید، برنامه Gemini Enterprise را ایجاد کنید (Engine)، و خروجی برون‌سپاری را به «دروازه نماینده» (agentGatewaySetting) ملزم کنید.
  6. وارد کردن اتصال‌دهنده داده MCP سفارشی: اتصال‌دهنده داده REGISTRY_MCP (:setUpDataConnector) را که با auth_type: "OAUTH" پیکربندی شده است ایجاد و فعال کنید تا سرور MCP ثبت‌شده که از فروشگاه داده پشتیبانی می‌کند به برنامه Gemini Enterprise پیوند داده شود.
  7. اعتبارسنجی: جریان موافقت یک‌باره کاربر با OAuth 2.0 را تکمیل کنید، ابزارهای MCP را ازطریق دستیار Gemini Enterprise فراخوانی کنید (egress_source_ip و authenticated_user را تأیید کنید)، و اجرای خط‌مشی و ترجمه NAT پروتکل اینترنتی ایستا را در Cloud Logging درستی‌سنجی کنید.

معماری سرور منبع MCP محافظت‌شده با OAuth + IdP مرکزی

در استقرار سازمانی، مدیریت هویت و اجرای ابزار از جداسازی استاندارد نقش‌ها در OAuth 2.0 بین ارائه‌دهنده هویت متمرکز (سرور مجوز) و سرور منبع MCP محافظت‌شده پیروی می‌کند:

نقش OAuth 2.0

عنصر در این Codelab

مسئولیت

مالک منبع

کاربر نهایی (${USER_IDENTITY})

به سیستم برنامه تحت وب Gemini Enterprise وارد می‌شود و درطول جریان مجوز OAuth 2.0 سه‌طرفه یک‌باره موافقت خود را اعلام می‌کند.

کارخواه OAuth 2.0

Gemini Enterprise custom_mcp Data Connector

OAUTH_CLIENT_ID و OAUTH_CLIENT_SECRET را نگه می‌دارد، کد مجوز را در oauth2.googleapis.com/token مبادله می‌کند، نشان‌های OAuth 2.0 کاربر را در خزانه قرار می‌دهد، و Authorization: Bearer [access_token] را در هر تماس ابزار MCP خروجی ارائه می‌دهد.

سرور صدور مجوز

Google Identity OAuth 2.0 (accounts.google.com و oauth2.googleapis.com/token)

کاربر را درطول هدایت مجدد موافقت مرورگر اصالت‌سنجی می‌کند و ژتون‌های دسترسی و بازآوری OAuth 2.0 را برای Gemini Enterprise صادر می‌کند.

سرور منبع

برون‌سازمانی mcp-sprockets سرور (https://mcp.[MCP_EXT_IP].sslip.io/mcp)

بااستفاده از دیوار آتش VPC خود (${NAT_EXT_IP}/32) هویت شبکه لایه ۳ و با درستی‌سنجی سرایند Authorization: Bearer [access_token] دربرابر https://oauth2.googleapis.com/tokeninfo هویت کاربر لایه ۷ را اعمال می‌کند.

ازآنجایی‌که بازارسال موافقت مرورگر (accounts.google.com) و تبادل کد کانال پشتی (oauth2.googleapis.com/token) دربرابر نقاط پایانی OAuth 2.0 مدیریت‌شده توسط Google انجام می‌شود، دیوار آتش سرور MCP خارجی فقط درخواست‌های زمان اجرای MCP JSON-RPC (POST /mcp) را ازطریق Cloud NAT از «دروازه عامل» دریافت می‌کند، و به دیوار آتش ورودی آن اجازه می‌دهد به‌طور دقیق به ${NAT_EXT_IP}/32 محدود شود.

مدل منبع «موتور اکتشاف»

برنامه Gemini Enterprise (که به‌عنوان منبع Engine در Discovery Engine API نشان داده می‌شود) لایه هماهنگی مرکزی و میانای مکالمه‌ای برای کاربران نهایی است. این عامل جلسه‌های گپ کاربر را مدیریت می‌کند، مدل‌های زایا را براساس داده‌های سازمانی زمینه‌سازی می‌کند، و اجرای ابزارهای پویا را هماهنگ می‌کند.

برنامه‌های «سازمانی Gemini» ازطریق مخازن داده با داده‌ها و سیستم‌ها تعامل می‌کنند:

  • فروشگاه‌های داده دانش: محتوای ایستا (برای نمونه، Cloud Storage،‏ Google Drive،‏ BigQuery) را برای تولید با کمک بازیابی (RAG) جذب و نمایه‌گذاری کنید.
  • اتصال‌دهنده‌های داده (ارائه‌دهندگان کنش): به میاناهای برنامه‌سازی کاربردی طرف سوم یا سفارشی پویا متصل شوید. انبار داده سرور MCP سفارشی ابزارهای تعریف‌شده توسط «پروتکل بافتار مدل» (MCP) را آشکار می‌کند و به مدل امکان می‌دهد تا به‌صورت پویا توابع خارجی را درطول مکالمه فراخوانی کند.

برون‌برد Gemini Enterprise

وقتی هم agentGatewaySetting در Engine و هم use_agent_gateway_egress: true در DataConnector پیکربندی شده باشند، Gemini Enterprise درخواست‌های ابزار سرور MCP سفارشی را به «درگاه نماینده» هدایت می‌کند.

figure2

شکل ۲. معماری خروجی Gemini Enterprise

برنامه Gemini Enterprise مسیریابی ابزار را در چهار حوزه کلیدی سازمان‌دهی می‌کند:

  1. ابزاره (default_search_widget_config):
    • میانای کارخواه وب را ارائه می‌کند. ابزاره پیام‌واره‌هایی از کاربر دریافت می‌کند، وقتی ابزاری به مجوز نیاز دارد، هدایت رضایت کاربر OAuth 2.0 یک‌باره را راه‌اندازی می‌کند، و جلسه‌های گپ را با موتور زیربنایی آغاز می‌کند.
  2. دستیار اصلی (assistants/default_assistant/agents/default/core_assistant):
    • عامل استدلال مکالمه‌ای ریشه در موتور. وقتی «دستیار اصلی» پُرسمان کاربر را ارزیابی می‌کند، ابزارهای دردسترس را بازرسی می‌کند و اجرای آن را به عامل فرعی «درگاه عامل» ترکیبی واگذار می‌کند.
  3. «انبار داده» و «اتصال‌دهنده داده»:
    • DataStore: وقتی :setUpDataConnector اجرا می‌شود، در Collection اختصاصی آماده می‌شود و طرحواره‌های ابزار «ثبت عامل» واردشده (get_sprockets،‏ get_sprocket_by_id)، انواع آرگومان، و دستورالعمل‌های عامل را به Gemini Enterprise Engine پیوند می‌دهد (dataStoreIds).
    • DataConnector: اتصال کنش REGISTRY_MCP (createBapConnection: true) به سرور MCP از دور (instance_uri) را مدیریت می‌کند، منبع سرور MCP «ثبت‌کننده عامل» (registry_mcp_server_name) را حل‌وفصل می‌کند، نشانه OAuth 2.0 Bearer ذخیره‌شده کاربر (Authorization: Bearer [access_token]) را پیوست می‌کند، و خروجی «درگاه عامل» (use_agent_gateway_egress: true) را فعال می‌کند.
  4. هویت نماینده، ثبت نماینده، و درگاه نماینده:
    • وقتی «اتصال‌دهنده داده» تماس ابزار خروجی را ارسال می‌کند، ترافیک را به دروازه مشخص‌شده در agentGatewaySetting هدایت می‌کند. «دستیار اصلی» یک SPIFFE نشان هویت ضرب می‌کند که هویت بار کاری آن را تأیید می‌کند: principal://agents.global.org-.../agents/default/core_assistant.
    • «دروازه عامل» بااستفاده از فیلد registries با «ثبت عامل» ادغام می‌شود تا نقاط پایانی مقصد و طرحواره‌های ابزار ثبت‌شده را به‌صورت پویا حل کند، خط‌مشی‌های مجوز را بااستفاده از IAP ارزیابی می‌کند، و درخواست‌های مجاز را (با حفظ سرایند کاربر Authorization: Bearer) بااستفاده از AgentConnectivityTemplate به شبکه VPC بازارسال می‌کند.

اتصال‌پذیری VPC دروازه و NAT پروتکل اینترنتی ایستا

«درگاه عامل» از اتصال‌پذیری شبکه VPC بااستفاده از منبع AgentConnectivityTemplate که agentConnectivityTemplate در درگاه به آن ارجاع می‌دهد پشتیبانی می‌کند. الگوی egressNetworkConfig تعریف می‌کند که ترافیک چگونه ازطریق پیوست شبکه PSC وارد VPC شما می‌شود:

  • PRIVATE_RANGES_ONLY (پیش‌فرض): فقط محدوده‌های IP خصوصی RFC 1918،‏ RFC 6598، و کلاس E را ازطریق پیوست شبکه PSC مسیریابی می‌کند. ترافیک اینترنت از VPC شما عبور نمی‌کند و مستقیماً ازطریق خروجی اینترنت پیش‌فرض Google خارج می‌شود.
  • ALL_TRAFFIC (در این Codelab استفاده می‌شود): همه ترافیک خروجی از «دروازه عامل»—ازجمله اینترنت عمومی و نقاط پایانی MCP شریک خارجی—را ازطریق پیوست شبکه PSC (10.10.10.2) به زیرشبکه VPC شما هدایت می‌کند.

وقتی در حالت ALL_TRAFFIC کار می‌کنید، زیرشبکه پیوست PSC به دو پیکربندی نیاز دارد:

  • دسترسی خصوصی به Google (--enable-private-ip-google-access): تضمین می‌کند که تماس‌های داخلی با Google Cloud APIs (*.googleapis.com) همچنان به‌صورت خصوصی در شبکه Google مسیریابی شوند.
  • Cloud Router و Cloud NAT (MANUAL_ONLY): ترافیک اینترنتی ورودی به زیرشبکه پیوست PSC از مسیر پیش‌فرض (0.0.0.0/0) ازطریق Cloud NAT پیروی می‌کند، که «ترجمه نشانی شبکه مبدأ» (SNAT) را به نشانی IPv4 خارجی ایستا رزروشده شما (${NAT_EXT_IP}) انجام می‌دهد. بنابراین، دیوارهای آتش خارجی می‌توانند دسترسی ورودی را به‌طور دقیق به ${NAT_EXT_IP}/32 محدود کنند.

محدودیت‌ها و الزامات

مکان برنامه Gemini Enterprise

مکان «دروازه عامل» و «ترجمه نشانی شبکه»

مکان «ثبت‌کننده عامل»

global

us-central1

‫us-central1، us، یا global

us

us-central1

‫us-central1 یا us

eu

europe-west1

‫europe-west1 یا eu

بخش مفاهیم به پایان رسید… در ادامه به بخش راه‌اندازی می‌پردازیم.

۳. راه‌اندازی

نقش‌های IAM الزامی

برای تکمیل این Codelab، نقش‌های زیر الزامی است:

دامنه

نقش‌های IAM الزامی

پروژه و IAM

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

شبکه‌سازی و درگاه

roles/networkservices.admin
roles/networksecurity.admin
roles/serviceextensions.admin
roles/iap.admin
roles/compute.networkAdmin
roles/compute.securityAdmin

Gemini Enterprise و «ثبت»

roles/discoveryengine.admin
roles/agentregistry.admin

Workloads

roles/compute.instanceAdmin.v1 (یا roles/compute.admin)

قابلیت مشاهده

roles/logging.viewer

یا از نقش پایه گسترده‌ای مثل roles/owner همراه با roles/orgpolicy.policyAdmin استفاده کنید (چون roles/owner به‌تنهایی نمی‌تواند خط‌مشی‌های سازمان را تغییر دهد).

دسترسی به پروژه

این Codelab از یک پروژه Google Cloud استفاده می‌کند. مراحل پیکربندی از gcloud CLI و فرمان‌های پوسته Linux استفاده می‌کنند.

با دسترسی به خط فرمان پروژه Google Cloud شروع کنید:

تنظیم شناسه پروژه

# set target project id
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"
export ZONE="us-central1-a"

echo ${SLUG}
echo ${REGION}
echo ${ZONE}
# 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 MCP_NAME="mcp-sprockets"

echo ${AGW_NAME}
echo ${AGW_URI}
echo ${MCP_NAME}
# create resource vars for gemini enterprise (automatic)
export GE_LOCATION="global"
export GE_APP_ORG_NAME="${SLUG}, Inc."
export GE_APP_DISPLAY_NAME="${SLUG} ${GE_LOCATION} app"
export GE_APP_NAME="app-${SLUG}-${GE_LOCATION}"
export GE_APP_INIT="${GE_APP_NAME}_$(date +%s)"

echo ${GE_LOCATION}
echo ${GE_APP_ORG_NAME}
echo ${GE_APP_DISPLAY_NAME}
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

اگر نصب خودگردانی از Google Cloud SDK را اجرا می‌کنید (یعنی خارج از Cloud Shell)، مؤلفه‌ها را به جدیدترین نسخه به‌روز کنید.

# update gcloud cli
gcloud components update

فعال کردن خدمات میانای برنامه‌سازی کاربردی

# enable google cloud apis
gcloud services enable \
  agentregistry.googleapis.com \
  aiplatform.googleapis.com \
  cloudapiregistry.googleapis.com \
  cloudresourcemanager.googleapis.com \
  compute.googleapis.com \
  discoveryengine.googleapis.com \
  dns.googleapis.com \
  iam.googleapis.com \
  iap.googleapis.com \
  logging.googleapis.com \
  monitoring.googleapis.com \
  networkconnectivity.googleapis.com \
  networksecurity.googleapis.com \
  networkservices.googleapis.com \
  orgpolicy.googleapis.com \
  serviceextensions.googleapis.com \
  serviceusage.googleapis.com

خط‌مشی‌های سازمان

محدودیت‌های خط‌مشی سازمان مدیریت‌شده پیش‌فرض Google Cloud و خط‌مشی‌های جعبه ایمنی می‌توانند ویژگی‌های استفاده‌شده در این Codelab را محدود کنند:

  • compute.vmExternalIpAccess: نشانی‌های IPv4 خارجی را در ماشین‌های مجازی Compute Engine در سازمان‌های جعبه شنی قفل‌شده محدود می‌کند.
  • ‫discoveryengine.managed.disableCustomMcpServerConnector: ایجاد اتصالات داده‌ای را که از سرور MCP سفارشی (custom_mcp) به‌عنوان منبع داده استفاده می‌کنند محدود می‌کند (به‌طور پیش‌فرض اعمال می‌شود).
  • discoveryengine.managed.allowedEgressFqdns: وقتی «کنترل‌های سرویس‌های VPC» (VPC-SC) فعال است یا پروژه در enforcedProjects فهرست شده است، دامنه‌های خروجی برون‌سپاری (instance_uri نام کاملاً واجدشرایط) را برای اتصال‌دهنده‌های داده محدود می‌کند.
  • ‫discoveryengine.managed.allowedDataSources: وقتی VPC-SC فعال است یا پروژه در enforcedProjects فهرست شده است، انواع مجاز اتصال‌دهنده داده (dataSource) را محدود می‌کند.

محدودیت‌های خط‌مشی سازمان موروثی را در سطح پروژه ملغی کنید.

غیرفعال کردن محدودیت سفارشی MCP

# disable data connector constraint (allow custom mcp servers)
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/discoveryengine.managed.disableCustomMcpServerConnector
spec:
  rules:
  - enforce: false
EOF

غیرفعال کردن محدودیت‌های اتصال‌دهنده داده شرطی

# disable egress fqdn constraint on project
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/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_ID}/policies/discoveryengine.managed.allowedDataSources
spec:
  rules:
  - enforce: false
EOF

غیرفعال کردن محدودیت خط‌مشی دسترسی

# 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

اجازه دادن به نشانی‌های IP خارجی

# allow external ip address for vms on project
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/compute.vmExternalIpAccess
spec:
  rules:
  - allowAll: true
EOF

درستی‌سنجی خط‌مشی‌های سازمان

بررسی کنید که compute.vmExternalIpAccess روی allowAll: True تنظیم شده باشد و خط‌مشی‌های دیگر enforce: False باشند:

# verify effective org policy constraints on project
for policy in \
  discoveryengine.managed.disableCustomMcpServerConnector \
  discoveryengine.managed.allowedEgressFqdns \
  discoveryengine.managed.allowedDataSources \
  iam.managed.disableAccessPolicyBinding \
  compute.vmExternalIpAccess; do
  gcloud org-policies describe ${policy} \
    --project=${PROJ_ID} \
    --effective \
    --format="flattened[no-pad](name.basename(),spec.rules[0])"
done

درستی‌سنجی اتصال‌های عامل سرویس (اقدام احتیاطی)

در پروژه جدید، وقتی networkservices.googleapis.com برای اولین‌بار فعال می‌شود، Google Cloud به‌طور خودکار عامل سرویس «درگاه عامل» را آماده می‌کند و roles/agentgateway.serviceAgent را به آن اعطا می‌کند. اگر از پروژه موجودی استفاده مجدد می‌کنید که در آن پاک‌سازی قبلی ممکن است پیوندهای عامل خدمات پیش‌فرض را برداشته باشد، دستورات زیر را به‌عنوان یک اقدام احتیاطی اجرا کنید تا مطمئن شوید که هویت و پیوند نقش دست‌نخورده باقی می‌مانند:

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

بخش راه‌اندازی به پایان رسید… در ادامه به بخش شبکه می‌پردازیم.

۴. شبکه

در این بخش، نشانی‌های IPv4 خارجی ایستا را رزرو می‌کنید، شبکه VPC خروجی داخلی و شبکه VPC خارجی مجزا را ایجاد می‌کنید، پیوست شبکه PSC را آماده می‌کنید، Cloud NAT را پیکربندی می‌کنید، و قوانین دیوار آتش را ایجاد می‌کنید.

نشانی‌های پروتکل اینترنتی خارجی ایستا را رزرو کنید

دو نشانی «پروتکل اینترنتی نسخه ۴» خارجی ایستا منطقه‌ای برای Cloud NAT و ماشین مجازی سرور MCP خارجی رزرو کنید:

# reserve static external ipv4 address for cloud nat
gcloud compute addresses create ip-${SLUG}-nat \
  --region=${REGION}

# reserve static external ipv4 address for the mcp server
gcloud compute addresses create ip-${SLUG}-mcp \
  --region=${REGION}

درستی‌سنجی نشانی‌های IP خارجی ایستا

‫Gemini Enterprise لازم می‌داند که نقطه‌های پایانی MCP از دور از HTTPS با گواهینامه TLS مورداعتماد عمومی استفاده کنند. به‌جای ثبت دامنه سفارشی برای این آزمایشگاه، از sslip.io استفاده می‌کنید، سرویس ساناد رایگان کاراکتر عام که هر نام میزبانی را که حاوی نشانی IP باشد (مثل mcp.[IP].sslip.io) مستقیماً به آن IP برمی‌گرداند. ازآنجایی‌که «مراجع صدور گواهینامه» مثل Let's Encrypt برای نشانی‌های IP بدون واسطه گواهینامه صادر نمی‌کنند، این نام میزبان sslip.io به پراکسی معکوس Caddy نام دامنه معتبری می‌دهد تا گواهینامه «امنیت لایه انتقال» مطمئنی را به‌طور خودکار برای سرور MCP تدارک دهد.

هر دو نشانی IPv4 را صادر کنید و نام دامنه و نشانی وب sslip.io را برای سرور MCP خارجی بسازید:

# export static ip addresses and set vars for domain
export NAT_EXT_IP=$(gcloud compute addresses describe ip-${SLUG}-nat \
  --region=${REGION} \
  --format="value(address)")

export MCP_EXT_IP=$(gcloud compute addresses describe ip-${SLUG}-mcp \
  --region=${REGION} \
  --format="value(address)")

export MCP_DOMAIN="mcp.${MCP_EXT_IP}.sslip.io"
export MCP_URL="https://${MCP_DOMAIN}/mcp"

echo "cloud nat external ip    : ${NAT_EXT_IP}"
echo "mcp server external ip   : ${MCP_EXT_IP}"
echo "mcp url                  : ${MCP_URL}"

برونداد نمونه:

cloud nat external ip    : 203.0.113.10
mcp server external ip   : 203.0.113.20
mcp url                  : https://mcp.203.0.113.20.sslip.io/mcp

ایجاد شبکه داخلی

وقتی الگوی اتصال «درگاه عامل» برای استفاده از egressNetworkConfig با networkAttachment پیکربندی می‌شود، زیرشبکه‌ای که پیوست شبکه PSC را میزبانی می‌کند باید حداقل یک بلوک CIDR /28 باشد و دسترسی خصوصی Google (--enable-private-ip-google-access) در آن فعال باشد.

ایجاد شبکه VPC جهانی برای خروجی «دروازه عامل» داخلی:

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

# create subnet for agent gateway psc na
gcloud compute networks subnets create subnet-${REGION}-agw \
  --network=vnet-${SLUG}-internal \
  --range=10.10.10.0/28 \
  --region=${REGION} \
  --enable-private-ip-google-access

ایجاد قوانین دیوار آتش داخلی

خط‌مشی دیوار آتشی ایجاد کنید تا همه ترافیک خروجی را با فعال بودن ثبت گزارش مجاز کند. از این برای نظارت بر ترافیک خروجی از «درگاه عامل» به شبکه VPC داخلی استفاده خواهد شد. ‫Cloud NGFW از هر دو سطح Essentials و Standard برای امنیت شبکه و پایش ترافیک پشتیبانی می‌کند.

# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG}-internal --global
# create fw policy rule
gcloud compute network-firewall-policies rules create 1001 \
  --description="allow all out and log" \
  --firewall-policy=fw-policy-${SLUG}-internal \
  --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}-internal \
  --firewall-policy=fw-policy-${SLUG}-internal \
  --network=vnet-${SLUG}-internal \
  --global-firewall-policy

ایجاد پیوست شبکه PSC

پیوست شبکه «اتصال سرویس خصوصی» (PSC) را ایجاد کنید که برای پذیرفتن خودکار اتصال‌ها از «دروازه عامل» پیکربندی شده است. پیوست شبکه طرف شبکه VPC مصرف‌کننده اتصال را برقرار می‌کند تا به‌طور ایمن با طرف تولیدکننده «دروازه عامل» برای ترافیک خروجی پیوند برقرار کند. برای کسب اطلاعات بیشتر درباره الزامات زیرشبکه و مشخصات محدوده 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}

نشانی وب منبع پیوست شبکه PSC را بازیابی کنید و آن را در متغیر محیطی PSC_NA_URI ذخیره کنید. این نشانی وب در پیکربندی «دروازه عامل» (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}

ایجاد Cloud NAT

از Cloud NAT برای ترجمه نشانی IP منبع ترافیک خروجی «دروازه عامل» به نشانی IP عمومی رزروشده برای مسیریابی در اینترنت عمومی استفاده می‌شود.

فقط منابعی از زیرشبکه پیوست شبکه خروجی «درگاه عامل» به‌عنوان واجدشرایط برای استفاده از Cloud NAT تعریف شده‌اند.

# create router for nat
gcloud compute routers create cr-nat-${SLUG}-${REGION} \
  --network=vnet-${SLUG}-internal \
  --asn=16550 \
  --region=${REGION}

# create nat
gcloud compute routers nats create nat-${SLUG}-${REGION} \
  --router=cr-nat-${SLUG}-${REGION} \
  --region=${REGION} \
  --nat-custom-subnet-ip-ranges="subnet-${REGION}-agw" \
  --nat-external-ip-pool="ip-${SLUG}-nat" \
  --enable-logging \
  --log-filter=ALL

درستی‌سنجی Cloud NAT

وضعیت Cloud NAT را بررسی کنید و منبع natIP موردانتظار را پیکربندی کنید:

# verify cloud nat configuration
gcloud compute routers nats describe nat-${SLUG}-${REGION} \
  --router=cr-nat-${SLUG}-${REGION} \
  --region=${REGION} \
  --format="yaml(name,natIps,subnetworks.name)"

برونداد نمونه:

name: nat-foo-us-central1
natIps:
- https://www.googleapis.com/compute/v1/projects/[PROJ_ID]/regions/us-central1/addresses/ip-foo-nat

ایجاد شبکه خارجی

شبکه VPC جداگانه و ایزوله‌ای برای میزبانی ماشین مجازی سرور MCP خارجی ایجاد کنید.

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

# create subnet for mcp server
gcloud compute networks subnets create subnet-${REGION}-mcp \
  --network=vnet-${SLUG}-external \
  --range=240.240.240.0/24 \
  --region=${REGION} \
  --enable-private-ip-google-access

ایجاد قوانین دیوار آتش خارجی

دو قانون دیوار آتش ورودی در شبکه VPC خارجی ایجاد کنید:

  • 2001: درگاه TCP ورودی 80 را مجاز می‌کند تا Let's Encrypt بتواند چالش اعتبارسنجی دامنه ACME HTTP-01 را برای ${MCP_DOMAIN} تکمیل کند.
  • ‫2002: در ابتدا به درگاه TCP ورودی 443 از 0.0.0.0/0 اجازه می‌دهد تا آمادگی TLS و اجرای OAuth 2.0 tokeninfo را از پوسته محلی قبل‌از محدود کردن آن به‌طور دقیق به ${NAT_EXT_IP}/32 درستی‌سنجی کند.
# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG}-external --global
# create fw policy rules
gcloud compute network-firewall-policies rules create 2001 \
  --description="allow in any http" \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:80 \
  --src-ip-ranges=0.0.0.0/0 \
  --dest-ip-ranges=240.240.240.0/24 \
  --enable-logging

gcloud compute network-firewall-policies rules create 2002 \
  --description="allow in any https" \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:443 \
  --src-ip-ranges=0.0.0.0/0 \
  --dest-ip-ranges=240.240.240.0/24 \
  --enable-logging
# bind fw policy to network
gcloud compute network-firewall-policies associations create \
  --name=fw-policy-bind-${SLUG}-external \
  --firewall-policy=fw-policy-${SLUG}-external \
  --network=vnet-${SLUG}-external \
  --global-firewall-policy

بخش شبکه به پایان رسید… در ادامه به بخش درگاه نماینده می‌پردازیم.

۵. دروازه نماینده

در این بخش، الگوی اتصال‌پذیری عامل را با vpcEgress: ALL_TRAFFIC مستقر می‌کنید، درگاه عامل منطقه‌ای را مستقر می‌کنید، و تفویض اختیار را به «پراکسی آگاه از هویت» (IAP) واگذار می‌کنید، و قوانین خط‌مشی دسترسی یکپارچه IAM را برای مدیریت درخواست‌های شبکه خروجی تعریف می‌کنید.

ایجاد الگوی اتصال‌پذیری

مشخصات الگوی اتصال‌پذیری موارد زیر را تعریف می‌کند:

  • egressNetworkConfig.networkAttachment: به پیوست شبکه PSC اشاره می‌کند و «دروازه عامل» را به شبکه VPC شما متصل می‌کند.
  • egressNetworkConfig.vpcEgress: روی ALL_TRAFFIC تنظیم کنید تا همه اتصالات برون‌سپاری عامل (ازجمله نقاط پایانی MCP اینترنت عمومی) به شبکه VPC مسیریابی شوند و بااستفاده از ترجمه نشانی IP منبع Cloud NAT خارج شوند.

فایل پیکربندی الگوی اتصال‌پذیری را ایجاد و وارد کنید:

# create connectivity template config file (vpcEgress: ALL_TRAFFIC)
cat > cfg/act-${AGW_NAME}.yaml << EOF
accessPath: AGENT_TO_ANYWHERE
name: projects/${PROJ_NO}/locations/${REGION}/agentConnectivityTemplates/act-${AGW_NAME}
deploymentModel: CENTRALIZED
egressNetworkConfig:
  networkAttachment: ${PSC_NA_URI}
  vpcEgress: ALL_TRAFFIC
EOF
# import connectivity template file (create template)
gcloud network-services agent-connectivity-templates import act-${AGW_NAME} \
  --source="cfg/act-${AGW_NAME}.yaml" \
  --location=${REGION}

ایجاد «درگاه عامل»

مشخصات «درگاه عامل» موارد زیر را تعریف می‌کند:

  • agentConnectivityTemplate: به الگوی اتصال‌پذیری اشاره می‌کند، بنابراین دروازه می‌تواند از پیوست شبکه PSC برای اتصال‌پذیری VPC استفاده کند.
  • registries: درگاه را با «ثبت‌کننده عامل منطقه‌ای» مرتبط می‌کند تا نقطه‌های پایانی MCP فهرست‌شده و طرحواره‌های ابزار را حل کند.

فایل پیکربندی «دروازه عامل» را ایجاد و وارد کنید:

# create agent gateway config file
cat > cfg/${AGW_NAME}.yaml << EOF
name: ${AGW_NAME}
protocols:
  - MCP
googleManaged:
  governedAccessPath: AGENT_TO_ANYWHERE
agentConnectivityTemplate: projects/${PROJ_NO}/locations/${REGION}/agentConnectivityTemplates/act-${AGW_NAME}
registries:
  - "//agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}"
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
  --source="cfg/${AGW_NAME}.yaml" \
  --location=${REGION}

درستی‌سنجی استقرار «دروازه عامل»

پیکربندی الگوی اتصال و «ثبت عامل» را تأیید کنید:

# verify agent gateway deployment details
gcloud network-services agent-gateways describe ${AGW_NAME} \
  --location=${REGION} \
  --format="yaml(name,agentConnectivityTemplate,registries)"

برونداد نمونه:

agentConnectivityTemplate: projects/[PROJ_NO]/locations/us-central1/agentConnectivityTemplates/act-foo-us-central1
name: projects/[PROJ_ID]/locations/us-central1/agentGateways/agw-foo-us-central1-ata
registries:
- //agentregistry.googleapis.com/projects/[PROJ_ID]/locations/us-central1

پیوست شبکه PSC را بازرسی کنید تا اتصال دروازه را تأیید کنید:

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

برونداد نمونه:

connectionEndpoints:
- ipAddress: 10.10.10.2
  projectIdOrNum: '[TENANT_PROJ_NO]'
  status: ACCEPTED
  subnetwork: https://www.googleapis.com/compute/v1/projects/[PROJ_ID]/regions/us-central1/subnetworks/subnet-us-central1-agw

واگذاری مجوز

«دروازه عامل» بااستفاده از خط‌مشی‌های مجوز (networksecurity.authzPolicies) یکپارچه‌شده با خط‌مشی‌های دسترسی یکپارچه (UAP) «پراکسی آگاه از هویت» (IAP)، ترافیک ابزار خروجی را ایمن و مدیریت می‌کند.

درحالی‌که «دروازه عامل» از قوانین ALLOW و DENY درون‌خطی پایه پشتیبانی می‌کند، محیط‌های سازمانی به مدیریت متمرکز و هویت‌محور نیاز دارند. با «خط‌مشی‌های دسترسی یکپارچه IAM» (یا خط‌مشی‌های دسترسی)، قوانین دسترسی خروجی را بااستفاده از خط‌مشی‌های دسترسی استاندارد IAM v3 مدیریت می‌کنید.

figure3

شکل ۳. معماری مجوز

جریان مجوز سه جزء را به هم متصل می‌کند:

  1. خط‌مشی مجوز درگاه (authzPolicy):
    • منبع منطقه‌ای که «دروازه کارگزار» را هدف‌یابی می‌کند.
    • با policyProfile: REQUEST_AUTHZ و action: CUSTOM پیکربندی شده است تا همه بررسی‌های مجوز خروجی را به افزونه مجوز IAP هدایت کند.
  2. افزونه سرویس IAP (authzExtension):
    • منبع منطقه‌ای که صدور مجوز درخواست را به «پراکسی هویت‌آگاه» (iap.googleapis.com) واگذار می‌کند.
    • خط‌مشی‌ها را در حالت ENFORCE بااستفاده از نسخه خط‌مشی V2 ارزیابی می‌کند.
  3. خط‌مشی و اتصال دسترسی یکپارچه IAM (accessPolicy و policyBinding):
    • منابع جهانی IAM نسخه ۳ حاوی قوانین دسترسی دقیق.
    • هویت اصلی SPIFFE عامل تماس‌گیرنده را اصالت‌سنجی می‌کند، اجازه جهانی iap.googleapis.com/resources.egressViaIAP را درستی‌سنجی می‌کند، و شرایط «زبان عبارت مشترک» (CEL) را دربرابر مشخصه‌های مقصد ارزیابی می‌کند.

استقرار افزونه مجوز

# 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 authz extension config file (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,
    service:label=SERVICE,
    metadata:label=METADATA,
    timeout:label=TIMEOUT
  )"

استقرار خط‌مشی مجوز

پیکربندی خط‌مشی مجوز network-security ایجاد کنید که «درگاه عامل» را هدف‌یابی کند و درستی‌سنجی درخواست را به افزونه مجوز برای 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,
    policyProfile:label=POLICY_PROFILE,
    customProvider.authzExtension.resources[0].basename():label=CUSTOM_PROVIDER_RESOURCE
  )"

ایجاد خط‌مشی‌های دسترسی IAM

«درگاه کارگزار» اکنون بررسی‌های مجوز را به IAP واگذار می‌کند و فراداده مقصد را از «ثبت کارگزار» حل‌وفصل می‌کند. سپس، قانون خط‌مشی دسترسی یکپارچه IAM را برای کنترل اجرای ابزار خروجی تعریف کنید.

‫IAP عبارت‌های مشخصه CEL را دربرابر مشخصه‌های مقصد «ثبت عامل» زیر ارزیابی می‌کند:

  • وضعیت ثبت‌شده (destination.is_registered):
    • بولی (true/false) که نشان می‌دهد مقصد در «ثبت عامل» فهرست‌بندی شده است یا نه.
  • نام سرور MCP (destination.agent_registry.mcp_server.name):
    • نام منبع سرور MCP کانونی در «ثبت عامل» ثبت شده است.
  • روش MCP (destination.agent_registry.mcp_server.method):
    • روش MCP که فراخوانی می‌شود (مثلاً tools/call،‏ tools/list،‏ initialize).
  • نام ابزار (destination.agent_registry.mcp_server.tool.name):
    • نام ابزار خاصی که فراخوانده شده است (برای نمونه، get_sprocket_by_id یا get_sprockets)، که امکان صدور مجوز دقیق در سطح ابزار را در سرورهای MCP ثبت‌شده فراهم می‌کند.

تعریف قانون خط‌مشی دسترسی IAM

مانیفست قانون خط‌مشی IAM موارد زیر را مشخص می‌کند:

  • اصول: هویت اصلی SPIFFE که نماینده عامل دستیار اصلی Gemini Enterprise است.
  • اجازه‌ها: اجازه جهانی iap.googleapis.com/resources.egressViaIAP برای همه ترافیک خروجی تحت کنترل IAP لازم است.
  • شرایط: عبارت CEL (destination.is_registered == true) که تضمین می‌کند عامل فقط بتواند نقاط پایانی را که در «ثبت عامل» فهرست شده‌اند فراخوانی کند.

فایل مانیفست قانون خط‌مشی را ایجاد کنید:

# create access policy rule file
cat > cfg/uap-policy-${SLUG}-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-${SLUG} \
  --details-rules=cfg/uap-policy-${SLUG}-rules.json \
  --project=${PROJ_ID} \
  --location=global

درستی‌سنجی خط‌مشی دسترسی IAM

بررسی کنید خط‌مشی دسترسی IAM باموفقیت ایجاد شده باشد و جزئیات قانون را بازرسی کنید:

# show iam access policy details
gcloud iam access-policies describe uap-policy-${SLUG} \
  --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/app-foo-global_[EPOCH]/assistants/default_assistant/agents/default/core_assistant
name: projects/[PROJ_ID]/locations/global/accessPolicies/uap-policy-foo

خط‌مشی دسترسی IAM را به پروژه پیوند دهید

برای فعال کردن اجرای خط‌مشی در همه «دروازه‌های عامل» در پروژه‌تان، یک پیوند خط‌مشی ایجاد کنید که خط‌مشی دسترسی IAM را به منبع پروژه پیوست می‌کند:

# bind iam access policy to project resource
gcloud iam policy-bindings create uap-bind-${SLUG} \
  --policy="projects/${PROJ_ID}/locations/global/accessPolicies/uap-policy-${SLUG}" \
  --target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJ_ID}" \
  --project=${PROJ_ID} \
  --location=global

درستی‌سنجی اتصال خط‌مشی دسترسی IAM

بررسی کنید که نقاط اتصال خط‌مشی فعال به خط‌مشی و هدف صحیح اشاره می‌کند:

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

این بخش مربوط به «درگاه عامل» را به‌پایان می‌رساند… در ادامه به بخش سرور MCP می‌پردازیم.

‫۶. سرور MCP

در این بخش، یک سرور منبع OAuth 2.0 خارجی FastMCP (mcp-sprockets) را که ابزارهای get_sprockets و get_sprocket_by_id را نمایان می‌کند مستقر می‌کنید و تأیید می‌کنید که به‌صورت رمزنگاری‌شده نشان‌های Google OAuth 2.0 Bearer را دربرابر https://oauth2.googleapis.com/tokeninfo اعتبارسنجی می‌کند. در مرحله بعد، قانون دیوار آتش خارجی را به‌طور دقیق به پروتکل اینترنتی ایستا Cloud NAT محدود می‌کنید.

پیاده‌سازی سرور MCP خارجی

یک دستورگان راه‌اندازی Caddy و FastMCP را نصب می‌کند، سرور mcp-sprockets را در 127.0.0.1:8080 راه‌اندازی می‌کند، و Caddy را پیکربندی می‌کند تا HTTPS را در ${MCP_DOMAIN} ارائه دهد.

هر بار که Gemini Enterprise ابزار MCP را فرا می‌خواند (برای نمونه، get_sprockets و get_sprocket_by_id)، سرور این کارها را انجام می‌دهد:

  1. نشانی IP منبع تماس‌گیرنده را از سرایند X-Forwarded-For (egress_source_ip) بخوانید.
  2. سرصفحه Authorization: Bearer [access_token] را استخراج کنید و کد را دربرابر نقطه پایان درستی‌سنجی Google OAuth 2.0 (https://oauth2.googleapis.com/tokeninfo?access_token=[token]) درستی‌سنجی کنید.
  3. ‫"authenticated_user"‏ ([user_email]) را به‌همراه "egress_source_ip" برگردانید، که ثابت می‌کند سرور MCP خارجی هم نشانی IP استاتیک Cloud NAT و هم هویت کاربر نهایی Google OAuth 2.0 را درستی‌سنجی کرده است.
# create startup script for the sprockets mcp server vm
cat > cfg/server-startup.sh << 'EOF'
#!/bin/bash
set -euo pipefail

MCP_DOMAIN=$(curl -s -H "Metadata-Flavor: Google" \
  http://metadata.google.internal/computeMetadata/v1/instance/attributes/mcp-domain)

export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y caddy python3-venv curl

mkdir -p /opt/mcp-sprockets
python3 -m venv /opt/mcp-sprockets/venv
/opt/mcp-sprockets/venv/bin/pip install --upgrade pip
/opt/mcp-sprockets/venv/bin/pip install "fastmcp>=2.14.0" "uvicorn>=0.34.0"

cat <<'PYEOF' > /opt/mcp-sprockets/main.py
import json
import urllib.parse
import urllib.request
from typing import Any, Dict
from fastmcp import FastMCP
from fastmcp.server.dependencies import get_http_headers
from mcp.types import ToolAnnotations

mcp = FastMCP("mcp-sprockets")

SPROCKETS = {
    "SPK-101": {"id": "SPK-101", "model": "ANSI-40-12T", "teeth": 12, "pitch_in": 0.5, "material": "1045 Carbon Steel", "stock": 140, "unit_price": 18.50},
    "SPK-102": {"id": "SPK-102", "model": "ANSI-40-24T", "teeth": 24, "pitch_in": 0.5, "material": "1045 Carbon Steel", "stock": 85, "unit_price": 29.00},
    "SPK-103": {"id": "SPK-103", "model": "ANSI-60-16T", "teeth": 16, "pitch_in": 0.75, "material": "304 Stainless Steel", "stock": 60, "unit_price": 42.00},
    "SPK-104": {"id": "SPK-104", "model": "ANSI-60-32T", "teeth": 32, "pitch_in": 0.75, "material": "304 Stainless Steel", "stock": 35, "unit_price": 68.00},
    "SPK-105": {"id": "SPK-105", "model": "ANSI-80-20T", "teeth": 20, "pitch_in": 1.0, "material": "4140 Alloy Steel", "stock": 50, "unit_price": 95.00}
}

def verify_google_oauth_token(headers: Dict[str, str]) -> str:
    token = headers.get("authorization", "")[7:].strip() if headers.get("authorization", "").lower().startswith("bearer ") else ""
    if not token:
        return "unauthenticated (missing Bearer token)"
    url = "https://oauth2.googleapis.com/tokeninfo?" + urllib.parse.urlencode({"access_token": token})
    with urllib.request.urlopen(url, timeout=5) as resp:
        info = json.loads(resp.read().decode("utf-8"))
        return info.get("email", info.get("sub", "verified-oauth-user"))

@mcp.tool(
    description="list all sprockets in the inventory catalog",
    annotations=ToolAnnotations(
        readOnlyHint=True,
        destructiveHint=False,
        idempotentHint=True,
        openWorldHint=False
    )
)
def get_sprockets() -> Dict[str, Any]:
    headers = get_http_headers(include_all=True)
    caller_ip = headers.get("x-forwarded-for", "unknown").split(",")[0].strip()
    try:
        user_email = verify_google_oauth_token(headers)
    except Exception as exc:
        return {"egress_source_ip": caller_ip, "authenticated_user": None, "error": f"OAuth token verification failed: {exc}"}
    return {
        "egress_source_ip": caller_ip,
        "authenticated_user": user_email,
        "sprockets": list(SPROCKETS.values())
    }

@mcp.tool(
    description="fetch details of a specific sprocket by its ID (eg, SPK-101)",
    annotations=ToolAnnotations(
        readOnlyHint=True,
        destructiveHint=False,
        idempotentHint=True,
        openWorldHint=False
    )
)
def get_sprocket_by_id(sprocket_id: str) -> Dict[str, Any]:
    headers = get_http_headers(include_all=True)
    caller_ip = headers.get("x-forwarded-for", "unknown").split(",")[0].strip()
    try:
        user_email = verify_google_oauth_token(headers)
    except Exception as exc:
        return {"egress_source_ip": caller_ip, "authenticated_user": None, "error": f"OAuth token verification failed: {exc}"}
    sprocket = SPROCKETS.get(sprocket_id.upper())
    if sprocket:
        return {
            "egress_source_ip": caller_ip,
            "authenticated_user": user_email,
            "sprocket": sprocket
        }
    return {
        "egress_source_ip": caller_ip,
        "authenticated_user": user_email,
        "error": f"Sprocket '{sprocket_id}' not found."
    }

app = mcp.http_app(stateless_http=True)
PYEOF

cat <<'SVCEOF' > /etc/systemd/system/mcp-sprockets.service
[Unit]
Description=Sprockets FastMCP Server
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/mcp-sprockets
ExecStart=/opt/mcp-sprockets/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8080 --forwarded-allow-ips="*"
Restart=always

[Install]
WantedBy=multi-user.target
SVCEOF

systemctl daemon-reload
systemctl enable --now mcp-sprockets.service
systemctl restart mcp-sprockets.service

cat <<CADDYEOF > "/etc/caddy/Caddyfile"
${MCP_DOMAIN} {
    reverse_proxy 127.0.0.1:8080
}
CADDYEOF

systemctl restart caddy
EOF
# create vm instance
gcloud compute instances create vm-${MCP_NAME} \
  --zone=${ZONE} \
  --machine-type=e2-micro \
  --image-family=debian-12 \
  --image-project=debian-cloud \
  --shielded-secure-boot \
  --network-interface="subnet=subnet-${REGION}-mcp,address=${MCP_EXT_IP}" \
  --metadata="mcp-domain=${MCP_DOMAIN}" \
  --metadata-from-file="startup-script=cfg/server-startup.sh"

آماده بودن سرور MCP و اعتبارسنجی OAuth 2.0 tokeninfo را درستی‌سنجی کنید

چند دقیقه صبر کنید تا دستورگان راه‌اندازی FastMCP و Caddy را نصب کند و گواهینامه «امنیت لایه انتقال» Let's Encrypt را آماده کند.

# poll until caddy serves valid tls and fastmcp responds to tools/list
for i in $(seq 1 30); do
  RESP=$(curl -s -X POST "${MCP_URL}" \
    -H "Content-Type: application/json" \
    -H "Accept: application/json, text/event-stream" \
    -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' || true)
  if echo "${RESP}" | grep -q "get_sprockets"; then
    echo "mcp server and let's encrypt tls ready"
    break
  fi
  echo "...waiting for mcp server and let's encrypt tls (attempt ${i}/30)..."
  sleep 5
done

درستی‌سنجی تفکیک ساناد sslip.io، گواهینامه «امنیت لایه انتقال» Let's Encrypt که Caddy ارائه می‌دهد، و پاسخ FastMCP tools/list:

# query mcp server for tools list
curl -v -X POST "${MCP_URL}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' \
  2>&1 | grep -E "Connected to|subject:|issuer:|SSL certificate|HTTP/|event:|data:"

برونداد نمونه:

* Connected to mcp.203.0.113.20.sslip.io (203.0.113.20) port 443
*  subject: CN=mcp.203.0.113.20.sslip.io
*  issuer: C=US; O=Let's Encrypt; CN=E5
*  SSL certificate verify ok.
> POST /mcp HTTP/2
< HTTP/2 200
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"get_sprockets","description":"list all sprockets in the inventory catalog","inputSchema":{"properties":{},"type":"object"},"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}},{"name":"get_sprocket_by_id","description":"fetch details of a specific sprocket by its ID (eg, SPK-101)","inputSchema":{"properties":{"sprocket_id":{"type":"string"}},"required":["sprocket_id"],"type":"object"},"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}}]}}

قبل‌از ایمن کردن دیوار آتش خارجی، آزمایشی را اجرا کنید که tools/call کد حامل Google OAuth 2.0 (gcloud auth print-access-token) را ارسال می‌کند تا تأیید کند که mcp-sprockets کد را دربرابر https://oauth2.googleapis.com/tokeninfo اعتبارسنجی می‌کند و نشانی ایمیل "authenticated_user" شما را به‌همراه نشانی IP منبع تماس‌گیرنده برمی‌گرداند:

# query mcp server (test tools/call with google oauth 2.0 bearer token)
curl -s -X POST "${MCP_URL}" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "get_sprocket_by_id",
      "arguments": {"sprocket_id": "SPK-105"}
    }
  }' | sed -n 's/^data: //p' | jq '.result.structuredContent'

برونداد نمونه (نمایش IP مستقیم Cloud Shell شما قبل‌از قفل کردن دیواره آتش و ایمیل Google OAuth درستی‌سنجی‌شده شما):

{
  "egress_source_ip": "198.51.100.154",
  "authenticated_user": "user@example.com",
  "sprocket": {
    "id": "SPK-105",
    "model": "ANSI-80-20T",
    "teeth": 20,
    "pitch_in": 1.0,
    "material": "4140 Alloy Steel",
    "stock": 50,
    "unit_price": 95.0
  }
}

قفل کردن دیوار آتش در IP ثابت Cloud NAT

خط‌مشی فایروال شبکه VPC خارجی را به‌روز کنید تا درگاه TCP 443 ترافیک را فقط از نشانی IP خارجی ایستا Cloud NAT (‏${NAT_EXT_IP}/32) بپذیرد:

# create fw policy rule allowing https only from cloud nat static ip
gcloud compute network-firewall-policies rules create 2003 \
  --description="allow in any https from nat ip" \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:443 \
  --src-ip-ranges="${NAT_EXT_IP}/32" \
  --dest-ip-ranges=240.240.240.0/24 \
  --enable-logging
# delete temporary open fw policy rules
gcloud compute network-firewall-policies rules delete 2001 \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy

gcloud compute network-firewall-policies rules delete 2002 \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy

بررسی کنید که قوانین خط‌مشی دیوار آتش خارجی در جای خود قرار دارند:

# list all rules in the global network firewall policy
gcloud compute network-firewall-policies describe fw-policy-${SLUG}-external \
  --global \
  --flatten="rules[]" \
  --format="table(
    rules.priority:label=RULE,
    rules.action:label=ACTION,
    rules.direction:label=DIRECTION,
    firstof(
      rules.match.srcIpRanges,
      rules.match.srcAddressGroups,
      rules.match.srcSecureTags.name
    ).map().sub('projects/[^/]+/(locations/global/|global/)', '').list():label=SRC,
    firstof(
      rules.targetForwardingRules,
      rules.match.destIpRanges,
      rules.targetType
    ).map().sub('projects/[^/]+/(locations/global/|global/)', '').list():label=DST
  )"

بررسی کنید که اتصالات مستقیم خارج از IP استاتیک Cloud NAT اکنون مسدود شده‌اند:

# query mcp server
curl -i --connect-timeout 5 "${MCP_URL}" \
  || echo "Expected: Direct access blocked (not originating from ${NAT_EXT_IP})"

برونداد نمونه:

curl: (28) Connection timed out after 5001 milliseconds
Expected: Direct access blocked (not originating from 203.0.113.10)

بخش سرور MCP به پایان رسید… در ادامه به بخش ثبت‌کننده عامل می‌پردازیم.

‫۷. Agent Registry

«ثبت عامل» فهرست موجودی مرکزی همه عامل‌ها، سرورهای MCP، و نقطه‌های پایان (میاناهای برنامه‌سازی کاربردی) در بوم‌سازگان هوش مصنوعی است. این فهرست همچنین می‌تواند برای فهرست کردن، جستجو کردن، و کشف ابزارها و سرویس‌های ثبت‌شده دیگر برای استفاده در برنامه‌های هوش مصنوعی استفاده شود. ‫Agent Gateway از مدل داده ثبت به‌عنوان چارچوب حاکمیت برای اعمال کنترل دسترسی خروجی استفاده می‌کند. اعطای نقش IAM برای عاملان تماس اصلی دربرابر خط‌مشی پیوندخورده به منبع ثبت بررسی می‌شود.

در این بخش، سرور MCP و طرحواره ابزار آن (toolspec.json) را در ثبت‌کننده عامل ثبت خواهید کرد. برای پشتیبانی از تعامل Gemini Enterprise با Google APIs و «سرویس‌ها» ازطریق «درگاه عامل»، سرویس نقطه پایانی ثبت واحدی (oauth2-googleapis) نیز ایجاد خواهید کرد که رابط‌های Google API مورداستفاده Gemini Enterprise را برای تبادل کد اصالت‌سنجی با نشان‌ها مشخص می‌کند.

ثبت سرور MCP

برای اینکه Gemini Enterprise بتواند ابزارهای دردسترس در سرور MCP را پیدا کند، هنگام ثبت سرویس در «ثبت‌کننده عامل»، فایل مشخصات ابزار (cfg/toolspec.json) ارائه دهید.

ایجاد مشخصات ابزار MCP

# create tool spec file for the sprockets mcp server
cat <<'EOF' > cfg/toolspec.json
{
  "tools": [
    {
      "name": "get_sprockets",
      "description": "List all sprockets in the inventory catalog.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "isReadOnly": true,
      "isDestructive": false,
      "isIdempotent": true,
      "isOpenWorld": false
    },
    {
      "name": "get_sprocket_by_id",
      "description": "Fetch details of a specific sprocket by its ID (e.g., SPK-101).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sprocket_id": {
            "type": "string",
            "description": "The sprocket identifier (e.g., SPK-101, SPK-105)."
          }
        },
        "required": [
          "sprocket_id"
        ]
      },
      "isReadOnly": true,
      "isDestructive": false,
      "isIdempotent": true,
      "isOpenWorld": false
    }
  ]
}
EOF

ایجاد سرویس سرور MCP

# create registry service (mcp server)
gcloud agent-registry services create ${MCP_NAME} \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --display-name="${MCP_DOMAIN}" \
  --description="MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: You MUST \
ALWAYS invoke this tool (get_sprockets or get_sprocket_by_id) for ANY question \
about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through \
SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, \
material, stock levels, unit prices, authenticated_user, or egress_source_ip \
verification. NEVER guess or fabricate inventory data yourself and NEVER \
transfer sprocket queries to file_and_coding_agent or web search. Always \
delegate every sprocket or inventory lookup to this tool." \
  --mcp-server-spec-type=tool-spec \
  --mcp-server-spec-content=cfg/toolspec.json \
  --interfaces=protocolBinding=JSONRPC,url="${MCP_URL}"

تأیید سرور MCP در «ثبت عامل»

تأیید کنید که این سرویس به‌عنوان سرور MCP ثبت‌شده در منطقه همراه با نشانی وب نقطه پایان و ابزارهای دردسترس آن فهرست شده است:

# list registry regional mcp servers
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-5c39-1f6e542bb2b8   mcp.203.0.113.20.sslip.io  https://mcp.203.0.113.20.sslip.io/mcp  get_sprockets,get_sprocket_by_id

مشخصات پیکربندی سرویس را مشاهده کنید تا ببینید که تعاریف دقیق ابزار، طرح‌های ورودی، و نشان‌گذاری‌های رفتار را برای هر ابزار ثبت می‌کند:

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

ثبت نقطه پایان OAuth

برای اینکه زیرینه Gemini Enterprise DataConnector (که در جریان مجوز به‌عنوان کارخواه OAuth عمل می‌کند) بتواند درخواست‌های POST را ازطریق «درگاه عامل» به سرور مجوز Google OAuth 2.0 (https://oauth2.googleapis.com/token) ارسال کند، نقطه پایان کد باید در «ثبت عامل» ثبت شود تا IAP بتواند destination.is_registered == true را ارزیابی کند.

ایجاد سرویس نقطه پایان

# create registry service (endpoint)
gcloud agent-registry services create oauth2-googleapis \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --display-name="oauth2.googleapis.com" \
  --description="google oauth2 endpoint" \
  --endpoint-spec-type=no-spec \
  --interfaces=protocolBinding=JSONRPC,url=https://oauth2.googleapis.com

درستی‌سنجی ثبت نقطه پایان

# list registry regional endpoints
gcloud agent-registry endpoints list \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --flatten="interfaces[]" \
  --format="table(
    displayName,
    name.basename():label=ENDPOINT_ID,
    interfaces.url:label=URL
  )"

برونداد موردانتظار:

DISPLAY_NAME           ENDPOINT_ID                                         URL
oauth2.googleapis.com  agentregistry-00000000-0000-0000-0012-3456789abcde  https://oauth2.googleapis.com

خط‌مشی دسترسی IAM

ازآنجایی‌که خط‌مشی دسترسی IAM خط‌مشی مجاز برای هر سرویس ثبت‌شده‌ای را که برنامه Gemini Enterprise core_assistant درخواست می‌کند تعریف می‌کند، هیچ اتصال خط‌مشی IAM اضافه‌ای برای تبادل کد OAuth لازم نیست.

  - conditions:
      iap.googleapis.com:
        expression: destination.is_registered == true
    description: allow ge assistant to any registered service
    effect: ALLOW

این بخش «ثبت عامل» را به پایان می‌رساند… در ادامه به بخش Gemini Enterprise می‌پردازیم.

‫۸. Gemini Enterprise

در این بخش، ارائه‌دهنده هویت، پروانه آزمایشی، و اعتبارنامه‌های کارخواه Google Identity OAuth 2.0 را پیکربندی می‌کنید، برنامه Gemini Enterprise (${GE_APP_ID}) را ایجاد می‌کنید، خروجی برون‌سپاری را به «دروازه کارگزار» (${AGW_URI}) پیوند می‌دهید، و سرور MCP چرخ‌دنده‌های ثبت‌شده را به‌عنوان مخزن داده MCP سفارشی در OAuth 2.0 متصل می‌کنید.

ایجاد برنامه Gemini Enterprise

روش زیر از discoveryengine.googleapis.com API برای ایجاد منابع و پیکربندی برنامه 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}"
  },
  "observabilityConfig": {
    "observabilityEnabled": true,
    "sensitiveLoggingEnabled": true
  }
}
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}"

فعال کردن ارائه‌دهنده هویت

«هویت Google» را به‌عنوان ارائه‌دهنده هویت برای اصالت‌سنجی کاربر نهایی در برنامه Gemini Enterprise فعال کنید.

روش زیر از میانای برنامه‌سازی کاربردی discoveryengine.googleapis.com برای پیکربندی ارائه‌دهنده هویت برنامه «Gemini ویژه شرکت‌ها» استفاده می‌کند. برای پیکربندی بااستفاده از واسط کاربر Google Cloud Console، برای دریافت دستورالعمل‌ها به پیکربندی ارائه‌دهنده هویت مراجعه کنید.

# 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 را به‌مدت ۳۰ روز واجدشرایط کند. این کار پروانه پیش‌فرض را روی دوره آزمایشی جدید تنظیم می‌کند، بنابراین به هر کاربری که وارد سیستم می‌شود به‌طور خودکار جایگاهی اختصاص داده می‌شود:

# 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 (کارخواه OAuth 2.0) اجازه دهید یک حامل کد Google OAuth 2.0 واگذارشده ازسوی کاربر را دریافت کند و ازطرف شما به mcp-sprocketsسرور منبع ارائه دهد، صفحه موافقت OAuth «پلاتفرم Google Auth» را پیکربندی کنید و «شناسه کارخواه OAuth 2.0» برنامه وب را در پروژه‌تان ایجاد کنید.

نشانی وب مستقیم «کنسول Google Cloud» را برای نمای کلی پلاتفرم Google Auth در پروژه‌تان چاپ کنید:

# print google auth platform consent screen url
echo "https://console.cloud.google.com/auth/overview?project=${PROJ_ID}"
  1. نشانی وب را در مرورگرتان باز کنید و روی شروع به کار کلیک کنید (اگر قبلاً برای پروژه شما پیکربندی نشده است).
  2. در بخش اطلاعات برنامه، نام برنامه را روی mcp-sprockets-oauth تنظیم کنید و نشانی ایمیلتان (${USER_IDENTITY}) را به‌عنوان ایمیل پشتیبانی کاربر انتخاب کنید، سپس روی بعدی کلیک کنید.
  3. در بخش مخاطب، داخلی (اگر حسابتان متعلق به سازمان Google Workspace است توصیه می‌شود) یا خارجی (اگر از حساب شخصی استفاده می‌کنید؛ اگر خارجی را انتخاب کردید، ${USER_IDENTITY} را در بخش **کاربران آزمایش مخاطب** اضافه کنید) را انتخاب کنید، سپس روی بعدی کلیک کنید.
  4. نشانی ایمیل خود را در بخش اطلاعات تماس وارد کنید، موافقت با خط‌مشی را بپذیرید، و روی ایجاد کلیک کنید.

۲. ایجاد شناسه کارخواه OAuth 2.0 برنامه وب

نشانی وب مستقیم Google Cloud Console را برای صفحه کارخواه‌ها چاپ کنید:

# print google auth platform clients url
echo "https://console.cloud.google.com/auth/clients?project=${PROJ_ID}"
  1. نشانی وب را باز کنید و روی + ایجاد مشتری کلیک کنید.
  2. برنامه وب را به‌عنوان نوع برنامه انتخاب کنید و نام را روی ge-mcp-sprockets-client تنظیم کنید.
  3. برای تعیین مشتری OAuth برای گردش‌های کار عامل هوشواره‌ای که ازطرف کاربران عمل می‌کند، چارگوش انتخاب این مشتری توسط عامل هوشواره‌ای استفاده خواهد شد را انتخاب کنید.
  4. در بخش شناسه‌های وب هدایت مجاز، روی + افزودن شناسه وب کلیک کنید و شناسه وب تماس برگشتی Gemini Enterprise OAuth را اضافه کنید:
    • https://vertexaisearch.cloud.google.com/oauth-redirect
  5. روی ایجاد کلیک کنید، شناسه کارخواه و رمز کارخواه تولیدشده را کپی کنید، و آن‌ها را در جلسه پوسته صادر کنید:

شناسه کارخواه OAuth 2.0 و رمز کارخواه تولیدشده از مرحله قبلی را تنظیم کنید:

# set oauth 2.0 client id (paste in id)
export OAUTH_CLIENT_ID="SET_YOUR_OAUTH_CLIENT_ID_HERE"
# set oauth 2.0 client secret (paste in secret)
export OAUTH_CLIENT_SECRET="SET_YOUR_OAUTH_CLIENT_SECRET_HERE"

بررسی کنید شناسه کارخواه تنظیم شده باشد:

# print oauth 2.0 client id
echo "oauth client id: ${OAUTH_CLIENT_ID}"

اتصال به «دروازه عامل»

مسیردهی ترافیک خروجی از Gemini Enterprise ازطریق «درگاه نماینده» یک مرز اجرای متمرکز و مسیردهی پروتکل اینترنتی ایستا برای همه فراخوانی‌های ابزار نماینده هوش مصنوعی ایجاد می‌کند:

  • اجرای متمرکز خط‌مشی: «دروازه عامل» به‌عنوان یک پراکسی درون‌خطی عمل می‌کند که درخواست‌های ابزار خروجی را دربرابر خط‌مشی‌های مجوز قبل‌از خروج ترافیک از محیط عامل ارزیابی می‌کند.
  • خروجی قطعیتی VPC و Cloud NAT: پیوند دادن Gemini Enterprise به «دروازه عامل» پیکربندی‌شده با vpcEgress: ALL_TRAFFIC تضمین می‌کند که تماس‌های ابزار ازطریق پیوست شبکه PSC هدایت شود و بااستفاده از IP استاتیک Cloud NAT رزروشده شما خارج شود.
  • قابلیت ممیزی یکپارچه: گزارش‌های درخواست متمرکز و ردپای ممیزی را در همه سرورهای MCP متصل ارائه می‌دهد.

موتور 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": "${AGW_URI}"
    }
  }
}
EOF

درستی‌سنجی اتصال «درگاه عامل»

پیکربندی برنامه را بازیابی کنید تا اتصال 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 print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq '{name: .name, displayName: .displayName, agentGatewaySetting: .agentGatewaySetting}'

برونداد نمونه:

{
  "name": "projects/[PROJ_NO]/locations/global/collections/default_collection/engines/app-foo-global_[EPOCH]",
  "displayName": "foo global app",
  "agentGatewaySetting": {
    "defaultEgressAgentGateway": {
      "name": "projects/[PROJ_ID]/locations/us-central1/agentGateways/agw-foo-us-central1-ata"
    }
  }
}

ایجاد کردن مخزن داده سرور MCP سفارشی

در این بخش، با ایجاد یک فروشگاه داده MCP سفارشی OAuth 2.0 که با «هویت Google» پیکربندی شده است (https://accounts.google.com/o/oauth2/v2/auth و https://oauth2.googleapis.com/token)، سرور mcp-sprockets را به Gemini Enterprise متصل خواهید کرد.

بااستفاده از Discovery Engine API، این فرایند دو مرحله دارد:

  1. ایجاد (:setUpDataConnector): منبع Collection اختصاصی (${MCP_NAME}-collection-%timestamp) ایجاد می‌کند، DataConnector (custom_mcp) را با auth_type: "OAUTH" پیوست می‌کند، و DataStore پشتیبان آن (..._mcp_data) را تأمین می‌کند.
  2. فعال کردن (PATCH .../dataConnector?updateMask=actionConfig): زمان اجرای کنش اتصال‌دهنده (actionState: "ACTIVE") را بااستفاده از مشخصات ابزار «ثبت عامل»، پارامترهای Google Identity OAuth 2.0، فعال می‌کند و DataStore (dataStoreIds) را به Engine شما در Gemini Enterprise پیوند می‌دهد.
# fetch mcp server agent registry resource name
export MCP_REGISTRY_URI=$(gcloud agent-registry mcp-servers list \
  --location=${REGION} \
  --project=${PROJ_ID} \
  --filter="displayName:${MCP_DOMAIN}" \
  --format="value(name)")

echo "mcp registry name: ${MCP_REGISTRY_URI}"
echo "mcp url: ${MCP_URL}"

ساختن رابط داده

# create custom mcp data connector with google identity oauth 2.0 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}-collection-$(date +%s)",
  "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": "OAUTH",
        "instance_uri": "${MCP_URL}",
        "auth_uri": "https://accounts.google.com/o/oauth2/v2/auth",
        "auth_uri_params": "&access_type=offline&prompt=consent",
        "token_uri": "https://oauth2.googleapis.com/token",
        "client_id": "${OAUTH_CLIENT_ID}",
        "client_secret": "${OAUTH_CLIENT_SECRET}",
        "scopes": "openid email profile",
        "client_secret_basic_override": true,
        "mcp_server_source": "REGISTRY_MCP",
        "registry_mcp_server_name": "${MCP_REGISTRY_URI}",
        "mcp_agent_instructions": "MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: Always invoke get_sprockets or get_sprocket_by_id for any question about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, material, stock levels, unit prices, authenticated_user, or egress_source_ip verification.",
        "use_agent_gateway_egress": true,
        "agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
      }
    }
  }
}
EOF

تأیید ایجاد اتصال‌دهنده داده

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

بررسی کنید که فیلد "registry_mcp_server_name" با UUID «ثبت عامل» برای سرور MCP تکمیل شده باشد و "auth_type" برابر با OAUTH باشد:

# 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, auth_type: .actionConfig.actionParams.auth_type, registry_mcp_server_name: .actionConfig.actionParams.registry_mcp_server_name}'

ورودی ثبت سرور MCP را در واسط کاربر Google Cloud Console مشاهده کنید:

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 with google identity oauth 2.0
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": "OAUTH",
      "instance_uri": "${MCP_URL}",
      "auth_uri": "https://accounts.google.com/o/oauth2/v2/auth",
      "auth_uri_params": "&access_type=offline&prompt=consent",
      "token_uri": "https://oauth2.googleapis.com/token",
      "client_id": "${OAUTH_CLIENT_ID}",
      "client_secret": "${OAUTH_CLIENT_SECRET}",
      "scopes": "openid email profile",
      "client_secret_basic_override": true,
      "mcp_server_source": "REGISTRY_MCP",
      "registry_mcp_server_name": "${MCP_REGISTRY_URI}",
      "mcp_agent_instructions": "MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: Always invoke get_sprockets or get_sprocket_by_id for any question about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, material, stock levels, unit prices, authenticated_user, or egress_source_ip verification.",
      "use_agent_gateway_egress": true,
      "agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
    }
  }
}
EOF

پیوندهای سرور 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}'

فروشگاه داده پیوندشده "dataStoreIds": ["mcp-sprockets-collection-[EPOCH]_mcp_data"] را بررسی کنید.

# 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, auth_type: .actionConfig.actionParams.auth_type}'

"state": "ACTIVE" و "auth_type": "OAUTH" را بررسی کنید.

کنش‌های ابزار

وقتی فروشگاه داده mcp-sprockets-collection را در داشبورد Gemini Enterprise بازرسی می‌کنید، متوجه خواهید شد که از برگه کنش‌ها استفاده نمی‌شود و دکمه ↻ بار کردن مجدد کنش‌های سفارشی غیرفعال است. این رفتار موردانتظار است.

صفحه جزئیات فروشگاه داده را در واسط کاربر Google Cloud Console مشاهده کنید:

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

بسته به اینکه چگونه سرور MCP سفارشی را به Gemini Enterprise متصل می‌کنید، شناسایی و حاکمیت ابزار به یکی از دو روش زیر انجام می‌شود:

  • «پروتکل بافتار مدل» سفارشی مستقیم (BYO_MCP گردش کار): وقتی سرور «پروتکل بافتار مدل» سفارشی را مستقیماً در Gemini Enterprise بدون «ثبت عامل» پیکربندی می‌کنید، فروشگاه داده خود کاتالوگ ابزار را مدیریت می‌کند (connectorModes: ["FEDERATED", "ACTIONS"]). باید برگه کنش‌ها را باز کنید، روی ↻ بار کردن مجدد کنش‌های سفارشی کلیک کنید تا طرحواره tools/list واکشی شود، و ابزارهای تکی (add و subtract) را به‌صورت دستی در «میانای کاربر» روشن یا خاموش کنید.
  • وارد کردن «ثبت عامل» (REGISTRY_MCP گردش کار استفاده‌شده در این codelab): وقتی سرور MCP را از ثبت عامل وارد می‌کنید، «ثبت عامل» به‌عنوان منبع معتبر حقیقت برای نقطه پایانی MCP، فراداده رابط آن، و کاتالوگ ابزار آن (connectorModes: ["FEDERATED"]) عمل می‌کند. Gemini Enterprise ابزارهای MCP ثبت‌شده را به‌طور خودکار در زمان اجرا ازطریق تنظیم موتور درگاه عامل فعال می‌کند، بدون اینکه نیاز باشد کنش‌ها را در واسط کاربر فروشگاه داده به‌صورت دستی مجدد بار کنید یا تغییر دهید.

این بخش Gemini Enterprise را به‌پایان می‌رساند… در ادامه به بخش اعتبارسنجی می‌پردازیم.

‫۹. راستی‌آزمایی

در این بخش، جریان موافقت کاربر Google OAuth 2.0 یک‌باره را تکمیل می‌کنید، ابزارهای MCP را در سرور mcp-sprockets خارجی از Gemini Enterprise فرا می‌خوانید، و تأیید می‌کنید که سرور MCP خارجی هر دو IP استاتیک Cloud NAT رزروشده شما (egress_source_ip) و هویت Google OAuth 2.0 شما (authenticated_user) را اعتبارسنجی کرده است.

دسترسی کاربر

ساختن نشانی وب برای برنامه تحت وب 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 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}"

قبل‌از پُرسمان کردن عامل، باید جریان موافقت OAuth 2.0 یک‌باره‌ای را تکمیل کنید که به Gemini Enterprise اجازه می‌دهد برای هویت Google شما (${USER_IDENTITY}) یک کد دسترسی دریافت کند. این کار به Gemini Enterprise امکان می‌دهد تماس‌های ابزار خروجی را ازطریق «درگاه عامل» اصالت‌سنجی کند تا سرور خارجی mcp-sprockets بتواند هویت شما را در هر درخواست درستی‌سنجی کند.

  1. ${GE_APP_USER_URL} را در مرورگرتان باز کنید و روی شروع به کار کلیک کنید.
  2. در چارگوش گپ، روی نماد اتصال‌دهنده‌ها (نماد قطعه پازل) کلیک کنید و روی مجوز دادن در کنار mcp-sprockets-collection کلیک کنید.
  3. پنجره جدیدی ظاهر می‌شود که از شما می‌خواهد حسابی را برای ادامه دادن mcp-sprockets-oauth (نام برنامه صفحه موافقت OAuth که پیکربندی کرده‌اید) انتخاب کنید. در آنجا حساب کاربری‌تان (${USER_IDENTITY}) را انتخاب کنید.
  4. در صفحه کسب رضایت Google OAuth، اجازه‌های درخواستی را که به Google (ارائه‌دهنده هویت) اجازه می‌دهد هویت کاربرتان (openid، email، profile) را با mcp-sprockets-oauth هم‌رسانی کند مرور کنید، سپس روی ادامه کلیک کنید.
  5. دوباره روی نماد اتصال‌دهنده‌ها کلیک کنید و مطمئن شوید که کلید mcp-sprockets-collection فعال است، این نشان می‌دهد که مجوز موفقیت‌آمیز بوده است.

پرسمان‌های عامل آزمایشی

آزمایش‌های میانای کاربر گپ «دستیار»

پُرسمان آزمایشی زیر را در گپ ارسال کنید:

look up sprocket SPK-105 and confirm the model, material, unit_price, authenticated_user, and egress_source_ip

پرسمان دومی را در گپ امتحان کنید:

list all sprockets in the inventory catalog and report the authenticated_user and egress_source_ip

تأیید کنید که دستیار پاسخ‌های صحیح را برمی‌گرداند و نشان استناد کنش تعاملی را نمایش می‌دهد.

برای مثال، «Sprocket Lookup SPK-105 (5s)نماد ابزار MCPAgent Gatewayنماد تیک در دایره» در زیر هر پاسخ، تأیید می‌کند که ابزار اجرا شده است.

ببینید که دستیار مشخصات چرخ دنده را به‌همراه "authenticated_user" منطبق با ${USER_IDENTITY} و "egress_source_ip" منطبق با ${NAT_EXT_IP} رزروشده شما برمی‌گرداند.

آزمایش‌های «میانای برنامه‌سازی کاربردی» «دستیار» streamAssist

پس‌از اینکه حساب کاربری‌تان اتصال‌دهنده OAuth 2.0 را مجاز کرد، می‌توانید default_assistant:streamAssist API را مستقیماً از «خط فرمان» نیز فراخوانی کنید و تأیید کنید که سرور خارجی mcp-sprockets هر دو نشانی IP ایستا Cloud NAT شما (${NAT_EXT_IP}) و هویت درستی‌سنجی‌شده Google OAuth 2.0 شما (${USER_IDENTITY}) را برمی‌گرداند:

پُرسمان آزمایشی زیر را ارسال کنید:

# query engine (ge app) streamAssist
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/assistants/default_assistant:streamAssist" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  -d @- <<EOF | jq -r '.[].answer.replies[]?.groundedContent?.content?.text // empty'
{
  "query": {
    "text": "look up sprocket SPK-103 and confirm the model, material, unit_price, authenticated_user, and egress_source_ip"
  },
  "toolsSpec": {
    "vertexAiSearchSpec": {
      "dataStoreSpecs": [
        {
          "dataStore": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/dataStores/${GE_COLLECTION_ID}_mcp_data"
        }
      ]
    }
  }
}
EOF

برونداد نمونه:

Here are the details for sprocket SPK-103 from the inventory catalog:
- Model: ANSI-60-16T
- Material: 304 Stainless Steel
- Unit Price: $42.00
- Authenticated User (Google OAuth 2.0): user@example.com
- Egress Source IP (Cloud NAT): 203.0.113.10

پُرسمان دیگری را امتحان کنید:

# query engine (ge app) streamAssist
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/assistants/default_assistant:streamAssist" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  -d @- <<EOF | jq -r '.[].answer.replies[]?.groundedContent?.content?.text // empty'
{
  "query": {
    "text": "find a sprocket model i can get for under \$20 and report the details, authenticated_user, and egress_source_ip"
  },
  "toolsSpec": {
    "vertexAiSearchSpec": {
      "dataStoreSpecs": [
        {
          "dataStore": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/dataStores/${GE_COLLECTION_ID}_mcp_data"
        }
      ]
    }
  }
}
EOF

بررسی گزارش‌ها در Cloud Logging

با بازرسی گزارش‌ها در Cloud Logging، تأیید کنید که Gemini Enterprise تماس‌های ابزار را ازطریق «دروازه عامل»، پیوست شبکه PSC، و Cloud NAT مسیریابی کرده است.

درستی‌سنجی گزارش‌های «درگاه عامل»

تأیید کنید که «درگاه عامل» درخواست را رهگیری کرده است، هدف را در «ثبت عامل» حل‌وفصل کرده است، خط‌مشی مجوز را ارزیابی کرده است، و فراخوانی ابزار را بازارسال کرده است:

# show agent gateway logs
gcloud logging read \
  "resource.type=networkservices.googleapis.com/Gateway
   AND resource.labels.location=${REGION}" \
  --project=${PROJ_ID} \
  --limit=8 \
  --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.ZZZ  200     203.0.113.20:443  tools/call                 get_sprocket_by_id  ALLOWED  agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ  200     203.0.113.20:443  tools/list                                     ALLOWED  agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ  202     203.0.113.20:443  notifications/initialized                      ALLOWED  agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ  200     203.0.113.20:443  initialize                                     ALLOWED  agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8

تأیید کنید که برونداد شامل موارد زیر باشد:

  • STATUS: 200 (اجرای موفق) و 202 (notifications/initialized دست دادن).
  • SERVER_IP: نشانی IP و درگاه سرور MCP خارجی (${MCP_EXT_IP}:443).
  • MCP_METHOD و TOOL: توالی پروتکل MCP (initialize، notifications/initialized، tools/list، و tools/call با get_sprocket_by_id).
  • AUTHZ: ALLOWED (خروج مجاز با مجوز IAP).
  • REGISTRY_MCP: شناسه منبع «ثبت کارگزار» حل‌وفصل‌شده (agentregistry-...).

درستی‌سنجی گزارش‌های Cloud NAT

تأیید کنید که Cloud NAT اتصال خروجی را از نشانی IP پیوست شبکه Agent Gateway PSC (10.10.10.2) به نشانی IPv4 خارجی ایستا رزروشده شما (${NAT_EXT_IP}) هنگام اتصال به ${MCP_EXT_IP}:443 ترجمه کرده است:

# show cloud nat logs
gcloud logging read \
  "resource.type=nat_gateway
   AND resource.labels.gateway_name=nat-${SLUG}-${REGION}
   AND jsonPayload.connection.dest_ip=${MCP_EXT_IP}" \
  --project=${PROJ_ID} \
  --limit=8 \
  --format="table(
    timestamp.date('', tz=LOCAL):label=TIMESTAMP,
    jsonPayload.allocation_status:label=ALLOCATION_STATUS,
    jsonPayload.connection.src_ip:label=SRC_IP,
    jsonPayload.connection.nat_ip:label=NAT_IP,
    jsonPayload.connection.dest_ip:label=DEST_IP,
    jsonPayload.connection.dest_port:label=PORT
  )"

برونداد نمونه:

TIMESTAMP                ALLOCATION_STATUS  SRC_IP      NAT_IP        DEST_IP       PORT
YYYY-MM-DDTHH:MM:SS.ZZZ  OK                 10.10.10.2  203.0.113.10  203.0.113.20  443

تأیید گزارش‌های دیوار آتش

تأیید کنید که خط‌مشی دیوار آتش داخلی (fw-policy-${SLUG}-internal) ترافیک خروجی از «درگاه عامل» به مقصد اینترنت را مجاز کرده است:

# show firewall policy logs (internal)
gcloud logging read \
  "logName:compute.googleapis.com%2Ffirewall
   AND jsonPayload.rule_details.reference:fw-policy-${SLUG}-internal" \
  --project=${PROJ_ID} \
  --limit=8 \
  --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.vpc.vpc_name:label=VPC_NETWORK,
    jsonPayload.rule_details.reference.basename():label=POLICY,
    jsonPayload.rule_details.priority:label=RULE,
    jsonPayload.rule_details.direction:label=DIRECTION,
    jsonPayload.disposition:label=DISPOSITION
  )"

تأیید کنید که خط‌مشی دیوار آتش خارجی (fw-policy-${SLUG}-external) ترافیک ورودی به سرور MCP را از نشانی IP NAT عمومی شبکه داخلی مجاز کرده است:

# show firewall policy logs (external)
gcloud logging read \
  "logName:compute.googleapis.com%2Ffirewall
   AND jsonPayload.rule_details.reference:fw-policy-${SLUG}-external" \
  --project=${PROJ_ID} \
  --limit=8 \
  --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.vpc.vpc_name:label=VPC_NETWORK,
    jsonPayload.rule_details.reference.basename():label=POLICY,
    jsonPayload.rule_details.priority:label=RULE,
    jsonPayload.rule_details.direction:label=DIRECTION,
    jsonPayload.disposition:label=DISPOSITION
  )"

این بخش اعتبارسنجی را به پایان می‌رساند… در ادامه به بخش پاک‌سازی می‌پردازیم.

‫۱۰. پاک‌سازی

برای حذف منابع و پیکربندی‌های ایجادشده در این آزمایشگاه، این مراحل را دنبال کنید.

برداشتن عناصر 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"}}'

برای برداشتن اعتبارنامه‌های کارخواه OAuth 2.0 (ge-mcp-sprockets-client)، صفحه «کارخواه‌های پلاتفرم اصالت‌سنجی Google» را باز کنید و روی نماد حذف (سطل زباله) در کنار ge-mcp-sprockets-client کلیک کنید:

# print google auth platform clients url
echo "https://console.cloud.google.com/auth/clients?project=${PROJ_ID}"

برداشتن سرور MCP و عناصر «ثبت عامل»

# delete external mcp server vm
gcloud -q compute instances delete vm-${MCP_NAME} --zone=${ZONE}

# delete agent registry mcp service
gcloud -q agent-registry services delete ${MCP_NAME} --location=${REGION}

# delete agent registry oauth2 endpoint
gcloud -q agent-registry services delete oauth2-googleapis --location=${REGION}

برداشتن عناصر «درگاه کارگزار»

# delete gateway authz policy and iap service extension
gcloud -q network-security authz-policies delete ${AGW_NAME}-authz-policy-iap \
  --location=${REGION}

gcloud -q service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
  --location=${REGION}

# delete agent gateway and connectivity template
gcloud -q network-services agent-gateways delete ${AGW_NAME} \
  --location=${REGION}

gcloud -q network-services agent-connectivity-templates delete act-${AGW_NAME} \
  --location=${REGION}
# delete iam unified access policy binding and access policy
gcloud -q iam policy-bindings delete uap-bind-${SLUG} \
  --location=global \
  --project=${PROJ_ID}

gcloud -q iam access-policies delete uap-policy-${SLUG} \
  --location=global \
  --project=${PROJ_ID}

برداشتن عناصر دیوار آتش

# delete network firewall policy associations
gcloud -q compute network-firewall-policies associations delete \
  --name=fw-policy-bind-${SLUG}-internal \
  --firewall-policy=fw-policy-${SLUG}-internal \
  --global-firewall-policy

gcloud -q compute network-firewall-policies associations delete \
  --name=fw-policy-bind-${SLUG}-external \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy

# delete custom firewall policy rules
gcloud -q compute network-firewall-policies rules delete 1001 \
  --firewall-policy=fw-policy-${SLUG}-internal \
  --global-firewall-policy

gcloud -q compute network-firewall-policies rules delete 2003 \
  --firewall-policy=fw-policy-${SLUG}-external \
  --global-firewall-policy

# delete network firewall policies
gcloud -q compute network-firewall-policies delete fw-policy-${SLUG}-internal \
  --global

gcloud -q compute network-firewall-policies delete fw-policy-${SLUG}-external \
  --global

برداشتن عناصر شبکه

# delete cloud nat gateway and cloud router
gcloud -q compute routers nats delete nat-${SLUG}-${REGION} \
  --router=cr-nat-${SLUG}-${REGION} \
  --region=${REGION}

gcloud -q compute routers delete cr-nat-${SLUG}-${REGION} \
  --region=${REGION}

# delete psc network attachment
gcloud -q compute network-attachments delete psc-na-${REGION}-agw \
  --region=${REGION}

# delete subnets
gcloud -q compute networks subnets delete subnet-${REGION}-agw \
  --region=${REGION}

gcloud -q compute networks subnets delete subnet-${REGION}-mcp \
  --region=${REGION}

# delete reserved static external ip addresses
gcloud -q compute addresses delete ip-${SLUG}-nat ip-${SLUG}-mcp \
  --region=${REGION}

# delete internal and external vpc networks
gcloud -q compute networks delete \
  vnet-${SLUG}-internal \
  vnet-${SLUG}-external

برداشتن ملغی کردن خط‌مشی سازمان و فایل‌های محلی

# delete project-level organization policy overrides
for policy in \
  discoveryengine.managed.disableCustomMcpServerConnector \
  discoveryengine.managed.allowedEgressFqdns \
  discoveryengine.managed.allowedDataSources \
  iam.managed.disableAccessPolicyBinding \
  compute.vmExternalIpAccess; do
  gcloud -q org-policies delete ${policy} --project=${PROJ_ID} 2>/dev/null || true
done

# remove local project files
rm -rf cfg

این کار پاک‌سازی را به پایان می‌رساند… در ادامه به نتیجه‌گیری می‌پردازیم!

‫۱۱. نتیجه‌گیری

تبریک! معماری سرتاسری ساختید که به برنامه Gemini Enterprise امکان می‌دهد ابزارها را در سرور MCP سفارشی با فهرست مجاز IP خارجی و محافظت‌شده با OAuth 2.0 به‌طور ایمن پیدا و فراخوانی کند:

  • برون‌گرایی VPC با پروتکل اینترنتی ایستا (ALL_TRAFFIC و Cloud NAT): همه ترافیک خروجی «درگاه عامل» را ازطریق پیوست شبکه PSC مسیریابی کردیم (10.10.10.2) و درخواست‌های اینترنتی را بااستفاده از Cloud NAT به نشانی IPv4 خارجی ایستای رزروشده (${NAT_EXT_IP}) ترجمه کردیم.
  • سرور منبع MCP و ثبت‌کننده عامل OAuth 2.0: سرور FastMCP HTTP جاری‌سازی‌پذیر خارجی (mcp-sprockets) را که با فهرست مجاز دیوار آتش IP منبع سخت‌گیرانه (${NAT_EXT_IP}/32) و درستی‌سنجی Google OAuth 2.0 tokeninfo محافظت می‌شود مستقر کرد و نقطه پایان و طرحواره ابزار آن (get_sprockets و get_sprocket_by_id) را در «ثبت‌کننده عامل» ثبت کرد.
  • یکپارچه‌سازی و حاکمیت Gemini Enterprise OAuth 2.0: برنامه Gemini Enterprise تأمین شد، ترافیک ابزار خروجی به درگاه عامل محدود شد، سرور MCP ثبت‌شده به‌عنوان رابط داده OAuth 2.0 REGISTRY_MCP پیوست شد، و egress_source_ip و authenticated_user درکنار تله‌متری Cloud Logging تأیید شد.

cosmopup

Cosmopup فکر می‌کند Codelabs عالی است!

مرحله بعدی چیست؟

بااستفاده از این فرم بازخورد، می‌توانید نظر، سؤال، یا اصلاحات خود را ارائه دهید.

متشکریم!