はじめに
OpenLibertyで簡単に実現するMCPサーバー 【1: 動かす編】では、サンプルアプリケーションの起動手順とAIエージェントと接続して利用した例をご紹介しました。
この記事では、サンプルプログラムの実装解説を行い、MCPサーバーを構築する手順や難易度を理解していきます。
前提条件
Open Liberty / WebSphere Libertyでの開発知識がある想定で記載しています。
定義ファイル
server.xml
MCPサーバーの機能を持つfeatureとしてmcpServerを指定します。ベータ版で指定可能なバージョンは1.0です。
mcpServerを導入することで、依存関係から次のfeatureも自動的に導入されます。
- cdi-4.0
- jsonb-3.0
- jsonp-2.1
- servlet-6.0
その他のfeatureは今回のアプリケーションで使用しています。
<featureManager>
<feature>mcpServer-1.0</feature>
<feature>enterpriseBeansLite-4.0</feature>
<feature>jdbc-4.3</feature>
<feature>transportSecurity-1.0</feature>
</featureManager>
MCPツールの実装
JAX-RSのようにアノテーションで宣言的に定義します
サンプルプログラムからのコード抜粋(一部読みやすいように整理しています)です。ポイントは次のとおりです。
- メソッドをツールとして宣言する
- メソッドの引数をツール引数として宣言する
@Tool(
name = "get-user",
title = "ユーザー情報取得",
description = "指定されたユーザー ID の名前とロールを取得します。")
public String getUser(
@ToolArg(
name = "userid",
description = "対象ユーザーのユーザーID。"
) String userId) {
return service.getUser(userId).toString();
}
この機能をJAX-RSでRESTAPIとして公開するとしたら、次のようなコードになるはずです。
@GET
@Path("/user")
@Produces(MediaType.APPLICATION_JSON)
public String getUser(@PathParam("userId") String userId) {
return service.getUser(userId).toString();
}
- アノテーションで外部公開のための定義を記載する
- メソッド内部はプレーンなJavaコードで実装する
という点で一致しているため、APIの開発経験があれば違和感なく実装できるでしょう。
SDKによる実装との比較
MCPの公式サイトにJava用のSDKが公開されています。
こちらを使用して実装した経験もあるのですが、次のようなコードを準備する必要があります。以下のコードは、上記サイトのサンプルコードから抜粋したものです。
1. 通信のインタフェースとなるTransportProviderを作成する
@Bean
public HttpServletStreamableServerTransportProvider servletStreamableMcpSessionTransport() {
return HttpServletStreamableServerTransportProvider.builder()
.objectMapper(new ObjectMapper())
.contextExtractor(TEST_CONTEXT_EXTRACTOR)
.mcpEndpoint(MESSAGE_ENDPOINT)
.keepAliveInterval(Duration.ofSeconds(1))
.build();
}
2.サーバー定義を行う(1のTransportProviderはここで紐づける)
McpSyncServer syncServer = McpServer.sync(transportProvider)
.serverInfo("my-server", "1.0.0")
.capabilities(ServerCapabilities.builder()
.tools(true) // Enable tool support
.build())
.build();
3.ツールをサーバーに追加する
var syncToolSpecification = new McpServerFeatures.SyncToolSpecification(
new Tool("calculator", "Basic calculator", schema),
(exchange, arguments) -> {
// Tool implementation
return new CallToolResult(result, false);
}
);
syncServer.addTool(syncToolSpecification);
このコードを実装するために、次のクラスの機能と役割を理解する必要があります。
- HttpServletStreamableServerTransportProvider
- McpSyncServer
- McpServerFeatures.SyncToolSpecification
- CallToolResult
大規模な開発に適用する場合は、難しい部分を隠ぺいして実装しやすくフレームワーク化する工夫もできるでしょう。ただ、独自の実装手順を準備するとなると保守性が気になります。
SDK固有の難しさを回避して、JAX-RSに似た形で宣言的、直感的に実装できることで開発の難易度が大きく下がります。
ツール定義
主な機能はOpenLibertyのブログに記載されています。ここではアノテーションで使用する代表的な要素についてご紹介します。
詳細はJavaDocにも記載されています。JavaDocはベータ版リソースのうち (展開フォルダ)\dev\api\ibm\javadoc\io.openliberty.mcp_1.0-javadoc.zip に存在します。
Tool アノテーション
| 項目 | 必須 | 説明 |
|---|---|---|
| name | 〇 | 一意に設定するツール名 |
| title | AIエージェントで表示するユーザー向けのツール表記 | |
| description | 〇 | AIがツール利用判定に使用する説明文 |
ToolArg アノテーション
| 項目 | 必須 | 説明 |
|---|---|---|
| name | 〇 | 一意に設定するツール名 |
| description | 〇 | AIがツール利用判定に使用する説明文 |
| required | 項目指定が必須の場合trueを指定する 指定しない場合のデフォルトはtrue |
ベータ版の制約
現時点で次の制約がある認識です。
日本語対応が今後の課題
ツールから出力するテキストの文字コードが適切に設定されていないようで、日本語が絡む出力は文字化けを起こします。そのため、サンプルプログラムではアノテーション定義やテストデータは英数字で統一しています。
requiredはまだ機能しない
ToolArgアノテーションにrequiredを指定できますが、1.0.108ではrequired=falseは機能していません。AIエージェント側はrequired=falseの定義に基づき、パラメータを渡さない挙動を取ることもありますが、この場合はサーバーサイドでランタイムエラーになります。
Issueとして管理されているためいずれ解消すると思いますが、現在はrequiredの指定は行わずにパラメータを全て埋める必要があります(サンプルプログラムでは設定不要なパラメータに * という文字列を渡すという仕様をDescriptionに記載し、サーバーロジックで * の場合は評価しないことで回避しています
)。
MCPエンドポイント
/mcpというパスがエンドポイントになります。
サンプルプログラムではコンテキストルートが librarymcp のため、librarymcp/mcp というパスがMCPサーバーのエンドポイントになります。
おわりに
MCPサーバーの実装としては、現状「RESTAPIで実装し、ブリッジを使いMCP化する」というパターンもあります。
「MCP ブリッジ」で検索すると、色々なブリッジのソリューションを見つけることができます。
ただ、Structured Content(ツールの出力構造を定義する)などの一部仕様は、ブリッジで対応可能な範囲を超えているようにみえます。
今後もMCP仕様は進化していく可能性があり、なるべくMCPサーバーを提供する場合にはネイティブ実装することを第一選択としたほうが無難であると考えます。
その際、Open Libertyが提供するMCPServerのFeatureはとても頼りになるといえるでしょう。
将来的にJakartaEEの仕様として採用され、Javaが得意とするエンタープライズ領域のアプリケーションでAIとの融合が幅広く展開されるといいですね。
...と半ば強引にJakartaEEのアドベントカレンダーに結びつけてみましたがいかがでしょうか![]()
「JavaとAI」というとAI駆動開発が注目されがちですが、アプリケーションの機能とAIのマッシュアップこそユーザーに価値を届ける組み合わせと考えます。MCPの機能などを駆使して、新しい世代のアプリケーションサービスを提供していきましょう。