IBM BobのMCP機能でJavaシステムを使うための、LLMへ渡す明細の設計
IBM WebSphere Application Server Liberty(以降、WAS Liberty)の mcp-1.0 を使うと、CDI Bean の Java メソッドを MCP Tool として AI から呼び出せます。ここでは、IBM Bob から既存の WAS Liberty 業務アプリケーションを呼び出すケースを想定します。
mcp-1.0 は WAS Liberty 26.0.0.9(2026年9月8日)で GA(正式提供)になりました。ベータ版の mcpServer-1.0 ではなく、GA 版の mcp-1.0 と <mcp> を前提に説明します。
この記事の前に、IBM BobからWAS Libertyの getExpenseSummary Tool を呼び出す最小サンプルを確認したい場合は、こちらを参照してください。
【IBM Bob × WAS Liberty】MCPで既存Javaシステムを自然言語で使う
この記事は、MCP Tool を1つ動かせた後に、既存の API や業務ロジックをどの粒度で公開するかを考えるための記事です。接続そのものは、別記事の最小サンプルで確認します。
MCP 化そのものがトークンを減らすわけではありません。Tool の説明や呼び出し結果も LLM のコンテキストに渡るため、設計が悪いとむしろ増えます。
それでも、Tool を適切な粒度で設計すれば、LLM に渡すデータ量、Tool 呼び出し回数、LLM に任せる計算を減らせます。
先に結論:MCP は節約機能ではない
LLM が消費する量には、ユーザーの質問だけでなく、Tool の名前・説明・引数定義と、Tool が返す結果も含まれます。そのため、Tool を追加すれば必ず安くなる、という話ではありません。
削減対象は、LLM に渡していた大量の明細と中間結果です。検索・結合・集計を WAS Liberty 側で済ませ、会話に必要な最終結果だけ返すと、総量を抑えやすくなります。
MCP クライアントによっては Tool 定義を必要なときに読み込むものもあるため、効果の出方はクライアント構成に依存します。それでも Tool の戻り値を絞ることは、どのクライアントでも会話に渡る情報量を減らす基本になります。
問題:細かい API をそのまま AI に渡す
会社員Aの交通費精算状況を調べるために、AI が次のような Tool を何度も呼ぶ構成を考えます。
getEmployee(employeeId)listTravelExpenses(employeeId)listExpenseApprovalStatus(employeeId)calculateUnsettledTravelExpense(employeeId)
AI は各結果を読み、結合し、未精算額と承認状況を判断して、最後に文章化します。
これは既存 API をそのまま MCP に載せただけの形です。交通費の明細が多ければ、その JSON が毎回 LLM に渡ります。複数回の Tool 呼び出しも必要になり、トークン、応答時間、判断の余地が増えます。
例えば「未精算と承認待ちの件数だけでよい」のに全明細を返す、未精算額を Java 側で計算できるのに LLM に明細を渡して計算させる、といった形は避けたいところです。
解決:業務上意味のある Tool にまとめる
交通費精算状況の確認という目的に合わせ、アプリケーション側で必要なデータを集計する Tool を用意します。
@Tool(
name = "getExpenseSummary",
description = "指定した社員の未精算交通費、承認待ち件数、差戻し件数を要約して返す"
)
public ExpenseSummary getExpenseSummary(
@ToolArg(name = "employeeId", description = "社員ID")
String employeeId
) {
// 指定の社員IDについて、未精算交通費、承認待ち件数、差戻し件数を取得・集計する。
return expenseRepository.findExpenseSummary(employeeId);
}
この Repository が実行する SQL のイメージは次のとおりです。テーブル名とステータス値は説明用のダミーです。
SELECT
employee_id,
COALESCE(SUM(CASE WHEN status = 'UNSETTLED' THEN amount ELSE 0 END), 0)
AS unsettled_travel_expense,
COUNT(CASE WHEN status = 'PENDING_APPROVAL' THEN 1 END)
AS pending_approval_count,
COUNT(CASE WHEN status = 'RETURNED' THEN 1 END)
AS returned_count
FROM travel_expenses
WHERE employee_id = :employeeId
GROUP BY employee_id;
つまり、LLM へ渡すのは「指定の社員ID、未精算交通費、承認待ち件数、差戻し件数」の4項目だけです。明細行そのものは WAS Liberty 側で集計し、会話へは返しません。
返すデータも、画面や会話に必要な範囲に絞ります。
{
"employeeId": "EMP-A001",
"unsettledTravelExpense": 12000,
"pendingApprovalCount": 2,
"returnedCount": 0
}
この形なら、検索、結合、集計は Java 側で決定的に実行されます。LLM は「いつ Tool を使うか」と「結果をどう説明するか」に集中できます。
何が減るのか
- 大量明細を会話に積む量
- 中間結果を読むための入力トークン
- 複数 Tool の往復回数
- LLM に計算や整合性判断をさせる場面
- 中間データの読み違いによる回答ミス
特に金額、権限、在庫、締め処理のように正確性が必要な処理は、LLM に推論させるよりアプリケーション側に寄せるべきです。
Tool を大きくしすぎない
逆に、何でも行う doEverything のような Tool は避けます。説明が曖昧になり、AI が使いどころを判断しにくくなります。
目安は、DB テーブルや REST API の単位ではなく、利用者が達成したい業務単位です。
- 会社員の交通費精算状況を把握する →
getExpenseSummary - 注文の配送状況を把握する →
getOrderDeliveryStatus - 指定期間の売上を確認する →
getSalesSummary
入力と返却内容を絞り、必要なら最大件数や期間も Tool の引数として明示します。
また、すべての Tool を最初から AI に提示する必要はありません。利用場面が異なる Tool は MCP サーバーや接続先を分けることも、Tool 定義そのものの説明量を抑える一つの方法です。
まとめ
WAS Liberty の MCP 対応は、Java の業務ロジックを AI から使える Tool にする機能です。
重要なのは「API をそのまま公開する」ことではなく、アプリケーション側で情報取得・計算・絞り込みを済ませ、LLM に答えに近い小さな結果だけ渡すことです。MCP は、その境界を標準的な形で実装するための手段になります。
実際に動かす
Java 25 移行済みの備品管理アプリを GitHub から取得し、既存の Service を変えずに MCP Tool を追加して IBM Bob から呼び出す手順は、こちらです。
【IBM Bob × Liberty】既存Java 25アプリにMCP Toolを追加するハンズオン
参考: Expose your Liberty business logic as AI tools - a guide to the MCP feature