PlugWiki

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. 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 mcp module. Spring AI 2.0+ adds Spring Boot starters and the @Tool annotation; 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. 2

    Add the dependency

    Add the mcp-bom and the mcp artifact to your pom.xml as in the Code section. The BOM sets the versions, so the mcp dependency needs none. The SDK docs show BOM 2.2.0-M2, a milestone. Swap in 2.1.0 for the latest release.

    The mcp artifact bundles mcp-core with Jackson 3. Use mcp-core plus mcp-json-jackson2 if your project needs Jackson 2.

  3. 3

    Write the server

    Copy EchoServer.java from the Code section. StdioServerTransportProvider serves over stdin and stdout, McpServer.sync(...) builds a blocking server, and toolCall(...) 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 text is present.

    Tip: Never print to System.out in a stdio server. Log through SLF4J to stderr or a file.

  4. 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. 5

    Test it in MCP Inspector

    Run npx @modelcontextprotocol/inspector java -jar /absolute/path/to/echo-server.jar and open the URL it prints. Go to Tools, pick echo, enter any text and run it. The result is the same text.

    The Inspector needs Node 22.19 or later. See MCP Inspector for details.

  6. 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 claude and run /mcp to see echo connected with its tool listed.

    Prompt
    Use the echo server to repeat "hello from Java".
  7. 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=true and its Windows tab shows -Dspring.ai.mcp.server.transport=STDIO, so check the Spring AI docs for your version.

  8. 8

    Serve it over HTTP when others need it

    The core mcp module 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 set spring.ai.mcp.server.protocol=STREAMABLE.

Code

pom.xml
<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>
Java 17 or later. The SDK docs show BOM 2.2.0-M2, a milestone; 2.1.0 is the latest release on GitHub.
EchoServer.java
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();
    }
}
Assembled from the stdio, server-builder and toolCall snippets on the SDK Server page. Imports and signatures match release 2.1.0.
terminal
# 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
Needs an executable jar. The Inspector takes the launch command after its own name.
claude_desktop_config.json
{
  "mcpServers": {
    "echo": {
      "command": "java",
      "args": ["-jar", "/absolute/path/to/echo-server.jar"]
    }
  }
}
Fully quit and reopen Claude Desktop after saving. On Windows use escaped backslashes in the path.
McpServerApplication.java
@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) { ... }
The Spring AI route, trimmed from the MCP tutorial. Add spring-ai-starter-mcp-server and spring-web as dependencies.

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.

    Source

  • 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.

    Source

  • 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.

    Source

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 8
  1. MCP Java SDK README (Java version badge) · github.com
  2. SDKs - Model Context Protocol · modelcontextprotocol.io
  3. Java SDK release v2.1.0 · github.com
  4. Quickstart - MCP Java SDK · java.sdk.modelcontextprotocol.io
  5. Build an MCP server (Java tab) · modelcontextprotocol.io
  6. MCP Server - Java SDK · java.sdk.modelcontextprotocol.io
  7. MCP Inspector · modelcontextprotocol.io
  8. Connect to a real host (Python SDK docs) · py.sdk.modelcontextprotocol.io

Updated Nov 3, 2026.