การค้นหาเซิร์ฟเวอร์ MCP แบบไดนามิกด้วย Agent Registry และ ADK

1. บทนำ

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีใช้ Google Cloud Agent Registry และ Agent Development Kit (ADK) เพื่อค้นหาและเรียกใช้เซิร์ฟเวอร์ Model Context Protocol (MCP) ที่ลงทะเบียนไว้แบบไดนามิกที่รันไทม์ ซึ่งจะช่วยลดการกำหนดค่าปลายทางและเครื่องมือที่ฮาร์ดโค้ดไว้

ห้องทดลองนี้ใช้ ADK และภาษาโปรแกรม Python เพื่อสร้างแอปพลิเคชัน หลักการเดียวกันนี้สามารถนำไปใช้ในภาษาโปรแกรมอื่นๆ และใช้เฟรมเวิร์กการพัฒนา Agent อื่นๆ ได้

สิ่งที่คุณต้องทำ

  • เปิดใช้และกำหนดค่า Google Cloud Agent Registry ในโปรเจ็กต์
  • ติดตั้งใช้งานเซิร์ฟเวอร์ MCP ใน Cloud Run และลงทะเบียนใน Agent Registry
  • สร้าง ADK Agent ที่เรียกใช้เซิร์ฟเวอร์ MCP โดยใช้ URL ที่ฮาร์ดโค้ด
  • เปลี่ยน Agent เพื่อค้นหาเซิร์ฟเวอร์ MCP ใน Agent Registry ตามข้อมูลประจำตัว
  • เปลี่ยน Agent ให้ค้นหาเซิร์ฟเวอร์ MCP ขณะรันไทม์โดยใช้การค้นหาเชิงความหมาย

สิ่งที่คุณต้องมี

  • เว็บเบราว์เซอร์ที่ทันสมัย (เช่น Chrome)
  • โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
  • บัญชีที่มีสิทธิ์สร้างและจัดการทรัพยากร รวมถึงกำหนดค่านโยบาย IAM ในโปรเจ็กต์ Google Cloud

2. ตั้งค่าสภาพแวดล้อม

วิธีการใน Codelab นี้จะถือว่าคุณเรียกใช้คำสั่งใน Cloud Shell ในคอนโซล Google Cloud Cloud Shell เป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานใน Google Cloud ซึ่งมาพร้อมกับเครื่องมือที่จำเป็นที่โหลดไว้ล่วงหน้า หากคุณติดตั้ง gcloud CLI, git และ Python 3 ในสภาพแวดล้อมภายในเครื่อง คุณจะเรียกใช้คำสั่งในสภาพแวดล้อมดังกล่าวได้ด้วย

สร้างโปรเจ็กต์ Google Cloud

  1. ในคอนโซล Google Cloud ในหน้าตัวเลือกโปรเจ็กต์ ให้สร้างโปรเจ็กต์ Google Cloud
  2. ตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ที่อยู่ในระบบคลาวด์แล้ว ดูวิธีตรวจสอบว่ามีการเปิดใช้การเรียกเก็บเงินในโปรเจ็กต์หรือไม่

เริ่มเทอร์มินัล Cloud Shell

  1. ใช้เครื่องมือเลือกทรัพยากรเพื่อเลือกโปรเจ็กต์ Google Cloud ที่คุณสร้างขึ้น
  2. คลิกเปิดใช้งาน Cloud Shell ไอคอนเปิดใช้งาน Cloud Shell ที่ด้านบนของคอนโซล Google Cloud
  3. เมื่อเชื่อมต่อกับ Cloud Shell แล้ว ให้ยืนยันการตรวจสอบสิทธิ์โดยทำดังนี้
    gcloud auth list
    
  4. ยืนยันว่าได้กำหนดค่าโปรเจ็กต์แล้ว โดยทำดังนี้
    gcloud config get project
    
  5. หากโปรเจ็กต์ไม่ได้ตั้งค่าตามที่คาดไว้ หรือหากคุณใช้สภาพแวดล้อมในเครื่องแทน Cloud Shell ให้ตั้งค่ารหัสโปรเจ็กต์โดยทำดังนี้
    export GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
    gcloud config set project "${GOOGLE_CLOUD_PROJECT}"
    

เลือกโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google และตั้งค่าตัวแปรสภาพแวดล้อม

  1. เปิดใช้ Google Cloud API ที่จำเป็น ดังนี้
    gcloud services enable \
      agentregistry.googleapis.com \
      aiplatform.googleapis.com \
      cloudbuild.googleapis.com \
      run.googleapis.com \
      --project="${GOOGLE_CLOUD_PROJECT}"
    

ตั้งค่าสภาพแวดล้อม Python

  1. สร้างและเปิดใช้งานสภาพแวดล้อมเสมือน และติดตั้งทรัพยากร Dependency ที่จำเป็น ดังนี้
    mkdir -p adk-dynamic-discovery && cd adk-dynamic-discovery
    python3 -m venv .venv
    source .venv/bin/activate
    pip install "fastmcp<5.0.0" "google-adk[mcp,a2a,agent-identity]>=2.5.0,<3.0.0"
    

3. สร้างและลงทะเบียนเซิร์ฟเวอร์ Zoo MCP

ในขั้นตอนนี้ คุณจะสร้างและลงทะเบียนเซิร์ฟเวอร์ Zoo MCP เซิร์ฟเวอร์จะแสดงเครื่องมือ 3 อย่าง ได้แก่ list_species แสดงรายการสายพันธุ์ทั้งหมดที่อาศัยอยู่ในสวนสัตว์ get_animals_by_species แสดงรายการสัตว์ของสายพันธุ์ที่เฉพาะเจาะจง และ get_animal_details รับข้อมูลเพิ่มเติมเกี่ยวกับสัตว์ที่เฉพาะเจาะจง

คุณดูไฟล์ทั้งหมดสำหรับขั้นตอนนี้ได้ใน GitHub

สร้างเซิร์ฟเวอร์ MCP

  1. ตั้งค่าโฟลเดอร์และโปรเจ็กต์ Python สำหรับเซิร์ฟเวอร์ MCP
    mkdir mcp-on-cloudrun && cd mcp-on-cloudrun
    uv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13
    uv add "fastmcp<5.0.0" --no-sync
    
  2. ดาวน์โหลดโค้ดเซิร์ฟเวอร์ MCP โดยทำดังนี้
    curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step3/server.py -o server.py
    

ติดตั้งใช้งานเซิร์ฟเวอร์ MCP ใน Cloud Run และลงทะเบียนที่ Agent Registry

ถัดไป คุณจะสร้าง Dockerfile สำหรับเซิร์ฟเวอร์และติดตั้งใช้งานเซิร์ฟเวอร์ใน Cloud Run

  1. สร้าง Dockerfile:
    cat << EOF > Dockerfile
    # Use the official Python image
    FROM python:3.13-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
    
    # Run the FastMCP server
    CMD ["uv", "run", "server.py"]
    EOF
    
  2. สร้างบัญชีบริการที่กำหนดสำหรับเซิร์ฟเวอร์ โดยทำดังนี้
    gcloud iam service-accounts create zoo-mcp-server-sa \
        --display-name="Zoo MCP Server Service Account"
    
  3. ติดตั้งใช้งานเซิร์ฟเวอร์ในภูมิภาค us-west1
    gcloud run deploy zoo-mcp-server \
        --service-account=zoo-mcp-server-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
        --region=us-west1 \
        --source=. \
        --labels=dev-tutorial=codelab-dynamic-mcp-discovery \
        --invoker-iam-check \
        --no-allow-unauthenticated
    
    หากเห็นข้อความแจ้งต่อไปนี้ ให้ยืนยันการสร้างที่เก็บ Artifact Registry ใหม่ ข้อความแจ้งนี้จะแสดงขึ้นหากคุณไม่มีที่เก็บ Artifact Registry ในโปรเจ็กต์สำหรับภูมิภาค us-west1
    Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named
    [cloud-run-source-deploy] in region [us-west1] will be created.
    
    Do you want to continue (Y/n)?
    
  4. ลงทะเบียนเซิร์ฟเวอร์ MCP ใน Agent Registry ที่ตำแหน่ง "global" โดยทำดังนี้
    fastmcp inspect server.py --format mcp | jq 'del(..|nulls) | del(.tools[]?._meta?)' > toolspec.json
    MCP_URL=$(gcloud run services describe zoo-mcp-server --region=us-west1 --format='value(status.url)')
    gcloud agent-registry services create zoo-mcp-server \
        --display-name="zoo-mcp-server" \
        --project="${GOOGLE_CLOUD_PROJECT}" \
        --location=global \
        --mcp-server-spec-type="tool-spec" \
        --mcp-server-spec-content="toolspec.json" \
        --interfaces="url=${MCP_URL}/mcp,protocolBinding=jsonrpc"
    
    คำสั่งเหล่านี้จะสร้าง toolspec.json พร้อมไฟล์ Manifest ของเครื่องมือและเรียกใช้ Agent Registry API เพื่อลงทะเบียนเซิร์ฟเวอร์
  5. ตรวจสอบว่า Agent ปรากฏในรีจิสทรีโดยทำดังนี้
    gcloud agent-registry mcp-servers list \
        --location=global \
        --filter="display_name=zoo-mcp-server"
    
    คุณจะเห็นเอาต์พุต YAML ที่มีข้อมูลเซิร์ฟเวอร์ MCP ดังนี้
    ---
    attributes:
      agentregistry.googleapis.com/system/RuntimeReference:
        uri: //agentregistry.googleapis.com/projects/[PROJECT_NUMBER]/locations/global/services/zoo-mcp-server
    createTime: '<create time datetime in ISO 8601>'
    displayName: zoo-mcp-server
    interfaces:
    - protocolBinding: JSONRPC
      url: https://zoo-mcp-server-[PROJECT_NUMBER].us-west1.run.app/mcp
    mcpServerId: urn:mcp:projects-[PROJECT_NUMBER]:projects:[PROJECT_NUMBER]:locations:global:agentregistry:services:zoo-mcp-server
    name: projects/[PROJECT_ID]/locations/global/mcpServers/agentregistry-00000000-0000-0000-1234-56789abcdef
    tools:
    - annotations:
        idempotentHint: true
        readOnlyHint: true
      description: |-
        Returns every species in the zoo. Use it first for zoo-wide questions
        such as counting all animals or listing everything the zoo has.
      name: list_species
    - annotations:
        idempotentHint: true
        readOnlyHint: true
      description: |-
        Retrieves all animals of a specific species from the zoo.
        Can also be used to collect the base data for aggregate queries
        of animals of a specific species - like counting the number of penguins
        or finding the oldest lion.
      name: get_animals_by_species
    - annotations:
        idempotentHint: true
        readOnlyHint: true
      description: Retrieves the details of a specific animal by its name.
      name: get_animal_details
    updateTime: '<last updated datetime in ISO 8601>'
    

4. สร้าง ADK Agent พื้นฐานเพื่อใช้เซิร์ฟเวอร์ MCP ของสวนสัตว์

ในขั้นตอนนี้ คุณจะสร้าง ADK Agent เพื่อตอบคำขอของผู้ใช้เกี่ยวกับสวนสัตว์ด้วยความช่วยเหลือจาก URL ของเซิร์ฟเวอร์ MCP ของสวนสัตว์ที่ฮาร์ดโค้ดไว้ การฮาร์ดโค้ดจะบังคับให้คุณต้องทราบ URL ของเซิร์ฟเวอร์ MCP ก่อนที่จะติดตั้งใช้งาน Agent

คุณดูไฟล์ต้นฉบับสำหรับขั้นตอนนี้ได้ใน GitHub

สร้างแอปพลิเคชัน Agent

สร้างโครงสร้างของโปรเจ็กต์ ADK และ Agent สวนสัตว์ที่ใช้เซิร์ฟเวอร์ MCP ของสวนสัตว์

  1. ตั้งค่าโฟลเดอร์และโปรเจ็กต์สำหรับ Agent ของ Zoo ดังนี้
    mkdir ../sample-agent && cd ../sample-agent
    uv init --description "Example of ADK agent to showcase dynamic MCP discovery" --bare --python 3.13
    uv add "google-adk[mcp,a2a,agent-identity]>=2.5.0,<3.0.0" --no-sync
    
  2. สร้างโฟลเดอร์แพ็กเกจ Agent และดาวน์โหลดไฟล์ __init__.py โดยทำดังนี้
    mkdir zoo_agent
    curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step4/zoo_agent/__init__.py -o zoo_agent/__init__.py
    
  3. สร้างไฟล์ .env และป้อนตัวแปรสภาพแวดล้อมที่ใช้ในขั้นตอนนี้และขั้นตอนต่อไปนี้
    MCP_URL=$(gcloud run services describe zoo-mcp-server --region=us-west1 --format='value(status.url)')
    cat << EOF > zoo_agent/.env
    GOOGLE_GENAI_USE_ENTERPRISE=TRUE
    GOOGLE_CLOUD_LOCATION=global
    GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT}"
    GOOGLE_CLOUD_PROJECT_NUMBER=$(gcloud projects describe ${GOOGLE_CLOUD_PROJECT} \
       --format='value(projectNumber)')
    MCP_SERVER_URL="${MCP_URL}"
    EOF
    
    คำสั่งนี้จะเขียนตัวแปรสภาพแวดล้อมทั้งหมดที่จำเป็นในขั้นตอนนี้และขั้นตอนการค้นหาที่ตามมาลงใน zoo_agent/.env คุณจึงไม่จำเป็นต้องสร้างไฟล์อีกครั้งในภายหลัง ในขั้นตอนนี้ ระบบจะใช้ตัวแปรต่อไปนี้
    • GOOGLE_GENAI_USE_ENTERPRISE, GOOGLE_CLOUD_PROJECT และ GOOGLE_CLOUD_LOCATION: ADK และ Google GenAI SDK จะใช้โดยนัยเพื่อกำหนดเส้นทางการเรียกใช้โมเดล Gemini ผ่าน Vertex AI ในโปรเจ็กต์ที่อยู่ในระบบคลาวด์และตำแหน่ง Google Cloud ของคุณ (global) นอกจากนี้ยังจัดเก็บตำแหน่งสำหรับ Agent Registry ที่ลงทะเบียนเซิร์ฟเวอร์ MCP ด้วย
    • GOOGLE_CLOUD_PROJECT_NUMBER: ไม่ได้ใช้ในขั้นตอนนี้ แต่จะป้อนข้อมูลล่วงหน้าที่นี่เพื่อใช้ในขั้นตอนถัดไป
    • MCP_SERVER_URL: อ่านโดยตรงใน zoo_agent/agent.py เพื่อกำหนดค่า McpToolset ด้วย URL ของ Cloud Run ที่ฮาร์ดโค้ดของเซิร์ฟเวอร์ Zoo MCP
  4. ดาวน์โหลด agent.py พร้อมโค้ดสำหรับ Zoo Agent ที่เชื่อมต่อกับเซิร์ฟเวอร์ Zoo MCP:
    curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step4/zoo_agent/agent.py -o zoo_agent/agent.py
    

วิธีการทำงานของการให้สิทธิ์เซิร์ฟเวอร์ MCP

เนื่องจากมีการติดตั้งใช้งานบริการ Cloud Run zoo-mcp-server ด้วยแฟล็ก --invoker-iam-check และ --no-allow-unauthenticated คำขอ HTTP ทุกรายการที่ส่งไปยังเซิร์ฟเวอร์ MCP จึงต้องมีโทเค็นระบุตัวตนที่ลงนามโดย Google ในส่วนหัว Authorization โทเค็นต้องระบุผู้โทรที่มีสิทธิ์ run.routes.invoke ในบริการ

ใน zoo_agent/agent.py คลาส _GoogleAuthHeaders จะได้รับข้อมูลเข้าสู่ระบบของโทเค็นระบุตัวตนด้วยวิธีใดวิธีหนึ่งจาก 2 วิธี ขั้นแรก ระบบจะเรียกใช้ fetch_id_token_credentials() เพื่อรับโทเค็นระบุตัวตนสำหรับ URL ของบริการจากเซิร์ฟเวอร์ข้อมูลเมตาหรือคีย์บัญชีบริการ หากไม่สำเร็จ ระบบจะใช้โทเค็นระบุตัวตนของข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) ของผู้ใช้ ทุกครั้งที่มีการเรียกใช้อินสแตนซ์ ระบบจะรีเฟรชโทเค็นหากจำเป็น และแสดงผลส่วนหัว Authorization ดังนี้

class _GoogleAuthHeaders:
    def __init__(self, audience: str):
        self._request = Request()
        self._id_token = False
        try:
            self._credentials = id_token.fetch_id_token_credentials(audience, request=self._request)
        except exceptions.DefaultCredentialsError:
            self._credentials, _ = google.auth.default()
            self._id_token = True
            if not isinstance(self._credentials, credentials.Credentials):
                raise

    def __call__(self, unused_context: ReadonlyContext | None = None) -> dict[str, str]:
        if not self._credentials.valid or (self._id_token and not self._credentials.id_token):
            self._credentials.refresh(self._request)
        token = self._credentials.id_token if self._id_token else self._credentials.token
        return {"Authorization": f"Bearer {token}"}

Agent จะส่งอินสแตนซ์ของคลาสไปยัง McpToolset เป็นอาร์กิวเมนต์ header_provider ADK จะเรียกใช้ผู้ให้บริการส่วนหัวและแนบส่วนหัวที่แสดงผลไปยังคำขอทุกรายการที่ส่งไปยังเซิร์ฟเวอร์ MCP เนื่องจากไคลเอ็นต์ HTTP สร้างขึ้นโดย ADK โค้ดเดียวกันจึงทำงานได้ไม่ว่าคุณจะติดตั้ง MCP Python SDK และไลบรารี HTTP เวอร์ชันใดก็ตาม

zoo_mcp_toolset = McpToolset(
    connection_params=StreamableHTTPConnectionParams(
        url=f"{MCP_SERVER_URL}/mcp",
        timeout=30.0,
    ),
    header_provider=_GoogleAuthHeaders(MCP_SERVER_URL),
)

กลุ่มเป้าหมายที่ขอคือ URL ของบริการ (MCP_SERVER_URL) ส่วน URL การเชื่อมต่อจะมีเส้นทาง /mcp ที่เซิร์ฟเวอร์ FastMCP แสดงโปรโตคอล MCP ระยะหมดเวลา 30 วินาทีช่วยให้มีเวลาสำหรับ Cold Start ของ Cloud Run

ทดสอบ Agent โดยใช้ Playground ของ ADK ในสภาพแวดล้อมในเครื่อง

ก่อนทดสอบ Agent โปรดตรวจสอบว่าบัญชีผู้ใช้ของคุณเรียกใช้เซิร์ฟเวอร์ MCP ได้

  1. เทอร์มินัลในเครื่องเท่านั้น (ข้ามขั้นตอนนี้ใน Cloud Shell): เริ่มต้น ADC ด้วยข้อมูลเข้าสู่ระบบของผู้ใช้ โดยทำดังนี้
    gcloud auth application-default login
    
    ทำตามวิธีการเพื่อเริ่มต้นใช้งาน ADC ให้เสร็จสมบูรณ์
  2. (ไม่บังคับ) ให้สิทธิ์บัญชีผู้ใช้ในการเรียกใช้เซิร์ฟเวอร์ MCP ระยะไกล โดยทำดังนี้
    gcloud run services add-iam-policy-binding zoo-mcp-server \
       --region=us-west1 \
       --project=${GOOGLE_CLOUD_PROJECT} \
       --member=user:$(gcloud config get-value account) \
       --role='roles/run.invoker'
    
  3. เรียกใช้ Agent ด้วยคำสั่ง adk run ดังนี้
    adk run zoo_agent
    
    หรือเรียกใช้อินเทอร์เฟซเว็บ ADK ด้วยคำสั่ง adk web ดังนี้
    adk web --port 8080
    
    แล้วเปิด URL ที่คำสั่งพิมพ์ในเบราว์เซอร์ หากใช้ Cloud Shell ให้เพิ่มอาร์กิวเมนต์ --allow_origins เพื่ออนุญาตให้เปิดอินเทอร์เฟซเว็บจาก Cloud Shell
    adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
    
    หลังจากเรียกใช้คำสั่งแล้ว ให้ค้นหาไอคอนตัวอย่างเว็บไอคอนตัวอย่างเว็บในแถบเครื่องมือ Cloud Shell (ด้านขวา) คลิกไอคอนดังกล่าว แล้วเลือกแสดงตัวอย่างในพอร์ต 8080 Cloud Shell จะเปิดแท็บเบราว์เซอร์ใหม่ที่แสดงอินเทอร์เฟซเว็บของ ADK
  4. เริ่มแชทกับตัวแทน เช่น ถามเกี่ยวกับสัตว์ในสวนสัตว์
    How many animals are in the zoo?
    
    Agent จะเรียกใช้ list_species แล้วเรียกใช้ get_animals_by_species สำหรับแต่ละสายพันธุ์เพื่อคำนวณคำตอบ

อินเทอร์เฟซเว็บของ ADK ช่วยให้คุณสำรวจวิธีการทำงานของ Agent ได้ รวมถึงการเรียกไปยังเซิร์ฟเวอร์ MCP ของสวนสัตว์ ดูวิธีได้ที่เอกสารประกอบเกี่ยวกับ Web UI

5. ค้นหาปลายทางของเซิร์ฟเวอร์ MCP แบบไดนามิก

ในขั้นตอนนี้ คุณจะเปลี่ยน Agent ให้ค้นหาปลายทางของเซิร์ฟเวอร์ MCP ของสวนสัตว์ที่ลงทะเบียนไว้ใน Agent Registry แทนการฮาร์ดโค้ด URL ปลายทาง

คุณดูไฟล์ทั้งหมดสำหรับขั้นตอนนี้ได้ใน GitHub

คุณใช้การผสานรวม ADK กับ Agent Registry เพื่อค้นหาและดึงข้อมูล URL ของเซิร์ฟเวอร์ คุณต้องมีข้อมูลต่อไปนี้เพื่อติดตั้งใช้งาน

  • หมายเลขโปรเจ็กต์และตำแหน่งของ Agent Registry ที่เซิร์ฟเวอร์ MCP ของคุณลงทะเบียนไว้ (global)
  • รหัสบริการที่คุณใช้ลงทะเบียนเซิร์ฟเวอร์ MCP (zoo-mcp-server)

อัปเดตตัวแทนเพื่อใช้ Agent Registry

  1. ดาวน์โหลดไฟล์ agent.py ที่อัปเดตแล้วจาก GitHub เพื่อลบล้าง Agent เวอร์ชันแรก
    curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step5/zoo_agent/agent.py -o zoo_agent/agent.py
    

    ตัวแปรสภาพแวดล้อมในขั้นตอนนี้

    ในการอัปเดตนี้ Agent จะใช้ตัวแปรสภาพแวดล้อมต่อไปนี้จาก zoo_agent/.env
    • GOOGLE_CLOUD_PROJECT_NUMBER: ตอนนี้จำเป็นต้องสร้าง URN ข้อมูลประจำตัวของเซิร์ฟเวอร์ MCP (MCP_SERVER_URN)
    • GOOGLE_CLOUD_PROJECT, GOOGLE_GENAI_USE_ENTERPRISE และ GOOGLE_CLOUD_LOCATION: ADK ใช้เพื่อกำหนดค่าการเข้าถึง Vertex AI นอกจากนี้ ระบบยังใช้ตำแหน่งเพื่อค้นหาเซิร์ฟเวอร์ MCP ด้วย
    • ไม่จำเป็นต้องใช้แล้ว: ระบบจะไม่ใช้ MCP_SERVER_URL อีกต่อไปเนื่องจาก Agent จะดึงข้อมูล URL ปลายทางของเซิร์ฟเวอร์ MCP จาก Agent Registry แทนที่จะอ่านจากสภาพแวดล้อม

    วิธีการทำงานของข้อมูลระบุตัวตนและการค้นพบเซิร์ฟเวอร์ MCP ใน AgentRegistry

    ใน Agent Registry เซิร์ฟเวอร์ MCP ที่ลงทะเบียนแต่ละเครื่องจะมีตัวระบุที่ไม่ซ้ำกันซึ่งจัดเก็บไว้ในช่อง mcpServerId โดยจัดรูปแบบเป็น Uniform Resource Name (URN) คุณจะเห็นรหัสดังกล่าวในเอาต์พุตของคำสั่ง gcloud agent-registry mcp-servers list ในขั้นตอนที่ 3 ตัวแทนจะสร้างตัวระบุนี้ขึ้นใหม่จากตัวแปรสภาพแวดล้อม ดังนี้
    PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"]
    PROJECT_NUMBER = os.environ["GOOGLE_CLOUD_PROJECT_NUMBER"]
    LOCATION = os.environ.get("GOOGLE_CLOUD_LOCATION", "global")
    MCP_SERVER_URN = f"urn:mcp:projects-{PROJECT_NUMBER}:projects:{PROJECT_NUMBER}:locations:{LOCATION}:agentregistry:services:zoo-mcp-server"
    
    URN จะเข้ารหัสหมายเลขโปรเจ็กต์ของรีจิสทรี (projects-{PROJECT_NUMBER}) หมายเลขโปรเจ็กต์และตำแหน่งที่ลงทะเบียนเซิร์ฟเวอร์ (projects:{PROJECT_NUMBER}:locations:{LOCATION}) และรหัสบริการที่คุณใช้ในคำสั่ง gcloud agent-registry services create (agentregistry:services:zoo-mcp-server) ตัวแทนจะแสดงรายการเซิร์ฟเวอร์ MCP ที่ลงทะเบียนด้วย registry.list_mcp_servers() และจับคู่ mcpServerId ของเซิร์ฟเวอร์แต่ละเครื่องกับ MCP_SERVER_URN จากนั้นจะส่งทรัพยากร name (projects/.../locations/.../mcpServers/...) ของเซิร์ฟเวอร์ที่ตรงกันไปยัง registry.get_mcp_toolset() ซึ่งจะอ่าน URL ปลายทางจากอินเทอร์เฟซที่ลงทะเบียนของเซิร์ฟเวอร์ (https://...run.app/mcp) และแสดงผล McpToolset ที่เชื่อมต่อกับ URL ดังกล่าว
    header_provider = _GoogleAuthHeaders()
    registry = AgentRegistry(
        project_id=PROJECT_ID,
        location=LOCATION,
        header_provider=header_provider,
    )
    
    mcp_server_name = next(
        (
            s["name"]
            for s in registry.list_mcp_servers().get("mcpServers", [])
            if s.get("mcpServerId") == MCP_SERVER_URN
        ),
        None,
    )
    if not mcp_server_name:
        raise RuntimeError(f"MCP server '{MCP_SERVER_URN}' not found in Agent Registry.")
    zoo_mcp_toolset = registry.get_mcp_toolset(mcp_server_name=mcp_server_name)
    header_provider.bind(zoo_mcp_toolset.connection_params.url)
    zoo_mcp_toolset.connection_params.timeout = 30.0
    
    get_mcp_toolset() จะใส่ชื่อที่แสดงของเซิร์ฟเวอร์ไว้หน้าชื่อเครื่องมือ เพื่อให้ Agent เห็นเครื่องมือเป็น zoo_mcp_server_list_species, zoo_mcp_server_get_animals_by_species และ zoo_mcp_server_get_animal_details คำนำหน้าจะช่วยป้องกันไม่ให้ชื่อซ้ำกันเมื่อ Agent ใช้เครื่องมือจากเซิร์ฟเวอร์ MCP หลายเครื่อง บรรทัดสุดท้ายจะเพิ่มระยะหมดเวลาการเชื่อมต่อจากค่าเริ่มต้น 5 วินาทีเพื่อให้มีเวลาสำหรับ Cold Start ของ Cloud Run

    การให้สิทธิ์เปลี่ยนแปลงไปอย่างไรเมื่อใช้ AgentRegistry

    AgentRegistry ตรวจสอบสิทธิ์การเรียก API ของตนเอง เช่น list_mcp_servers() ด้วย ADC ดังนั้นจึงจำเป็นต้องใช้ผู้ให้บริการส่วนหัวสำหรับการเรียกไปยังเซิร์ฟเวอร์ MCP ที่ค้นพบเท่านั้น เนื่องจาก AgentRegistry สร้าง McpToolset ภายใน คุณจึงส่งผู้ให้บริการส่วนหัวไปยังคอนสตรัคเตอร์ AgentRegistry ในขั้นตอนก่อนหน้า กลุ่มเป้าหมายคือค่า MCP_SERVER_URL ที่คุณทราบล่วงหน้า ตอนนี้ URL จะเป็นที่รู้จักหลังจากการค้นพบเท่านั้น ADK จะเรียกใช้ผู้ให้บริการส่วนหัวเมื่อ Agent ส่งคำขอไปยังเซิร์ฟเวอร์ MCP ไม่ใช่เมื่อสร้าง AgentRegistry ซึ่งจะช่วยให้ Agent สร้างผู้ให้บริการก่อนและเชื่อมโยงกับปลายทางที่ค้นพบหลังจาก get_mcp_toolset() แสดงผล เมธอด bind() จะรับข้อมูลเข้าสู่ระบบในลักษณะเดียวกับคอนสตรัคเตอร์ในขั้นตอนก่อนหน้า โดยกลุ่มเป้าหมายจะนำมาจาก URL ปลายทางที่ค้นพบโดยไม่มีเส้นทาง /mcp ดังนี้
        def bind(self, endpoint_url: str) -> None:
            parsed = urlparse(endpoint_url)
            audience = f"{parsed.scheme}://{parsed.netloc}"
            try:
                self._credentials = id_token.fetch_id_token_credentials(audience, request=self._request)
            except exceptions.DefaultCredentialsError:
                self._credentials, _ = google.auth.default()
                self._id_token = True
                if not isinstance(self._credentials, credentials.Credentials):
                    raise
    
    เมธอด __call__ จะเหมือนกับในขั้นตอนก่อนหน้า ยกเว้นว่าจะแสดงข้อผิดพลาดหากมีการเรียกใช้ก่อน bind()
  2. เรียกใช้ Agent เพื่อทดสอบการเปลี่ยนแปลง ใช้คำสั่ง adk run ดังนี้
    adk run zoo_agent
    
    หรือเรียกใช้อินเทอร์เฟซเว็บ ADK ด้วยคำสั่ง adk web ดังนี้
    adk web --port 8080
    
    แล้วเปิด URL ที่คำสั่งพิมพ์ในเบราว์เซอร์ หากใช้ Cloud Shell ให้เพิ่มอาร์กิวเมนต์ --allow_origins เพื่ออนุญาตให้เปิดอินเทอร์เฟซเว็บจาก Cloud Shell
    adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
    
    ถามคำถามเดียวกับในขั้นตอนก่อนหน้ากับตัวแทน คำตอบยังคงเหมือนเดิม แต่ในอินเทอร์เฟซเว็บของ ADK การเรียกใช้เครื่องมือจะปรากฏเป็น zoo_mcp_server_list_species และ zoo_mcp_server_get_animals_by_species

การเปลี่ยนแปลงนี้ช่วยให้คุณไม่ต้องใช้ URL ของเซิร์ฟเวอร์ MCP ที่ชัดเจน อย่างไรก็ตาม คุณยังคงต้องทราบหมายเลขโปรเจ็กต์ ตำแหน่งรีจิสทรี และรหัสบริการที่ใช้ลงทะเบียนเซิร์ฟเวอร์ MCP และการค้นพบจะดำเนินการแบบคงที่ระหว่างการเริ่มต้น Agent

6. ใช้การค้นหาเชิงความหมายสำหรับเซิร์ฟเวอร์ MCP ในการค้นพบแบบไดนามิก

ในขั้นตอนนี้ คุณจะปรับปรุงการค้นพบแบบไดนามิกของเซิร์ฟเวอร์ MCP โดยแทนที่การจับคู่ URN แบบตรงทั้งหมดเมื่อเริ่มต้นระบบด้วยการค้นหาเชิงความหมายขณะรันไทม์ วิธีนี้ช่วยให้ไม่จำเป็นต้องทราบหมายเลขโปรเจ็กต์ที่มีการติดตั้งใช้งานเซิร์ฟเวอร์หรือข้อมูลประจำตัวที่แน่นอนของเซิร์ฟเวอร์ (MCP_SERVER_URN) และผสานรวมการค้นพบเครื่องมือเข้ากับเวิร์กโฟลว์รันไทม์มาตรฐานของ Agent โดยตรง แทนที่จะจัดการที่การเริ่มต้น

คุณดูไฟล์ทั้งหมดสำหรับขั้นตอนนี้ได้ใน GitHub

อัปเดต Agent ให้ใช้การค้นหาเชิงความหมายที่รันไทม์

  1. ดาวน์โหลดไฟล์ agent.py ที่อัปเดตแล้วจาก GitHub เพื่อเขียนทับการติดตั้งใช้งานที่มีอยู่ โดยทำดังนี้
    curl -fsSL https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/codelabs/agent-registry-dynamic-discovery-with-adk/steps/step6/zoo_agent/agent.py -o zoo_agent/agent.py
    

    ตัวแปรสภาพแวดล้อมในขั้นตอนนี้

    เนื่องจาก Agent ไม่ได้สร้าง URN ของเซิร์ฟเวอร์ MCP อีกต่อไป การกำหนดค่าที่จำเป็นจึงง่ายขึ้นไปอีก ดังนี้
    • GOOGLE_CLOUD_PROJECT, GOOGLE_GENAI_USE_ENTERPRISE และ GOOGLE_CLOUD_LOCATION: ADK ใช้เพื่อกำหนดค่าการเข้าถึง Vertex AI นอกจากนี้ ระบบยังใช้ตำแหน่งเพื่อค้นหาเซิร์ฟเวอร์ MCP ด้วย
    • ไม่จำเป็นอีกต่อไป: ไม่จำเป็นต้องใช้ GOOGLE_CLOUD_PROJECT_NUMBER อีกต่อไป (นอกเหนือจาก MCP_SERVER_URL ซึ่งนำออกไปแล้วในขั้นตอนก่อนหน้า)
    แทนที่จะเรียกใช้ registry.list_mcp_servers() ระหว่างการเริ่มต้นโมดูลและเปรียบเทียบแต่ละรายการกับ MCP_SERVER_URN ที่สร้างขึ้น ตอนนี้ agent.py จะกำหนดฟังก์ชันเครื่องมือการค้นพบ discover_zoo_mcp_servers ที่เรียกใช้ registry.search_mcp_servers() ด้วย search_type="SEMANTIC":
    def discover_zoo_mcp_servers(query: str, tool_context: ToolContext) -> dict[str, Any]:
        """Discovers Zoo MCP server(s) matching the query using semantic search.
    
        Args:
            query: Semantic description of zoo capabilities needed (e.g. 'zoo animal info')
        """
        cached = _fresh_discovery(tool_context.state)
        if cached:
            return {
                "status": "already_discovered",
                "message": "Zoo MCP servers are already discovered.",
                "servers": cached["servers"],
            }
    
        try:
            response = registry.search_mcp_servers(
                search_string=query,
                search_type="SEMANTIC",
                page_size=5,
            )
        except Exception as e:
            return {
                "status": "error",
                "message": f"Agent Registry search failed: {e}",
            }
    
        found_servers = response.get("mcpServers", [])
        if not found_servers:
            return {
                "status": "not_found",
                "message": f"No MCP servers found in Agent Registry at {LOCATION} matching '{query}'.",
            }
    
        valid_servers = [s["name"] for s in found_servers if "name" in s]
        tool_context.state[DISCOVERY_STATE_KEY] = {
            "servers": valid_servers,
            "discovered_at": time.time(),
        }
        return {
            "status": "discovered",
            "message": f"Successfully discovered {len(valid_servers)} Zoo MCP server(s).",
            "servers": valid_servers,
        }
    
    ซึ่งจะช่วยให้ Agent ค้นหา Agent Registry ได้ที่รันไทม์โดยใช้คำอธิบายภาษาธรรมชาติเกี่ยวกับความสามารถที่ต้องการ (เช่น "zoo animals, exhibits, habitat, care, feeding schedule") และบันทึกชื่อทรัพยากรเซิร์ฟเวอร์ที่ค้นพบไว้ในสถานะเซสชัน ADK (tool_context.state)

    วิธีผสานรวมการค้นพบแบบไดนามิกเข้ากับเวิร์กโฟลว์ของ Agent

    หากต้องการต่อเชื่อมเครื่องมือจากเซิร์ฟเวอร์ที่ค้นพบขณะรันไทม์และแนะนำ Agent ผ่านขั้นตอนการค้นพบแล้วเรียกใช้ agent.py จะรวมการติดตั้งใช้งาน BaseToolset ที่กำหนดเอง (RegistryDiscoveredToolset) เข้ากับผู้ให้บริการคำสั่งแบบไดนามิก (zoo_guide_instruction) ดังนี้
    1. ชุดเครื่องมือแบบไดนามิก (RegistryDiscoveredToolset): คลาสย่อย BaseToolset และตั้งค่า self._use_invocation_cache = False เพื่อให้ ADK ประเมินเครื่องมือที่ใช้ได้อีกครั้งทันทีหลังจาก discover_zoo_mcp_servers อัปเดตสถานะเซสชัน แทนที่จะแคชรายการเครื่องมือที่ว่างเปล่าในตอนแรก เมื่อเรียกใช้ get_tools() ระบบจะอ่านชื่อเซิร์ฟเวอร์ที่ค้นพบจากสถานะ สร้าง McpToolset ที่ตรวจสอบสิทธิ์แล้วสำหรับเซิร์ฟเวอร์แต่ละรายการในเทรดผู้ปฏิบัติงาน และแสดงเครื่องมือที่ใช้งานอยู่ทั้งหมด การเข้าถึงเซิร์ฟเวอร์หนึ่งไม่สำเร็จจะไม่ส่งผลต่อเซิร์ฟเวอร์อื่นๆ _build_toolset() ดำเนินการ I/O แบบบล็อก ดังนั้น _tools_of() จึงเรียกใช้ในเทรดผู้ปฏิบัติงาน
      class RegistryDiscoveredToolset(BaseToolset):
          def __init__(self, agent_registry: AgentRegistry):
              super().__init__()
              self._registry = agent_registry
              self._toolsets: dict[str, McpToolset] = {}
              self._use_invocation_cache = False
      
          def _build_toolset(self, server_name: str) -> McpToolset:
              header_provider = _GoogleAuthHeaders()
              server_registry = AgentRegistry(
                  project_id=self._registry.project_id,
                  location=self._registry.location,
                  header_provider=header_provider,
              )
              toolset = server_registry.get_mcp_toolset(server_name)
              header_provider.bind(toolset.connection_params.url)
              toolset.connection_params.timeout = 30.0
              return toolset
      
          async def _tools_of(self, server_name: str, ctx: ReadonlyContext) -> list[BaseTool]:
              try:
                  if server_name not in self._toolsets:
                      self._toolsets[server_name] = await asyncio.to_thread(
                          self._build_toolset, server_name
                      )
                  return await self._toolsets[server_name].get_tools_with_prefix(ctx)
              except Exception as e:
                  print(f"Skipping MCP server {server_name}: {e}")
                  return []
      
          async def get_tools(self, readonly_context: ReadonlyContext | None = None) -> list[BaseTool]:
              if not readonly_context:
                  return []
              record = _fresh_discovery(readonly_context.state)
              if not record or not record.get("servers"):
                  if self._toolsets:
                      await self.close()
                  return []
              per_server = await asyncio.gather(
                  *(self._tools_of(name, readonly_context) for name in record["servers"])
              )
              return [tool for tools in per_server for tool in tools]
      
    2. คำสั่ง Agent แบบไดนามิก (zoo_guide_instruction): ประเมินสถานะเซสชันก่อนแต่ละเทิร์นของโมเดล เมื่อยังไม่พบเซิร์ฟเวอร์ ระบบจะเพิ่ม _DISCOVERY_PROMPT เพื่อสั่งให้ Agent เรียกใช้ discover_zoo_mcp_servers ก่อน เมื่อการค้นพบสำเร็จ ระบบจะอัปเดตพรอมต์เพื่อแสดงรายการเซิร์ฟเวอร์ MCP ที่ใช้งานอยู่ และสั่งให้ Agent ใช้เครื่องมือสวนสัตว์ที่ต่อเชื่อมโดยตรงโดยไม่ต้องเรียกใช้การค้นพบอีกครั้ง
      def zoo_guide_instruction(ctx: ReadonlyContext) -> str:
          record = _fresh_discovery(ctx.state)
          if record is None:
              return _ROLE + _DISCOVERY_PROMPT
          return _ROLE + (
              f"\nYour active Zoo MCP servers: {', '.join(record['servers'])}. "
              "Do not run discovery again; use the active zoo tools directly to fulfill the visitor's request."
          )
      

    การให้สิทธิ์สำหรับเซิร์ฟเวอร์ที่ค้นพบแบบไดนามิก

    การค้นหาเชิงความหมายสามารถแสดงผลเซิร์ฟเวอร์ได้หลายรายการ และ ADK จะเรียกใช้ผู้ให้บริการส่วนหัวโดยไม่บอกว่าคำขอจะส่งไปยังเซิร์ฟเวอร์ใด ดังนั้น _build_toolset() จึงสร้าง _GoogleAuthHeaders และ AgentRegistry เฉพาะสำหรับเซิร์ฟเวอร์ที่ค้นพบแต่ละรายการ และเชื่อมโยงผู้ให้บริการกับปลายทางของเซิร์ฟเวอร์นั้น ผู้ให้บริการจะเหมือนกับในขั้นตอนก่อนหน้า โดยมีแฟล็ก _bound ที่ทำให้ดำเนินการไม่สำเร็จหากใช้ก่อน bind()

    ตรรกะการเก็บรักษาและการรีเฟรช

    เพื่อหลีกเลี่ยงการค้นหา Agent Registry ในทุกรอบขณะที่ยังคงรีเฟรชปลายทางที่ค้นพบเป็นระยะๆ agent.py จะใช้การเก็บรักษาสถานะด้วย Time-to-Live (TTL) ดังนี้
    DISCOVERY_STATE_KEY = "app:zoo_mcp_servers"
    DISCOVERY_TTL_SECONDS = 24 * 60 * 60
    
    def _fresh_discovery(state: Any) -> dict[str, Any] | None:
        if not state:
            return None
        record = state.get(DISCOVERY_STATE_KEY)
        if not record or not record.get("servers"):
            return None
        if time.time() - record.get("discovered_at", 0) > DISCOVERY_TTL_SECONDS:
            return None
        return record
    
    • การเก็บรักษาที่กำหนดขอบเขตระดับแอปพลิเคชัน: ชื่อเซิร์ฟเวอร์ที่ค้นพบและการประทับเวลา discovered_at จะจัดเก็บไว้ในสถานะเซสชันภายใต้คีย์ app:zoo_mcp_servers การใช้คำนำหน้า app: ของ ADK จะกำหนดขอบเขตของระเบียนการค้นพบที่แคชไว้ตลอดการเรียกใช้แอปพลิเคชัน
    • การตรวจสอบ TTL และการรีเฟรชอัตโนมัติ: _fresh_discovery() จะยืนยันว่ามีระเบียนที่บันทึกไว้และอายุของระเบียนไม่เกิน DISCOVERY_TTL_SECONDS (24 ชั่วโมง) ขณะที่ระเบียนยังใหม่อยู่ RegistryDiscoveredToolset จะใช้การเชื่อมต่อ McpToolset ที่แคชไว้ (self._toolsets) ซ้ำ zoo_guide_instruction จะข้ามพรอมต์การค้นพบ และการเรียกซ้ำไปยัง discover_zoo_mcp_servers จะแสดงผล "already_discovered" ทันที เมื่อ TTL 24 ชั่วโมงหมดอายุ _fresh_discovery() จะแสดงผล None ซึ่งทำให้ RegistryDiscoveredToolset.get_tools() ปิดเซสชันไคลเอ็นต์ MCP ที่มีอยู่ (await self.close()) และ zoo_guide_instruction จะแจ้งให้ Agent ทำการค้นหาใหม่
  2. เรียกใช้ Agent เพื่อทดสอบเวิร์กโฟลว์การค้นพบเชิงความหมาย ใช้คำสั่ง adk run ดังนี้
    adk run zoo_agent
    
    หรือเรียกใช้อินเทอร์เฟซเว็บ ADK ด้วยคำสั่ง adk web ดังนี้
    adk web --port 8080
    
    แล้วเปิด URL ที่คำสั่งพิมพ์ในเบราว์เซอร์ หากใช้ Cloud Shell ให้เพิ่มอาร์กิวเมนต์ --allow_origins เพื่ออนุญาตให้เปิดอินเทอร์เฟซเว็บจาก Cloud Shell
    adk web --port 8080 --allow_origins="regex:https://.*\.cloudshell\.dev"
    
    เมื่อคุณถามคำถาม Agent เกี่ยวกับสวนสัตว์ (เช่น How many animals are in the zoo?) ให้สังเกตว่า Agent จะเรียกใช้ discover_zoo_mcp_servers ก่อน จากนั้นจะต่อเชื่อมเครื่องมือจากเซิร์ฟเวอร์ MCP ที่ค้นพบแบบไดนามิก แล้วเรียกใช้เครื่องมือสวนสัตว์ เช่น zoo_mcp_server_list_species และ zoo_mcp_server_get_animals_by_species เพื่อตอบคำถามของคุณ ลองถามคำถามติดตามผล เช่น Which is the oldest lion? Agent จะตอบโดยใช้เครื่องมือ Zoo ที่ต่อเชื่อมอยู่แล้ว และจะไม่เรียกใช้ discover_zoo_mcp_servers อีกครั้ง เนื่องจากระเบียนการค้นพบในสถานะเซสชันยังคงเป็นปัจจุบันอยู่

7. ล้างข้อมูล

ตัวเลือกที่ 1: ลบโปรเจ็กต์

หากคุณสร้างโปรเจ็กต์เฉพาะสำหรับ Codelab นี้ วิธีที่ง่ายที่สุดในการกำจัดการเรียกเก็บเงินคือการลบโปรเจ็กต์ โดยทำดังนี้

gcloud projects delete "${GOOGLE_CLOUD_PROJECT}" --quiet

ตัวเลือกที่ 2: ลบทรัพยากรทีละรายการ

หากคุณใช้โปรเจ็กต์ที่มีอยู่และต้องการเก็บไว้ ให้ลบทรัพยากรแต่ละรายการที่สร้างขึ้นระหว่าง Codelab นี้ โดยทำดังนี้

  1. ลบการลงทะเบียนเซิร์ฟเวอร์ MCP ออกจาก Agent Registry เนื่องจากคุณลงทะเบียนเซิร์ฟเวอร์ด้วยตนเอง การลบบริการ Cloud Run จึงไม่ได้นำการลงทะเบียนออก
    gcloud agent-registry services delete zoo-mcp-server \
        --location=global \
        --project="${GOOGLE_CLOUD_PROJECT}" \
        --quiet
    
  2. ลบบริการเซิร์ฟเวอร์ MCP ของ Cloud Run โดยทำดังนี้
    gcloud run services delete zoo-mcp-server \
        --region=us-west1 \
        --project="${GOOGLE_CLOUD_PROJECT}" \
        --quiet
    
  3. ลบบัญชีบริการที่สร้างขึ้นสำหรับเซิร์ฟเวอร์ MCP โดยทำดังนี้
    gcloud iam service-accounts delete \
        "zoo-mcp-server-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
        --project="${GOOGLE_CLOUD_PROJECT}" \
        --quiet
    
  4. หากสร้างที่เก็บ Artifact Registry cloud-run-source-deploy ขึ้นมาโดยเฉพาะในระหว่างที่ทำ Codelab นี้ ให้ลบที่เก็บดังกล่าวเพื่อหลีกเลี่ยงค่าใช้จ่ายในการจัดเก็บอิมเมจคอนเทนเนอร์ โดยทำดังนี้
    gcloud artifacts repositories delete cloud-run-source-deploy \
        --location=us-west1 \
        --project="${GOOGLE_CLOUD_PROJECT}" \
        --quiet
    
  5. (ไม่บังคับ) นำไดเรกทอรีโปรเจ็กต์ที่อยู่ในเครื่องที่สร้างใน Cloud Shell ออกโดยทำดังนี้
    cd ~ && rm -rf adk-dynamic-discovery
    

8. ขอแสดงความยินดี

ใน Codelab นี้ คุณได้เรียนรู้วิธีค้นหาและใช้เซิร์ฟเวอร์ MCP แบบไดนามิกด้วย Google Cloud Agent Registry และ Agent Development Kit (ADK) ดังนี้

  1. ลงทะเบียนเซิร์ฟเวอร์ MCP: ติดตั้งใช้งานเซิร์ฟเวอร์ MCP ที่ปลอดภัยใน Cloud Run และลงทะเบียนใน Agent Registry
  2. ค้นพบเซิร์ฟเวอร์ MCP ตามข้อมูลระบุตัวตน: แก้ไขปลายทางของเซิร์ฟเวอร์ MCP จาก Agent Registry แทนการฮาร์ดโค้ด URL
  3. ค้นพบเซิร์ฟเวอร์ MCP ตามความหมาย: อนุญาตให้ Agent ค้นหาและต่อเชื่อมเครื่องมือ MCP ขณะรันไทม์โดยใช้การค้นหาด้วยภาษาธรรมชาติ พร้อมการเก็บรักษาและการรีเฟรช

ขั้นตอนถัดไป