תחילת העבודה עם MCP, ‏ ADK ו-A2A

1. סקירה כללית

הפופולריות של סוכני AI גדלה במהירות, והם משנים את האופן שבו משימות מבוצעות באופן אוטומטי והחלטות מתקבלות. הם יכולים לפעול באופן אוטונומי, ללמוד ולקיים אינטראקציה עם הסביבה כדי להשיג יעדים.

אבל איך בדיוק יוצרים סוכן? בשיעור הזה של Codelab נסביר איך ליצור סוכן מטבע שיכול להמיר בין מטבעות של מדינות שונות. המטרה היא להסביר על הטכנולוגיות העדכניות כדי לעזור לכם להבין את ראשי התיבות שראיתם באינטרנט (MCP, ‏ ADK, ‏ A2A).

ארכיטקטורה

Model Context Protocol (MCP)

Model Context Protocol (פרוטוקול הקשר של מודל, MCP) הוא פרוטוקול פתוח שמגדיר איך אפליקציות מספקות הקשר ל-LLM. ‫MCP מספק דרך סטנדרטית לחבר מודלים של AI למשאבים, להנחיות ולכלים.

ערכת פיתוח של סוכנים (ADK)

Agent Development Kit (ADK) היא מסגרת גמישה לניהול תהליכים, שמאפשרת לפתח ולפרוס סוכני AI. ה-ADK לא תלוי במודל או בפריסה, והוא מיועד לתאימות למסגרות אחרות. ה-ADK נועד להפוך את פיתוח הסוכנים לתהליך שדומה יותר לפיתוח תוכנה, כדי להקל על מפתחים ליצור, לפרוס ולתזמר ארכיטקטורות של סוכנים שמבצעות משימות פשוטות ועד תהליכי עבודה מורכבים.

פרוטוקול Agent2Agent (A2A)

הפרוטוקול Agent2Agent (A2A) הוא תקן פתוח שנועד לאפשר תקשורת ושיתוף פעולה חלקים בין סוכני AI. בדומה ל-MCP שמספק דרך סטנדרטית לתת למודלים גדולים של שפה (LLM) גישה לנתונים ולכלים, A2A מספק דרך סטנדרטית לסוכנים לתקשר עם סוכנים אחרים. בעולם שבו סוכנים נבנים באמצעות מסגרות מגוונות ועל ידי ספקים שונים, A2A מספק שפה משותפת, מבטל את הבידוד ומקדם יכולת פעולה הדדית.

מה תלמדו

  • איך יוצרים שרת MCP מקומי
  • פריסת שרת ה-MCP ב-Cloud Run
  • איך יוצרים סוכן באמצעות ערכה לפיתוח סוכנים שמשתמשת בכלים של MCP
  • איך חושפים סוכן ADK כשרת A2A
  • בדיקת שרת A2A באמצעות לקוח A2A

מה נדרש

  • דפדפן, כמו Chrome או Firefox
  • פרויקט ב-Google Cloud שהחיוב בו מופעל.

‫2. לפני שמתחילים

יצירת פרויקט

  1. במסוף Google Cloud, בדף לבחירת הפרויקט, בוחרים או יוצרים פרויקט ב-Google Cloud.
  2. הקפידו לוודא שהחיוב מופעל בפרויקט שלכם ב-Cloud. כך בודקים אם החיוב מופעל בפרויקט
  3. לוחצים על הקישור כדי להפעיל את Cloud Shell. אפשר לעבור בין Cloud Shell Terminal (כדי להפעיל פקודות בענן) לבין Editor (כדי ליצור פרויקטים) בלחיצה על הכפתור המתאים ב-Cloud Shell.
  4. אחרי שמתחברים ל-Cloud Shell, בודקים שכבר בוצע אימות ושהפרויקט מוגדר למזהה הפרויקט באמצעות הפקודה הבאה:
gcloud auth list
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט.
gcloud config list project
  1. משתמשים בפקודה הבאה כדי להגדיר את הפרויקט:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
  1. מפעילים את ממשקי ה-API הנדרשים באמצעות הפקודה הבאה. היא עשויה להימשך כמה דקות.
gcloud services enable cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       aiplatform.googleapis.com \
                       compute.googleapis.com
  1. מוודאים שמותקנת גרסה Python 3.10 ומעלה

אפשר לעיין במאמרי העזרה בנושא פקודות gcloud ושימוש בהן.

3. התקנה

  1. משכפלים את המאגר:
git clone https://github.com/jackwotherspoon/currency-agent.git
cd currency-agent
  1. מתקינים את uv (משמש לניהול יחסי תלות):
# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (uncomment below line)
# powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
  1. הגדרת משתני סביבה (באמצעות קובץ .env):

יוצרים קובץ .env על ידי הרצת הפקודה הבאה:

echo "GOOGLE_GENAI_USE_VERTEXAI=TRUE" >> .env \
&& echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> .env \
&& echo "GOOGLE_CLOUD_LOCATION=us-central1" >> .env

4. יצירת שרת MCP מקומי

לפני שתתחילו לתזמן את סוכן המטבעות, תצטרכו ליצור שרת MCP כדי לחשוף את הכלים שהסוכן יצטרך.

שרת MCP מאפשר לכם לכתוב תוכנות קלות משקל כדי לחשוף יכולות ספציפיות (כמו אחזור של שערי חליפין) ככלים. סוכן אחד או כמה סוכנים יכולים לגשת לכלים האלה באמצעות Model Context Protocol (MCP) סטנדרטי.

אפשר להשתמש בחבילת Python‏ FastMCP כדי ליצור שרת MCP שחושף כלי יחיד בשם get_exchange_rate. הכלי get_exchange_rate שולח קריאה באינטרנט אל Frankfurter API כדי לקבל את שער החליפין הנוכחי בין שני מטבעות.

הקוד של שרת ה-MCP נמצא בקובץ mcp-server/server.py:

import logging
import os

import httpx
from fastmcp import FastMCP

# Set up logging
logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)

mcp = FastMCP("Currency MCP Server 💵")

@mcp.tool()
def get_exchange_rate(
    currency_from: str = 'USD',
    currency_to: str = 'EUR',
    currency_date: str = 'latest',
):
    """Use this to get current exchange rate.

    Args:
        currency_from: The currency to convert from (e.g., "USD").
        currency_to: The currency to convert to (e.g., "EUR").
        currency_date: The date for the exchange rate or "latest". Defaults to "latest".

    Returns:
        A dictionary containing the exchange rate data, or an error message if the request fails.
    """
    logger.info(f"--- 🛠️ Tool: get_exchange_rate called for converting {currency_from} to {currency_to} ---")
    try:
        response = httpx.get(
            f'https://api.frankfurter.app/{currency_date}',
            params={'from': currency_from, 'to': currency_to},
        )
        response.raise_for_status()

        data = response.json()
        if 'rates' not in data:
            return {'error': 'Invalid API response format.'}
        logger.info(f'✅ API response: {data}')
        return data
    except httpx.HTTPError as e:
        return {'error': f'API request failed: {e}'}
    except ValueError:
        return {'error': 'Invalid JSON response from API.'}

if __name__ == "__main__":
    logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}")
    # Could also use 'sse' transport, host="0.0.0.0" required for Cloud Run.
    asyncio.run(
        mcp.run_async(
            transport="http",
            host="0.0.0.0",
            port=os.getenv("PORT", 8080),
        )
    )

כדי להפעיל את שרת ה-MCP באופן מקומי, פותחים טרמינל ומריצים את הפקודה הבאה (השרת יופעל בכתובת http://localhost:8080):

uv run mcp-server/server.py

בודקים ששרת ה-MCP פועל בצורה תקינה ושכלי get_exchange_rate נגיש באמצעות פרוטוקול הקשר של המודל.

בחלון טרמינל חדש (כדי לא לעצור את שרת ה-MCP המקומי), מריצים את הפקודה הבאה:

uv run mcp-server/test_server.py

שער החליפין הנוכחי של 1 דולר ארה"ב לאירו יוצג:

--- 🛠️ Tool found: get_exchange_rate ---
--- 🪛 Calling get_exchange_rate tool for USD to EUR ---
---  Success: {
  "amount": 1.0,
  "base": "USD",
  "date": "2025-05-26",
  "rates": {
    "EUR": 0.87866
  }
} ---

מדהים! יש לכם שרת MCP פעיל עם כלי שהסוכן יוכל לגשת אליו.

לפני שעוברים לתחנה הבאה, עוצרים את שרת ה-MCP שפועל באופן מקומי על ידי הפעלת הפקודה Ctrl+C (או Command+C ב-Mac) במסוף שבו הפעלתם אותו.

5. פריסת שרת MCP ב-Cloud Run

עכשיו אפשר לפרוס את שרת ה-MCP כשרת MCP מרוחק ב-Cloud Run 🚀☁️

היתרונות בהפעלת שרת MCP מרחוק

להפעלת שרת MCP מרחוק ב-Cloud Run יש כמה יתרונות:

  • 📈יכולת הרחבה: Cloud Run מתוכנן להרחבה מהירה כדי לטפל בכל הבקשות הנכנסות. שרת ה-MCP יותאם אוטומטית ב-Cloud Run בהתאם לביקוש.
  • 👥שרת מרכזי: אתם יכולים לשתף גישה לשרת MCP מרכזי עם חברי הצוות באמצעות הרשאות IAM, וכך לאפשר להם להתחבר אליו מהמחשבים המקומיים שלהם במקום להפעיל שרתים משלהם באופן מקומי. אם יבוצע שינוי בשרת MCP, כל חברי הצוות ייהנו ממנו.
  • 🔐אבטחה: Cloud Run מספק דרך קלה לאכיפת בקשות מאומתות. כך אפשר לאפשר רק חיבורים מאובטחים לשרת ה-MCP ולמנוע גישה לא מורשית.

עוברים לספרייה mcp-server:

cd mcp-server

פורסים את שרת ה-MCP ב-Cloud Run:

gcloud run deploy mcp-server --no-allow-unauthenticated --region=us-central1 --source .

אם הפריסה של השירות הושלמה בהצלחה, תוצג הודעה כמו זו:

Service [mcp-server] revision [mcp-server-12345-abc] has been deployed and is serving 100 percent of traffic.

אימות לקוחות MCP

מכיוון שציינתם --no-allow-unauthenticated כדי לדרוש אימות, כל לקוח MCP שמתחבר לשרת MCP מרוחק יצטרך לעבור אימות.

במסמכים הרשמיים בנושא אירוח שרתי MCP ב-Cloud Run יש מידע נוסף על הנושא הזה, בהתאם למקום שבו מריצים את לקוח ה-MCP.

תצטרכו להריץ את Cloud Run proxy כדי ליצור מנהרה מאומתת לשרת MCP המרוחק במחשב המקומי.

כברירת מחדל, כדי לגשת לכתובת ה-URL של שירותי Cloud Run, צריך לאשר את כל הבקשות באמצעות תפקיד ה-IAM‏ Cloud Run Invoker‏ (roles/run.invoker). הקישור הזה של מדיניות IAM מבטיח שמנגנון אבטחה חזק ישמש לאימות של לקוח MCP מקומי.

צריך לוודא שלכם או לכל חבר צוות שמנסה לגשת לשרת ה-MCP המרוחק יש את תפקיד ה-IAM‏ roles/run.invoker שמשויך לישות ה-IAM (חשבון Google Cloud).

gcloud run services proxy mcp-server --region=us-central1

הפלט הבא אמור להתקבל:

Proxying to Cloud Run service [mcp-server] in project [<YOUR_PROJECT_ID>] region [us-central1]
http://127.0.0.1:8080 proxies to https://mcp-server-abcdefgh-uc.a.run.app

כל התנועה אל http://127.0.0.1:8080 תאומת ותועבר לשרת ה-MCP המרוחק.

בדיקת שרת ה-MCP המרוחק

בטרמינל חדש, חוזרים לתיקיית הבסיס ומריצים מחדש את קובץ mcp-server/test_server.py כדי לוודא ששרת ה-MCP המרוחק פועל.

cd ..
uv run mcp-server/test_server.py

הפלט שיוצג יהיה דומה לזה שמוצג כשמריצים את השרת באופן מקומי:

--- 🛠️ Tool found: get_exchange_rate ---
--- 🪛 Calling get_exchange_rate tool for USD to EUR ---
---  Success: {
  "amount": 1.0,
  "base": "USD",
  "date": "2025-05-26",
  "rates": {
    "EUR": 0.87866
  }
} ---

אם רוצים לוודא שהייתה קריאה לשרת המרוחק, אפשר להריץ שאילתה ביומנים של שרת ה-MCP של Cloud Run שנפרס:

gcloud run services logs read mcp-server --region us-central1 --limit 5

הפלט הבא אמור להופיע ביומנים:

2025-06-04 14:28:29,871 [INFO]: --- 🛠️ Tool: get_exchange_rate called for converting USD to EUR ---
2025-06-04 14:28:30,610 [INFO]: HTTP Request: GET https://api.frankfurter.app/latest?from=USD&to=EUR "HTTP/1.1 200 OK"
2025-06-04 14:28:30,611 [INFO]:  API response: {'amount': 1.0, 'base': 'USD', 'date': '2025-06-03', 'rates': {'EUR': 0.87827}}

עכשיו, אחרי שיש לכם שרת MCP מרוחק, אפשר להמשיך ליצירת סוכן. 🤖

6. יצירת סוכן באמצעות ערכה לפיתוח סוכנים (ADK)

אחרי שפרסתם שרת MCP, הגיע הזמן ליצור את סוכן המטבע באמצעות ערכת פיתוח סוכנים (ADK).

לאחרונה הושקה גרסה יציבה של Agent Development Kit‏ (ADK) – גרסה 1.0.0. ההישג הזה מציין שערכת ה-ADK של Python מוכנה עכשיו לשימוש בסביבת ייצור, ומציעה פלטפורמה אמינה וחזקה למפתחים, שבעזרתה הם יכולים לפתח ולפרוס את הסוכנים שלהם בסביבות פעילות בביטחון.

ערכת ה-ADK מאפשרת ליצור סוכנים קלים מאוד ולחבר אותם בקלות לשרתי MCP עם תמיכה מובנית ב-MCP Tools. סוכן המטבע יגש לכלי get_exchange_rate באמצעות המחלקה MCPToolset של ADK.

הקוד של סוכן המטבע נמצא ב-currency_agent/agent.py:

import logging
import os

from dotenv import load_dotenv
from google.adk.agents import LlmAgent
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from google.adk.tools.mcp_tool import MCPToolset, StreamableHTTPConnectionParams

logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)

load_dotenv()

SYSTEM_INSTRUCTION = (
    "You are a specialized assistant for currency conversions. "
    "Your sole purpose is to use the 'get_exchange_rate' tool to answer questions about currency exchange rates. "
    "If the user asks about anything other than currency conversion or exchange rates, "
    "politely state that you cannot help with that topic and can only assist with currency-related queries. "
    "Do not attempt to answer unrelated questions or use tools for other purposes."
)

logger.info("--- 🔧 Loading MCP tools from MCP Server... ---")
logger.info("--- 🤖 Creating ADK Currency Agent... ---")

root_agent = LlmAgent(
    model="gemini-2.5-flash",
    name="currency_agent",
    description="An agent that can help with currency conversions",
    instruction=SYSTEM_INSTRUCTION,
    tools=[
        MCPToolset(
            connection_params=StreamableHTTPConnectionParams(
                url=os.getenv("MCP_SERVER_URL", "http://localhost:8080/mcp")
            )
        )
    ],
)

כדי לבדוק במהירות את סוכן המטבעות, אפשר להשתמש בממשק המשתמש למפתחים של ADK. כדי לגשת אליו, מריצים את הפקודה adk web:

uv run adk web

בדפדפן, עוברים אל http://localhost:8000 כדי לראות את הסוכן ולבדוק אותו.

מוודאים שהסמל currency_agent נבחר כסוכן בפינה הימנית העליונה של ממשק המשתמש האינטרנטי.

ממשק משתמש באינטרנט של ADK

אפשר לשאול את הסוכן באזור הצ'אט שאלה כמו "What is 250 CAD to USD?‎". אפשר לראות שהנציג מתקשר לכלי get_exchange_rate MCP שלנו לפני שהוא נותן תשובה.

ADK Web Currency Agent

הסוכן עובד! הוא יכול לטפל בשאילתות שקשורות להמרות מטבעות 💸.

7. פרוטוקול Agent2Agent ‏ (A2A)

הפרוטוקול Agent2Agent (A2A) הוא תקן פתוח שנועד לאפשר תקשורת ושיתוף פעולה חלקים בין סוכני AI. הפרוטוקול מאפשר לסוכנים שנבנו באמצעות מסגרות מגוונות ועל ידי ספקים שונים לתקשר זה עם זה בשפה משותפת, וכך לשבור את המחסומים ולעודד פעולה הדדית.

פרוטוקול A2A

התכונה A2A מאפשרת לסוכנים:

  • גילוי: אפשר למצוא סוכנים אחרים וללמוד על הכישורים (AgentSkill) והיכולות (AgentCapabilities) שלהם באמצעות כרטיסי סוכן סטנדרטיים.
  • תקשורת: החלפת הודעות ונתונים באופן מאובטח.
  • שיתוף פעולה: הקצאת משימות ותיאום פעולות להשגת יעדים מורכבים.

פרוטוקול A2A מאפשר את התקשורת הזו באמצעות מנגנונים כמו 'כרטיסי סוכן' שמשמשים ככרטיסי ביקור דיגיטליים שסוכנים יכולים להשתמש בהם כדי לפרסם את היכולות שלהם ואת פרטי החיבור שלהם.

כרטיס נציג A2A

עכשיו צריך לחשוף את סוכן המטבע באמצעות A2A כדי שסוכנים ולקוחות אחרים יוכלו לקרוא לו.

A2A Python SDK

A2A Python SDK מספק מודלים של Pydantic לכל אחד מהמשאבים שצוינו למעלה: AgentSkill, ‏ AgentCapabilities ו-AgentCard. היא מספקת ממשק שמקדם את הפיתוח והשילוב עם פרוטוקול A2A.

AgentSkill היא הדרך שבה תפרסמו לסוכנים אחרים שלסוכן המטבע יש כלי לget_exchange_rate:

# A2A Agent Skill definition
skill = AgentSkill(
    id='get_exchange_rate',
    name='Currency Exchange Rates Tool',
    description='Helps with exchange values between various currencies',
    tags=['currency conversion', 'currency exchange'],
    examples=['What is exchange rate between USD and GBP?'],
)

לאחר מכן, כחלק מAgentCard, יפורטו הכישורים והיכולות של הסוכן לצד פרטים נוספים כמו מצבי קלט ופלט שהסוכן יכול לטפל בהם:

# A2A Agent Card definition
agent_card = AgentCard(
    name='Currency Agent',
    description='Helps with exchange rates for currencies',
    url=f'http://{host}:{port}/',
    version='1.0.0',
    defaultInputModes=["text"],
    defaultOutputModes=["text"],
    capabilities=AgentCapabilities(streaming=True),
    skills=[skill],
)

הגיע הזמן לשלב את הכל עם סוכן המטבע ולהציג את העוצמה של A2A!

8. חשיפת שרת A2A של סוכן המטבע

ערכת ה-ADK מפשטת את התהליך של בניית סוכנים וחיבור שלהם באמצעות פרוטוקול A2A. כדי להפוך סוכן ADK קיים לנגיש (לחשוף אותו) כשרת A2A, משתמשים בפונקציה to_a2a(root_agent) של ADK (פרטים מלאים זמינים בתיעוד של ADK).

הפונקציה to_a2a ממירה סוכן קיים לעבודה עם A2A, ומאפשרת לחשוף אותו כשרת באמצעות uvicorn. זה אומר שיש לכם שליטה הדוקה יותר על מה שאתם רוצים לחשוף אם אתם מתכננים להעביר את הסוכן לייצור. הפונקציה to_a2a() יוצרת באופן אוטומטי כרטיס של סוכן על סמך קוד הסוכן שלכם באמצעות A2A Python SDK.

אם בודקים את הקובץ currency_agent/agent.py אפשר לראות את השימוש ב-to_a2a ואיך סוכן המטבע מוצג כשרת A2A עם שתי שורות קוד בלבד.

from google.adk.a2a.utils.agent_to_a2a import to_a2a
# ... see file for full code

# Make the agent A2A-compatible
a2a_app = to_a2a(root_agent, port=10000)

כדי להריץ את שרת A2A, מריצים את הפקודה הבאה בטרמינל חדש:

uv run uvicorn currency_agent.agent:a2a_app --host localhost --port 10000

אם השרת יופעל בהצלחה, הפלט ייראה כך ויציין שהוא פועל ביציאה 10000:

[INFO]: --- 🔧 Loading MCP tools from MCP Server... ---
[INFO]: --- 🤖 Creating ADK Currency Agent... ---
INFO:     Started server process [45824]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://localhost:10000 (Press CTRL+C to quit)

סוכן המטבעות פועל עכשיו בהצלחה כשרת A2A, ויש לו אפשרות לקבל קריאות מסוכנים או מלקוחות אחרים באמצעות פרוטוקול A2A.

אימות של הפעלת הסוכן המרוחק

כדי לוודא שהסוכן פועל, אפשר להיכנס לכתובת ה-URL של כרטיס הסוכן של סוכן המטבע שנוצר אוטומטית באמצעות הפונקציה to_a2a().

בדפדפן, עוברים אל [http://localhost:10000/.well-known/agent.json]

יוצג לכם כרטיס הנציג הבא:

{
  "capabilities": {

  },
  "defaultInputModes": [
    "text/plain"
  ],
  "defaultOutputModes": [
    "text/plain"
  ],
  "description": "An agent that can help with currency conversions",
  "name": "currency_agent",
  "preferredTransport": "JSONRPC",
  "protocolVersion": "0.3.0",
  "skills": [
    {
      "description": "An agent that can help with currency conversions I am a specialized assistant for currency conversions. my sole purpose is to use the 'get_exchange_rate' tool to answer questions about currency exchange rates. If the user asks about anything other than currency conversion or exchange rates, politely state that I cannot help with that topic and can only assist with currency-related queries. Do not attempt to answer unrelated questions or use tools for other purposes.",
      "id": "currency_agent",
      "name": "model",
      "tags": [
        "llm"
      ]
    },
    {
      "description": "Use this to get current exchange rate.\n\nArgs:\n    currency_from: The currency to convert from (e.g., \"USD\").\n    currency_to: The currency to convert to (e.g., \"EUR\").\n    currency_date: The date for the exchange rate or \"latest\". Defaults to \"latest\".\n\nReturns:\n    A dictionary containing the exchange rate data, or an error message if the request fails.",
      "id": "currency_agent-get_exchange_rate",
      "name": "get_exchange_rate",
      "tags": [
        "llm",
        "tools"
      ]
    }
  ],
  "supportsAuthenticatedExtendedCard": false,
  "url": "http://localhost:10000",
  "version": "0.0.1"
}

בדיקת שרת A2A

עכשיו אפשר לבדוק את השרת על ידי שליחת כמה בקשות באמצעות A2A.

‫A2A Python SDK מספק מחלקה a2a.client.A2AClient שמפשטת את התהליך הזה.

הקובץ currency_agent/test_client.py מכיל קוד שמופעל דרך כמה תרחישי בדיקה שונים מול שרת A2A.

# ... see file for full code

# Example test using A2AClient
async def run_single_turn_test(client: A2AClient) -> None:
    """Runs a single-turn non-streaming test."""

    send_message_payload = create_send_message_payload(text="how much is 100 USD in CAD?")
    request = SendMessageRequest(
        id=str(uuid4()), params=MessageSendParams(**send_message_payload)
    )

    print("--- ✉️  Single Turn Request ---")
    # Send Message
    response: SendMessageResponse = await client.send_message(request)
    print_json_response(response, "📥 Single Turn Request Response")
    if not isinstance(response.root, SendMessageSuccessResponse):
        print("received non-success response. Aborting get task ")
        return

    if not isinstance(response.root.result, Task):
        print("received non-task response. Aborting get task ")
        return

    task_id: str = response.root.result.id
    print("--- ❔ Query Task ---")
    # query the task
    get_request = GetTaskRequest(id=str(uuid4()), params=TaskQueryParams(id=task_id))
    get_response: GetTaskResponse = await client.get_task(get_request)
    print_json_response(get_response, "📥 Query Task Response")

# ----- Main Entrypoint (Create client --> Run tests) -----
async def main() -> None:
    """Main function to run the tests."""
    print(f'--- 🔄 Connecting to agent at {AGENT_URL}... ---')
    try:
        async with httpx.AsyncClient() as httpx_client:
            # Create a resolver to fetch the agent card
            resolver = A2ACardResolver(
                httpx_client=httpx_client,
                base_url=AGENT_URL,
            )
            agent_card = await resolver.get_agent_card()
            # Create a client to interact with the agent
            client = A2AClient(
                httpx_client=httpx_client,
                agent_card=agent_card,
            )
            print('--- ✅ Connection successful. ---')

            await run_single_turn_test(client)
            await run_multi_turn_test(client)

    except Exception as e:
        traceback.print_exc()
        print(f'--- ❌ An error occurred: {e} ---')
        print('Ensure the agent server is running.')

מריצים את הבדיקות באמצעות הפקודה הבאה:

uv run currency_agent/test_client.py

אם בדיקת ההפעלה תצליח, יקרו הדברים הבאים:

--- 🔄 Connecting to agent at http://localhost:10000... ---
---  Connection successful. ---
--- ✉️ Single Turn Request ---
--- 📥 Single Turn Request Response ---
{"id":"3bc92d7b-d857-4e93-9ff0-b2fb865f6e35","jsonrpc":"2.0","result":{"artifacts":[{"artifactId":"35e89e14-b977-4397-a23b-92c84bc32379","parts":[{"kind":"text","text":"Based on the current exchange rate, 1 USD is equivalent to 1.3704 CAD. Therefore, 100 USD would be 137.04 CAD.\n"}]}],"contextId":"2d66f277-152c-46ef-881d-7fe32866e9f5","history":[{"contextId":"2d66f277-152c-46ef-881d-7fe32866e9f5","kind":"message","messageId":"59819269f7d04849b0bfca7d43ec073c","parts":[{"kind":"text","text":"how much is 100 USD in CAD?"}],"role":"user","taskId":"52ae2392-84f5-429a-a14b-8413d3d20d97"},{"contextId":"2d66f277-152c-46ef-881d-7fe32866e9f5","kind":"message","messageId":"286095c6-12c9-40cb-9596-a9676d570dbd","parts":[],"role":"agent","taskId":"52ae2392-84f5-429a-a14b-8413d3d20d97"}],"id":"52ae2392-84f5-429a-a14b-8413d3d20d97","kind":"task","status":{"state":"completed"}}}

// ...

--- 🚀 First turn completed, no further input required for this test case. ---

זה עובד! הבדיקה שלך הצליחה ואתה יכול לתקשר עם סוכן המטבע באמצעות שרת A2A. 🎉

כדי לראות תרחישי שימוש מתקדמים יותר, אפשר לעיין במאגר a2a-samples ב-GitHub.

רוצה לפרוס את הסוכן? ‫Vertex AI Agent Engine מספק חוויה מנוהלת לפריסת סוכני AI בסביבת ייצור.

9. מזל טוב

מעולה! יצרתם ופרסתם בהצלחה שרת MCP מרוחק, יצרתם סוכן מטבע באמצעות Agent Development Kit (ADK) שמתחבר לכלים באמצעות MCP, וחשפתם את הסוכן באמצעות פרוטוקול Agent2Agent (A2A). הנציג של המטבע זמין עכשיו לאינטראקציה עם נציגים אחרים בכל מסגרת באמצעות A2A!

כאן אפשר למצוא קישור לתיעוד המלא של הקוד.

מה נכלל

  • איך יוצרים שרת MCP מקומי
  • פריסת שרת ה-MCP ב-Cloud Run
  • איך יוצרים סוכן באמצעות ערכה לפיתוח סוכנים שמשתמשת בכלים של MCP
  • איך חושפים סוכן ADK כשרת A2A
  • בדיקת שרת A2A באמצעות לקוח A2A

הסרת המשאבים

כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם במעבדה הזו:

  1. במסוף Google Cloud, עוברים לדף Manage resources.
  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.