Build a Java MCP Server in 10 Minutes: No Spring Needed
Welcome, developers. In today's article, we're continuing our series on the Model Context Protocol (MCP) with an important twist. We'll be implementing an MCP server using only the core Java SDK, without the Spring framework. For those who've read previous articles on MCP, this tutorial will expand your toolkit by showing you how to work with the standard Java implementation. This approach gives you more flexibility and lighter dependencies when Spring isn't needed in your project.
This article will walk you through: - Setting up the core MCP Java dependency. - Implementing an MCP server using the standard Java SDK. - Working with default transport implementations. - Testing your implementation with the MCP inspector tool.
The MCP inspector will be our testing companion, helping us verify our server implementation works correctly and follows the protocol specification. Let's dive into building a streamlined MCP server with pure Java.
Understanding the Model Context Protocol (MCP)
Before we dive into the code, it's useful to visit the official website, modelcontextprotocol.io
. This is where you can find comprehensive information about MCP. The Java SDK section, in particular, details what we are covering today and offers much more information on the advanced features of the Model Context Protocol Java SDK for building MCP clients and servers.
A key point, which can sometimes be confusing, is that while the project was donated by the Spring Team, you do not need Spring to use it. The io.textprotocol.mcp.sdk
core provides default STDIO and SSE (Server-Sent Events) transports without requiring any external web framework. However, if you are a Spring developer, optional dependencies are available to integrate smoothly.
Setting Up the Java Project
We'll start by creating a new Java project. Using IntelliJ, you can create a new Maven project. We'll name it java-mcp-example
with a JDK 24.
Next, we need to add a couple of dependencies to our pom.xml
. We'll add the model context protocol SDK and SLF4J for logging, which helps in monitoring the application's behavior. We will also use the maven-shade-plugin
to package our application into an executable JAR file.
Here is the complete pom.xml
configuration:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.danvega</groupId>
<artifactId>java-mcp-server</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>24</maven.compiler.source>
<maven.compiler.target>24</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mcp.version>0.9.0</mcp.version>
<slf4j.version>2.0.13</slf4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.textprotocol.mcp</groupId>
<artifactId>mcp-sdk-bom</artifactId>
<version>${mcp.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.textprotocol.mcp</groupId>
<artifactId>mcp-sdk</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>dev.danvega.Application</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Defining the Data Model and Tools
Before implementing the MCP server logic, let's define our data model and business logic. We'll create a Presentation
record to hold information about presentations from the Java 1 conference.
public record Presentation(String title, String url, int year) {
}
Next, we'll create a PresentationTools
class to manage a collection of these presentations. This class will simulate a data source and provide methods to access the data, which we will later expose as tools to the MCP server.
import java.util.ArrayList;
import java.util.List;
public class PresentationTools {
private final List<Presentation> presentations = new ArrayList<>();
public PresentationTools() {
// Initialize with some data
var keynote1 = new Presentation("Java + AI: A Concerto for Human and Machine by Dr. Heinz M. Kabutz", "https://www.youtube.com/watch?v=J025aB9-6sQ", 2025);
var keynote2 = new Presentation("Keynote: To the Future of Java and Beyond by Brian Goetz", "https://www.youtube.com/watch?v=G4t3K-oP3v4", 2025);
var p3 = new Presentation("Stream Gatherers: A New Tool for Your Toolbelt by Nicolai Parlog", "https://www.youtube.com/watch?v=HNWd439aaA", 2025);
var p4 = new Presentation("AI 2: The Rise of the Machines by Venkat Subramaniam", "https://www.youtube.com/watch?v=B2Shy4d52sI", 2025);
var p5 = new Presentation("Sequenced Collections: A New Order by Stuart Marks", "https://www.youtube.com/watch?v=v951f5P1gA", 2025);
presentations.addAll(List.of(keynote1, keynote2, p3, p4, p5));
}
public List<Presentation> getPresentations() {
return presentations;
}
public List<Presentation> getPresentationsByYear(int year) {
return presentations.stream()
.filter(p -> p.year() == year)
.toList();
}
}
Implementing the MCP Server
Now we can implement the MCP server in our main application class.
- Setup Logger and Tools: First, we'll get a logger and instantiate our
PresentationTools
. - Configure Transport: We'll use the
StdioServerTransportProvider
, which is a standard transport mechanism. It requires a JacksonObjectMapper
, which is a transitive dependency from the MCP SDK. - Define Tool Specification: The
getSyncToolSpecification
method defines the tool we want to expose. It creates aSyncToolSpecification
for ourgetPresentations
method. This involves defining the tool's name, description, and schema. The core logic here is to call our Java method (presentationTools.getPresentations()
) and transform the result into a list ofMCP.Schema.Content
objects that the protocol understands. - Build and Start the Server: Finally, we create and configure the server using
MCP.Server.serve()
. We provide server info, define its capabilities (enabling tools and logging), and register our tool specification.
Here is the full Application.java
:
import com.fasterxml.jackson.databind.ObjectMapper;
import io.textprotocol.mcp.MCP;
import io.textprotocol.mcp.sdk.protocol.TransportProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
private static final PresentationTools presentationTools = new PresentationTools();
public static void main(String[] args) {
log.info("Starting server...");
var transportProvider = new MCP.StdioServerTransportProvider(new ObjectMapper());
var syncToolSpecification = getSyncToolSpecification();
MCP.Server.serve(transportProvider, server -> {
server.info("Java 1 MCP Server", "0.0.1");
server.capabilities(
new MCP.Schema.ServerCapabilities.Builder()
.tools(true)
.logging(true)
.build()
);
server.tools(syncToolSpecification);
server.build();
});
}
private static MCP.Server.Features.SyncToolSpecification getSyncToolSpecification() {
var schema = new MCP.Schema.Tool(
"operation",
null
);
var syncToolSpecification = new MCP.Server.Features.SyncToolSpecification(
"getPresentations",
"Get a list of all presentations from Java 1",
schema,
(exchange, arguments) -> {
List<Presentation> presentations = presentationTools.getPresentations();
List<MCP.Schema.Content> contents = new ArrayList<>();
for (Presentation presentation : presentations) {
contents.add(new MCP.Schema.TextContent(presentation.toString()));
}
return new MCP.Schema.CallToolResult(contents, false);
}
);
return syncToolSpecification;
}
}
Packaging and Testing the Server
With the code in place, package the application into an executable JAR file using Maven:
mvn clean package
This command will produce a JAR file in the target
directory. Now, we can use the MCP Inspector to test our server. Run the inspector using npx
:
npx @vscode/mcp-inspector
In the MCP Inspector UI:
1. Select STDIO
as the transport type.
2. For the command, enter java -jar
followed by the absolute path to your generated JAR file (e.g., java -jar /path/to/your/project/target/java-mcp-server-1.0.0.jar
).
3. Click Connect.
You should see the "Starting server..." log message from our application. The inspector will connect, and you can now interact with your server.
- List Tools: Click
list-tools
. The client will query the server, and you should see ourgetPresentations
tool listed with its description. - Run Tool: Click
run-tool
. This executes the tool, and the server will return the list of presentations, which will be displayed in the inspector.
Client Integration
A real-world MCP client, like Claude Code, can attach to this server. Once connected, the client becomes aware of the available tools. When you ask a relevant question, such as "Can you provide me a list of all presentations from Java 1?", the client will recognize that it has a tool for that, request your permission, and execute the call to your MCP server to fetch the data. The result is a seamless integration of your custom Java logic into the AI assistant.
This article demonstrated how to build a simple "Hello, World" MCP server in pure Java, using the official SDK without any external frameworks. This approach is lightweight and gives you full control over your implementation.
Join the 10xdev Community
Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.