java-mcp-server-generator について
公式のMCP Java SDK 2.xを使ったJava MCPサーバーの作成を支援するスキルです。プロジェクト作成、実装、子プロセスでのテスト、ビルド、クライアント設定に加え、SDK固有の注意点も扱います。
主な機能
- 01Mavenプロジェクトのひな型作成
- 02Java SDK 2.xでのサーバー実装
- 03ツールスキーマと結果の検証
- 04stdioを使った子プロセステスト
- 05ビルドとクライアント設定の案内
- 06SDK移行とトランスポートの注意点
活用シーン
- 01依頼されたツールを備えるJava MCPサーバーの生成
- 02SDKクライアントを使ったstdio動作のテスト
- 03VS CodeまたはClaude Desktopからのサーバー起動設定
MCP 対応
公式Java SDK 2.xを使ってMCPサーバーを作成し、デフォルトのトランスポートとしてstdioを案内します。VS Code、Claude Desktop、Streamable HTTP向けのクライアント設定も説明します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill java-mcp-server-generatorインストール後、Claude Code で/java-mcp-server-generatorを入力して読み込まれたか確認します。
同梱ファイルreferences/gradle.mdreferences/streamable-http.md
詳細
Java MCP サーバー生成ツール
公式のMCP Java SDK 2.xを使用して、JavaでModel Context Protocol(MCP)サーバーを作成します。SDK 2.0.xは、MCP仕様のリビジョン2025-11-25と、それ以前のリビジョンをサポートしています。SDK 3.xでは、リビジョン2026-07-28が追加される予定です。
ワークフロー
このチェックリストをコピーして、進捗を記録してください。
- ステップ 1:プロジェクトを作成します。
- ステップ 2:サーバーを実装します。
- ステップ 3:テストを実装します。
- ステップ 4:テストに合格するまでビルドします。
- ステップ 5:クライアントを設定します。
ステップ 1:プロジェクトを作成する
デフォルトではMavenを使用します。プロジェクトがGradleを使用する場合、またはユーザーがGradleを希望する場合は、references/gradle.mdを読んでください。ステップ 1、ステップ 4、ステップ 5でその内容を使用します。
次の構成を作成します。
project-name/
├── pom.xml
└── src/
├── main/java/com/example/McpServerApp.java
└── test/java/com/example/McpServerAppTest.java
pom.xmlを記述します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mcp-server-demo</artifactId>
<version>0.1.0</version>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-bom</artifactId>
<version>2.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>6.1.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.17</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.McpServerApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
mcpアーティファクトには、mcp-coreとJackson 3のJSONマッパーmcp-json-jackson3が含まれています。slf4j-simpleは、SDKのログをstderrに出力します。- shadeプラグインは、すべての依存関係を含む実行可能JARを1つ作成します。
ステップ 2:サーバーを実装する
次のテンプレートから始めます。
package com.example;
import java.util.List;
import java.util.Map;
import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
import io.modelcontextprotocol.spec.McpSchema.Tool;
public final class McpServerApp {
static SyncToolSpecification divideTool() {
Tool tool = Tool.builder("divide", Map.of(
"type", "object",
"properties", Map.of(
"a", Map.of("type", "number", "description", "Dividend"),
"b", Map.of("type", "number", "description", "Divisor")),
"required", List.of("a", "b")))
.description("Divide a by b.")
.build();
return SyncToolSpecification.builder()
.tool(tool)
.callHandler((exchange, request) -> {
double a = ((Number) request.arguments().get("a")).doubleValue();
double b = ((Number) request.arguments().get("b")).doubleValue();
if (b == 0) {
return CallToolResult.builder().addTextContent("b must not be zero.").isError(true).build();
}
return CallToolResult.builder().addTextContent(String.valueOf(a / b)).build();
})
.build();
}
public static void main(String[] args) {
McpServer.sync(new StdioServerTransportProvider(McpJsonDefaults.getMapper()))
.serverInfo("demo", "0.1.0")
.capabilities(ServerCapabilities.builder().tools(false).build())
.tools(divideTool())
.build();
}
}
次に、ユーザーのリクエストに合わせてテンプレートを変更します。
divideTool()を、ユーザーが求めるツールに置き換えます。ツールごとにメソッドを1つ作成します。- 各ツールにJSON Schemaの
inputSchemaとdescriptionを設定します。説明には、モデルがそのツールをいつ使用するかを記述します。 - クライアントが機械可読データを必要とする場合は、ツールに
.outputSchema(Map)を追加します。CallToolResult.builder().structuredContent(map)でデータを返します。古いクライアント向けに、同じデータをテキストコンテンツとしても追加します。 - 読み取り専用のツールには
.annotations(ToolAnnotations.builder().readOnlyHint(true).build())を設定します。破壊的なツールにはdestructiveHint(true)を使用します。 - ユーザーが求めた場合にのみ、リソース、リソーステンプレート、プロンプトを追加します。また、
ServerCapabilitiesでそれらを有効にします。
デフォルトではstdioを使用します。ユーザーがリモートサーバー、HTTPサーバー、またはSpring Bootを求めた場合にのみ、references/streamable-http.mdを読んでください。
ステップ 3:テストを実装する
テストではサーバーをサブプロセスとして起動し、SDKクライアントで接続します。各ツールと各エラー結果のテストを作成します。
package com.example;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.file.Path;
import java.util.Map;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.ServerParameters;
import io.modelcontextprotocol.client.transport.StdioClientTransport;
import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.TextContent;
class McpServerAppTest {
private static McpSyncClient client;
@BeforeAll
static void startServer() {
String java = Path.of(System.getProperty("java.home"), "bin", "java").toString();
ServerParameters server = ServerParameters.builder(java)
.args("-cp", System.getProperty("java.class.path"), McpServerApp.class.getName())
.build();
client = McpClient.sync(new StdioClientTransport(server, McpJsonDefaults.getMapper())).build();
client.initialize();
}
@AfterAll
static void stopServer() {
client.close();
}
@Test
void divide() {
CallToolResult result = client.callTool(
CallToolRequest.builder("divide").arguments(Map.of("a", 6, "b", 3)).build());
assertEquals("2.0", ((TextContent) result.content().get(0)).text());
}
@Test
void divideByZero() {
CallToolResult result = client.callTool(
CallToolRequest.builder("divide").arguments(Map.of("a", 1, "b", 0)).build());
assertTrue(result.isError());
assertTrue(((TextContent) result.content().get(0)).text().contains("must not be zero"));
}
}
- テストでは、Mavenの実行に使用されるJDKの
javaコマンドを使用します。PATHにあるjavaコマンドは使用しないでください。 - テストでは、実際のstdioトランスポートと実際のJSON-RPCメッセージを使用します。
ステップ 4:テストに合格するまでビルドする
mvn verifyを実行します。このコマンドはコードをコンパイルし、テストを実行して、target/mcp-server-demo-0.1.0.jarを作成します。- テストが失敗した場合は、エラーを確認します。サーバーまたはテストを修正します。
mvn verifyを再度実行します。- ビルドが成功するまで続けます。
ステップ 5:クライアントを設定する
VS Codeの場合は、.vscode/mcp.jsonを記述します。
{
"servers": {
"demo": {
"type": "stdio",
"command": "java",
"args": ["-jar", "/absolute/path/to/project/target/mcp-server-demo-0.1.0.jar"]
}
}
}
Claude Desktopの場合は、同じcommandとargsをclaude_desktop_config.jsonのmcpServersキーの下に記述します。
HTTPサーバーの場合は、references/streamable-http.mdにあるクライアント設定を使用します。
次の情報をユーザーに伝えます。
java -jar target/mcp-server-demo-0.1.0.jarでstdioサーバーが起動します。サーバーはstdinでホストからの接続を待機します。SDKのログはstderrに出力されます。- サーバーを手動でテストするには、同じコマンドでMCP Inspectorを起動します。InspectorはNode.jsを使用します。
注意点
SDK 2.x では、SDK 0.x および 1.x のパターンの多くが変更されています。以前のバージョンの例をそのまま使わないでください。詳細については、移行ガイドをお読みください。
- 必須フィールドを先に受け取るビルダーを使用してください:
Tool.builder(name, inputSchema)、Resource.builder(uri, name)、Prompt.builder(name)、TextContent.builder(text)、およびReadResourceResult.builder(contents)。引数を取らないビルダーは非推奨です。 - 必須フィールドに
nullを指定してはいけません。null値を指定するとIllegalArgumentExceptionが発生します。 - ツール名は1~128文字で、使用できる文字は英字、数字、
_、-、.です。サーバービルダーは、不正な名前をIllegalArgumentExceptionで拒否します。実行時のaddTool()では名前をチェックしません。 inputSchemaとoutputSchemaはMap<String, Object>の値です。JsonSchemaレコードは非推奨です。- サーバーは、
build()またはaddTool()を呼び出したときに各スキーマを JSON Schema 2020-12 に照らして検証します。不正なスキーマを指定するとIllegalArgumentExceptionが発生します。 - SDK はツールの引数を
inputSchemaに照らして検証します。また、structuredContentをoutputSchemaに照らして検証します。検証に失敗すると、クライアントにはisErrorがtrueに設定されたツール結果が返されます。そのため、ハンドラーが受け取るのは有効な引数のみです。 - ツールに
outputSchemaがある場合は、成功した結果ごとにstructuredContentを返してください。返さない場合、SDK はisErrorがtrueに設定されたツール結果を返します。 - モデルに読み取らせるエラーには、
isError(true)を指定したCallToolResultを返してください。 - ツールの失敗時に例外や
McpErrorをスローしないでください。クライアントにはツール結果ではなく、JSON-RPC エラーが返されます。多くのホストでは、このエラーはモデルに表示されません。 - stdio サーバーでは、stdout はプロトコルの通信チャネルです。
System.out.println()を呼び出さないでください。 - SLF4J で stderr にログを出力してください。Logback のデフォルトのコンソールアペンダーは stdout に書き込みます。Logback を使用する場合は、出力先を
System.errに設定してください。 - Spring トランスポートは Spring AI 2.0 以降(グループ
org.springframework.ai)に移行しました。io.modelcontextprotocol.sdk:mcp-spring-*アーティファクトは使用しないでください。 - 非推奨の SSE トランスポートは使用しないでください。リモートサーバーには Streamable HTTP を使用してください。
- 2026-07-28 の改訂により、以下の機能は非推奨になりました(SEP-2577)。新しいサーバーには追加しないでください:
- サンプリング(
exchange.createMessage()):LLM プロバイダーの API を直接呼び出してください。 - プロトコルロギング(
exchange.loggingNotification()):SLF4J を使用してください。 - ルート(
exchange.listRoots()):ツールの引数、リソース URI、またはサーバー設定からパスを取得してください。
- サンプリング(