1. 概要
現代の旅行者は、会話型のエクスペリエンスを期待しています。複雑な UI フィルタを操作する代わりに、「午前 9 時のボストン行きのバスに犬を連れて行けますか?」と質問したいと考えています。これには、非構造化データ(PDF ポリシー)と構造化データ(SQL スケジュール)を推論できるエージェントが必要です。
このラボでは、次のものを使用して Cymbal Transit Agent を構築します。
- LangChain4j: AI オーケストレーション用の主要な Java フレームワーク。
- AlloyDB: 高性能な PostgreSQL 互換データベース。
- MCP ツールボックス Java SDK: Java エージェントを外部のツールやデータソースに接続するための標準化された方法。
作成するアプリの概要
Cymbal Bus Agent。次の要素で構成される Java Spring Boot アプリケーション。
- エージェントを使用したツールのオーケストレーション用の AlloyDB データベースと MCP ツールボックス Java SDK。
- ツールボックスのデプロイとアプリケーション(エージェントのデプロイ)用の Cloud Run。
- Java 17 を使用した Spring Boot アプリケーションのエージェントと LLM フレームワーク用の LangChain4J ライブラリ。
学習内容
- LangChain4J を使用して、データベース向け MCP ツールボックス Java SDK を使用してオーケストレートされた特殊なエージェントとサブエージェントを作成する方法
- データと AI 用の AlloyDB を設定して使用する方法。
- MCP ツールボックスを使用してエージェントを AlloyDB データツールに接続する方法。
- Cloud Run を使用してソリューションをデプロイする方法、またはローカルで実行する方法。
アーキテクチャ
- AlloyDB for PostgreSQL: ルート、ポリシー、予約レコードを保持する高性能な運用データベースとして機能します。ベクトル検索と取得を強化します。
- データベース向け MCP ツールボックス Java SDK:「オーケストレーション マエストロ」として機能し、AlloyDB データをエージェントが呼び出すことができる実行可能なツールとして公開します。
MCP Toolbox Java SDK を使用すると、エンタープライズ グレードのアプリケーションでデータベース ツールを使用してエージェントを簡単にオーケストレートできます。
- LangChain4J: 大規模言語モデル(LLM)を Java アプリケーションに簡単に統合できるオープンソースの Java ライブラリ。chatbot、エージェント、検索拡張生成(RAG)システムなど、AI を活用したアプリケーションを構築するためのツールと抽象化を提供します。
- Cloud Run: あらゆる言語、ライブラリ、バイナリでアプリやウェブサイトを簡単に迅速に構築してデプロイできる、フルマネージドのサーバーレス プラットフォーム。お好みの言語、フレームワーク、ライブラリを使用してコードを記述し、それをコンテナとしてパッケージ化して「gcloud run deploy」を実行すれば、本番環境での稼働に必要なものがすべて揃った状態でアプリがデプロイされます。コンテナの構築は完全に任意です。Go、Node.js、Python、Java、.NET Core、Ruby を使用している場合は、使用している言語のベスト プラクティスに従って、コンテナをビルドするソースベースのデプロイ オプションを使用できます。
要件
2. 始める前に
プロジェクトを作成する
- Google Cloud コンソールのプロジェクト選択ページで、Google Cloud プロジェクトを選択または作成します。
- Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。
- Google Cloud 上で動作するコマンドライン環境の Cloud Shell を使用します。Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします。
![[Cloud Shell をアクティブにする] ボタンの画像](https://codelabs.developers.google.com/static/cymbal-bus-agent-mcp-toolbox-java/img/91567e2f55467574.png?hl=ja)
- Cloud Shell に接続したら、次のコマンドを使用して、すでに認証済みであることと、プロジェクトがプロジェクト ID に設定されていることを確認します。
gcloud auth list
- Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
- プロジェクトが設定されていない場合は、次のコマンドを使用して設定します。
gcloud config set project <YOUR_PROJECT_ID>
- 必要な API を有効にする: リンクにアクセスして、API を有効にします。
または、gcloud コマンドを使用することもできます。gcloud コマンドとその使用方法については、ドキュメントをご覧ください。
注意点とトラブルシューティング
「ゴースト プロジェクト」症候群 |
|
請求のバリケード | プロジェクトを有効にしたが、請求先アカウントを忘れた。AlloyDB は高性能エンジンです。ガソリン タンク(課金)が空の場合、起動しません。 |
API 伝播の遅延 | [API を有効にする] をクリックしたのに、コマンドラインに |
割り当て Quags | 新しいトライアル アカウントを使用している場合は、AlloyDB インスタンスのリージョン割り当てに達する可能性があります。 |
「非表示」サービス エージェント | AlloyDB サービス エージェントに |
3. データベースの設定
アプリケーションの中核となるのは AlloyDB for PostgreSQL です。強力なベクトル機能と統合されたカラム型エンジンを活用して、50,000 件を超える SCM レコードのエンベディングを生成しました。これにより、ほぼリアルタイムのベクトル分析が可能になり、エージェントはミリ秒単位で大規模なデータセット全体にわたって在庫の異常やロジスティクスのリスクを特定できます。
このラボでは、テストデータのデータベースとして AlloyDB を使用します。クラスタを使用して、データベースやログなどのすべてのリソースを保持します。各クラスタには、データへのアクセス ポイントを提供するプライマリ インスタンスがあります。テーブルには実際のデータが格納されます。
テスト データセットを読み込む AlloyDB クラスタ、インスタンス、テーブルを作成しましょう。
- ボタンをクリックするか、以下のリンクを Google Cloud コンソールのユーザーがログインしているブラウザにコピーします。
または、課金アカウントを利用したプロジェクトから Cloud Shell ターミナルに移動し、次のコマンドを使用して github リポジトリ のクローンを作成してプロジェクトに移動することもできます。
git clone https://github.com/AbiramiSukumaran/easy-alloydb-setup
cd easy-alloydb-setup
- この手順が完了すると、リポジトリがローカルの Cloud Shell エディタにクローンされ、プロジェクト フォルダから次のコマンドを実行できるようになります(プロジェクト ディレクトリにいることを確認することが重要です)。
sh run.sh
- UI を使用します(ターミナルのリンクをクリックするか、ターミナルの [ウェブでプレビュー] リンクをクリックします)。
- プロジェクト ID、クラスタ名、インスタンス名の詳細を入力して、開始します。
- ログがスクロールしている間にコーヒーを飲んで、裏側で何が行われているかについてはこちらをご覧ください。
注意点とトラブルシューティング
「忍耐」の問題 | データベース クラスタは重いインフラストラクチャです。ページを更新したり、「フリーズした」ように見えるため Cloud Shell セッションを強制終了したりすると、部分的にプロビジョニングされた「ゴースト」インスタンスが作成され、手動で介入しないと削除できなくなる可能性があります。 |
リージョンが一致しない |
|
ゾンビ クラスタ | 以前にクラスタに同じ名前を使用していて、削除していない場合、スクリプトでクラスタ名がすでに存在すると表示されることがあります。クラスタ名はプロジェクト内で一意にする必要があります。 |
Cloud Shell のタイムアウト | コーヒー ブレイクに 30 分かかると、Cloud Shell がスリープ状態になり、 |
4. スキーマのプロビジョニング
AlloyDB クラスタとインスタンスが実行されたら、AlloyDB Studio の SQL エディタに移動して、AI 拡張機能を有効にしてスキーマをプロビジョニングします。

インスタンスの作成が完了するまで待つ必要がある場合があります。完了したら、クラスタの作成時に作成した認証情報を使用して AlloyDB にログインします。PostgreSQL の認証には次のデータを使用します。
- ユーザー名: 「
postgres」 - データベース: 「
postgres」 - パスワード: 「
alloydb」(作成時に設定したパスワード)
AlloyDB Studio への認証が成功すると、エディタに SQL コマンドが入力されます。最後のウィンドウの右にあるプラス記号を使用して、複数のエディタ ウィンドウを追加できます。

必要に応じて [実行]、[形式]、[クリア] オプションを使用して、エディタ ウィンドウに AlloyDB のコマンドを入力します。
拡張機能を有効にする
このアプリのビルドには、拡張機能 pgvector と google_ml_integration を使用します。pgvector 拡張機能を使用すると、ベクトル エンベディングを保存して検索できます。google_ml_integration 拡張機能は、Vertex AI 予測エンドポイントにアクセスして SQL で予測を取得するために使用する関数を提供します。次の DDL を実行して、これらの拡張機能を有効にします。
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
権限を付与
次のステートメントを実行して、「embedding」関数に対する実行権限を付与します。
GRANT EXECUTE ON FUNCTION embedding TO postgres;
AlloyDB サービス アカウントに Vertex AI ユーザーロールを付与する
Google Cloud IAM コンソールで、AlloyDB サービス アカウント(service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com のような形式)に「Vertex AI ユーザー」ロールへのアクセス権を付与します。PROJECT_NUMBER にはプロジェクト番号が設定されます。
または、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"
テーブルを作成する
AlloyDB Studio で次の DDL ステートメントを使用してテーブルを作成できます。
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
);
policy_embedding 列では、一部のテキスト フィールドのベクトル値を保存できます。
データの取り込み
次の SQL ステートメントを実行して、各テーブルにレコードを一括挿入します。
- 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.'));
- generate_series を使用して 7 日間のリアルなスケジュールを 200 件以上生成する
-- 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!
エンベディングを生成する
エンベディングは、関数「embedding('text-embedding-005', '<<policytext>>')」を使用して、transit_policies テーブルへの挿入ステートメントで自動的にカバーされます。
注意点とトラブルシューティング
「パスワード忘れ」ループ | 「ワンクリック」設定を使用していて、パスワードを忘れた場合は、コンソールのインスタンスの基本情報ページに移動し、[編集] をクリックして |
「拡張機能が見つかりません」というエラー |
|
IAM の伝播に関する問題 |
|
ベクトル ディメンションの不一致 |
|
プロジェクト ID の誤字脱字 |
|
5. ツールとツールボックスの設定
データベース向け MCP ツールボックスは、データベース用のオープンソースの MCP サーバーです。これにより、接続プーリングや認証などの複雑な処理に対応して、ツールの開発をより簡単、迅速、セキュアに行うことができます。ツールボックスを使用すると、エージェントがデータベース内のデータにアクセスできる生成 AI ツールを構築できます。
データベース向け Model Context Protocol(MCP)ツールボックスを「コンダクター」として使用します。エージェントと AlloyDB の間の標準化されたミドルウェアとして機能します。tools.yaml 構成を定義すると、ツールボックスは複雑なデータベース オペレーションを find-bus-schedules and routes や query-schedules for specific routes などのクリーンで実行可能なツールとして自動的に公開し、book-ticket などの自律アクションを実行します。これにより、エージェント ロジック内で手動で接続プールを作成したり、ボイラープレート SQL を記述したりする必要がなくなります。
ツールボックス サーバーのインストール
Cloud Shell ターミナルで、新しいツール YAML ファイルとツールボックス バイナリを保存するフォルダを作成します。
mkdir cymbal-bus-toolbox
cd cymbal-bus-toolbox
その新しいフォルダ内で、次のコマンドセットを実行します。
# 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
次に、Cloud Shell エディタに移動して、その新しいフォルダ内に tools.yaml ファイルを作成し、この repo ファイルの内容を 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;
注:
- tools.yaml の設定で、alloydb ソース構成に ipType: "private" を含めることを忘れないでください。
- また、authServices 構成の clientId パラメータに MCP ツールボックス サービス URL を含めることも忘れないでください。リンクは初回デプロイ後にのみ取得できる場合があります。そのため、認証済みツールのユースケースが機能することを確認するには、デプロイ手順を 2 回実行する必要があります。
- AlloyDB 接続がプライベートに設定されている場合、ツールボックスをローカルでテストする以下のオプションは機能しません。ローカルでテストするには、パブリックに設定するか、接続にプロキシを使用する必要があります。ただし、ご心配は無用です。この例では、Cloud Run に直接デプロイしてテストします。
ローカル サーバーで tools.yaml ファイルをテストするには:
./toolbox --tools-file "tools.yaml"
UI でテストすることもできます。
./toolbox --ui
次の手順で Cloud Run にデプロイしましょう。
Cloud Run Deployment
- PROJECT_ID 環境変数を設定します。
export PROJECT_ID="my-project-id"
- gcloud CLI を初期化します。
gcloud init
gcloud config set project $PROJECT_ID
- 次の API が有効になっている必要があります。
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
secretmanager.googleapis.com
- バックエンド サービス アカウントがない場合は、作成します。
gcloud iam service-accounts create toolbox-identity
- Secret Manager を使用する権限を付与します。
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/secretmanager.secretAccessor
- AlloyDB ソースに固有の追加の権限(roles/alloydb.client と 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
- tools.yaml をシークレットとしてアップロードします。
gcloud secrets create tools-cymbal-transit --data-file=tools.yaml
- Secret がすでに存在し、Secret バージョンを更新する場合は、次のコマンドを実行します。
gcloud secrets versions add tools-cymbal-transit --data-file=tools.yaml
- Cloud Run に使用するコンテナ イメージに環境変数を設定します。
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
- 次のコマンドを使用して、ツールボックスを Cloud Run にデプロイします。
AlloyDB で公開アクセスを有効にしている場合は、次のコマンドに沿って 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
VPC ネットワークを使用している場合は、次のコマンドを使用します。
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
注: デプロイが完了したら、Cloud Run サービスリストに移動し、そのサービスの [セキュリティ] タブで [パブリック アクセスを許可] が選択されていることを確認します。
6. エージェント アプリケーションのセットアップ
このリポジトリをプロジェクトにクローンして、内容を確認しましょう。
このクローンを作成するには、Cloud Shell ターミナル(ルート ディレクトリまたはこのプロジェクトを作成する場所)から次のコマンドを実行します。
git clone https://github.com/googleapis/mcp-toolbox-sdk-java
上記のコマンドは、実際には mcp-toolbox-sdk-java 全体のクローンを作成します。必要なのはサンプル プロジェクトのみです。リポジトリ内のプロジェクトのルート ディレクトリに移動します。
cd mcp-toolbox-sdk-java/demo-applications/cymbal-transit
- これでプロジェクトが作成されます。Cloud Shell エディタで確認できます。

- CymbalTransitController.java を開き、環境変数を設定します。
- GCP_PROJECT_ID
- GCP_REGION
- GEMINI_MODEL_NAME
- MCP_TOOLBOX_URL
別の方法(開発目的のみ)として、それぞれのフォールバック値のプレースホルダを置き換えることもできます。
7. コードのチュートリアル
CymbalTransitController は、Cloud Run サービスのエントリ ポイントとして機能します。会話フローを管理し、エージェントがユーザーの現在のリクエストにアクセスできるようにします。
実装は、AI オーケストレーション、ツール ブリッジング、低レベルの MCP 通信を分離するレイヤード アーキテクチャに従います。
1. AI エージェントの構成(AgentConfiguration)
このクラスは、Spring の @Configuration を使用して AI コンポーネントをブートストラップします。VertexAiGeminiChatModel を初期化し、Agent インターフェースにバインドします。
@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();
}
重要度: AiServices はインターフェースを LLM にバインドします。MessageWindowChatMemory を使用すると、エージェントは 1 回のセッション内で最大 20 件のメッセージについて、ユーザーの設定(前述のペット用キャリーなど)を記憶できます。
2. AI エージェント インターフェース(TransitAgent)
@SystemMessage アノテーションは、「ペルソナ」と運用上の制約(特にルーティング戦略)を定義します。
@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);
重要度: この戦略では、レイテンシが最小限に抑えられます。エージェントは、まず広範なデータを取得することで、冗長なバックエンド呼び出しを行わずに、内部コンテキストを使用して一般的なルーティングの質問に回答できます。
3. ツールボックス ブリッジ(TransitAgentTools)
このサービスはエージェントの「手」として機能し、LangChain4j ツール呼び出しを実行ロジックに変換します。
@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();
}
同期実行: MCP 呼び出しは非同期(CompletableFuture を返す)ですが、LLM は「思考」プロセスを続行する前に結果を必要とします。.join() を使用して、エージェントに同期結果を返します。
4. MCP ツールボックス サービス(McpToolboxService)
これは、MCP ツールボックス Java SDK を使用して 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(", ", "[", "]"));
});
}
重要性: McpToolboxClient は、JSON-RPC 通信の重い処理を処理します。bookTicket メソッドは、複雑なパラメータを動的にバインドする SDK の機能を具体的に示しています。
5. REST コントローラ(TransitAgentController)
LangChain4j が状態とロジックを管理するため、最終的なエンドポイントは大幅に簡素化されます。
@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);
}
重要性: HttpSession ID を @MemoryId にマッピングすることで、コントローラのコードをクリーンで読みやすい状態に保ちながら、異なるユーザーの旅行プランが混同されないようにします。
8. MCP Toolbox: 重要性と Java SDK
MCP とは
Model Context Protocol(MCP)は、AI のユニバーサル トランスレータのようなものです。MCP は、AI モデルが外部のツールやデータセットに接続する方法を標準化するために作成されており、カスタムの断片的な統合スクリプトをセキュアなユニバーサル プロトコルに置き換えます。エージェントがトランザクション SQL クエリの実行、数千件のポリシー ドキュメントの検索、REST API のトリガーを行う必要がある場合でも、MCP は単一の統合インターフェースを提供します。
データベース向け MCP ツールボックス
エンジニアリング チームは、単純な chatbot から、ミッション クリティカルなデータベースと直接やり取りするエージェント システムの構築へと移行しています。しかし、このようなエンタープライズ エージェントを構築する際には、カスタムのグルーコード、脆弱な API、複雑なデータベース ロジックという統合の壁にぶつかることがよくあります。
これらのハードコードされたボトルネックを安全で統合されたコントロール プレーンに置き換えるため、データベース向け Model Context Protocol(MCP)ツールボックスの Java SDK をリリースしました。このリリースにより、世界で最も広く採用されているエンタープライズ エコシステムで、最高水準の型安全なエージェント オーケストレーションが実現します。Java の成熟したアーキテクチャは、このような厳しい要求に対応できるよう構築されており、本番環境でミッション クリティカルな AI エージェントを安全にスケールするために必要な高い同時実行性、厳格なトランザクションの整合性、堅牢な状態管理を提供します。
Java SDK を使用する理由
MCP ツールボックス Java SDK を使用すると、Java デベロッパーは次のことができます。
- ツールを使用する: MCP サーバー(AlloyDB 用 MCP ツールボックスなど)に接続し、その機能を LangChain4j が理解できる Java メソッドに自動的に変換します。
- 型安全性: Java の厳密な型指定をツール パラメータに活用し、ツール呼び出しでのランタイムの「ハルシネーション」エラーを減らします。
- エンタープライズ対応: Spring Boot、Quarkus、Micronaut などと簡単に統合できます。
- 簡単に接続: ボイラープレート JSON-RPC コードを記述する必要がありません。
- 認証の標準化: Google Cloud OIDC トークンのネイティブ サポートにより、安全なツールの実行が保証されます。
依存関係: pom.xml 構成
最新の MCP Toolbox Java SDK を含めるには、Maven プロジェクトに次の依存関係を追加します。
<dependency>
<groupId>com.google.cloud.mcp</groupId>
<artifactId>mcp-toolbox-sdk-java</artifactId>
<version>0.2.0</version>
</dependency>
LangChain4j アーティファクトを含めるには、Maven プロジェクトに次の依存関係を追加します。
<!-- LangChain4j Core & Gemini -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.35.0</version>
</dependency>
以上です。プロジェクトのクローンを作成し、エージェント、MCP Toolbox Java SDK、コンテキストの詳細を確認しました。
9. ローカルでの実行
マシンでエージェントをテストするには、デプロイされた MCP Toolbox サーバーを指すようにエージェントを設定する必要があります。
- 環境変数を設定します。
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"
- Maven で実行します。
mvn compile
mvn spring-boot:run
これでエージェントがローカルで起動し、テストできるようになります。
10. Cloud Run にデプロイしましょう。
プロジェクトがクローンされた Cloud Shell ターミナルから次のコマンドを実行して、Cloud Run にデプロイします。プロジェクトのルートフォルダにいることを確認してください。
現在のプロジェクトのルートフォルダにいない場合は、Cloud Shell ターミナルで次のコマンドを実行します。
cd cymbal-transit
すでに cymbal-transit ルートにいる場合は、次のコマンドを実行して、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
プレースホルダ <<YOUR_PROJECT>> and <<YOUR_MCP_TOOLBOX_URL>> の値を置き換えます。
コマンドが完了すると、サービス URL が出力されます。コピーします。
Cloud Run サービス アカウントに AlloyDB クライアント ロールを付与します。これにより、サーバーレス アプリケーションがデータベースに安全にトンネル接続できるようになります。
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"
注: デプロイが完了したら、Cloud Run サービスリストに移動し、そのサービスの [セキュリティ] タブで [パブリック アクセスを許可] が選択されていることを確認します。
サービス URL(先ほどコピーした Cloud Run エンドポイント)を使用して、アプリをテストします。
注: サービスの問題が発生し、その理由としてメモリが挙げられている場合は、割り当てられたメモリ上限を 1 GiB に増やしてテストしてみてください。
11. デモ
エージェントに「明日の朝、ニューヨークからボストンまで移動する必要があります。ゴールデンレトリバーを連れて行ってもいいですか?」エージェントが次のことを行っているか確認します。
- 大型犬のポリシーを検索します。
- 特定のスケジュールを検索します。
- Trip ID を使用して最速のルートを要約します。
- また、そのアクション リクエストをフォローアップすると、チケットも予約されます。

12. クリーンアップ
このラボが完了したら、alloyDB クラスタとインスタンスを削除してください。
クラスタとそのインスタンスをクリーンアップする必要があります。
13. 完了
高度な Java ベースのトランジット エージェントが正常に作成されました。オーケストレーションに LangChain4j を使用し、データ接続に MCP ツールボックス Java SDK を使用することで、エージェント、ツール、データソース全体で推論できるシステムを作成しました。複数のデータベース(プラットフォーム間を含む)で MCP Toolbox for Databases を使用してエージェント アプリケーションのオーケストレーションを開始する場合は、今すぐ Java SDK をお試しください。ライブラリについて詳しくは、こちらのリリース アナウンスのブログをご覧ください。このようなアプリケーションをハンズオンで作成したい場合は、自分のペースでインストラクターの指導を受けながら無料で作成できる Code Vipassana(https://codevipassana.dev)に登録してください。
