Cymbal Transit: system z wieloma agentami korzystający z pakietu LangChain4J i zestawu narzędzi MCP Toolbox Java SDK

1. Przegląd

Współcześni podróżni oczekują interakcji konwersacyjnych. Zamiast korzystać ze skomplikowanych filtrów interfejsu, chcą zapytać: „Czy mogę zabrać psa na autobus do Bostonu o 9:00?”. Wymaga to agenta, który potrafi analizować dane nieuporządkowane (zasady w formacie PDF) i dane strukturalne (harmonogramy SQL).

W tym module utworzymy agenta Cymbal Transit, korzystając z tych narzędzi:

  • LangChain4j: najlepsza platforma Java do orkiestracji AI.
  • AlloyDB: baza danych o wysokiej wydajności zgodna z PostgreSQL.
  • MCP Toolbox Java SDK: standardowy sposób łączenia agentów Java z narzędziami zewnętrznymi i źródłami danych.

Co utworzysz

e68388d533c9997e.png

Cymbal Bus Agent, aplikacja Java Spring Boot składająca się z:

  1. Baza danych AlloyDB i pakiet MCP Toolbox Java SDK do orkiestracji narzędzi za pomocą agentów.
  2. Cloud Run na potrzeby wdrożenia i aplikacji Toolbox (wdrożenie agenta).
  3. Biblioteka LangChain4J dla agenta i platformy LLM w aplikacji Spring Boot z Java 17.

Czego się nauczysz

  • Jak używać LangChain4J do tworzenia wyspecjalizowanych agentów i podagentów, którymi zarządza MCP Toolbox for Databases Java SDK
  • Jak skonfigurować i używać AlloyDB do danych i AI.
  • Jak używać MCP Toolbox do łączenia agentów z narzędziami do danych AlloyDB.
  • Jak wdrożyć rozwiązanie za pomocą Cloud Run lub uruchomić je lokalnie.

Architektura

  1. AlloyDB for PostgreSQL: wydajna operacyjna baza danych, w której przechowujemy rekordy dotyczące tras, zasad i rezerwacji. Umożliwia wyszukiwanie i pobieranie wektorowe.
  2. Pakiet MCP Toolbox for Databases Java SDK: pełni rolę „mistrza orkiestracji”, udostępniając dane AlloyDB jako wykonywalne narzędzia, które mogą wywoływać agenci.

Pakiet MCP Toolbox Java SDK umożliwia łatwe zarządzanie agentami za pomocą narzędzi do obsługi baz danych w aplikacjach klasy korporacyjnej.

  1. LangChain4J: biblioteka open source w języku Java, która upraszcza integrację dużych modeli językowych (LLM) z aplikacjami w tym języku. Zawiera narzędzia i abstrakcje do tworzenia aplikacji opartych na AI, w tym czatbotów, agentów i systemów generowania wspomaganego wyszukiwaniem (RAG).
  2. Cloud Run: w pełni zarządzana platforma BEZSERWEROWA, która umożliwia łatwe tworzenie i szybkie wdrażanie aplikacji lub stron internetowych w dowolnym języku, z dowolną biblioteką i dowolnym plikiem binarnym. Możesz pisać kod w ulubionym języku, frameworku i bibliotekach, spakować go jako kontener, uruchomić „gcloud run deploy” i udostępnić aplikację, która będzie miała wszystko, czego potrzebuje do działania w środowisku produkcyjnym. Tworzenie kontenera jest całkowicie opcjonalne. Jeśli używasz Go, Node.js, Pythona, Javy, .NET Core lub Ruby, możesz skorzystać z opcji wdrażania na podstawie kodu źródłowego, która tworzy kontener za Ciebie, korzystając z najlepszych praktyk dla używanego języka.

Wymagania

  • przeglądarka, np. Chrome lub Firefox;
  • Projekt Google Cloud z włączonymi płatnościami.
  • Podstawowa znajomość SQL i Javy.

2. Zanim zaczniesz

Utwórz projekt

  1. W konsoli Google Cloud na stronie wyboru projektu wybierz lub utwórz projekt Google Cloud.
  2. Sprawdź, czy w projekcie Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy w projekcie włączone są płatności.
  1. Będziesz używać Cloud Shell, czyli środowiska wiersza poleceń działającego w Google Cloud. U góry konsoli Google Cloud kliknij Aktywuj Cloud Shell.

Obraz przycisku aktywowania Cloud Shell

  1. Po połączeniu z Cloud Shell sprawdź, czy uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu, używając tego polecenia:
gcloud auth list
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project
  1. Jeśli projekt nie jest ustawiony, użyj tego polecenia, aby go ustawić:
gcloud config set project <YOUR_PROJECT_ID>
  1. Włącz wymagane interfejsy API: kliknij link i włącz interfejsy API.

Możesz też użyć polecenia gcloud. Informacje o poleceniach gcloud i ich użyciu znajdziesz w dokumentacji.

Pułapki i rozwiązywanie problemów

Syndrom „projektu widma”

Uruchomiono polecenie gcloud config set project, ale w interfejsie konsoli wyświetlany jest inny projekt. Sprawdź identyfikator projektu w menu w lewym górnym rogu.

Bariera rozliczeniowa

Projekt został włączony, ale zapomniano o koncie rozliczeniowym. AlloyDB to wydajny mechanizm, który nie uruchomi się, jeśli „zbiornik paliwa” (płatności) jest pusty.

Opóźnienie propagacji interfejsu API

Kliknięto „Włącz interfejsy API”, ale w wierszu poleceń nadal wyświetla się Service Not Enabled. Odczekaj 60 sekund. Chmura potrzebuje chwili, aby aktywować swoje neurony.

Limit Quags

Jeśli korzystasz z nowego konta próbnego, możesz osiągnąć regionalny limit instancji AlloyDB. Jeśli us-central1 się nie powiedzie, spróbuj us-east1.

„Ukryty” agent usługi

Czasami agentowi usługi AlloyDB nie jest automatycznie przyznawana rola aiplatform.user. Jeśli zapytania SQL nie będą później mogły komunikować się z Gemini, zwykle jest to przyczyną problemu.

3. Konfiguracja bazy danych

W centrum naszej aplikacji znajduje się AlloyDB for PostgreSQL. Wykorzystaliśmy jego zaawansowane funkcje wektorowe i zintegrowany silnik kolumnowy do wygenerowania osadzeń dla ponad 50 tys. rekordów SCM. Umożliwia to analizę wektorową w czasie zbliżonym do rzeczywistego, dzięki czemu nasi agenci mogą w ciągu milisekund wykrywać anomalie w asortymencie lub ryzyko logistyczne w ogromnych zbiorach danych.

W tym module użyjemy AlloyDB jako bazy danych do przechowywania danych testowych. Używa klastrów do przechowywania wszystkich zasobów, takich jak bazy danych i logi. Każdy klaster ma instancję podstawową, która zapewnia punkt dostępu do danych. Tabele będą zawierać rzeczywiste dane.

Utwórzmy klaster, instancję i tabelę AlloyDB, do których zostanie załadowany testowy zbiór danych.

  1. Kliknij przycisk lub skopiuj poniższy link do przeglądarki, w której zalogowany jest użytkownik konsoli Google Cloud.

Możesz też otworzyć terminal Cloud Shell w projekcie, w którym zostało wykorzystane konto rozliczeniowe, sklonować repozytorium GitHub i przejść do projektu, używając tych poleceń:

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

cd easy-alloydb-setup
  1. Po wykonaniu tego kroku repozytorium zostanie sklonowane do lokalnego edytora Cloud Shell i będziesz mieć możliwość uruchomienia poniższego polecenia z folderu projektu (ważne jest, aby upewnić się, że jesteś w katalogu projektu):
sh run.sh
  1. Teraz użyj interfejsu (kliknij link w terminalu lub link „Podgląd w internecie” w terminalu).
  2. Aby rozpocząć, wpisz szczegóły identyfikatora projektu, klastra i nazw instancji.
  3. Idź po kawę, podczas gdy dzienniki będą się przewijać. Tutaj możesz przeczytać, jak to działa za kulisami.

Pułapki i rozwiązywanie problemów

Problem z „cierpliwością”

Klastry baz danych to rozbudowana infrastruktura. Jeśli odświeżysz stronę lub zakończysz sesję Cloud Shell, ponieważ „utknęła”, możesz skończyć z „duchem” instancji, która jest częściowo udostępniona i nie można jej usunąć bez ręcznej interwencji.

Niezgodny region

Jeśli interfejsy API zostały włączone w regionie us-central1, ale klaster jest wdrażany w regionie asia-south1, mogą wystąpić problemy z limitami lub opóźnienia w przypisywaniu uprawnień do konta usługi. W całym module trzymaj się jednego regionu.

Zombie Clusters

Jeśli nazwa klastra była już wcześniej używana i nie została usunięta, skrypt może wyświetlić komunikat, że nazwa klastra już istnieje. Nazwy klastrów muszą być unikalne w projekcie.

Limit czasu Cloud Shell

Jeśli przerwa na kawę trwa 30 minut, Cloud Shell może przejść w stan uśpienia i odłączyć proces sh run.sh. Pozostaw kartę aktywną.

4. Obsługa administracyjna schematu

Gdy klaster i instancja AlloyDB będą działać, przejdź do edytora SQL w AlloyDB Studio, aby włączyć rozszerzenia AI i udostępnić schemat.

1e3ac974b18a8113.png

Może być konieczne poczekanie na zakończenie tworzenia instancji. Gdy to zrobisz, zaloguj się w AlloyDB, używając danych logowania utworzonych podczas tworzenia klastra. Do uwierzytelniania w PostgreSQL użyj tych danych:

  • Nazwa użytkownika: „postgres
  • Baza danych: „postgres
  • Hasło: „alloydb” (lub inne hasło ustawione podczas tworzenia)

Po pomyślnym uwierzytelnieniu w AlloyDB Studio polecenia SQL są wpisywane w Edytorze. Możesz dodać wiele okien Edytora, klikając znak plusa po prawej stronie ostatniego okna.

28cb9a8b6aa0789f.png

Polecenia dla AlloyDB będziesz wpisywać w oknach edytora, w razie potrzeby korzystając z opcji Uruchom, Formatuj i Wyczyść.

Włączanie rozszerzeń

Do utworzenia tej aplikacji użyjemy rozszerzeń pgvectorgoogle_ml_integration. Rozszerzenie pgvector umożliwia przechowywanie wektorów dystrybucyjnych i wyszukiwanie ich. Rozszerzenie google_ml_integration udostępnia funkcje, których możesz używać do uzyskiwania dostępu do punktów końcowych prognozowania Vertex AI w celu uzyskiwania prognoz w SQL. Włącz te rozszerzenia, uruchamiając te DDL:

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

Przyznaj uprawnienia

Aby przyznać uprawnienia do wykonywania funkcji „embedding”, uruchom to polecenie:

GRANT EXECUTE ON FUNCTION embedding TO postgres;

Przyznawanie roli Użytkownik Vertex AI kontu usługi AlloyDB

W konsoli IAM Google Cloud przyznaj kontu usługi AlloyDB (które wygląda tak: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) dostęp do roli „Użytkownik Vertex AI”. Zmienna PROJECT_NUMBER będzie zawierać numer Twojego projektu.

Możesz też uruchomić to polecenie w terminalu 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"

Tworzenie tabeli

Tabelę możesz utworzyć za pomocą instrukcji DDL poniżej w 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
);

Kolumna policy_embedding będzie umożliwiać przechowywanie wartości wektorowych niektórych pól tekstowych.

Pozyskiwanie danych

Uruchom poniższy zestaw instrukcji SQL, aby zbiorczo wstawić rekordy do odpowiednich tabel:

  1. Wstawianie nieustrukturyzowanych zasad i NATIVE GENERATE REAL EMBEDDINGS w 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. Generowanie ponad 200 realistycznych harmonogramów na 7 dni za pomocą funkcji 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!

Generowanie wektorów dystrybucyjnych

Osadzanie jest automatycznie uwzględniane w instrukcji wstawiania do tabeli transit_policies za pomocą funkcji „embedding('text-embedding-005', '<<policytext>>')”.

Pułapki i rozwiązywanie problemów

Pętla „amnezji hasła”

Jeśli używasz konfiguracji „Jedno kliknięcie” i nie pamiętasz hasła, otwórz stronę podstawowych informacji o instancji w konsoli i kliknij „Edytuj”, aby zresetować hasło postgres.

Błąd „Nie znaleziono rozszerzenia”

Jeśli CREATE EXTENSION się nie powiedzie, często dzieje się tak, ponieważ instancja jest nadal w stanie „Konserwacja” lub „Aktualizowanie” od czasu początkowego udostępnienia. Sprawdź, czy krok tworzenia instancji został ukończony, a w razie potrzeby poczekaj kilka sekund.

Problemy z propagacją uprawnień

Uruchomiono polecenie gcloud IAM, ale polecenie SQL CALL nadal kończy się niepowodzeniem z powodu błędu uprawnień. Rozpowszechnienie zmian w IAM może trochę potrwać w sieci szkieletowej Google. Weź oddech.***KRYTYCZNE:

  1. Czasami konto usługi AlloyDB może wyglądać inaczej niż w przypadku formatu używanego przez nas w kroku dotyczącym uprawnień. Aby mieć 100% pewności, że konto usługi AlloyDB ma rolę użytkownika Vertex AI: otwórz stronę Klastry AlloyDB w konsoli Google Cloud. Kliknij klaster i na karcie Przegląd znajdź pole Konto usługi.
    Skopiuj wartość, a następnie otwórz IAM i dodaj rolę użytkownika Vertex AI.
  2. Jeśli w sekcji „Zanim zaczniesz” pominiesz krok „Włącz API”, możesz mieć problemy z dostępem do osadzania z AlloyDB.

Niezgodność wymiarów wektora

Kolumna policy_embedding tabeli transit_policies ma wartość VECTOR(768). Jeśli później spróbujesz użyć innego modelu (np. 1536-wymiarowego), wstawki zostaną rozszerzone. Trzymaj się text-embedding-005.

Błąd w identyfikatorze projektu

Jeśli w wywołaniu create_model pozostawisz nawiasy « » lub wpiszesz nieprawidłowy identyfikator projektu, rejestracja modelu będzie wyglądać na udaną, ale nie powiedzie się podczas pierwszego rzeczywistego zapytania. Sprawdź dokładnie ciąg znaków.

5. Narzędzia i konfiguracja zestawu narzędzi

MCP Toolbox for Databases to serwer MCP typu open source przeznaczony do baz danych. Umożliwia łatwiejsze, szybsze i bezpieczniejsze tworzenie narzędzi dzięki obsłudze złożonych procesów, takich jak pula połączeń, uwierzytelnianie i inne. Zestaw narzędzi pomaga tworzyć narzędzia generatywnej AI, które umożliwiają agentom dostęp do danych w bazie danych.

Jako „dyrygenta” używamy zestawu narzędzi Model Context Protocol (MCP) do baz danych. Działa jako standardowe oprogramowanie pośredniczące między naszymi agentami a AlloyDB. Dzięki zdefiniowaniu tools.yaml konfiguracji zestaw narzędzi automatycznie udostępnia złożone operacje na bazie danych jako proste, wykonywalne narzędzia, takie jak find-bus-schedules and routes lub query-schedules for specific routes, i wykonuje autonomiczne działania, takie jak book-ticket. Eliminuje to konieczność ręcznego tworzenia puli połączeń lub standardowego kodu SQL w logice agenta.

Instalowanie serwera Toolbox

W terminalu Cloud Shell utwórz folder, w którym zapiszesz nowy plik YAML narzędzi i binarny plik przybornika:

mkdir cymbal-bus-toolbox

cd cymbal-bus-toolbox

W tym nowym folderze uruchom te polecenia:

# 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

Następnie utwórz w tym nowym folderze plik tools.yaml. W tym celu otwórz edytor Cloud Shell i skopiuj zawartość tego pliku z repozytorium do pliku 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;

Uwaga:

  1. W konfiguracji tools.yaml nie zapomnij uwzględnić ipType: "private" w konfiguracji źródła AlloyDB.
  2. Pamiętaj też, aby w parametrze clientId konfiguracji authServices uwzględnić adres URL usługi MCP Toolbox. Link możesz otrzymać dopiero po pierwszym wdrożeniu, więc musisz wykonać kroki wdrażania 2 razy, aby mieć pewność, że narzędzia uwierzytelnione działają prawidłowo.
  3. Poniższe opcje testowania zestawu narzędzi lokalnie nie będą działać, jeśli połączenie z AlloyDB jest prywatne. Aby przetestować je lokalnie, musisz ustawić je jako publiczne lub użyć serwera proxy do połączenia. Ale nie musisz się tym przejmować. W naszym przypadku wdrożymy go bezpośrednio w Cloud Run, a potem przetestujemy.

Aby przetestować plik tools.yaml na serwerze lokalnym:

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

Możesz też przetestować ją w interfejsie:

./toolbox --ui

Wdróżmy go w Cloud Run w ten sposób:

Wdrożenie Cloud Run

  1. Ustaw zmienną środowiskową PROJECT_ID:
export PROJECT_ID="my-project-id"
  1. Zainicjuj gcloud CLI:
gcloud init
gcloud config set project $PROJECT_ID
  1. Musisz mieć włączone te interfejsy API:
gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       iam.googleapis.com \
                       secretmanager.googleapis.com
  1. Jeśli nie masz jeszcze konta usługi backendu, utwórz je:
gcloud iam service-accounts create toolbox-identity
  1. Przyznaj uprawnienia do korzystania z usługi Secret Manager:
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/secretmanager.secretAccessor
  1. Przyznaj kontu usługi dodatkowe uprawnienia specyficzne dla naszego źródła AlloyDB (role/alloydb.client i 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. Prześlij plik tools.yaml jako tajny token:
gcloud secrets create tools-cymbal-transit --data-file=tools.yaml
  1. Jeśli masz już obiekt tajny i chcesz zaktualizować jego wersję, wykonaj te czynności:
gcloud secrets versions add tools-cymbal-transit --data-file=tools.yaml
  1. Ustaw zmienną środowiskową na obraz kontenera, którego chcesz użyć w Cloud Run:
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
  1. Wdróż Toolbox w Cloud Run za pomocą tego polecenia:

Jeśli masz włączony publiczny dostęp do instancji AlloyDB, wykonaj to polecenie, aby wdrożyć ją w 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

Jeśli używasz sieci VPC, użyj tego polecenia:

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

Uwaga: po wdrożeniu otwórz listę usług Cloud Run i upewnij się, że na karcie bezpieczeństwa tej usługi jest zaznaczona opcja „Zezwalaj na dostęp publiczny”.

6. Konfiguracja aplikacji agenta

Sklonuj to repozytorium do swojego projektu i przejdźmy przez nie.

Repozytorium GitHub

Aby sklonować ten projekt, uruchom to polecenie w terminalu Cloud Shell (w katalogu głównym lub w dowolnym miejscu, w którym chcesz utworzyć ten projekt):

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

Powyższe polecenie klonuje cały pakiet mcp-toolbox-sdk-java. Potrzebujemy tylko projektu próbnego. Przejdź do katalogu głównego projektu w repozytorium:

cd mcp-toolbox-sdk-java/demo-applications/cymbal-transit
  1. Powinno to spowodować utworzenie projektu, co możesz sprawdzić w edytorze Cloud Shell.

a494664032904c77.png

  1. Otwórz plik CymbalTransitController.java i ustaw zmienne środowiskowe:
  2. GCP_PROJECT_ID
  3. GCP_REGION
  4. GEMINI_MODEL_NAME
  5. MCP_TOOLBOX_URL

Możesz też (tylko na potrzeby programowania) zastąpić odpowiednie symbole zastępcze wartości rezerwowych.

7. Instrukcja dotycząca kodu

Symbol CymbalTransitController działa jako punkt wejścia dla naszej usługi Cloud Run. Zarządza ona przebiegiem rozmowy i zapewnia agentowi dostęp do bieżącego żądania użytkownika.

Implementacja ma architekturę warstwową, która rozdziela orkiestrację AI, łączenie narzędzi i komunikację MCP niskiego poziomu.

1. Konfiguracja agenta AI (AgentConfiguration)

Ta klasa używa @Configuration Springa do uruchamiania komponentów AI. Inicjuje VertexAiGeminiChatModel i wiąże go z naszym interfejsem agenta.

@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();
}

Znaczenie: AiServices wiąże interfejs z LLM. MessageWindowChatMemory zapewnia, że agent zapamięta preferencje użytkownika (np. wspomnianą wcześniej torbę dla zwierząt) w przypadku maksymalnie 20 wiadomości w ramach jednej sesji.

2. Interfejs agenta AI (TransitAgent)

Adnotacja @SystemMessage określa „Personę” i ograniczenia operacyjne, w szczególności strategię routingu.

@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);

Znaczenie: ta strategia minimalizuje opóźnienie. Pobierając najpierw ogólne dane, agent może odpowiadać na ogólne pytania dotyczące routingu, korzystając z kontekstu wewnętrznego, bez wykonywania zbędnych wywołań backendu.

3. Toolbox Bridge (TransitAgentTools)

Ta usługa działa jak „ręce” agenta, tłumacząc wywołania narzędzi LangChain4j na logikę wykonania.

@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();
}

Wykonanie synchroniczne: wywołania MCP są asynchroniczne (zwracają CompletableFuture), ale LLM wymaga wyniku, zanim będzie mógł kontynuować proces „myślenia”. Używamy .join(), aby synchronicznie przekazywać wyniki do agenta.

4. Usługa MCP Toolbox (McpToolboxService)

Jest to warstwa komunikacyjna, która używa pakietu MCP Toolbox Java SDK do interakcji z backendem 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(", ", "[", "]"));
    });
}

Znaczenie: McpToolboxClient zajmuje się obsługą komunikacji JSON-RPC. Metoda bookTicket pokazuje, że pakiet SDK może dynamicznie wiązać złożone parametry.

5. Kontroler REST (TransitAgentController)

Końcowy punkt końcowy jest znacznie uproszczony, ponieważ LangChain4j zarządza stanem i logiką.

@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);
}

Znaczenie: przypisując identyfikator HttpSession do @MemoryId, dbamy o to, aby plany podróży różnych użytkowników nie były ze sobą mylone, a kod kontrolera był przejrzysty i czytelny.

8. MCP Toolbox: znaczenie i pakiet SDK Javy

Co to jest MCP?

Protokół Model Context Protocol (MCP) to uniwersalny tłumacz dla AI. Protokół MCP został stworzony, aby ujednolicić sposób, w jaki modele AI łączą się z narzędziami i zbiorami danych zewnętrznych. Zastępuje on niestandardowe, rozproszone skrypty integracyjne bezpiecznym, uniwersalnym protokołem. Niezależnie od tego, czy agent musi wykonać transakcyjne zapytanie SQL, przeszukać tysiące dokumentów dotyczących zasad czy wywołać interfejs API REST, MCP zapewnia jeden ujednolicony interfejs.

Zestaw narzędzi MCP do baz danych

Zespoły inżynierów wykraczają poza proste chatboty i tworzą systemy agentowe, które wchodzą w bezpośrednią interakcję z bazami danych o kluczowym znaczeniu. Jednak tworzenie takich agentów klasy korporacyjnej często wiąże się z koniecznością pokonania bariery integracji, która polega na użyciu niestandardowego kodu łączącego, niestabilnych interfejsów API i złożonej logiki bazy danych.

Aby zastąpić te zakodowane na stałe wąskie gardła bezpieczną, ujednoliconą platformą sterującą, z przyjemnością ogłaszamy wprowadzenie pakietu SDK w języku Java do zestawu narzędzi Model Context Protocol (MCP) dla baz danych. Ta wersja wprowadza do najpopularniejszego ekosystemu dla przedsiębiorstw najwyższej klasy, bezpieczną pod względem typów orkiestrację agentów. Dojrzała architektura Javy została stworzona z myślą o tych rygorystycznych wymaganiach. Zapewnia wysoką współbieżność, ścisłą integralność transakcyjną i solidne zarządzanie stanem, które są niezbędne do bezpiecznego skalowania w środowisku produkcyjnym kluczowych agentów AI.

Dlaczego warto używać pakietu SDK Java?

Pakiet MCP Toolbox Java SDK umożliwia programistom Java:

  1. Narzędzia do wykorzystania: połącz się z serwerem MCP (np. MCP Toolbox for AlloyDB) i automatycznie przekształć jego możliwości w metody Java, które rozumie LangChain4j.
  2. Bezpieczeństwo typów: wykorzystaj silne typowanie w języku Java w przypadku parametrów narzędzia, aby ograniczyć błędy „halucynacji” w wywołaniach narzędzia.
  3. Gotowość do użycia w firmie: łatwa integracja z Spring Boot, Quarkus, Micronaut itp.
  4. Łatwe łączenie: nie musisz pisać powtarzalnego kodu JSON-RPC.
  5. Ujednolicone uwierzytelnianie: natywna obsługa tokenów OIDC Google Cloud zapewnia bezpieczne wykonywanie narzędzi.

i wiele innych.

Zależności: konfiguracja pliku pom.xml

Aby dodać najnowszy pakiet MCP Toolbox SDK w języku Java, dodaj do projektu Maven tę zależność:

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

Aby uwzględnić artefakt LangChain4j, dodaj do projektu Maven tę zależność:

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

To wszystko!!! Udało Ci się sklonować projekt i zapoznać się ze szczegółami agenta, pakietu MCP Toolbox Java SDK i kontekstu.

9. Uruchamianie lokalne

Aby przetestować agenta na swoim komputerze, musisz skierować go na wdrożony serwer MCP Toolbox.

  1. Ustaw zmienne środowiskowe:
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. Uruchom za pomocą narzędzia Maven:
mvn compile

mvn spring-boot:run

Spowoduje to uruchomienie agenta lokalnie i umożliwi jego przetestowanie.

10. Wdróżmy go w Cloud Run

Wdróż go w Cloud Run, uruchamiając to polecenie w terminalu Cloud Shell, w którym projekt jest sklonowany. Upewnij się, że jesteś w folderze głównym projektu.

JEŚLI NIE ZNAJDUJESZ SIĘ W FOLDERZE GŁÓWNYM AKTUALNEGO PROJEKTU, uruchom to polecenie w terminalu Cloud Shell:

cd cymbal-transit

Jeśli jesteś już w katalogu głównym cymbal-transit, uruchom to polecenie, aby bezpośrednio wdrożyć aplikację w 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

Zastąp wartości symboli zastępczych <<YOUR_PROJECT>> and <<YOUR_MCP_TOOLBOX_URL>>

Po zakończeniu polecenia wyświetli się URL usługi. Skopiuj go.

Przyznaj kontu usługi Cloud Run rolę Klient AlloyDB.Umożliwi to aplikacji bezserwerowej bezpieczne tunelowanie do bazy danych.

Uruchom to polecenie w terminalu 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"

Uwaga: po wdrożeniu otwórz listę usług Cloud Run i upewnij się, że na karcie bezpieczeństwa tej usługi jest zaznaczona opcja „Zezwalaj na dostęp publiczny”.

Teraz użyj adresu URL usługi (skopiowanego wcześniej punktu końcowego Cloud Run) i przetestuj aplikację.

Uwaga: jeśli napotkasz problem z usługą, a jako przyczynę podano pamięć, spróbuj zwiększyć przydzielony limit pamięci do 1 GiB, aby to sprawdzić.

11. Prezentacja

Zapytaj agenta: „Muszę jutro rano dostać się z Nowego Jorku do Bostonu. Czy mogę zabrać ze sobą golden retrievera? Obserwuj, jak agent:

  1. Wyszukuje zasady dotyczące dużych psów.
  2. znajdować konkretne harmonogramy;
  3. Podsumowuje najszybszą podróż za pomocą identyfikatora podróży.
  4. Rezerwuje też bilet, jeśli wykonasz to działanie.

aa0408a81074d0fc.png

12. Czyszczenie danych

Po ukończeniu tego modułu nie zapomnij usunąć klastra i instancji AlloyDB.

Powinien on wyczyścić klaster wraz z instancjami.

13. Gratulacje

Udało Ci się utworzyć zaawansowanego agenta transportu opartego na Javie. Dzięki wykorzystaniu LangChain4j do orkiestracji i pakietu MCP Toolbox Java SDK do łączności z danymi udało Ci się utworzyć system, który może wnioskować na podstawie agentów, narzędzi i źródeł danych. Jeśli chcesz zacząć koordynować aplikacje oparte na agentach za pomocą MCP Toolbox for Databases w wielu bazach danych, nawet na różnych platformach, już dziś zacznij korzystać z pakietu Java SDK. Więcej informacji o bibliotece znajdziesz w tym poście na blogu z ogłoszeniem o jej uruchomieniu. Jeśli chcesz samodzielnie tworzyć więcej takich aplikacji, bezpłatnie, we własnym tempie i pod okiem instruktora, zarejestruj się na Code Vipassana na stronie https://codevipassana.dev.