1. 總覽
現代旅客期待對話體驗。他們不想使用複雜的 UI 篩選器,而是想問:「我可以在早上 9 點搭乘前往波士頓的巴士,並攜帶狗狗嗎?」這需要代理程式能夠根據非結構化資料 (PDF 政策) 和結構化資料 (SQL 時間表) 進行推理。
在本實驗室中,我們將使用下列項目建構 Cymbal Transit Agent:
- LangChain4j:頂尖的 Java AI 自動化調度管理框架。
- AlloyDB:與 PostgreSQL 相容的高效能資料庫。
- MCP Toolbox Java SDK:以標準化方式將 Java 代理程式連結至外部工具和資料來源。
建構項目
Cymbal Bus Agent,這是一個 Java Spring Boot 應用程式,包含:
- AlloyDB 資料庫和 MCP Toolbox Java SDK,用於自動化調度管理代理的工具。
- Cloud Run for Toolbox Deployment and Application (agent deployment)。
- 在 Java 17 的 Spring Boot 應用程式中,使用 LangChain4J 程式庫做為代理程式和 LLM 架構。
課程內容
- 如何使用 LangChain4J 建立專用代理和子代理,並透過 MCP Toolbox for Databases Java SDK 協調運作
- 如何設定及使用 AlloyDB for Data and AI。
- 如何使用 MCP Toolbox 將代理程式連結至 AlloyDB 資料工具。
- 如何使用 Cloud Run 部署解決方案,或在本機執行解決方案。
架構
- AlloyDB for PostgreSQL:做為高效能的作業資料庫,儲存路線、政策和預訂記錄。可支援向量搜尋和檢索。
- MCP Toolbox for Databases Java SDK:扮演「自動調度大師」的角色,將 AlloyDB 資料公開為代理可呼叫的可執行工具。
MCP Toolbox Java SDK 可輕鬆運用資料庫工具協調代理,打造企業級應用程式。
- LangChain4J:開放原始碼 Java 程式庫,可簡化大型語言模型 (LLM) 與 Java 應用程式的整合作業。提供建構 AI 輔助應用程式的工具和抽象化功能,包括聊天機器人、代理程式和檢索增強生成 (RAG) 系統。
- Cloud Run:全代管的無伺服器平台,可讓您輕鬆建構及部署應用程式或網站,並支援任何語言、程式庫和二進位檔。您可以使用慣用的語言、架構和程式庫編寫程式碼、將程式碼封裝為容器,然後執行「gcloud run deploy」指令,應用程式就能正式上線,而且系統會為應用程式提供投入正式環境所需的一切運作資源。是否建構容器全由您決定。如果您使用的是 Go、Node.js、Python、Java、.NET Core 或 Ruby,可以利用「以來源為基礎的部署選項」,透過所用語言的最佳做法來建構容器。
需求條件
2. 事前準備
建立專案
- 在 Google Cloud 控制台的專案選取器頁面中,選取或建立 Google Cloud 專案。
- 確認 Cloud 專案已啟用計費功能。瞭解如何檢查專案是否已啟用計費功能。
- 您將使用 Cloud Shell,這是 Google Cloud 中執行的指令列環境。點選 Google Cloud 控制台頂端的「啟用 Cloud Shell」。

- 連至 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 (按一下終端機中的連結,或按一下終端機中的「preview on web」連結)。
- 輸入專案 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 控制台中,將「Vertex AI 使用者」角色授予 AlloyDB 服務帳戶 (看起來像這樣:service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com)。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 Toolbox for Databases 是資料庫專用的開放原始碼 MCP 伺服器。這項服務可處理連線集區、驗證和其他複雜作業,讓您更輕鬆、快速且安全地開發工具。您可以透過工具箱建構生成式 AI 工具,讓代理程式存取資料庫中的資料。
我們使用 Model Context Protocol (MCP) Toolbox for Databases 做為「指揮家」。這項服務可做為代理程式和 AlloyDB 之間的標準化中介軟體。定義 tools.yaml 設定後,工具箱會自動將複雜的資料庫作業公開為可執行的乾淨工具,例如 find-bus-schedules and routes 或 query-schedules for specific routes,並執行 book-ticket 等自主動作。因此您不必在代理程式邏輯中手動建立連線集區或樣板 SQL。
安裝 Toolbox 伺服器
在 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
接著,在該新資料夾中建立 tools.yaml 檔案,方法是前往 Cloud Shell 編輯器,然後將這個 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 Toolbox 服務網址。您可能要等到初始部署完成後才會收到連結,因此您必須執行兩次部署步驟,確保已驗證的工具使用案例正常運作。
- 如果 AlloyDB 連線設為私有,以下本機測試工具箱的選項將無法運作,您必須將連線設為公開,才能在本機測試,或使用 Proxy 連線。但請不必擔心,在本例中,我們會直接部署至 Cloud Run,然後進行測試。
如要在本機伺服器中測試 tools.yaml 檔案,請執行下列步驟:
./toolbox --tools-file "tools.yaml"
您也可以在 UI 中測試:
./toolbox --ui
請按照下列步驟,在 Cloud Run 中部署。
Cloud Run 部署作業
- 設定 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 上傳為 Secret:
gcloud secrets create tools-cymbal-transit --data-file=tools.yaml
- 如果您已有密鑰,並想更新密鑰版本,請執行下列指令:
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
- 執行下列指令,將 Toolbox 部署至 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 可確保服務專員在單一工作階段中,記住最多 20 則訊息的使用者偏好設定 (例如先前提及的寵物提籠)。
2. AI 代理介面 (TransitAgent)
@SystemMessage 註解會定義「Persona」和作業限制,特別是路徑策略。
@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 Toolbox 服務 (McpToolboxService)
這是通訊層,使用 MCP Toolbox 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 Toolbox for Databases
工程團隊不再只開發簡單的聊天機器人,而是建構能直接與任務關鍵資料庫互動的代理系統。不過,建構這些企業代理程式通常意味著會遇到整合瓶頸,例如自訂黏著程式碼、脆弱的 API 和複雜的資料庫邏輯。
為以安全且統一的控制平面取代這些硬式編碼瓶頸,我們很高興宣布推出資料庫適用的 Model Context Protocol (MCP) Toolbox Java SDK。這項版本將一流的型別安全代理程式協調功能,帶到全球最廣泛採用的企業生態系統。Java 的成熟架構專為這些嚴格需求而設計,可提供高並行性、嚴格的交易完整性,以及強大的狀態管理功能,確保重要 AI 代理程式在正式環境中安全無虞地擴充。
為何選擇 Java SDK?
Java 開發人員可透過 MCP Toolbox Java SDK 執行下列操作:
- 使用工具:連線至 MCP 伺服器 (例如 MCP Toolbox for AlloyDB),並自動將伺服器的功能轉換為 LangChain4j 可理解的 Java 方法。
- 型別安全:針對工具參數運用 Java 的嚴格型別,減少工具呼叫中的執行階段「幻覺」錯誤。
- 企業就緒:輕鬆整合 Spring Boot、Quarkus、Micronaut 等。
- 輕鬆連線:避免編寫樣板 JSON-RPC 程式碼。
- 標準化驗證:原生支援 Google Cloud OIDC 權杖,確保工具安全執行。
更多。
依附元件:pom.xml 設定
將下列依附元件新增至 Maven 專案,即可納入最新版 MCP Toolbox Java SDK:
<dependency>
<groupId>com.google.cloud.mcp</groupId>
<artifactId>mcp-toolbox-sdk-java</artifactId>
<version>0.2.0</version>
</dependency>
將下列依附元件新增至 Maven 專案,即可納入 LangChain4j 構件:
<!-- 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>> 的值替換為實際值
指令完成後,會輸出服務網址。複製。
將「AlloyDB Client」(AlloyDB 用戶端) 角色授予 Cloud Run 服務帳戶。這樣一來,無伺服器應用程式就能安全地連線至資料庫。
在 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 服務清單 ,並確認該服務的安全防護分頁中已選取「允許公開存取」。
現在請使用服務網址 (先前複製的 Cloud Run 端點) 測試應用程式。
注意:如果遇到服務問題,且系統指出原因為記憶體不足,請嘗試將分配的記憶體上限提高至 1 GiB,然後進行測試。
11. 試用版
詢問服務專員:「我明天早上需要從紐約前往波士頓。我可以帶黃金獵犬來嗎?"觀察代理程式如何:
- 搜尋大型犬的政策。
- 尋找特定行程。
- 歸納出最快的行程,並提供行程 ID。
- 如果你後續採取行動要求,也會預訂票證。

12. 清除所用資源
完成本實驗室後,請務必刪除 AlloyDB 叢集和執行個體。
這應該會清除叢集及其執行個體。
13. 恭喜
您已成功建構以 Java 為基礎的複雜轉運代理程式。您運用 LangChain4j 進行自動調度管理,並使用 MCP Toolbox Java SDK 連結資料,建立的系統可跨代理、工具和資料來源進行推理。如要開始使用 MCP Toolbox for Databases 協調多個資料庫 (甚至是跨平台) 的代理式應用程式,請立即使用 Java SDK!請參閱這篇發布公告網誌文章,進一步瞭解程式庫。如要親自建構更多這類應用程式,請前往 https://codevipassana.dev 註冊 Code Vipassana,免費參加由講師帶領的課程,按照自己的步調學習!
