How to Build an MCP Server in Java
Build a Java MCP server with the official MCP Java SDK, or with Spring AI on top of it, then test it in MCP Inspector and add it to Claude.
You build a Java MCP server with the official MCP Java SDK (Maven group io.modelcontextprotocol.sdk, artifact mcp). It needs Java 17 or later and offers blocking and reactive APIs. If your project is already Spring Boot, Spring AI adds starters and an @Tool annotation on top of the SDK, and the MCP tutorial uses that route.
The MCP site lists the Java SDK as Tier 2, one step below TypeScript, Python, C#, Go, Rust and Ruby. The latest GitHub release is 2.1.0 (October 2026). The SDK docs show a newer milestone, 2.2.0-M2, so check the version your snippet targets.
The tutorial's server speaks protocol version 2025-11-25. Clients that support only 2026-07-28 cannot connect to it.
Good for
- Java developers who want Claude to call their own code or services
- Spring Boot teams exposing an internal service as MCP tools
- Teams that already run Java services and want one language across the stack
Build, test and connect a Java MCP server
- 1
Choose SDK only or Spring AI
The SDK alone has no framework dependency. It ships stdio, SSE and Streamable HTTP transports in the core
mcpmodule. Spring AI 2.0+ adds Spring Boot starters and the@Toolannotation; the MCP tutorial's Java server uses it and needs Spring Boot 4.1.x or later.Our advice: use Spring AI if the service is already a Spring Boot app, and the plain SDK for a small standalone server. This guide's main steps use the SDK.
- 2
Add the dependency
Add the
mcp-bomand themcpartifact to yourpom.xmlas in the Code section. The BOM sets the versions, so themcpdependency needs none. The SDK docs show BOM 2.2.0-M2, a milestone. Swap in 2.1.0 for the latest release.The
mcpartifact bundlesmcp-corewith Jackson 3. Usemcp-coreplusmcp-json-jackson2if your project needs Jackson 2. - 3
Write the server
Copy
EchoServer.javafrom the Code section.StdioServerTransportProviderserves over stdin and stdout,McpServer.sync(...)builds a blocking server, andtoolCall(...)registers one tool with its schema and handler.The SDK validates each call's arguments against the schema before your handler runs, so the handler can trust that
textis present.Tip: Never print to System.out in a stdio server. Log through SLF4J to stderr or a file.
- 4
Package a runnable jar
Claude launches your server as a program, so it needs an executable jar with its dependencies and a
Main-Class. Build it with your build tool, for example a Maven shade or Spring Boot plugin. The tutorial's Spring Boot build produces one with./mvnw clean install.Note the absolute path of the jar for the next steps.
- 5
Test it in MCP Inspector
Run
npx @modelcontextprotocol/inspector java -jar /absolute/path/to/echo-server.jarand open the URL it prints. Go to Tools, pickecho, enter anytextand run it. The result is the same text.The Inspector needs Node 22.19 or later. See MCP Inspector for details.
- 6
Add it to Claude Code
Run
claude mcp add echo -- java -jar /absolute/path/to/echo-server.jar. Everything after--is the launch command.Start
claudeand run/mcpto seeechoconnected with its tool listed.PromptUse the echo server to repeat "hello from Java". - 7
Or add it to Claude Desktop
Add the entry from the Code section to
claude_desktop_config.json(macOS:~/Library/Application Support/Claude/claude_desktop_config.json, Windows:%APPDATA%\Claude\claude_desktop_config.json). Use the absolute path to the jar.Fully quit and reopen Claude Desktop. For the Spring AI server, the tutorial adds a system property to the
args. Its macOS/Linux tab shows-Dspring.ai.mcp.server.stdio=trueand its Windows tab shows-Dspring.ai.mcp.server.transport=STDIO, so check the Spring AI docs for your version. - 8
Serve it over HTTP when others need it
The core
mcpmodule includes a Servlet-based Streamable HTTP transport, so you can serve the same server by URL. In a Spring app, Spring AI's WebMVC and WebFlux starters provide the HTTP transports. The tutorial says to setspring.ai.mcp.server.protocol=STREAMABLE.
Code
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-bom</artifactId>
<version>2.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
</dependency>
</dependencies>import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
import io.modelcontextprotocol.spec.McpSchema.Tool;
import java.util.List;
import java.util.Map;
public class EchoServer {
public static void main(String[] args) {
var transportProvider =
new StdioServerTransportProvider(McpJsonDefaults.getMapper());
Map<String, Object> schema = Map.of(
"type", "object",
"properties", Map.of("text", Map.of("type", "string")),
"required", List.of("text"));
McpServer.sync(transportProvider)
.serverInfo("echo-server", "1.0.0")
.capabilities(ServerCapabilities.builder().tools(true).build())
.toolCall(
Tool.builder("echo", schema).description("Echoes input").build(),
(exchange, request) -> CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(
request.arguments().get("text").toString())))
.build())
.build();
}
}# Test in MCP Inspector
npx @modelcontextprotocol/inspector java -jar /absolute/path/to/echo-server.jar
# Claude Code (everything after -- is the launch command)
claude mcp add echo -- java -jar /absolute/path/to/echo-server.jar{
"mcpServers": {
"echo": {
"command": "java",
"args": ["-jar", "/absolute/path/to/echo-server.jar"]
}
}
}@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
}
// In your service class, annotate each tool method:
// @Tool(description = "Get weather alerts for a US state")
// public String getAlerts(@ToolParam(description = "Two-letter US state code") String state) { ... }Common errors and fixes
Server connects, then drops, or shows as failed in Claude
Cause: Something wrote to stdout, such as System.out.println. On stdio, stdout carries the protocol.
Fix: Remove it. Use a logging library that writes to stderr or a file, and make sure it is not configured to write to stdout.
claude-desktop, claude-code Source
Server does not appear in Claude Desktop after editing claude_desktop_config.json
Cause: A relative jar path, a JSON syntax error, or Claude Desktop is still running with the old config.
Fix: Use the absolute path to the jar, check the JSON, then fully quit and reopen Claude Desktop.
claude-desktop Source
A tool call returns an error and never reaches your handler
Cause: The SDK validates arguments against the tool's input schema by default and rejects calls that do not match.
Fix: Fix the arguments or the schema. You can turn the check off with validateToolInputs(false) on the server builder.
A method from the SDK docs does not exist in your version
Cause: The docs' dependency snippets show the 2.2.0-M2 milestone, while the latest release is 2.1.0.
Fix: Check which version the docs page targets and match your BOM to it.
A newer client cannot connect to the tutorial server
Cause: The tutorial server speaks protocol version 2025-11-25. Clients that support only 2026-07-28 cannot connect.
Fix: Use a client that also supports 2025-11-25, or check the Java SDK docs for the 2026-07-28 preview server.
Questions
Is there an official MCP SDK for Java?
Yes. The MCP Java SDK is in the modelcontextprotocol GitHub organisation. The MCP site lists it as a Tier 2 SDK.
Which Java version do I need?
Java 17 or later. The Spring AI route in the MCP tutorial also needs Spring Boot 4.1.x or later.
Should I use the Java SDK or Spring AI?
Spring AI is built on the SDK and adds Spring Boot starters and an @Tool annotation. Our advice: use it if you already run Spring Boot, and the plain SDK for a small standalone server.
Which SDK version should I use?
The latest GitHub release is 2.1.0. The SDK docs show 2.2.0-M2, a milestone, in their dependency snippets. If a method in the docs is missing in your version, check which version the page targets.
Sync or async server?
Both exist. McpServer.sync(...) gives a blocking API and McpServer.async(...) a reactive one built on Project Reactor. Start with sync unless you already use reactive code.
How do I test a Java MCP server with MCP Inspector?
Run npx @modelcontextprotocol/inspector java -jar /absolute/path/to/your.jar and open the URL it prints. You can call each tool and see the result. The Inspector needs Node 22.19 or later.
How do I add a Java MCP server to Claude Code?
Run claude mcp add <name> -- java -jar /absolute/path/to/your.jar, then /mcp in a session to confirm it is connected.
How do I add it to Claude Desktop?
Add an entry under mcpServers in claude_desktop_config.json with java as command and -jar plus the absolute jar path as args. Then fully quit and reopen Claude Desktop.
Why does System.out.println break my server?
On stdio, stdout carries the protocol messages. Anything you print there corrupts them and the connection breaks. Use a logging library that writes to stderr or a file.
Can a Java MCP server run over HTTP?
Yes. The core SDK includes a Servlet-based Streamable HTTP transport, and Spring AI adds WebMVC and WebFlux transports.
Sources
Docs, issue trackers and discussions this page is built from.
Show all 8Hide
- MCP Java SDK README (Java version badge) · github.com
- SDKs - Model Context Protocol · modelcontextprotocol.io
- Java SDK release v2.1.0 · github.com
- Quickstart - MCP Java SDK · java.sdk.modelcontextprotocol.io
- Build an MCP server (Java tab) · modelcontextprotocol.io
- MCP Server - Java SDK · java.sdk.modelcontextprotocol.io
- MCP Inspector · modelcontextprotocol.io
- Connect to a real host (Python SDK docs) · py.sdk.modelcontextprotocol.io