Premiers pas avec MCP et A2A avec ADK

1. Présentation

Les agents IA gagnent rapidement en popularité, révolutionnant l'automatisation des tâches et la prise de décision grâce à leur capacité à fonctionner de manière autonome, à apprendre et à interagir avec leur environnement pour atteindre des objectifs.

Cet atelier de programmation vous aidera à vous lancer en créant un système multi-agent de bout en bout. Vous allez créer un serveur MCP de devises, un agent de devises qui utilise le serveur MCP et est exposé via le protocole Agent2Agent (A2A), un agent de voyage avec un sous-agent météo en cours d'exécution qui utilise l'agent de devises via A2A, et enfin déployer tous les services sur Cloud Run.

Architecture

Technologie principale

Protocole MCP (Model Context Protocol)

Le Model Context Protocol (MCP) est un protocole ouvert qui standardise la façon dont les applications fournissent du contexte et des outils aux LLM. Le protocole MCP est un peu comme un port USB-C pour les applications d'IA : il fournit un moyen standardisé de connecter des modèles d'IA à des sources de données, des API et des outils externes.

Dans cet atelier de programmation, le currency_mcp_server expose un outil get_exchange_rate via HTTP diffusable (/mcp), soutenu par l'API Frankfurter publique.

Agent Development Kit (ADK)

Agent Development Kit (ADK) est un framework d'orchestration flexible permettant de développer et de déployer des agents IA. ADK est indépendant des modèles et du déploiement, et est conçu pour être compatible avec d'autres frameworks. ADK permet de développer des agents comme s'il s'agissait d'une ingénierie logicielle standard, ce qui facilite la création, le test et l'orchestration de workflows agentiques complexes.

ADK gère les conversations des utilisateurs, diffuse l'UI Web interactive, se connecte aux outils MCP via McpToolset et gère les communications A2A.

Protocole Agent2Agent (A2A)

Le protocole Agent2Agent (A2A) est une norme ouverte conçue pour permettre la communication et la collaboration entre les agents IA. Tout comme le protocole MCP standardise les connexions entre les agents et les outils, le protocole A2A standardise la collaboration entre les agents. Dans un monde où les agents sont créés sur différents frameworks, environnements d'hébergement et organisations, l'A2A fournit un langage commun pour la découverte et la délégation de tâches.

ADK expose currency_agent en tant que service A2A (to_a2a) et permet à travel_agent de l'utiliser à distance en tant qu'AgentTool (RemoteA2aAgent).

Sous-agents locaux et agents A2A distants

Cette architecture met en évidence un modèle crucial dans la conception multi-agent :

  • Outil d'agent local (weather_agent) : s'exécute en cours de traitement dans l'orchestrateur en tant qu'AgentTool, sans latence réseau ni surcharge de sérialisation de protocole.
  • Outil d'agent distant (currency_agent) : s'exécute en tant que microservice indépendant, appelé sur le réseau via le protocole A2A.

Points abordés

  • Créer et tester un serveur MCP local à l'aide de FastMCP sur HTTP diffusable
  • Comment créer un agent avec ADK qui utilise des outils MCP (McpToolset)
  • Exposer un agent ADK en tant que serveur A2A (to_a2a)
  • Tester un serveur A2A à l'aide du client Python A2A (a2a.client)
  • Créer un agent orchestrateur qui combine des outils de sous-agents locaux avec des agents A2A distants
  • Exécuter et tester le système multi-agent complet localement avec l'UI Web d'ADK
  • Conteneuriser et déployer les trois composants sur Google Cloud Run

Prérequis

  • Un navigateur tel que Chrome.
  • Un projet Google Cloud avec facturation activée.

2. Avant de commencer

Créer un projet

Si vous n'avez pas de projet Google Cloud, créez-en un.

Dans la console Google Cloud, sur la page du sélecteur de projet, sélectionnez ou créez un projet Google Cloud.

Assurez-vous également que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier si la facturation est activée sur un projet.

Activer Cloud Shell

Google Cloud Shell est un environnement de développement interactif basé sur un navigateur, fourni directement dans la console Google Cloud. C'est le moyen le plus simple de faire vos premiers pas avec Google Cloud sans avoir à installer d'outils localement.

Cliquez sur ce lien pour activer Cloud Shell. Vous pouvez basculer entre le terminal Cloud Shell (pour exécuter des commandes cloud) et l'éditeur (pour afficher des fichiers) en cliquant sur le bouton correspondant dans Cloud Shell.

Une fois connecté à Cloud Shell, vérifiez que vous êtes authentifié :

gcloud auth list

Vérifiez que la commande gcloud reconnaît votre projet :

gcloud config list project

Définissez votre ID de projet :

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

Activer API Cloud

Activez les API requises pour Cloud Run, Cloud Build, Artifact Registry et Vertex AI :

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

Obtenir le code

Clonez le dépôt et accédez au répertoire python :

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

Installez les dépendances avec uv.

uv est un gestionnaire de paquets et de projets Python rapide. Il est préinstallé dans Cloud Shell. Si vous exécutez le code localement, vous pouvez l'installer comme suit :

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

Le répertoire Python est structuré comme un uv unifié.

Workspace. Installez toutes les dépendances de tous les membres de l'espace de travail (currency_mcp_server, currency_agent et travel_agent) dans un seul environnement virtuel en exécutant la commande suivante :

uv sync

Configurer les variables d'environnement

Configurez les variables d'environnement dans un fichier .env du répertoire python :

Option A : 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

Option B : Google AI Studio (clé API locale)

Si vous préférez utiliser une clé API de Google AI Studio :

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

3. Créer le serveur MCP Currency

Avant de créer vos agents, vous allez d'abord explorer le serveur MCP qui expose l'outil de conversion de devises.

Un serveur MCP vous permet d'écrire des programmes légers pour exposer des fonctionnalités en tant qu'outils. Un ou plusieurs agents peuvent ensuite accéder à ces outils à l'aide du Model Context Protocol standardisé.

Le package Python FastMCP peut être utilisé pour créer un serveur MCP qui expose un seul outil appelé get_exchange_rate. L'outil get_exchange_rate appelle l'API Frankfurter pour obtenir le taux de change actuel entre deux devises.

Le code du serveur MCP se trouve dans currency_mcp_server/server.py :

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

Démarrer le serveur MCP localement

Démarrez le serveur MCP dans votre terminal :

uv run python currency_mcp_server/server.py

Le serveur démarre sur le port 8080 avec le point de terminaison HTTP en flux continu disponible sur /mcp (http://localhost:8080/mcp).

Tester le serveur MCP

Ouvrez une deuxième fenêtre de terminal (en laissant le serveur MCP s'exécuter dans la première), accédez au dossier python (cd getting-started-mcp-a2a-adk/python), puis exécutez le script de test :

uv run python currency_mcp_server/test_server.py

Le script de test se connecte au point de terminaison MCP à l'aide de Client de FastMCP, liste les outils et appelle get_exchange_rate :

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

Formidable ! Vous disposez d'un serveur MCP fonctionnel qui expose un outil de conversion de devises en temps réel. Laissez ce terminal ouvert pour les étapes suivantes.

4. Créer l'agent de conversion de devises avec ADK

Il est maintenant temps de créer l'agent de conversion de devises à l'aide d'Agent Development Kit (ADK).

ADK est compatible de manière intégrée avec les outils MCP via la classe McpToolset. L'agent de devises se connecte à notre serveur MCP à l'aide de StreamableHTTPConnectionParams.

Examinez la définition de l'agent de devise dans currency_agent/agent.py :

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
            )
        )
    ],
)

Notez que McpToolset détecte et charge automatiquement l'outil get_exchange_rate directement depuis le serveur MCP en cours d'exécution via HTTP.

Tester l'agent de conversion de devises avec l'UI Web d'ADK

Vous pouvez tester l'agent de manière isolée à l'aide de l'interface Web de développement d'ADK. Dans votre deuxième terminal, exécutez la commande suivante :

uv run adk web --allow_origins "*" currency_agent

Ouvrez votre navigateur à l'adresse http://localhost:8000 (ou cliquez sur Aperçu sur le Web dans Cloud Shell).

Agent de conversion de devises ADK Web

Demandez à l'agent :

"Combien font 250 USD en EUR ?"

Vous verrez l'agent appeler l'outil MCP get_exchange_rate et renvoyer le montant converti. Arrêtez le processus adk web à l'aide de Ctrl+C avant de continuer.

5. Protocole Agent2Agent (A2A)

Le protocole Agent2Agent (A2A) est une norme ouverte conçue pour permettre la communication et la collaboration entre les agents IA.

Dans les systèmes multi-agents modernes, les agents sont souvent créés à l'aide de différents frameworks (ADK, LangChain, CrewAI, AutoGen) et déployés sur différentes infrastructures. L'A2A élimine ces silos en définissant un contrat de communication standardisé.

Protocole A2A

Concepts clés du protocole A2A

  • Découverte d'agents (carte d'agent) : chaque agent compatible avec l'A2A annonce ses capacités, les modes d'E/S compatibles, les exigences d'authentification et ses compétences via un fichier JSON standard hébergé à l'adresse /.well-known/agent-card.json.
  • Compétences de l'agent (AgentSkill) : fonctionnalités ou outils spécifiques que l'agent peut exécuter. Les autres agents lisent ces compétences pour déterminer quand déléguer des tâches.
  • Communication JSON-RPC : les agents échangent des messages, des tâches et des artefacts structurés via des transports standards tels que HTTP JSON-RPC 2.0.

Carte d'agent A2A

À l'étape suivante, vous allez exposer notre agent de conversion de devises ADK en tant que serveur A2A afin que d'autres agents puissent le découvrir et lui déléguer des tâches de conversion de devises.

6. Exposer l'agent de conversion de devises en tant que serveur A2A

ADK permet de transformer n'importe quel LlmAgent en serveur compatible A2A sans effort grâce à la fonction utilitaire to_a2a().

Examinez la partie inférieure de currency_agent/agent.py :

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

L'outil d'aide to_a2a() effectue automatiquement les opérations suivantes :

  1. Inspecte les outils et les instructions de LlmAgent.
  2. Génère un AgentCard A2A décrivant ses compétences (par exemple, currency_agent-get_exchange_rate).
  3. Encapsule l'agent dans une application FastAPI (a2a_app) compatible avec les points de terminaison JSON-RPC.
  4. Configure de manière dynamique l'url annoncé dans la fiche de l'agent en fonction de AGENT_URL (ou de l'hôte local).

Démarrer le serveur A2A de l'agent Currency

Dans votre deuxième terminal, démarrez l'agent de devises :

uv run python currency_agent/agent.py

Le serveur démarre sur le port 8081 :

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

Inspecter la fiche de l'agent

Dans votre navigateur, accédez au point de terminaison de la fiche d'agent : http://localhost:8081/.well-known/agent-card.json.

Les métadonnées JSON générées automatiquement s'affichent :

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

Tester avec le client A2A

Ouvrez un troisième terminal, accédez au dossier python (cd getting-started-mcp-a2a-adk/python), puis testez le point de terminaison A2A à l'aide du script client de test A2A dédié :

uv run python currency_agent/test_a2aclient.py

Le client résout la fiche de l'agent à l'aide de A2ACardResolver et envoie un message JSON-RPC :

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

L'agent Currency fonctionne désormais comme un serveur A2A entièrement fonctionnel.

7. Créer l'agent de voyage

Vous allez maintenant créer l'agent de voyage d'orchestration. Cet agent montre comment un agent ADK peut combiner sans effort deux paradigmes d'outils différents :

  1. Local Agent Tool (weather_agent): Un sous-agent ADK en cours d'exécution dans le même environnement d'exécution Python, évitant toute latence réseau ou de sérialisation.
  2. Outil d'agent distant (currency_agent) : agent externe connecté au réseau via le protocole A2A à l'aide de RemoteA2aAgent.
                    +-----------------------------+
                    |        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. Sous-agent "Météo locale"

Examinez l'élément travel_agent/subagents/weather_agent.py :

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],
)

L'agent météo est un LlmAgent doté d'un outil de fonction qui récupère la météo en temps réel à partir de wttr.in avec un remplacement résilient.

2. L'outil d'orchestration d'agents de voyage

Regardez maintenant travel_agent/agent.py :

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)

Principaux points forts :

  • RemoteA2aAgent récupère la carte de l'agent de devise auprès de http://localhost:8081/.well-known/agent-card.json.
  • currency_remote_agent et weather_agent sont encapsulés à l'aide de AgentTool d'ADK.
  • L'exécution de travel_agent/agent.py démarre directement l'UI Web d'ADK sur le port 8082 à l'aide de get_fast_api_app(web=True).

8. Exécuter et tester le système multi-agent localement

Les trois composants sont maintenant prêts. Exécutons et testons le système complet en local.

Exécuter les trois services

Assurez-vous que les services sont exécutés dans trois fenêtres de terminal distinctes (à partir du répertoire getting-started-mcp-a2a-adk/python) dans l'ordre suivant :

Terminal 1 (serveur MCP de devises) :

uv run python currency_mcp_server/server.py

(Running on port 8080)

Terminal 2 (agent A2A de devise) :

uv run python currency_agent/agent.py

(Exécution sur le port 8081)

Terminal 3 (agent de voyage avec UI Web) :

uv run python travel_agent/agent.py

(Exécution sur le port 8082)

Tester via l'UI Web d'ADK

Ouvrez votre navigateur à l'adresse http://localhost:8082 (ou utilisez l'aperçu sur le Web sur le port 8082 dans Cloud Shell).

Posez à l'agent de voyage une question complexe nécessitant les deux outils :

"Je prévois un voyage à Londres. Quel temps fait-il et combien font 200 EUR en GBP ?"

Regardez le flux d'exécution :

  1. L'agent de voyage reçoit la requête dans l'UI Web.
  2. Il délègue la question sur la météo en cours de traitement au weather_agent local, qui récupère les conditions actuelles à partir de wttr.in.
  3. Il délègue la conversion de devises via le protocole A2A à currency_agent sur le port 8081.
  4. currency_agent appelle currency_mcp_server sur le port 8080 via MCP pour récupérer le taux de change.
  5. Tous les résultats sont synthétisés et vous sont renvoyés dans une réponse unifiée et utile.

Agent de conversion de devises distant ADK Web

Tester via la ligne de commande

Vous pouvez également tester des requêtes directement depuis la CLI sans ouvrir de navigateur :

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

Maintenant que tout fonctionne parfaitement sur votre ordinateur local, déployons l'ensemble du système sur Google Cloud Run.

9. Déployer le système multi-agents sur Cloud Run

Chaque composant possède son propre Dockerfile et un pyproject.toml autonome, ce qui permet de le créer et de le déployer indépendamment sur Cloud Run.

À l'aide de gcloud, vous allez déployer chaque service et associer automatiquement leurs URL.

Définir des variables d'environnement

Définissez l'ID de votre projet Cloud et la région cible :

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

Étape 1 : Déployer le serveur MCP Currency

Déployez le serveur MCP directement à partir de la source :

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

Étape 2 : Déployer l'agent de conversion de devises

Étant donné que l'URL publique de currency-agent est attribuée lors de son premier déploiement, déployez d'abord le service, capturez son URL et mettez à jour sa variable d'environnement AGENT_URL afin que sa carte d'agent A2A annonce l'adresse HTTPS publique correcte :

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

Étape 3 : Déployer l'agent de voyage

Déployez maintenant l'agent de voyage en le configurant avec le CURRENCY_AGENT_URL :

# 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. Tester le système multi-agent dans Cloud Run

Maintenant que les trois microservices sont déployés, vérifions chaque couche dans Cloud Run.

1. Tester le serveur MCP distant

Testez le serveur MCP Cloud Run déployé à partir de votre ligne de commande :

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

L'outil doit s'afficher dans la liste et être appelé avec succès sur Cloud Run.

2. Tester l'agent de conversion de devises via A2A

Testez l'agent de conversion de devises déployé à l'aide du client de test A2A :

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

Le client récupérera la carte d'agent distante depuis Cloud Run et échangera des messages via HTTPS JSON-RPC.

3. Tester l'UI Web de l'agent de voyage dans Cloud Run

Ouvrez $TRAVEL_AGENT_URL dans votre navigateur.

L'UI Web d'ADK complète est diffusée directement depuis Cloud Run. Essayez ces requêtes :

"Je prévois un voyage à Tokyo. Quel temps fait-il et combien font 500 USD en JPY ?"

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

Les trois services évoluent indépendamment sur une infrastructure sans serveur et communiquent de manière fluide via des protocoles ouverts.

11. Félicitations et nettoyage

Ce que vous avez accompli

Félicitations ! Vous avez créé et déployé un système multi-agent de qualité professionnelle :

  • Model Context Protocol (MCP) : vous avez créé un serveur FastMCP exposant des outils d'API en direct via HTTP diffusable.
  • Agent Development Kit (ADK) : vous avez créé des agents modulaires à l'aide de LlmAgent, connecté des outils MCP avec McpToolset et hébergé l'UI Web d'ADK.
  • Protocole Agent2Agent (A2A) : vous avez exposé un agent en tant que service A2A (to_a2a), publié des fiches d'agent (agent-card.json) et utilisé des agents distants à l'aide de RemoteA2aAgent.
  • Architecture multi-agent : combinaison de sous-agents locaux en cours d'exécution (weather_agent) et d'agents distants distribués (currency_agent).
  • Déploiement sans serveur Cloud Run : conteneurisation et déploiement des trois services avec configuration automatisée.

Pour obtenir le code complet (y compris les implémentations Python et Java) et les futures mises à jour, consultez le dépôt getting-started-mcp-a2a-adk.

Effectuer un nettoyage

Pour éviter que les services Cloud Run créés dans cet atelier de programmation ne soient facturés sur votre compte Google Cloud :

Supprimez les services Cloud Run déployés :

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

Si vous avez créé un projet dédié pour cet atelier de programmation, vous pouvez également l'arrêter complètement :

gcloud projects delete $PROJECT_ID