ブログ
これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。
JAVAでMCP構築
Morita
3 weeks
MCP、AIエージェント基本メモ
このページでは、MCP(Modular Component Protocol)とAIエージェントの基本的な仕組みと、 Java 25およびSpring 3.5.4を使ったメモ。
MCPとAIでできること
AIが「やりたいこと」を理解し、MCPが外部ツールやサービスを安全かつ標準化された方法で呼び出す役割を担います。 つまり、AIが「頭脳」、MCPが「道具箱への接続規格」として機能します。
具体例
-
ソフトウェア開発の自動化
- ユーザーが「顧客管理APIを作って」と指示
- AIエージェントがタスクを分解(コード生成 → テスト → Gitコミット)
- MCPサーバが各機能を提供
- 結果:コードが生成され、テストされ、リポジトリに保存される
-
ドキュメント処理・要約
- ユーザーが「この契約書を要約して」と依頼
- エージェントが要約タスクを決定
- MCPサーバがAI要約機能を呼び出し、結果を返す
- 結果:要約済み文書が提示される
-
データ分析・レポート生成
- ユーザーが「売上データから月次レポートを作って」と依頼
- エージェントが「データ取得 → 分析 → グラフ生成 → レポート作成」とタスク分解
- MCPサーバが各処理を提供
- 結果:自動生成されたレポートが完成
-
業務フローの自動化
- ユーザーが「毎週の会議資料をまとめてメール送信して」と依頼
- エージェントが「資料生成 → PDF化 → メール送信」と段取り
- MCPサーバが各機能を提供
- 結果:会議資料が自動作成・送信される
システム構成と起動手順
使用技術
- Java 25
- Spring Framework 3.5.4
起動順序
-
MCPサーバを起動
-
MCPクライアントを起動
@Override
public void run(String... args) throws Exception {
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();
System.out.println("取得したツール数: " + (toolCallbacks == null ? 0 : toolCallbacks.length));
}
メッセージ送受信例
- URL:
http://localhost:8080/api/generate?prompt=明日の天気は? - メッセージ送信:「明日の天気は?」
- 返答例:「天気予報では、現時点での天気を詳細に示す機能もあるようです。現在の天気は『曇り』です。」
処理の流れ
- MCPサーバ起動
- MCPクライアント起動
- APIでメッセージ受信
- LLMがMCPサーバの機能を選定
- 選定機能をMCPサーバで実行
- 実行結果を受け取る
- 結果をLLMで返答文に変換
- 返答を送信元に返却
MCPサーバ側のツール登録例
@Tool(description = "与えられた場所の天気の情報を取得します。")
public String getWeather(String place) {
Objects.requireNonNull(place, "place must not be null");
var weathers = List.of("晴れ", "晴れ", "雨", "曇り", "曇り", "雪");
return weathers.get(ThreadLocalRandom.current().nextInt(weathers.size()));
}
@Tool(description = "現在時刻を返します")
public String getTime() {
return LocalDateTime.now().toString();
}
MCPクライアント起動時のツール取得例
@Component
public class McpClientRunner implements CommandLineRunner {
private final AsyncMcpToolCallbackProvider toolCallbackProvider;
public McpClientRunner(AsyncMcpToolCallbackProvider toolCallbackProvider) {
this.toolCallbackProvider = toolCallbackProvider;
}
@Override
public void run(String... args) throws Exception {
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();
System.out.println("取得したツール数: " + (toolCallbacks == null ? 0 : toolCallbacks.length));
}
}
メッセージ受信からツール選択・実行までの流れ
String userp = "あなたはツール選択エージェントです。以下のツール一覧から、ユーザーの質問に最も適したツール名を1つだけ返してください。 "
+ toolList.getToolList()
+ "ユーザー入力:"
+ prompt
+ " 最も適したツール名を1つだけ返してください。 ";
String result = webClient.post()
.uri("/chat/completions")
.bodyValue(Map.of(
"model", "ai/llama3.2",
"messages", List.of(Map.of("role", "user", "content", userp))
))
.retrieve()
.bodyToMono(String.class)
.block();
public String callWeatherTool() {
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();
if (toolCallbacks == null || toolCallbacks.length == 0) {
System.out.println("ツールが登録されていません。設定を確認してください。");
return "";
}
for (ToolCallback callback : toolCallbacks) {
if ("getWeather".equalsIgnoreCase(callback.getToolDefinition().name())) {
try {
Map<String, Object> args = new HashMap<>();
args.put("place", "Tokyo");
String jsonArgs = new ObjectMapper().writeValueAsString(args);
String result = callback.call(jsonArgs);
System.out.println("WeatherTool 呼び出し結果: " + result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return "";
}
実行結果をLLMに渡して自然言語応答を生成
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(weatherClient.callWeatherTool());
String weatherRaw = root.get(0).path("text").asText();
String weather = weatherRaw.replace("\"", "");
String toolResponse =
"ツールから「" + weather + "」という天気情報が返ってきました。" +
"これをユーザーに伝える自然な日本語の文章にしてください。説明文は不要です。";
String result2 = webClient.post()
.uri("/chat/completions")
.bodyValue(Map.of(
"model", "ai/llama3.2",
"messages", List.of(Map.of("role", "user", "content", toolResponse))
))
.retrieve()
.bodyToMono(String.class)
.block();
JAVAでMCP構築
JAVAでMCP構築
2026-01-22 22:23:15
2026-02-18 12:38:41
コメントはありません。