ADK ile MCP ve A2A'ya Giriş

1. Genel Bakış

Yapay zeka ajanları, otonom çalışma, öğrenme ve hedeflere ulaşmak için çevreleriyle etkileşim kurma yetenekleriyle görev otomasyonunda ve karar alma süreçlerinde devrim yaratarak hızla popülerlik kazanıyor.

Bu codelab, uçtan uca çoklu ajan sistemi oluşturarak kullanmaya başlamanıza yardımcı olur. Para birimi MCP sunucusu oluşturacak, MCP sunucusunu kullanan ve Agent2Agent (A2A) protokolü üzerinden sunulan bir para birimi temsilcisi oluşturacak, para birimi temsilcisini A2A üzerinden kullanan işlem içi hava durumu alt temsilcisi içeren bir seyahat acentesi oluşturacak ve son olarak tüm hizmetleri Cloud Run'da dağıtacaksınız.

Mimari

Temel Teknolojiler

Model Context Protocol (MCP)

Model Context Protocol (MCP), uygulamaların LLM'lere bağlam ve araç sağlama şeklini standartlaştıran açık bir protokoldür. MCP'yi yapay zeka uygulamaları için bir USB-C bağlantı noktası gibi düşünebilirsiniz. Yapay zeka modellerini harici veri kaynaklarına, API'lere ve araçlara bağlamak için standart bir yöntem sunar.

Bu codelab'de currency_mcp_server, herkese açık Frankfurter API tarafından desteklenen Streamable HTTP (/mcp) üzerinden bir get_exchange_rate aracı sunar.

Agent Development Kit (ADK)

Agent Development Kit (ADK), yapay zeka ajanları geliştirmek ve dağıtmak için esnek bir düzenleme çerçevesidir. ADK, modelden ve dağıtımdan bağımsızdır ve diğer çerçevelerle uyumlu olacak şekilde tasarlanmıştır. ADK, temsilci geliştirmeyi standart yazılım mühendisliği gibi hissettirerek karmaşık temsilci tabanlı iş akışları oluşturmayı, test etmeyi ve yönetmeyi kolaylaştırır.

ADK, kullanıcı görüşmelerini yönetir, etkileşimli web kullanıcı arayüzünü sunar, McpToolset aracılığıyla MCP araçlarına bağlanır ve A2A iletişimlerini yönetir.

Agent2Agent (A2A) Protokolü

Agent2Agent (A2A) Protokolü, yapay zeka ajanları arasında iletişim ve ortak çalışmayı sağlamak için tasarlanmış açık bir standarttır. MCP, temsilci-araç bağlantılarını standartlaştırırken A2A, temsilciler arası işbirliğini standartlaştırır. Temsilcilerin farklı çerçeveler, barındırma ortamları ve kuruluşlar genelinde oluşturulduğu bir dünyada, A2A keşif ve görev devri için ortak bir dil sağlar.

ADK, currency_agent hizmetini A2A hizmeti (to_a2a) olarak sunar ve travel_agent tarafından AgentTool (RemoteA2aAgent) olarak uzaktan kullanılmasına olanak tanır.

Yerel alt aracılar ve uzak A2A aracıları

Bu mimari, çoklu temsilci tasarımında önemli bir kalıbı vurgular:

  • Yerel Temsilci Aracı (weather_agent): Ağ gecikmesi veya protokol serileştirme ek yükü olmadan, orkestratör içinde AgentTool olarak işlem sırasında çalışır.
  • Uzak Aracı Aracı (currency_agent): Bağımsız bir mikro hizmet olarak çalışır ve ağ üzerinden A2A protokolü aracılığıyla çağrılır.

Neler öğreneceksiniz?

  • Akışlı HTTP üzerinden FastMCP kullanarak yerel MCP sunucusu oluşturma ve test etme
  • MCP araçlarını kullanan ADK ile temsilci oluşturma (McpToolset)
  • ADK temsilcisini A2A sunucusu olarak gösterme (to_a2a)
  • A2A Python istemcisini (a2a.client) kullanarak A2A sunucusunu test etme
  • Yerel alt temsilci araçlarını uzak A2A aracılarıyla birleştiren bir düzenleyici aracı oluşturma
  • Çoklu temsilci sisteminin tamamını ADK Web kullanıcı arayüzü ile yerel olarak çalıştırma ve test etme
  • Üç bileşeni de container mimarisine alma ve Google Cloud Run'a dağıtma

İhtiyacınız olanlar

  • Chrome gibi bir tarayıcı.
  • Faturalandırmanın etkin olduğu bir Google Cloud projesi.

2. Başlamadan önce

Proje oluşturma

Google Cloud projeniz yoksa bir proje oluşturun.

Google Cloud Console'da, proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun.

Ayrıca Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bir projede faturalandırmanın etkin olup olmadığını nasıl kontrol edeceğinizi öğrenin.

Cloud Shell'i etkinleştirme

Google Cloud Shell, doğrudan Google Cloud Console'da sunulan etkileşimli, tarayıcı tabanlı bir geliştirme ortamıdır. Araçları yerel olarak yüklemenize gerek kalmadan Google Cloud'u kullanmaya başlamanın en kolay yoludur.

Bu bağlantıyı tıklayarak Cloud Shell'i etkinleştirin. Cloud Shell'deki ilgili düğmeyi tıklayarak Cloud Shell Terminali (bulut komutlarını çalıştırmak için) ve Düzenleyici (dosyaları görüntülemek için) arasında geçiş yapabilirsiniz.

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını onaylayın:

gcloud auth list

gcloud komutunun projenizi tanıdığını doğrulayın:

gcloud config list project

Projenizin kimliğini belirleyin:

export PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
gcloud config set project $PROJECT_ID

Cloud API'lerini etkinleştirme

Cloud Run, Cloud Build, Artifact Registry ve Vertex AI için gerekli API'leri etkinleştirin:

gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       aiplatform.googleapis.com

Kodu alın

Depoyu klonlayın ve python dizinine gidin:

git clone https://github.com/meteatamel/getting-started-mcp-a2a-adk.git
cd getting-started-mcp-a2a-adk/python

Bağımlılıkları uv ile yükleme

uv, hızlı bir Python paketi ve proje yöneticisidir. Cloud Shell'e önceden yüklenmiştir. Yerel olarak çalıştırıyorsanız aşağıdaki şekilde yükleyebilirsiniz:

# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
# powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Python dizini, birleşik bir uv olarak yapılandırılmıştır.

Workspace. Aşağıdaki komutu çalıştırarak tüm çalışma alanı üyelerindeki (currency_mcp_server, currency_agent ve travel_agent) tüm bağımlılıkları tek bir sanal ortama yükleyin:

uv sync

Ortam değişkenlerini yapılandırma

python dizinindeki bir .env dosyasında ortam değişkenlerini yapılandırın:

A seçeneği: Gemini Enterprise (Google Cloud / Cloud Shell)

echo "GOOGLE_GENAI_USE_ENTERPRISE=TRUE" >> .env \
&& echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> .env \
&& echo "GOOGLE_CLOUD_LOCATION=global" >> .env

B seçeneği: Google AI Studio (yerel API anahtarı)

Bunun yerine Google AI Studio'dan bir API anahtarı kullanmayı tercih ediyorsanız:

echo "GOOGLE_API_KEY=<your_api_key_here>"<>>/span>  .env \
&& echo "GOOGLE_GENAI_USE_ENTERPRISE=FALSE" >> .env

3. Para birimi MCP sunucusunu oluşturma

Temsilcilerinizi oluşturmadan önce para birimi dönüştürme aracını sunan MCP sunucusunu inceleyeceksiniz.

MCP sunucusu, özellikleri araç olarak kullanıma sunmak için basit programlar yazmanıza olanak tanır. Ardından bir temsilci (veya birden fazla temsilci), standartlaştırılmış Model Context Protocol'ü kullanarak bu araçlara erişebilir.

FastMCP Python paketi, get_exchange_rate adlı tek bir aracı gösteren bir MCP sunucusu oluşturmak için kullanılabilir. get_exchange_rate aracı, iki para birimi arasındaki güncel döviz kurunu almak için Frankfurter API'yi çağırır.

MCP sunucusunun kodu currency_mcp_server/server.py içinde bulunur:

import asyncio
import logging
import os

import httpx
from fastmcp import FastMCP

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.dev/v1/{currency_date}",
            params={"from": currency_from, "to": currency_to},
        )
        response.raise_for_status()

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


if __name__ == "__main__":
    port = int(os.getenv("PORT", 8080))
    logger.info(f"🚀 MCP server started on port {port}")
    # 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=port,
        )
    )

MCP sunucusunu yerel olarak başlatma

Terminalinizde MCP sunucusunu başlatın:

uv run python currency_mcp_server/server.py

Sunucu, 8080 bağlantı noktasında başlar ve akış yapılabilir HTTP uç noktası /mcp (http://localhost:8080/mcp) adresinde kullanılabilir.

MCP sunucusunu test etme

İkinci bir terminal penceresi açın (MCP sunucusunu ilk pencerede çalışır durumda bırakın), python klasörüne (cd getting-started-mcp-a2a-adk/python) gidin ve test komut dosyasını çalıştırın:

uv run python currency_mcp_server/test_server.py

Test komut dosyası, FastMCP'nin Client özelliğini kullanarak MCP uç noktasına bağlanır, araçları listeler ve get_exchange_rate aracını çağırır:

Connecting to MCP server at: http://localhost:8080/mcp
--- 🛠️  Tool found: get_exchange_rate ---
--- 🪛  Calling get_exchange_rate tool for USD to EUR ---
--- ✅  Success: {"amount":1.0,"base":"USD","date":"2026-09-29","rates":{"EUR":0.84919}} ---

Mükemmel! Canlı para birimi aracını gösteren çalışan bir MCP sunucunuz var. Sonraki adımlar için bu terminali açık tutun.

4. ADK ile para birimi temsilcisi oluşturma

Şimdi Agent Development Kit (ADK) kullanarak para birimi temsilcisini oluşturma zamanı.

ADK, McpToolset sınıfı aracılığıyla MCP araçları için yerleşik destek sunar. Currency Agent, StreamableHTTPConnectionParams kullanarak MCP sunucumuza bağlanır.

currency_agent/agent.py dilindeki para birimi temsilcisi tanımına göz atın:

import logging
import os
from urllib.parse import urlparse

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

mcp_server_url = os.getenv("MCP_SERVER_URL", "http://localhost:8080/mcp")
if not mcp_server_url.endswith("/mcp"):
    mcp_server_url = f"{mcp_server_url.rstrip('/')}/mcp"

logger.info(f"--- 🔧 Loading MCP tools from MCP Server at {mcp_server_url}... ---")
logger.info("--- 🤖 Creating ADK Currency Agent... ---")

root_agent = LlmAgent(
    model="gemini-3.8-flash",
    name="currency_agent",
    description="An agent that can help with currency conversions",
    instruction=SYSTEM_INSTRUCTION,
    tools=[
        McpToolset(
            connection_params=StreamableHTTPConnectionParams(
                url=mcp_server_url
            )
        )
    ],
)

McpToolset, get_exchange_rate aracını HTTP üzerinden çalışan MCP sunucusundan otomatik olarak nasıl bulup yüklediğine dikkat edin.

ADK web kullanıcı arayüzü ile para birimi temsilcisini test etme

ADK'nın geliştirme web arayüzünü kullanarak temsilciyi ayrı olarak test edebilirsiniz. İkinci terminalinizde şu komutu çalıştırın:

uv run adk web --allow_origins "*" currency_agent

Tarayıcınızda http://localhost:8000 adresini açın (veya Cloud Shell'de Web Preview'u (Web Önizlemesi) tıklayın).

ADK Web Currency Agent

Ajan'a sorun:

"250 ABD doları kaç avro eder?"

Temsilcinin get_exchange_rate MCP aracını çağırıp dönüştürülen tutarı döndürdüğünü görürsünüz. Devam etmeden önce Ctrl+C kullanarak adk web işlemini durdurun.

5. Agent2Agent (A2A) Protokolü

Agent2Agent (A2A) Protokolü, yapay zeka ajanları arasında iletişim ve ortak çalışmayı sağlamak için tasarlanmış açık bir standarttır.

Modern çoklu temsilci sistemlerinde temsilciler genellikle farklı çerçeveler (ADK, LangChain, CrewAI, AutoGen) kullanılarak oluşturulur ve farklı altyapılara dağıtılır. A2A, standartlaştırılmış bir iletişim sözleşmesi tanımlayarak bu siloları ortadan kaldırır.

A2A Protokolü

A2A ile ilgili temel kavramlar

  • Temsilci Keşfi (Temsilci Kartı): A2A uyumlu her temsilci; özelliklerini, desteklenen G/Ç modlarını, kimlik doğrulama koşullarını ve becerilerini /.well-known/agent-card.json adresinde barındırılan standart bir JSON dosyası aracılığıyla bildirir.
  • Temsilci Becerileri (AgentSkill): Temsilcinin kullanabileceği belirli özellikler veya araçlar. Diğer temsilciler, görevleri ne zaman devredeceklerine karar vermek için bu becerileri okur.
  • JSON-RPC iletişimi: Temsilciler; HTTP JSON-RPC 2.0 gibi standart aktarımlar üzerinden yapılandırılmış mesajlar, görevler ve yapılar paylaşır.

A2A Aracısı Kartı

Bir sonraki adımda, ADK Currency Agent'ımızı A2A sunucusu olarak kullanıma sunacaksınız. Böylece diğer temsilciler bu temsilciyi keşfedebilir ve para birimi dönüştürme görevlerini ona devredebilir.

6. Para birimi temsilcisini A2A sunucusu olarak kullanıma sunma

ADK, to_a2a() yardımcı işleviyle herhangi bir LlmAgent'ı A2A uyumlu bir sunucuya dönüştürmeyi kolaylaştırır.

currency_agent/agent.py sayfasının alt kısmını inceleyin:

# Make the agent A2A-compatible
PORT = int(os.getenv("PORT", 8081))
AGENT_URL = os.getenv("AGENT_URL")

if AGENT_URL:
    parsed = urlparse(AGENT_URL)
    protocol = parsed.scheme or "https"
    host = parsed.hostname
    port = parsed.port or 443
else:
    protocol = "http"
    host = "localhost"
    port = PORT

a2a_app = to_a2a(root_agent, host=host, port=port, protocol=protocol)

if __name__ == "__main__":
    import uvicorn

    logger.info(f"🚀 Starting currency_agent on port {PORT}")
    uvicorn.run(a2a_app, host="0.0.0.0", port=PORT)

to_a2a() yardımcısı otomatik olarak:

  1. LlmAgent aracını ve talimatlarını inceler.
  2. Becerilerini açıklayan bir A2A AgentCard oluşturur (ör. currency_agent-get_exchange_rate).
  3. Temsilciyi, JSON-RPC uç noktalarını destekleyen bir FastAPI uygulamasına (a2a_app) sarmalar.
  4. Temsilci kartında tanıtılan url, AGENT_URL (veya localhost) temel alınarak dinamik olarak yapılandırılır.

Currency Agent A2A sunucusunu başlatma

İkinci terminalinizde para birimi temsilcisini başlatın:

uv run python currency_agent/agent.py

Sunucu, 8081 numaralı bağlantı noktasında başlar:

[INFO]: --- 🔧 Loading MCP tools from MCP Server at http://localhost:8080/mcp... ---
[INFO]: --- 🤖 Creating ADK Currency Agent... ---
[INFO]: 🚀 Starting currency_agent on port 8081
INFO:     Started server process
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8081 (Press CTRL+C to quit)

Temsilci kartını inceleme

Tarayıcınızda temsilci kartı uç noktasını ziyaret edin: http://localhost:8081/.well-known/agent-card.json

Otomatik olarak üretilmiş JSON meta verilerini görürsünüz:

{
  "name": "currency_agent",
  "description": "An agent that can help with currency conversions",
  "supportedInterfaces": [
    {
      "url": "http://localhost:8081",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "version": "0.0.1",
  "capabilities": {
    "streaming": true
  },
  "defaultInputModes": [
    "text/plain"
  ],
  "defaultOutputModes": [
    "text/plain"
  ],
  "skills": [
    {
      "id": "currency_agent",
      "name": "model",
      "description": "An agent that can help with currency conversions",
      "tags": [
        "llm"
      ]
    },
    {
      "id": "currency_agent-get_exchange_rate",
      "name": "get_exchange_rate",
      "description": "Use this to get current exchange rate.",
      "tags": [
        "llm",
        "tools"
      ]
    }
  ]
}

A2A istemcisiyle test etme

Üçüncü bir terminal açın, python klasörüne (cd getting-started-mcp-a2a-adk/python) gidin ve özel A2A test istemci komut dosyasını kullanarak A2A uç noktasını test edin:

uv run python currency_agent/test_a2aclient.py

İstemci, A2ACardResolver kullanarak temsilci kartını çözer ve bir JSON-RPC mesajı gönderir:

🔄 Fetching the agent card at http://localhost:8081
✅ Successfully fetched the agent card
====================================================
                     AgentCard                      
====================================================
Name        : currency_agent
Description : An agent that can help with currency conversions
Interfaces  : [0] http://localhost:8081  (JSONRPC 1.0)
Skills      : currency_agent, currency_agent-get_exchange_rate
====================================================
🔄 Initializing a non-streaming client
Sending request: "how much is 100 USD in GBP?"
Response:
100 USD is currently equal to approximately 73.37 GBP...

Currency Agent artık tam işlevli bir A2A sunucusu olarak çalışıyor.

7. Seyahat acentesi oluşturma

Şimdi, düzenleyici Seyahat Acentesi'ni oluşturacaksınız. Bu temsilci, ADK temsilcisinin iki farklı araç paradigmasını nasıl kolayca birleştirebileceğini gösterir:

  1. Yerel Temsilci Aracı (weather_agent): Aynı Python çalışma zamanında çalışan, ağ veya serileştirme gecikmesini önleyen, işlem içi bir ADK alt temsilcisidir.
  2. Uzak Temsilci Aracı (currency_agent): RemoteA2aAgent kullanarak A2A protokolü üzerinden ağ üzerinden bağlanan harici bir temsilci.
                    +-----------------------------+
                    |        travel_agent         |
                    | (Orchestrator with Web UI)  |
                    +--------------+--------------+
                                   |
             +---------------------+---------------------+
             | (In-process call)                         | (A2A Network Hop)
             v                                           v
+-------------------------+                 +-------------------------+
|   weather_agent         |                 |   currency_agent        |
|  (Local AgentTool)      |                 |  (Remote A2A Agent)     |
|  Calls wttr.in API      |                 |  Calls Currency MCP Svc |
+-------------------------+                 +-------------------------+

1. Yerel Hava Durumu Alt Temsilcisi

travel_agent/subagents/weather_agent.py adlı videoya göz atın:

import logging
import httpx
from google.adk.agents import LlmAgent

logger = logging.getLogger(__name__)

SYSTEM_INSTRUCTION = (
    "You are a specialized assistant for providing weather forecasts and conditions for travel destinations. "
    "Your sole purpose is to use the 'get_weather' tool to fetch weather information. "
    "Provide clear, concise summaries of current weather conditions, temperatures, and forecasts to help travelers pack and plan."
)


def get_weather(location: str = "London") -> dict:
    """Gets the current weather and forecast for a given location or city."""
    logger.info(f"--- 🌤️ Tool: get_weather called for {location} ---")
    try:
        response = httpx.get(
            f"https://wttr.in/{location}?format=j1",
            headers={"User-Agent": "curl/7.68.0"},
            timeout=8.0,
        )
        response.raise_for_status()
        data = response.json()
        current = data["current_condition"][0]
        return {
            "location": location,
            "condition": current.get("weatherDesc", [{}])[0].get("value", "Unknown"),
            "temperature_celsius": f"{current.get('temp_C', 'N/A')}°C",
            "temperature_fahrenheit": f"{current.get('temp_F', 'N/A')}°F",
            "humidity": f"{current.get('humidity', 'N/A')}%",
            "wind_speed_kmph": f"{current.get('windspeedKmph', 'N/A')} km/h",
        }
    except Exception as e:
        logger.warning(f"⚠️ Weather lookup failed: {e}. Returning simulated estimate.")
        return {
            "location": location,
            "condition": "Partly Cloudy",
            "temperature_celsius": "20°C",
            "temperature_fahrenheit": "68°F",
            "humidity": "55%",
            "wind_speed_kmph": "10 km/h",
            "note": f"Live data unavailable ({e}); showing estimated conditions.",
        }


weather_agent = LlmAgent(
    model="gemini-3.8-flash",
    name="weather_agent",
    description="A local specialist agent that provides current weather reports and forecasts for travel destinations.",
    instruction=SYSTEM_INSTRUCTION,
    tools=[get_weather],
)

Hava durumu temsilcisi, esnek bir yedekle wttr.in adresinden anlık hava durumunu getiren bir işlev aracına sahip LlmAgent.

2. Seyahat Acentesi Düzenleyicisi

Şimdi travel_agent/agent.py adlı kullanıcıya bakalım:

import logging
import os
from dotenv import load_dotenv
from google.adk.agents import LlmAgent
from google.adk.tools.agent_tool import AgentTool
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent, AGENT_CARD_WELL_KNOWN_PATH

try:
    from travel_agent.subagents.weather_agent import weather_agent
except ImportError:
    from subagents.weather_agent import weather_agent

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

load_dotenv()

SYSTEM_INSTRUCTION = (
    "You are a helpful travel assistant. You help users plan trips, recommend places, "
    "and answer travel-related questions.\n\n"
    "- Whenever a user asks about currency exchange rates or money conversions, "
    "delegate the request to the 'currency_agent' tool.\n"
    "- Whenever a user asks about the weather, climate, or forecasts for a destination, "
    "delegate the request to the 'weather_agent' tool."
)

CURRENCY_AGENT_URL = os.getenv("CURRENCY_AGENT_URL", "http://localhost:8081").rstrip("/")

logger.info(
    "--- 🔗 Connecting to Remote A2A Currency Agent at %s... ---",
    CURRENCY_AGENT_URL,
)

currency_remote_agent = RemoteA2aAgent(
    name="currency_agent",
    agent_card=f"{CURRENCY_AGENT_URL}{AGENT_CARD_WELL_KNOWN_PATH}",
    description="An agent that can help with currency conversions and exchange rates.",
)

logger.info("--- 🤖 Creating ADK Travel Agent... ---")

root_agent = LlmAgent(
    model="gemini-3.8-flash",
    name="travel_agent",
    description="A travel assistant that can help plan trips, check weather forecasts via the local weather agent, and convert currencies via the remote currency agent.",
    instruction=SYSTEM_INSTRUCTION,
    tools=[
        AgentTool(agent=currency_remote_agent),
        AgentTool(agent=weather_agent),
    ],
)

if __name__ == "__main__":
    import uvicorn
    from google.adk.cli.fast_api import get_fast_api_app

    PORT = int(os.getenv("PORT", 8082))
    logger.info(f"🚀 Starting travel_agent Web UI on port {PORT}")
    app = get_fast_api_app(web=True, allow_origins=["*"], agents_dir=os.path.dirname(__file__) or ".")
    uvicorn.run(app, host="0.0.0.0", port=PORT)

Öne çıkan önemli noktalar:

  • RemoteA2aAgent, http://localhost:8081/.well-known/agent-card.json üzerinden para birimi temsilcisinin kartını getirir.
  • Hem currency_remote_agent hem de weather_agent, ADK'nin AgentTool kullanılarak sarmalanır.
  • travel_agent/agent.py komutunu çalıştırmak, get_fast_api_app(web=True) kullanarak 8082 bağlantı noktasında ADK Web kullanıcı arayüzünü doğrudan başlatır.

8. Çok ajanlı sistemi yerel olarak çalıştırma ve test etme

Artık üç bileşen de hazır. Sistemin tamamını yerel olarak çalıştırıp test edelim.

Üç hizmeti de çalıştırma

Hizmetlerin üç ayrı terminal penceresinde (getting-started-mcp-a2a-adk/python dizininden) aşağıdaki sırayla çalıştığından emin olun:

Terminal 1 (Para Birimi MCP Sunucusu):

uv run python currency_mcp_server/server.py

(8080 numaralı bağlantı noktasında çalışıyor)

Terminal 2 (Currency A2A Agent):

uv run python currency_agent/agent.py

(8081 numaralı bağlantı noktasında çalışıyor)

Terminal 3 (Web kullanıcı arayüzüne sahip seyahat acentesi):

uv run python travel_agent/agent.py

(8082 numaralı bağlantı noktasında çalışıyor)

ADK web kullanıcı arayüzü üzerinden test etme

Tarayıcınızda http://localhost:8082 adresini açın (veya Cloud Shell'de 8082 bağlantı noktasında Web Önizlemesi'ni kullanın).

Seyahat acentesine her iki aracı da gerektiren bileşik bir soru sorun:

"Londra'ya bir gezi planlıyorum. Hava nasıl ve 200 avro kaç sterlin?"

Yürütme akışını izleyin:

  1. Seyahat acentesi, isteği web kullanıcı arayüzünde alır.
  2. Hava durumu sorusunu işlem içi olarak yerel weather_agent'e yönlendirir. Bu araç da mevcut koşulları wttr.in'ten alır.
  3. A2A protokolü üzerinden para birimi dönüştürme işlemini 8081 numaralı bağlantı noktasında currency_agent'e devreder.
  4. currency_agent, döviz kurunu almak için MCP üzerinden 8080 numaralı bağlantı noktasında currency_mcp_server'ı çağırır.
  5. Tüm sonuçlar birleştirilir ve size birleşik, faydalı bir yanıt olarak sunulur.

ADK Web Uzaktan Para Birimi Temsilcisi

Komut satırı üzerinden test etme

Sorguları tarayıcı açmadan doğrudan KSA'dan da test edebilirsiniz:

uv run adk run travel_agent "What is the weather in London and how much is 100 USD in EUR?"

Yerel makinenizde her şey sorunsuz çalıştığına göre tüm sistemi Google Cloud Run'a dağıtabiliriz.

9. Çoklu temsilci sistemini Cloud Run'a dağıtma

Her bileşenin kendi Dockerfile ve bağımsız pyproject.toml vardır. Bu sayede her bileşen bağımsız olarak oluşturulup Cloud Run'a dağıtılabilir.

gcloud kullanarak her hizmeti dağıtacak ve URL'lerini otomatik olarak birbirine bağlayacaksınız.

Ortam değişkenlerini ayarlama

Cloud proje kimliğinizi ve hedef bölgenizi ayarlayın:

export PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
export REGION=us-central1

1. adım: Currency MCP sunucusunu dağıtın

MCP sunucusunu doğrudan kaynaktan dağıtın:

# 1. Deploy MCP server
gcloud run deploy currency-mcp-server \
  --source currency_mcp_server \
  --region $REGION \
  --allow-unauthenticated

# 2. Capture the deployed MCP server URL
MCP_SERVER_URL=$(gcloud run services describe currency-mcp-server --region $REGION --format='value(status.url)')/mcp
echo "MCP Server URL: $MCP_SERVER_URL"

2. adım: Currency Agent'ı dağıtın

currency-agent hizmetinin herkese açık URL'si ilk dağıtımında atandığından, önce hizmeti dağıtın, URL'sini alın ve AGENT_URL ortam değişkenini güncelleyin. Böylece A2A Aracı Kartı, doğru herkese açık HTTPS adresini bildirir:

# 1. Deploy Currency Agent connected to the deployed MCP Server
gcloud run deploy currency-agent \
  --source currency_agent \
  --region $REGION \
  --allow-unauthenticated \
  --update-env-vars MCP_SERVER_URL="$MCP_SERVER_URL",GOOGLE_GENAI_USE_ENTERPRISE="true",GOOGLE_CLOUD_PROJECT="$PROJECT_ID",GOOGLE_CLOUD_LOCATION="global"

# 2. Capture its assigned Cloud Run URL
CURRENCY_AGENT_URL=$(gcloud run services describe currency-agent --region $REGION --format='value(status.url)')
echo "Currency Agent URL: $CURRENCY_AGENT_URL"

# 3. Update AGENT_URL so the agent advertises its public HTTPS endpoint in its Agent Card
gcloud run services update currency-agent \
  --region $REGION \
  --update-env-vars AGENT_URL="$CURRENCY_AGENT_URL"

3. adım: Seyahat acentesini dağıtın

Şimdi seyahat acentesini dağıtın ve CURRENCY_AGENT_URL ile yapılandırın:

# 1. Deploy Travel Agent (with ADK Web UI) connected to Currency Agent
gcloud run deploy travel-agent \
  --source travel_agent \
  --region $REGION \
  --allow-unauthenticated \
  --update-env-vars CURRENCY_AGENT_URL="$CURRENCY_AGENT_URL",GOOGLE_GENAI_USE_ENTERPRISE="true",GOOGLE_CLOUD_PROJECT="$PROJECT_ID",GOOGLE_CLOUD_LOCATION="global"

# 2. Capture its assigned Cloud Run URL
TRAVEL_AGENT_URL=$(gcloud run services describe travel-agent --region $REGION --format='value(status.url)')
echo "Travel Agent URL: $TRAVEL_AGENT_URL"

10. Cloud Run'da çok ajanlı sistemi test etme

Üç mikro hizmet de dağıtıldığına göre Cloud Run'daki her katmanı doğrulayalım.

1. Uzak MCP sunucusunu test etme

Dağıtılan Cloud Run MCP sunucusunu komut satırınızdan test edin:

MCP_SERVER_URL="$MCP_SERVER_URL" uv run python currency_mcp_server/test_server.py

Aracın listelendiğini ve Cloud Run'da başarıyla çağrıldığını görürsünüz.

2. Para Birimi Temsilcisi'ni A2A üzerinden test etme

A2A test istemcisini kullanarak dağıtılan Currency Agent'ı test edin:

AGENT_URL="$CURRENCY_AGENT_URL" uv run python currency_agent/test_a2aclient.py

İstemci, Cloud Run'dan uzak Temsilci Kartı'nı getirir ve HTTPS JSON-RPC üzerinden mesaj alışverişi yapar.

3. Cloud Run'da seyahat acentesi web kullanıcı arayüzünü test etme

$TRAVEL_AGENT_URL uygulamasını tarayıcınızda açın.

ADK Web kullanıcı arayüzünün tamamı doğrudan Cloud Run'dan sunulur. Şunları sormayı deneyin:

"Tokyo'ya bir gezi planlıyorum. Hava nasıl ve 500 ABD doları kaç Japon yeni ediyor?"

[Browser] 
   │
   ▼ (HTTPS)
[Cloud Run: travel-agent]
   ├──> Local in-process tool: weather_agent (wttr.in)
   └──> A2A JSON-RPC (HTTPS)
           │
           ▼
        [Cloud Run: currency-agent]
           └──> MCP Streamable HTTP (HTTPS)
                   │
                   ▼
                [Cloud Run: currency-mcp-server] (Frankfurter API)

Üç hizmet de sunucusuz altyapıda bağımsız olarak ölçeklenir ve açık protokoller aracılığıyla sorunsuz bir şekilde iletişim kurar.

11. Tebrikler ve Temizlik

Başarılarınız

Tebrikler! Üretim düzeyinde çoklu temsilci sistemi oluşturup dağıttınız:

  • Model Context Protocol (MCP): Canlı API araçlarını Streamable HTTP üzerinden sunan bir FastMCP sunucusu oluşturuldu.
  • Agent Development Kit (ADK): LlmAgent kullanarak modüler temsilciler oluşturdu, MCP araçlarını McpToolset ile bağladı ve ADK Web kullanıcı arayüzünü barındırdı.
  • Agent2Agent (A2A) Protokolü: Bir temsilciyi A2A hizmeti (to_a2a) olarak kullanıma sundunuz, temsilci kartları (agent-card.json) yayınladınız ve RemoteA2aAgent kullanarak uzak temsilcilerden yararlandınız.
  • Çoklu Temsilci Mimarisi: Yerel işlem içi alt temsilciler (weather_agent) ile dağıtılmış uzak temsilciler (currency_agent) birleştirildi.
  • Cloud Run Sunucusuz Dağıtım: Üç hizmetin de container'larını oluşturup otomatik yapılandırma bağlantısıyla dağıttı.

Kodun tamamı (hem Python hem de Java uygulamaları dahil) ve gelecekteki güncellemeler için getting-started-mcp-a2a-adk deposunu ziyaret edin.

Temizleme

Bu codelab'de oluşturulan Cloud Run hizmetleri için Google Cloud hesabınızdan ücret alınmasını önlemek istiyorsanız:

Dağıtılan Cloud Run hizmetlerini silin:

gcloud run services delete currency-mcp-server --region $REGION --quiet
gcloud run services delete currency-agent --region $REGION --quiet
gcloud run services delete travel-agent --region $REGION --quiet

Alternatif olarak, bu codelab için özel bir proje oluşturduysanız projenin tamamını kapatabilirsiniz:

gcloud projects delete $PROJECT_ID