How to Build a Spring Boot MCP Server (2026)
Create a Model Context Protocol server in Java with Spring Boot
Start Building with Hypereal
Access Kling, Flux, Sora, Veo & more through a single API. Free credits to start, scale to millions.
No credit card required • 100k+ developers • Enterprise ready
How to Build a Spring Boot MCP Server (2026)
The Model Context Protocol (MCP) is an open standard created by Anthropic that enables AI assistants like Claude to interact with external tools and data sources. While most MCP server examples use TypeScript or Python, Java developers can build MCP servers using Spring Boot with the official MCP Java SDK. This guide walks you through building a fully functional MCP server from scratch.
What Is MCP?
MCP (Model Context Protocol) defines a standard way for AI assistants to:
- Call tools -- Execute functions like querying a database, calling an API, or running a calculation
- Read resources -- Access data like files, database records, or API responses
- Use prompts -- Retrieve pre-built prompt templates
Think of it as a plugin system for AI. When Claude connects to your MCP server, it discovers what tools are available and can call them during conversations.
MCP Architecture
┌─────────────┐ MCP Protocol ┌──────────────┐
│ Claude │ ◄──────────────────► │ MCP Server │
│ Desktop │ (JSON-RPC over │ (Spring Boot)│
│ or IDE │ stdio or SSE) │ │
└─────────────┘ └──────┬───────┘
│
┌──────┴───────┐
│ Your Tools │
│ - Database │
│ - APIs │
│ - Files │
└──────────────┘
Prerequisites
- Java 17 or later
- Maven or Gradle
- Spring Boot 3.2+
- Claude Desktop or any MCP-compatible client
Verify your Java version:
java --version
# Should output java 17.x.x or higher
mvn --version
# Apache Maven 3.9.x or higher
Step 1: Create the Spring Boot Project
Use Spring Initializr or create the project manually.
Using Spring Initializr
curl https://start.spring.io/starter.zip \
-d type=maven-project \
-d language=java \
-d bootVersion=3.4.2 \
-d baseDir=mcp-server \
-d groupId=com.example \
-d artifactId=mcp-server \
-d name=mcp-server \
-d packageName=com.example.mcpserver \
-d javaVersion=17 \
-d dependencies=web \
-o mcp-server.zip
unzip mcp-server.zip
cd mcp-server
Add MCP Dependencies
Add the MCP Java SDK to your pom.xml:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MCP Java SDK -->
<dependency>
<groupId>io.modelcontextprotocol</groupId>
<artifactId>mcp-spring-boot-starter</artifactId>
<version>0.6.0</version>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
Step 2: Configure the MCP Server
Create the application configuration in src/main/resources/application.yml:
server:
port: 8080
mcp:
server:
name: "my-spring-mcp-server"
version: "1.0.0"
transport: sse # Use "stdio" for CLI-based clients
Step 3: Define Your Tools
MCP tools are functions that Claude can call. Each tool has a name, description, input schema, and a handler.
Create a Tool Configuration Class
package com.example.mcpserver.tools;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.Tool;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.TextContent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
@Configuration
public class ToolConfiguration {
private final ObjectMapper objectMapper = new ObjectMapper();
@Bean
public McpServer.ToolRegistration weatherTool() {
// Define the input schema
String inputSchema = """
{
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name to get weather for"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units",
"default": "celsius"
}
},
"required": ["city"]
}
""";
Tool tool = new Tool(
"get_weather",
"Get the current weather for a given city",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String city = (String) arguments.get("city");
String units = (String) arguments.getOrDefault("units", "celsius");
// In a real app, call a weather API here
String weather = fetchWeather(city, units);
return new CallToolResult(
List.of(new TextContent(weather)),
false // isError
);
});
}
@Bean
public McpServer.ToolRegistration calculatorTool() {
String inputSchema = """
{
"type": "object",
"properties": {
"operation": {
"type": "string",
"enum": ["add", "subtract", "multiply", "divide"],
"description": "The math operation to perform"
},
"a": {
"type": "number",
"description": "First operand"
},
"b": {
"type": "number",
"description": "Second operand"
}
},
"required": ["operation", "a", "b"]
}
""";
Tool tool = new Tool(
"calculate",
"Perform a basic math calculation",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String operation = (String) arguments.get("operation");
double a = ((Number) arguments.get("a")).doubleValue();
double b = ((Number) arguments.get("b")).doubleValue();
double result = switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> {
if (b == 0) throw new ArithmeticException("Division by zero");
yield a / b;
}
default -> throw new IllegalArgumentException(
"Unknown operation: " + operation
);
};
return new CallToolResult(
List.of(new TextContent(String.valueOf(result))),
false
);
});
}
private String fetchWeather(String city, String units) {
// Placeholder - replace with actual API call
return String.format(
"Weather in %s: 22%s, partly cloudy, humidity 65%%",
city,
units.equals("celsius") ? "°C" : "°F"
);
}
}
Step 4: Add Resource Providers
Resources allow Claude to read data from your server:
package com.example.mcpserver.resources;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.spec.McpSchema.Resource;
import io.modelcontextprotocol.spec.McpSchema.ResourceContents;
import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class ResourceConfiguration {
@Bean
public McpServer.ResourceRegistration configResource() {
Resource resource = new Resource(
"config://app/settings",
"Application Settings",
"Current application configuration and settings",
"application/json"
);
return new McpServer.ResourceRegistration(resource, (uri) -> {
String configJson = """
{
"app_name": "My MCP Server",
"version": "1.0.0",
"features": ["weather", "calculator"],
"max_requests_per_minute": 60
}
""";
return new ResourceContents(
List.of(new TextResourceContents(uri, "application/json", configJson))
);
});
}
}
Step 5: Add a Database Tool (Practical Example)
Here is a more realistic example -- a tool that queries a database:
@Bean
public McpServer.ToolRegistration databaseQueryTool(JdbcTemplate jdbcTemplate) {
String inputSchema = """
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SQL SELECT query to execute (read-only)"
},
"limit": {
"type": "integer",
"description": "Maximum rows to return",
"default": 10
}
},
"required": ["query"]
}
""";
Tool tool = new Tool(
"query_database",
"Execute a read-only SQL query against the application database",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String query = (String) arguments.get("query");
int limit = ((Number) arguments.getOrDefault("limit", 10)).intValue();
// Security: only allow SELECT statements
if (!query.trim().toUpperCase().startsWith("SELECT")) {
return new CallToolResult(
List.of(new TextContent("Error: Only SELECT queries are allowed")),
true // isError
);
}
// Add LIMIT if not present
if (!query.toUpperCase().contains("LIMIT")) {
query += " LIMIT " + limit;
}
List<Map<String, Object>> results = jdbcTemplate.queryForList(query);
String json = objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(results);
return new CallToolResult(
List.of(new TextContent(json)),
false
);
});
}
Step 6: Run and Test
Build and Run
mvn clean package
java -jar target/mcp-server-0.0.1-SNAPSHOT.jar
The server starts on port 8080 with an SSE endpoint at /sse.
Test with cURL
# Check if the server is running
curl http://localhost:8080/sse
# List available tools (via MCP protocol)
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Step 7: Connect to Claude Desktop
Add your MCP server to Claude Desktop's configuration file.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
For SSE Transport
{
"mcpServers": {
"spring-mcp": {
"url": "http://localhost:8080/sse"
}
}
}
For stdio Transport
If you built your server with stdio transport, wrap the jar execution:
{
"mcpServers": {
"spring-mcp": {
"command": "java",
"args": [
"-jar",
"/path/to/mcp-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
Restart Claude Desktop after updating the configuration. Your tools should appear in Claude's tool list.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Server not found in Claude | Config file syntax error | Validate JSON; restart Claude Desktop |
| "Connection refused" | Server not running | Start the Spring Boot app first |
| Tools not appearing | Missing @Bean annotation |
Ensure tool beans are in a @Configuration class |
| SSE connection drops | Timeout settings | Configure server.servlet.session.timeout |
| JSON parse error | Schema mismatch | Validate your input schema against MCP spec |
Project Structure
mcp-server/
├── pom.xml
├── src/
│ └── main/
│ ├── java/com/example/mcpserver/
│ │ ├── McpServerApplication.java
│ │ ├── tools/
│ │ │ └── ToolConfiguration.java
│ │ └── resources/
│ │ └── ResourceConfiguration.java
│ └── resources/
│ └── application.yml
Conclusion
Building an MCP server with Spring Boot lets Java developers expose their existing services, databases, and APIs to AI assistants like Claude. The MCP Java SDK integrates naturally with Spring Boot's dependency injection and configuration system, making it straightforward to register tools and resources.
For teams that want to extend their MCP-enabled AI workflows with visual content generation -- such as creating product videos, generating images from descriptions, or building talking avatar interfaces -- Hypereal AI provides a unified API for video, image, and avatar generation that you can easily wrap as additional MCP tools.
Related Articles
Start Building Today
Get 35 free credits on signup. No credit card required. Generate your first image in under 5 minutes.
