Cymbal Transit: um sistema multiagente que usa o LangChain4J e o SDK Java do MCP Toolbox

1. Visão geral

Os viajantes modernos esperam experiências conversacionais. Em vez de navegar por filtros complexos da interface, eles querem perguntar: "Posso levar meu cachorro no ônibus das 9h para Boston?" Isso exige um agente que possa raciocinar com dados não estruturados (políticas em PDF) e estruturados (programações SQL).

Neste laboratório, vamos criar o Agente de trânsito da Cymbal usando:

  • LangChain4j:o principal framework Java para orquestração de IA.
  • AlloyDB:um banco de dados de alto desempenho compatível com PostgreSQL.
  • SDK do Java da MCP Toolbox:uma maneira padronizada de conectar agentes Java a ferramentas e fontes de dados externas.

O que você vai criar

e68388d533c9997e.png

Cymbal Bus Agent, um aplicativo Java Spring Boot que consiste em:

  1. Banco de dados do AlloyDB e SDK Java do MCP Toolbox para orquestração de ferramentas com os agentes.
  2. Cloud Run para implantação e aplicativo da caixa de ferramentas (implantação do agente).
  3. Biblioteca LangChain4J para o agente e o framework de LLM em um aplicativo Spring Boot com Java 17.

O que você vai aprender

  • Como usar o LangChain4J para criar agentes e subagentes especializados orquestrados usando o SDK do MCP Toolbox for Databases Java
  • Como configurar e usar o AlloyDB para dados e IA.
  • Como usar a MCP Toolbox para conectar agentes às ferramentas de dados do AlloyDB.
  • Como implantar a solução usando o Cloud Run ou executá-la localmente.

A arquitetura

  1. AlloyDB para PostgreSQL:serve como o banco de dados operacional de alto desempenho que contém nossos registros de rotas, políticas e reservas. Ele alimenta a pesquisa e a recuperação de vetores.
  2. SDK Java da MCP Toolbox for Databases:atua como o "maestro de orquestração", expondo dados do AlloyDB como ferramentas executáveis que os agentes podem chamar.

O SDK Java da MCP Toolbox permite orquestrar agentes com suas ferramentas de banco de dados sem esforço para aplicativos de nível empresarial.

  1. LangChain4J:uma biblioteca Java de código aberto que simplifica a integração de modelos de linguagem grandes (LLMs) em aplicativos Java. Ela oferece ferramentas e abstrações para criar aplicativos com tecnologia de IA, incluindo chatbots, agentes e sistemas de geração aumentada por recuperação (RAG).
  2. Cloud Run:uma plataforma sem servidor totalmente gerenciada que permite criar e implantar apps ou sites rapidamente em qualquer linguagem, biblioteca ou binário. Você pode escrever código usando sua linguagem, framework e bibliotecas favoritos, empacotá-lo como um contêiner, executar "gcloud run deploy". Seu app vai ser ativado, fornecendo tudo o que é necessário para ser executado na produção. Criar um contêiner é totalmente opcional. Se você usa Go, Node.js, Python, Java, .NET Core ou Ruby, pode usar a opção de implantação baseada em origem, que cria o contêiner para você seguindo as práticas recomendadas para a linguagem que você está usando.

Requisitos

  • Um navegador, como o Chrome ou o Firefox
  • Ter um projeto do Google Cloud com o faturamento ativado.
  • Ter noções básicas sobre SQL e Java.

2. Antes de começar

Criar um projeto

  1. No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
  2. Confira se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto.
  1. Você vai usar o Cloud Shell, um ambiente de linha de comando executado no Google Cloud. Clique em "Ativar o Cloud Shell" na parte de cima do console do Google Cloud.

Imagem do botão "Ativar o Cloud Shell"

  1. Depois de se conectar ao Cloud Shell, verifique se sua conta já está autenticada e se o projeto está configurado com o ID do seu projeto usando o seguinte comando:
gcloud auth list
  1. Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto.
gcloud config list project
  1. Se o projeto não estiver definido, use este comando:
gcloud config set project <YOUR_PROJECT_ID>
  1. Ative as APIs necessárias: siga o link e ative as APIs.

Como alternativa, use o comando gcloud. Consulte a documentação para ver o uso e os comandos gcloud.

Problemas e solução de problemas

A síndrome do projeto fantasma

Você executou gcloud config set project, mas está olhando para um projeto diferente na interface do Console. Verifique o ID do projeto no menu suspenso no canto superior esquerdo.

A barricada de faturamento

Você ativou o projeto, mas esqueceu a conta de faturamento. O AlloyDB é um mecanismo de alto desempenho. Ele não vai iniciar se o "tanque de combustível" (faturamento) estiver vazio.

Atraso na propagação da API

Você clicou em "Ativar APIs", mas a linha de comando ainda mostra Service Not Enabled. Aguarde 60 segundos. A nuvem precisa de um momento para ativar os neurônios.

Quags de cota

Se você estiver usando uma conta de teste nova, talvez atinja uma cota regional para instâncias do AlloyDB. Se us-central1 falhar, tente us-east1.

Agente de serviço"oculto"

Às vezes, o agente de serviço do AlloyDB não recebe automaticamente o papel aiplatform.user. Se as consultas SQL não puderem se comunicar com o Gemini mais tarde, esse geralmente é o motivo.

3. Configuração do banco de dados

O AlloyDB para PostgreSQL é a base do nosso aplicativo. Aproveitamos os recursos avançados de vetor e o mecanismo colunar integrado para gerar incorporações de mais de 50.000 registros da SCM. Isso permite uma análise de vetores quase em tempo real, permitindo que nossos agentes identifiquem anomalias de inventário ou riscos de logística em grandes conjuntos de dados em milissegundos.

Neste laboratório, vamos usar o AlloyDB como banco de dados para os dados de teste. Ele usa clusters para armazenar todos os recursos, como bancos de dados e registros. Cada cluster tem uma instância principal que fornece um ponto de acesso aos dados. As tabelas vão conter os dados reais.

Vamos criar um cluster, uma instância e uma tabela do AlloyDB em que o conjunto de dados de teste será carregado.

  1. Clique no botão ou copie o link abaixo para o navegador em que o usuário do console do Google Cloud está conectado.

Como alternativa, acesse o terminal do Cloud Shell no projeto em que você resgatou a conta de faturamento, clone o repositório do GitHub e navegue até o projeto usando os comandos abaixo:

git clone https://github.com/AbiramiSukumaran/easy-alloydb-setup

cd easy-alloydb-setup
  1. Depois que essa etapa for concluída, o repositório será clonado no editor local do Cloud Shell, e você poderá executar o comando abaixo na pasta do projeto. É importante verificar se você está no diretório do projeto:
sh run.sh
  1. Agora use a interface (clique no link no terminal ou no link "visualizar na Web" no terminal).
  2. Insira os detalhes do ID do projeto, do cluster e dos nomes das instâncias para começar.
  3. Tome um café enquanto os registros rolam e leia aqui como isso é feito nos bastidores.

Problemas e solução de problemas

O problema da "paciência"

Os clusters de banco de dados são uma infraestrutura pesada. Se você atualizar a página ou encerrar a sessão do Cloud Shell porque ela "parece travada", poderá acabar com uma instância "fantasma" parcialmente provisionada e impossível de excluir sem intervenção manual.

Incompatibilidade de região

Se você ativou as APIs em us-central1, mas tentou provisionar o cluster em asia-south1, talvez tenha problemas de cota ou atrasos na permissão da conta de serviço. Use uma região para todo o laboratório.

Clusters zumbis

Se você usou o mesmo nome para um cluster e não o excluiu, o script pode informar que o nome do cluster já existe. Os nomes de cluster precisam ser exclusivos em um projeto.

Tempo limite do Cloud Shell

Se o intervalo para o café durar 30 minutos, o Cloud Shell poderá entrar em modo de espera e desconectar o processo sh run.sh. Mantenha a guia ativa!

4. Provisionamento de esquema

Depois que o cluster e a instância do AlloyDB estiverem em execução, acesse o editor de SQL do AlloyDB Studio para ativar as extensões de IA e provisionar o esquema.

1e3ac974b18a8113.png

Talvez seja necessário aguardar a conclusão da criação da instância. Depois disso, faça login no AlloyDB usando as credenciais criadas ao criar o cluster. Use os seguintes dados para autenticar no PostgreSQL:

  • Nome de usuário : "postgres"
  • Banco de dados : "postgres"
  • Senha : "alloydb" (ou o que você definiu no momento da criação)

Depois de se autenticar no AlloyDB Studio, os comandos SQL são inseridos no editor. É possível adicionar várias janelas do Editor usando o sinal de mais à direita da última janela.

28cb9a8b6aa0789f.png

Você vai inserir comandos para o AlloyDB nas janelas do editor, usando as opções "Executar", "Formatar" e "Limpar" conforme necessário.

Ativar extensões

Para criar esse app, vamos usar as extensões pgvector e google_ml_integration. A extensão pgvector permite armazenar e pesquisar embeddings de vetores. A extensão google_ml_integration oferece funções que você usa para acessar endpoints de previsão da Vertex AI e receber previsões em SQL. Ative essas extensões executando os seguintes DDLs:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

Conceder permissão

Execute a instrução abaixo para conceder a execução na função "embedding":

GRANT EXECUTE ON FUNCTION embedding TO postgres;

Conceder o papel de usuário da Vertex AI à conta de serviço do AlloyDB

No console do Google Cloud IAM, conceda à conta de serviço do AlloyDB (que tem esta aparência: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) acesso à função "Usuário da Vertex AI". PROJECT_NUMBER vai ter o número do seu projeto.

Como alternativa, execute o comando abaixo no terminal do Cloud Shell:

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

Criar uma tabela

É possível criar uma tabela usando a instrução DDL abaixo no AlloyDB Studio:

DROP TABLE IF EXISTS transit_policies;
DROP TABLE IF EXISTS bus_schedules;
DROP TABLE IF EXISTS bookings;

-- Table 1: Transit Policies (Unstructured Data for RAG)
CREATE TABLE transit_policies (
    policy_id SERIAL PRIMARY KEY,
    category VARCHAR(50),
    policy_text TEXT,
    policy_embedding vector(768) 
);

-- Table 2: Intercity Bus Schedules (Structured Data)
CREATE TABLE bus_schedules (
    trip_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    origin_city VARCHAR(100),
    destination_city VARCHAR(100),
    departure_time TIMESTAMP,
    arrival_time TIMESTAMP,
    available_seats INT DEFAULT 50,
    ticket_price DECIMAL(6,2)
);

-- Table 3: Booking Ledger (Transactional Action Data)
CREATE TABLE bookings (
    booking_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    trip_id UUID REFERENCES bus_schedules(trip_id),
    passenger_id VARCHAR(100),
    status VARCHAR(20) DEFAULT 'CONFIRMED',
    booking_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

A coluna policy_embedding permite o armazenamento dos valores vetoriais de alguns campos de texto.

Ingestão de dados

Execute o conjunto de instruções SQL abaixo para inserir registros em massa nas respectivas tabelas:

  1. Inserir políticas não estruturadas e GERAR EMBEDDINGS REAIS de forma nativa no AlloyDB
-- 1. Insert Unstructured Policies and GENERATE REAL EMBEDDINGS natively in AlloyDB

INSERT INTO transit_policies (category, policy_text, policy_embedding) 
VALUES 
('Pets', 'Service animals are always welcome. Small pets (under 25 lbs) are allowed in secure carriers for a $25 fee. Large dogs are not permitted on standard coaches.', embedding('text-embedding-005', 'Service animals are always welcome. Small pets (under 25 lbs) are allowed in secure carriers for a $25 fee. Large dogs are not permitted on standard coaches.')),
('Luggage', 'Each passenger is allowed one carry-on (up to 15 lbs) and two stowed bags (up to 50 lbs each) free of charge. Additional bags cost $15 each.', embedding('text-embedding-005', 'Each passenger is allowed one carry-on (up to 15 lbs) and two stowed bags (up to 50 lbs each) free of charge. Additional bags cost $15 each.')),
('Refunds', 'Tickets are fully refundable up to 24 hours before departure. Within 24 hours, tickets can be exchanged for travel credit only.', embedding('text-embedding-005', 'Tickets are fully refundable up to 24 hours before departure. Within 24 hours, tickets can be exchanged for travel credit only.'));
  1. Gerar mais de 200 programações realistas para 7 dias usando generate_series
-- 2. Generate 200+ Realistic Schedules for the Next 7 Days using generate_series

INSERT INTO bus_schedules (origin_city, destination_city, departure_time, arrival_time, ticket_price, available_seats)
SELECT 
    origin,
    destination,
    -- Generate departures every 4 hours starting from tomorrow
    (CURRENT_DATE + 1) + (interval '4 hours' * seq) AS dep_time,
    (CURRENT_DATE + 1) + (interval '4 hours' * seq) + interval '4.5 hours' AS arr_time,
    ROUND((RANDOM() * 30 + 25)::numeric, 2) AS price, -- Random price between $25 and $55
    FLOOR(RANDOM() * 50 + 1) AS seats -- Random seats between 1 and 50
FROM 
    (VALUES 
        ('New York', 'Boston'), ('Boston', 'New York'),
        ('Philadelphia', 'Washington DC'), ('Washington DC', 'Philadelphia'),
        ('Seattle', 'Portland'), ('Portland', 'Seattle')
    ) AS routes(origin, destination)
CROSS JOIN generate_series(1, 40) AS seq; -- 6 routes * 40 time slots = 240 distinct trips ingested!

Gerar embeddings

Os embeddings são cobertos automaticamente na instrução de inserção na tabela "transit_policies" usando a função "embedding('text-embedding-005', '<<policytext>>')".

Problemas e solução de problemas

O loop de "amnésia de senha"

Se você usou a configuração "Um clique" e não se lembra da senha, acesse a página de informações básicas da instância no console e clique em "Editar" para redefinir a senha do postgres.

O erro "Extensão não encontrada"

Se CREATE EXTENSION falhar, geralmente é porque a instância ainda está no estado "Manutenção" ou "Atualização" do provisionamento inicial. Verifique se a etapa de criação da instância foi concluída e aguarde alguns segundos, se necessário.

Problemas de propagação do IAM

Você executou o comando do IAM gcloud, mas o SQL CALL ainda falha com um erro de permissão. As mudanças no IAM podem levar algum tempo para serem propagadas pela infraestrutura do Google. Respire fundo.***CRÍTICO:

  1. Às vezes, a conta de serviço do AlloyDB pode parecer diferente do formato usado na etapa de permissões. Para ter 100% de certeza de que a conta de serviço do AlloyDB tem o papel de usuário da Vertex AI: acesse a página Clusters do AlloyDB no console do Google Cloud. Clique no cluster e, na guia Visão geral, procure um campo chamado Conta de serviço.
    Copie o valor e acesse o IAM para adicionar o papel de usuário da Vertex AI.
  2. Além disso, se você pulou a etapa "Ativar API" na seção "Antes de começar", terá problemas para acessar incorporações do AlloyDB.

Incompatibilidade de dimensão do vetor

A coluna policy_embedding da tabela transit_policies está definida como VECTOR(768). Se você tentar usar um modelo diferente (como um modelo de 1536 dimensões) mais tarde, os encartes vão explodir. Use text-embedding-005.

Erro de digitação no ID do projeto

Na chamada create_model, se você deixar os colchetes « » ou digitar errado o ID do projeto, o registro do modelo vai parecer bem-sucedido, mas vai falhar durante a primeira consulta real. Verifique a string.

5. Configuração de ferramentas e da caixa de ferramentas

A MCP Toolbox for Databases é um servidor MCP de código aberto para bancos de dados. Ele permite desenvolver ferramentas com mais facilidade, rapidez e segurança, lidando com complexidades como pool de conexões, autenticação e muito mais. A caixa de ferramentas ajuda você a criar ferramentas de IA generativa que permitem que seus agentes acessem dados no seu banco de dados.

Usamos a Caixa de ferramentas do Protocolo de Contexto de Modelo (MCP) para bancos de dados como o "condutor". Ele atua como um middleware padronizado entre nossos agentes e o AlloyDB. Ao definir uma configuração tools.yaml, a caixa de ferramentas expõe automaticamente operações complexas de banco de dados como ferramentas limpas e executáveis, como find-bus-schedules and routes ou query-schedules for specific routes, e executa ações autônomas, como book-ticket. Isso elimina a necessidade de pool de conexões manual ou SQL boilerplate na lógica do agente.

Como instalar o servidor da caixa de ferramentas

No terminal do Cloud Shell, crie uma pasta para salvar o novo arquivo YAML de ferramentas e o binário da caixa de ferramentas:

mkdir cymbal-bus-toolbox

cd cymbal-bus-toolbox

Na nova pasta, execute o seguinte conjunto de comandos:

# see releases page for other versions
export VERSION=0.27.0
curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox

Em seguida, crie o arquivo tools.yaml dentro dessa nova pasta. Para isso, navegue até o editor do Cloud Shell e copie o conteúdo deste arquivo repo para o arquivo tools.yaml.

... (Refer to entire file in the repo)

tools:

   find-bus-schedules:
    kind: postgres-sql
    source: alloydb
    description: Find all available bus schedules.
    statement: |
      SELECT CAST(trip_id AS TEXT) trip_id, departure_time, arrival_time, ticket_price, available_seats , origin_city, destination_city 
      FROM bus_schedules;

   query-schedules:
    kind: postgres-sql
    source: alloydb
    description: Find available bus schedules between an origin and destination city.
    parameters:
      - name: origin
        type: string
        description: The departure city name.
      - name: destination
        type: string
        description: The arrival city name.
    statement: |
      SELECT CAST(trip_id AS TEXT) trip_id, departure_time, arrival_time, ticket_price, available_seats 
      FROM bus_schedules 
      WHERE lower(origin_city) = lower($1) 
        AND lower(destination_city) = lower($2) 
        AND available_seats > 0 
      ORDER BY departure_time ASC 
      LIMIT 5;

   book-ticket:
    kind: postgres-sql
    source: alloydb
    description: Books a ticket for a specific trip, decrementing available seats and generating a confirmed booking record.
    parameters:
      - name: trip_id
        type: string
        description: The UUID of the trip schedule to book.
      - name: passenger_name
        type: string
        description: Name or ID of the passenger (Bound securely via backend or AuthToken).
        authServices:
          - name: google_auth
            field: sub
    statement: |
      WITH updated_schedule AS (
          UPDATE bus_schedules 
          SET available_seats = available_seats - 1 
          WHERE trip_id = CAST($1 AS UUID) AND available_seats > 0
          RETURNING trip_id
      )
      INSERT INTO bookings (trip_id, passenger_id)
      SELECT trip_id, $2 
      FROM updated_schedule
      RETURNING CAST(booking_id as TEXT) as booking_id, trip_id, passenger_id, status, booking_time;

   search-policies:
    kind: postgres-sql
    source: alloydb
    description: Semantic search for transit policies regarding luggage, pets, refunds, and general rules.
    parameters:
      - name: search_query
        type: string
        description: The user's question about transit policies to be embedded and searched.
    statement: |
      SELECT category, policy_text 
      FROM transit_policies 
      ORDER BY policy_embedding <=> CAST(embedding('text-embedding-005', $1) AS vector(768))
      LIMIT 2;

Observação:

  1. Na configuração do tools.yaml, não se esqueça de incluir ipType: "private" na configuração de origem do AlloyDB.
  2. Não se esqueça de incluir o URL do serviço da caixa de ferramentas do MCP no parâmetro clientId para a configuração do authServices. Talvez você só receba o link após a implantação inicial. Portanto, sim, você terá que executar as etapas de implantação duas vezes para garantir que o caso de uso de ferramentas autenticadas funcione.
  3. As opções abaixo para testar a caixa de ferramentas localmente não vão funcionar se a conexão do AlloyDB estiver definida como privada. É necessário torná-la pública para testar localmente ou usar um proxy para conexão. Mas não se preocupe com isso. Neste caso, vamos implantar diretamente no Cloud Run e depois testar.

Para testar o arquivo tools.yaml no servidor local:

./toolbox --tools-file "tools.yaml"

Você também pode testar na interface:

./toolbox --ui

Vamos implantá-lo no Cloud Run da seguinte maneira.

Implantação do Cloud Run

  1. Defina a variável de ambiente PROJECT_ID:
export PROJECT_ID="my-project-id"
  1. Inicialize a CLI gcloud:
gcloud init
gcloud config set project $PROJECT_ID
  1. Você precisa ter as seguintes APIs ativadas:
gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       iam.googleapis.com \
                       secretmanager.googleapis.com
  1. Crie uma conta de serviço de back-end se ainda não tiver uma:
gcloud iam service-accounts create toolbox-identity
  1. Conceda permissões para usar o Secret Manager:
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/secretmanager.secretAccessor
  1. Conceda permissões adicionais à conta de serviço específicas da nossa origem do AlloyDB (roles/alloydb.client e roles/serviceusage.serviceUsageConsumer).
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/alloydb.client


gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/serviceusage.serviceUsageConsumer
  1. Faça upload de tools.yaml como um secret:
gcloud secrets create tools-cymbal-transit --data-file=tools.yaml
  1. Se você já tiver um secret e quiser atualizar a versão dele, execute o seguinte:
gcloud secrets versions add tools-cymbal-transit --data-file=tools.yaml
  1. Defina uma variável de ambiente para a imagem do contêiner que você quer usar no Cloud Run:
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
  1. Implante a caixa de ferramentas no Cloud Run usando o seguinte comando:

Se você tiver ativado o acesso público na instância do AlloyDB, siga o comando abaixo para implantação no Cloud Run:

gcloud run deploy toolbox-cymbal-transit \
    --image $IMAGE \
    --service-account toolbox-identity \
    --region us-central1 \
    --set-secrets "/app/tools.yaml=tools-cymbal-transit:latest" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    --allow-unauthenticated

Se você estiver usando uma rede VPC, use o comando abaixo:

gcloud run deploy toolbox-cymbal-transit \
    --image $IMAGE \
    --service-account toolbox-identity \
    --region us-central1 \
    --set-secrets "/app/tools.yaml=tools-cymbal-transit:latest" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    --network <<YOUR_NETWORK_NAME>> \
    --subnet <<YOUR_SUBNET_NAME>> \
    --allow-unauthenticated

Observação: depois da implantação, acesse a lista de serviços do Cloud Run e verifique se, na guia "Segurança" desse serviço, a opção "Permitir acesso público" está selecionada.

6. Configuração do aplicativo do agente

Clone este repositório no seu projeto e vamos analisar.

Repositório do GitHub

Para clonar, no terminal do Cloud Shell (no diretório raiz ou em qualquer lugar em que você queira criar o projeto), execute o seguinte comando:

git clone https://github.com/googleapis/mcp-toolbox-sdk-java

O comando acima clona todo o mcp-toolbox-sdk-java. Só precisamos do projeto de exemplo. Navegue até o diretório raiz do projeto dentro do repositório:

cd mcp-toolbox-sdk-java/demo-applications/cymbal-transit
  1. Isso vai criar o projeto, e você pode verificar no editor do Cloud Shell.

a494664032904c77.png

  1. Abra "CymbalTransitController.java" e defina as variáveis de ambiente:
  2. GCP_PROJECT_ID
  3. GCP_REGION
  4. GEMINI_MODEL_NAME
  5. MCP_TOOLBOX_URL

Como alternativa (apenas para fins de desenvolvimento), você também pode substituir os respectivos marcadores de posição de valor de substituição.

7. Instruções sobre o código

O CymbalTransitController atua como o ponto de entrada do nosso serviço do Cloud Run. Ele gerencia o fluxo da conversa e garante que o agente tenha acesso à solicitação atual do usuário.

A implementação segue uma arquitetura em camadas que separa a orquestração de IA, a ponte de ferramentas e a comunicação MCP de baixo nível.

1. Configuração do agente de IA (AgentConfiguration)

Essa classe usa o @Configuration do Spring para inicializar os componentes de IA. Ele inicializa o VertexAiGeminiChatModel e o vincula à nossa interface do agente.

@Bean
ChatLanguageModel geminiChatModel() {
    return VertexAiGeminiChatModel.builder()
        .project(projectId)
        .location(region)
        .modelName(modelName)
        .build();
}

@Bean
TransitAgent transitAgent(ChatLanguageModel chatLanguageModel, TransitAgentTools tools) {
    return AiServices.builder(TransitAgent.class)
        .chatLanguageModel(chatLanguageModel)
        .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(20))
        .tools(tools) 
        .build();
}

Significado : AiServices vincula a interface ao LLM. O MessageWindowChatMemory garante que o agente se lembre das preferências do usuário (como uma caixa de transporte de animais de estimação mencionada anteriormente) por até 20 mensagens em uma única sessão.

2. A interface do agente de IA (TransitAgent)

A anotação @SystemMessage define a "Persona" e as restrições operacionais, especificamente uma estratégia de roteamento.

@SystemMessage({
    "You are the Cymbal Transit Concierge.",
    "CRITICAL INSTRUCTION: On your very first interaction, you MUST use the 'findAllSchedules' tool to fetch and memorize the broad bus routes.",
    "ONLY if the user asks a specifically narrowed-down question... should you route to the specific tools like 'querySchedules', 'bookTicket', 'searchPolicies'.",
    "Don't show any asterisks while listing results. Keep it formatted and numbered or bulleted."
})
String chat(@MemoryId String sessionId, @UserMessage String userMessage);

Importância:essa estratégia minimiza a latência. Ao buscar primeiro dados gerais, o agente pode responder a perguntas gerais de roteamento usando o contexto interno sem fazer chamadas redundantes de back-end.

3. A Toolbox Bridge (TransitAgentTools)

Esse serviço atua como as "mãos" do agente, traduzindo chamadas de ferramentas do LangChain4j em lógica de execução.

@Tool("Fetches the initial, broad dataset of all available bus schedules and routes.")
public String findAllSchedules() {
    return mcpService.findAllSchedules().join();
}


@Tool("Book a ticket for a passenger using a specific trip ID.")
public String bookTicket(String tripId, String passengerName) {
    return mcpService.bookTicket(tripId, passengerName).join();
}

Execução síncrona:embora as chamadas da MCP sejam assíncronas (retornando CompletableFuture), o LLM exige um resultado antes de continuar o processo de "pensamento". Usamos .join() para fornecer resultados síncronos ao agente.

4. O serviço da caixa de ferramentas do MCP (McpToolboxService)

Essa é a camada de comunicação que usa o SDK do Java da caixa de ferramentas da MCP para interagir com o back-end do AlloyDB.

// Identity Management: Fetching OIDC ID Token for Auth
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
this.idToken = ((IdTokenProvider) credentials)
    .idTokenWithAudience(targetUrl, Collections.emptyList())
    .getTokenValue();

// Dynamic Invocation: Executing a tool by name
public CompletableFuture<String> findAllSchedules() {
    return mcpClient.invokeTool("find-bus-schedules", Collections.emptyMap()).thenApply(result -> {
        return result.content().stream()
            .map(content -> content.text())
            .collect(Collectors.joining(", ", "[", "]"));
    });
}

Importância : McpToolboxClient lida com o trabalho pesado da comunicação JSON-RPC. O método bookTicket mostra especificamente a capacidade do SDK de vincular parâmetros complexos de forma dinâmica.

5. O controlador REST (TransitAgentController)

O endpoint final é radicalmente simplificado porque o LangChain4j gerencia o estado e a lógica.

@PostMapping("/chat")
public ResponseEntity<String> handleUserChat(@RequestBody String userMessage, HttpSession session) {
    String sessionId = session.getId();
    String agentResponse = transitAgent.chat(sessionId, userMessage);
    return ResponseEntity.ok(agentResponse);
}

Importância:ao mapear o ID HttpSession para @MemoryId, garantimos que os planos de viagem de diferentes usuários não sejam misturados, mantendo o código do controlador limpo e legível.

8. MCP Toolbox: significância e SDK Java

O que é o MCP?

Pense no Protocolo de Contexto de Modelo (MCP) como um tradutor universal para IA. Criado para padronizar a forma como os modelos de IA se conectam a ferramentas e conjuntos de dados externos, o MCP substitui scripts de integração personalizados e fragmentados por um protocolo seguro e universal. Se o agente precisar executar uma consulta SQL transacional, pesquisar milhares de documentos de política ou acionar uma API REST, o MCP vai fornecer uma interface única e unificada.

MCP Toolbox para bancos de dados

As equipes de engenharia estão indo além dos chatbots simples para criar sistemas baseados em agentes que interagem diretamente com bancos de dados essenciais. No entanto, criar esses agentes empresariais geralmente significa enfrentar um bloqueio de integração de código de junção personalizado, APIs frágeis e lógica de banco de dados complexa.

Para substituir esses gargalos codificados por um plano de controle seguro e unificado, temos o prazer de anunciar o SDK Java para a caixa de ferramentas do Protocolo de Contexto de Modelo (MCP) para bancos de dados. Essa versão traz uma orquestração de agentes de primeira classe e com segurança de tipos para o ecossistema empresarial mais adotado do mundo. A arquitetura madura do Java foi criada especificamente para essas demandas rigorosas, oferecendo a alta simultaneidade, a integridade transacional estrita e o gerenciamento de estado robusto necessários para escalonar com segurança agentes de IA essenciais em produção.

Por que o SDK do Java?

O SDK Java da caixa de ferramentas do MCP permite que desenvolvedores Java:

  1. Consumir ferramentas:conecte-se a um servidor MCP (como o MCP Toolbox para AlloyDB) e transforme automaticamente os recursos dele em métodos Java que o LangChain4j entende.
  2. Segurança de tipo:aproveite a tipagem forte do Java para parâmetros de ferramentas, reduzindo erros de "alucinação" de tempo de execução em chamadas de ferramentas.
  3. Prontidão para empresas:integre facilmente com Spring Boot, Quarkus, Micronaut etc.
  4. Conexão sem esforço:evite escrever código JSON-RPC boilerplate.
  5. Padronizar a autenticação:o suporte nativo para tokens OIDC do Google Cloud garante a execução segura das ferramentas.

e muito mais .

Dependências: configuração pom.xml

Adicione a seguinte dependência ao seu projeto Maven para incluir o SDK mais recente da caixa de ferramentas do MCP para Java:

   <dependency>
        <groupId>com.google.cloud.mcp</groupId>
        <artifactId>mcp-toolbox-sdk-java</artifactId>
        <version>0.2.0</version>
    </dependency>

Adicione a seguinte dependência ao seu projeto Maven para incluir o artefato LangChain4j:

     <!-- LangChain4j Core & Gemini -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j</artifactId>
        <version>0.35.0</version>
    </dependency>

Pronto!!! Clonamos o projeto e explicamos os detalhes do agente, do SDK Java da caixa de ferramentas do MCP e do contexto.

9. Como executar no local

Para testar o agente na sua máquina, é necessário direcioná-lo ao servidor implantado da MCP Toolbox.

  1. Defina as variáveis de ambiente:
export GCP_PROJECT_ID="<<YOUR_PROJECT_ID>>"
export GCP_REGION="us-central1"
export GEMINI_MODEL_NAME="gemini-2.5-flash"
export MCP_TOOLBOX_URL="<<YOUR_TOOLBOX_ENDPOINT_URL>>/mcp"
  1. Executar com o Maven:
mvn compile

mvn spring-boot:run

Isso vai iniciar o agente localmente, e você poderá testá-lo.

10. Vamos implantar no Cloud Run

Implante no Cloud Run executando o seguinte comando no terminal do Cloud Shell, em que o projeto é clonado. Verifique se você está na pasta raiz do projeto.

SE VOCÊ NÃO ESTIVER NA PASTA ROOT DO PROJETO ATUAL, execute este comando no terminal do Cloud Shell:

cd cymbal-transit

Se você já estiver na raiz cymbal-transit, execute o comando abaixo para implantar o app diretamente no Cloud Run:

gcloud run deploy cymbal-transit --source . --set-env-vars GCP_PROJECT_ID=<<YOUR_PROJECT_ID>>,GCP_REGION=us-central1,GEMINI_MODEL_NAME=gemini-2.5-flash,MCP_TOOLBOX_URL=<<YOUR_MCP_TOOLBOX_URL>> --allow-unauthenticated

Substitua os valores dos marcadores <<YOUR_PROJECT>> and <<YOUR_MCP_TOOLBOX_URL>>

Quando o comando terminar, ele vai gerar um URL de serviço. Copie.

Conceda o papel Cliente do AlloyDB à conta de serviço do Cloud Run.Isso permite que seu aplicativo sem servidor faça um túnel seguro no banco de dados.

Execute este comando no terminal do Cloud Shell:

# 1. Get your Project ID and Project Number
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

# 2. Grant the AlloyDB Client role
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/alloydb.client"

Observação: depois da implantação, acesse a lista de serviços do Cloud Run e verifique se, na guia "Segurança" desse serviço, a opção "Permitir acesso público" está selecionada.

Agora use o URL do serviço (endpoint do Cloud Run que você copiou antes) e teste o app.

Observação:se você encontrar um problema no serviço e ele citar a memória como motivo, tente aumentar o limite de memória alocada para 1 GiB para testar.

11. Demonstração

Pergunte ao agente: "Preciso ir de Nova York para Boston amanhã de manhã. Posso levar meu Golden Retriever?" Observe como o agente:

  1. Pesquisa políticas para cachorros grandes.
  2. Encontra programações específicas.
  3. Resume a viagem mais rápida com um ID de viagem.
  4. Também reserva uma passagem se você seguir com essa solicitação de ação.

aa0408a81074d0fc.png

12. Limpar

Depois de concluir este laboratório, não se esqueça de excluir o cluster e a instância do AlloyDB.

Ele vai limpar o cluster e as instâncias dele.

13. Parabéns

Você criou um agente de trânsito sofisticado baseado em Java. Ao aproveitar o LangChain4j para orquestração e o SDK do Java da caixa de ferramentas do MCP para conectividade de dados, você criou um sistema que pode raciocinar entre agentes, ferramentas e fontes de dados. Se quiser começar a orquestrar seus aplicativos agênticos com o MCP Toolbox for Databases em vários bancos de dados, mesmo em plataformas diferentes, comece a usar o SDK Java hoje mesmo. Confira o blog de anúncio do lançamento com mais informações sobre a biblioteca. Se você quiser criar mais aplicativos assim na prática, sem custo financeiro, no seu ritmo e com orientação de um instrutor, inscreva-se no Code Vipassana em https://codevipassana.dev.