Como começar a usar o MCP e o A2A com o ADK

1. Visão geral

Os agentes de IA estão se tornando cada vez mais populares, revolucionando a automação de tarefas e a tomada de decisões com a capacidade de operar de forma autônoma, aprender e interagir com o ambiente para alcançar metas.

Este codelab vai ajudar você a começar a criar um sistema multiagente completo. Você vai criar um servidor MCP de moedas, um agente de moedas que consome o servidor MCP e é exposto pelo protocolo Agent2Agent (A2A), um agente de viagens com um subagente de clima em processo que consome o agente de moedas pelo A2A e, por fim, implantar todos os serviços no Cloud Run.

Arquitetura

Principais tecnologias

Protocolo de Contexto de Modelo (MCP)

O Protocolo de Contexto de Modelo (MCP) é um protocolo aberto que padroniza como os aplicativos fornecem contexto e ferramentas para LLMs. Pense no MCP como uma porta USB-C para aplicativos de IA: ele oferece uma maneira padronizada de conectar modelos de IA a fontes de dados, APIs e ferramentas externas.

Neste codelab, o currency_mcp_server expõe uma ferramenta get_exchange_rate por HTTP com streaming (/mcp), com suporte da API Frankfurter pública.

Kit de Desenvolvimento de Agente (ADK)

O Kit de Desenvolvimento de Agente (ADK) é um framework de orquestração flexível para desenvolver e implantar agentes de IA. O ADK é independente de modelo e de implantação e foi criado para ser compatível com outros frameworks. O ADK faz com que o desenvolvimento de agentes pareça engenharia de software padrão, facilitando a criação, o teste e a orquestração de Agentic Workflows complexos.

O ADK lida com as conversas dos usuários, exibe a interface da Web interativa, se conecta às ferramentas do MCP via McpToolset e gerencia as comunicações A2A.

Protocolo Agent2Agent (A2A)

O protocolo Agent2Agent (A2A) é um padrão aberto criado para permitir a comunicação e a colaboração entre agentes de IA. Assim como o MCP padroniza as conexões entre agentes e ferramentas, o A2A padroniza a colaboração entre agentes. Em um mundo em que os agentes são criados em diversos frameworks, ambientes de hospedagem e organizações, o A2A oferece uma linguagem comum para descoberta e delegação de tarefas.

O ADK expõe currency_agent como um serviço A2A (to_a2a) e permite que travel_agent o consuma remotamente como um AgentTool (RemoteA2aAgent).

Subagentes locais x agentes A2A remotos

Essa arquitetura destaca um padrão crucial no design de multiagentes:

  • Ferramenta de agente local (weather_agent): é executada em processo no orquestrador como um AgentTool, com latência de rede zero ou sobrecarga de serialização de protocolo.
  • Ferramenta de agente remoto (currency_agent): é executada como um microsserviço independente, chamado pela rede usando o protocolo A2A.

O que você vai aprender

  • Como criar e testar um servidor MCP local usando o FastMCP com HTTP transmissível
  • Como criar um agente com o ADK que usa ferramentas do MCP (McpToolset)
  • Como expor um agente do ADK como um servidor A2A (to_a2a)
  • Como testar um servidor A2A usando o cliente Python A2A (a2a.client)
  • Como criar um agente orquestrador que combina ferramentas de subagentes locais com agentes A2A remotos
  • Como executar e testar o sistema multiagente completo localmente com a interface da Web do ADK
  • Como conteinerizar e implantar os três componentes no Google Cloud Run

O que é necessário

  • Um navegador, como o Chrome.
  • Ter um projeto do Google Cloud com o faturamento ativado.

2. Antes de começar

Criar um projeto

Se você não tiver um projeto na nuvem do Google Cloud, crie um.

No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.

Verifique também se o faturamento está ativado para seu projeto na nuvem. Saiba como verificar se o faturamento está ativado em um projeto.

Ativar o Cloud Shell

O Google Cloud Shell é um ambiente de desenvolvimento interativo baseado em navegador, fornecido diretamente no console do Google Cloud. É a maneira mais fácil de começar a usar o Google Cloud sem precisar instalar ferramentas localmente.

Ative o Cloud Shell clicando neste link. Você pode alternar entre o terminal do Cloud Shell (para executar comandos na nuvem) e o editor (para visualizar arquivos) clicando no botão correspondente no Cloud Shell.

Depois de se conectar ao Cloud Shell, verifique se você está autenticado:

gcloud auth list

Confirme se o comando gcloud sabe sobre seu projeto:

gcloud config list project

Configure o ID do projeto:

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

Ativar APIs do Cloud

Ative as APIs necessárias para o Cloud Run, o Cloud Build, o Artifact Registry e a Vertex AI:

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

Acessar o código

Clone o repositório e navegue até o diretório python:

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

Instale as dependências com uv.

O uv é um gerenciador de pacotes e projetos rápido do Python. Ele vem pré-instalado no Cloud Shell. Se estiver executando localmente, instale-o da seguinte maneira:

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

O diretório do Python é estruturado como um uv unificado.

Workspace. Instale todas as dependências em todos os membros do espaço de trabalho (currency_mcp_server, currency_agent e travel_agent) em um único ambiente virtual executando:

uv sync

Configure as variáveis de ambiente

Configure as variáveis de ambiente em um arquivo .env no diretório python:

Opção 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

Opção B: Google AI Studio (chave de API local)

Se você preferir usar uma chave de API do Google AI Studio:

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

3. Criar o servidor MCP de moedas

Antes de criar seus agentes, você vai conhecer o servidor MCP que expõe a ferramenta de conversão de moedas.

Um servidor MCP permite que você escreva programas leves para expor recursos como ferramentas. Um agente (ou vários agentes) pode acessar essas ferramentas usando o Protocolo de Contexto de Modelo padronizado.

O pacote Python FastMCP pode ser usado para criar um servidor MCP que expõe uma única ferramenta chamada get_exchange_rate. A ferramenta get_exchange_rate chama a API Frankfurter para receber a taxa de câmbio atual entre duas moedas.

O código do servidor MCP está em 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,
        )
    )

Inicie o servidor MCP localmente

Inicie o servidor MCP no terminal:

uv run python currency_mcp_server/server.py

O servidor é iniciado na porta 8080 com o endpoint HTTP transmissível disponível em /mcp (http://localhost:8080/mcp).

Testar o servidor MCP

Abra uma segunda janela do terminal (deixando o servidor MCP em execução na primeira), navegue até a pasta python (cd getting-started-mcp-a2a-adk/python) e execute o script de teste:

uv run python currency_mcp_server/test_server.py

O script de teste se conecta ao endpoint do MCP usando o Client do FastMCP, lista as ferramentas e invoca 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}} ---

Incrível! Você tem um servidor MCP em funcionamento que expõe uma ferramenta de conversão de moedas em tempo real. Mantenha esse terminal aberto para as próximas etapas.

4. Criar o agente de moedas com o ADK

Agora é hora de criar o agente de moedas usando o Kit de Desenvolvimento de Agente (ADK).

O ADK oferece suporte integrado para ferramentas MCP por meio da classe McpToolset. O agente de moedas se conecta ao nosso servidor MCP usando StreamableHTTPConnectionParams.

Confira a definição do agente de moeda em 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
            )
        )
    ],
)

Observe como o McpToolset descobre e carrega automaticamente a ferramenta get_exchange_rate diretamente do servidor MCP em execução via HTTP.

Testar o agente de moedas com a interface da Web do ADK

É possível testar o agente de forma isolada usando a interface da web de desenvolvimento do ADK. No segundo terminal, execute:

uv run adk web --allow_origins "*" currency_agent

Abra o navegador em http://localhost:8000 (ou clique em Visualização da Web no Cloud Shell).

Agente de moedas do ADK Web

Pergunte ao agente:

"Quanto é 250 USD em EUR?"

Você vai notar que o agente invoca a ferramenta MCP get_exchange_rate e retorna o valor convertido. Interrompa o processo adk web usando Ctrl+C antes de continuar.

5. Protocolo Agent2Agent (A2A)

O protocolo Agent2Agent (A2A) é um padrão aberto criado para permitir a comunicação e a colaboração entre agentes de IA.

Em sistemas multiagente modernos, os agentes geralmente são criados usando diferentes frameworks (ADK, LangChain, CrewAI, AutoGen) e implantados em infraestruturas distintas. A A2A elimina esses silos definindo um contrato de comunicação padronizado.

Protocolo A2A

Principais conceitos do A2A

  • Descoberta de agentes (card do agente): cada agente compatível com A2A anuncia seus recursos, modos de E/S compatíveis, requisitos de autenticação e habilidades por um arquivo JSON padrão hospedado em /.well-known/agent-card.json.
  • Habilidades do agente (AgentSkill): recursos ou ferramentas específicas que o agente pode executar. Outros agentes leem essas habilidades para decidir quando delegar tarefas.
  • Comunicação JSON-RPC:os agentes trocam mensagens, tarefas e artefatos estruturados por transportes padrão, como HTTP JSON-RPC 2.0.

Card do agente A2A

Na próxima etapa, você vai expor nosso agente de moedas do ADK como um servidor A2A para que outros agentes possam descobri-lo e delegar tarefas de conversão de moedas a ele.

6. Expor o agente de conversão de moedas como um servidor A2A

O ADK facilita a transformação de qualquer LlmAgent em um servidor compatível com A2A usando a função utilitária to_a2a().

Revise a parte de baixo 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)

O assistente to_a2a() faz o seguinte automaticamente:

  1. Inspeciona as ferramentas e instruções do LlmAgent.
  2. Gera um AgentCard de A2A que descreve as habilidades dele (por exemplo, currency_agent-get_exchange_rate).
  3. Envolve o agente em um aplicativo FastAPI (a2a_app) compatível com endpoints JSON-RPC.
  4. Configura dinamicamente o url anunciado no card do agente com base em AGENT_URL (ou localhost).

Iniciar o servidor A2A do agente de moedas

No segundo terminal, inicie o agente de moeda:

uv run python currency_agent/agent.py

O servidor é iniciado na porta 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)

Inspecionar o card do agente

No navegador, acesse o endpoint do card do agente: http://localhost:8081/.well-known/agent-card.json

Você vai ver os metadados JSON gerados automaticamente:

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

Testar com o cliente A2A

Abra um terceiro terminal, navegue até a pasta python (cd getting-started-mcp-a2a-adk/python) e teste o endpoint A2A usando o script de cliente de teste A2A dedicado:

uv run python currency_agent/test_a2aclient.py

O cliente resolve o card do agente usando A2ACardResolver e envia uma mensagem 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...

O agente de moedas agora está operando como um servidor A2A totalmente funcional.

7. Criar o agente de viagens

Agora você vai criar o agente de viagens de orquestração. Este agente mostra como um agente do ADK pode combinar facilmente dois paradigmas de ferramentas diferentes:

  1. Ferramenta de agente local (weather_agent): um subagente do ADK em processo que é executado no mesmo ambiente de execução do Python, evitando qualquer latência de rede ou serialização.
  2. Ferramenta de agente remoto (currency_agent): um agente externo conectado pela rede usando o protocolo A2A com 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. Subagente de clima local

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

O agente de clima é um LlmAgent com uma ferramenta de função que busca o clima em tempo real de wttr.in com um substituto resiliente.

2. O orquestrador de agentes de viagens

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

Destaques:

  • RemoteA2aAgent busca o card do agente de moedas em http://localhost:8081/.well-known/agent-card.json.
  • currency_remote_agent e weather_agent são encapsulados usando o AgentTool do ADK.
  • A execução de travel_agent/agent.py inicializa diretamente a interface da Web do ADK na porta 8082 usando get_fast_api_app(web=True).

8. Executar e testar o sistema multiagente localmente

Agora, os três componentes estão prontos. Vamos executar e testar o sistema completo localmente.

Executar os três serviços

Verifique se os serviços estão em execução em três janelas do terminal separadas (no diretório getting-started-mcp-a2a-adk/python) na seguinte ordem:

Terminal 1 (servidor MCP de moedas):

uv run python currency_mcp_server/server.py

(em execução na porta 8080)

Terminal 2 (agente A2A de moeda):

uv run python currency_agent/agent.py

(em execução na porta 8081)

Terminal 3 (agente de viagens com interface da Web):

uv run python travel_agent/agent.py

(Running on port 8082)

Testar usando a interface da Web do ADK

Abra o navegador em http://localhost:8082 (ou use a Visualização da Web na porta 8082 no Cloud Shell).

Faça ao agente de viagens uma pergunta composta que exija as duas ferramentas:

"Estou planejando uma viagem para Londres. Como está o clima e quanto é 200 EUR em GBP?"

Assista ao fluxo de execução:

  1. O agente de viagens recebe a solicitação na interface da Web.
  2. Ele delega a pergunta sobre o clima em processo ao weather_agent local, que busca as condições atuais em wttr.in.
  3. Ele delega a conversão de moedas pelo protocolo A2A para currency_agent na porta 8081.
  4. O currency_agent chama o currency_mcp_server na porta 8080 pelo MCP para buscar a taxa de câmbio.
  5. Todos os resultados são sintetizados e retornados em uma resposta unificada e útil.

Agente de moeda remoto da Web do ADK

Testar pela linha de comando

Também é possível testar consultas diretamente da CLI sem abrir um navegador:

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

Agora que tudo funciona perfeitamente na sua máquina local, vamos implantar todo o sistema no Google Cloud Run.

9. Implantar o sistema multiagente no Cloud Run

Cada componente tem o próprio Dockerfile e um pyproject.toml independente para que possa ser criado e implantado de forma independente no Cloud Run.

Usando o gcloud, você vai implantar cada serviço e conectar os URLs deles automaticamente.

Defina as variáveis de ambiente

Defina o ID do projeto na nuvem e a região de destino:

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

Etapa 1: implantar o servidor MCP de moedas

Implante o servidor MCP diretamente da origem:

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

Etapa 2: implantar o agente de moedas

Como o URL público de currency-agent é atribuído na primeira implantação, implante o serviço primeiro, capture o URL e atualize a variável de ambiente AGENT_URL para que o card do agente A2A divulgue o endereço HTTPS público correto:

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

Etapa 3: implantar o agente de viagens

Agora, implante o agente de viagens, configurando-o com o 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. Testar o sistema multiagente no Cloud Run

Com os três microsserviços implantados, vamos verificar cada camada no Cloud Run.

1. Testar o servidor MCP remoto

Teste o servidor MCP do Cloud Run implantado na linha de comando:

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

A ferramenta vai aparecer na lista e será invocada no Cloud Run.

2. Testar o agente de moedas via A2A

Teste o agente de conversão de moedas implantado usando o cliente de teste A2A:

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

O cliente vai buscar o card do agente remoto no Cloud Run e trocar mensagens por JSON-RPC HTTPS.

3. Testar a interface da Web do agente de viagens no Cloud Run

Abra $TRAVEL_AGENT_URL no seu navegador.

A interface da Web completa do ADK é disponibilizada diretamente pelo Cloud Run. Tente perguntar:

"Estou planejando uma viagem para Tóquio. Como está o clima e quanto é 500 dólares em ienes?"

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

Os três serviços são escalonados de forma independente na infraestrutura sem servidor, comunicando-se perfeitamente por protocolos abertos.

11. Parabéns e limpeza

O que você realizou

Parabéns! Você criou e implantou um sistema multiagente de nível de produção:

  • Protocolo de Contexto de Modelo (MCP): criamos um servidor FastMCP que expõe ferramentas de API em tempo real por HTTP de streaming.
  • Kit de Desenvolvimento de Agente (ADK): criamos agentes modulares usando LlmAgent, conectamos ferramentas do MCP com McpToolset e hospedamos a interface da Web do ADK.
  • Protocolo Agent2Agent (A2A):expôs um agente como um serviço A2A (to_a2a), publicou cards de agente (agent-card.json) e consumiu agentes remotos usando RemoteA2aAgent.
  • Arquitetura multiagente:subagentes locais em processo (weather_agent) combinados com agentes remotos distribuídos (currency_agent).
  • Implantação sem servidor do Cloud Run:conteinerização e implantação dos três serviços com conexão de configuração automatizada.

Para conferir o código completo (incluindo as implementações em Python e Java) e as atualizações futuras, acesse o repositório getting-started-mcp-a2a-adk.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos serviços do Cloud Run criados neste codelab:

Exclua os serviços do Cloud Run implantados:

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

Como alternativa, se você criou um projeto dedicado para este codelab, é possível encerrar o projeto inteiro:

gcloud projects delete $PROJECT_ID