Ein minimaler MCP-Server (Model Context Protocol) auf Basis von Spring Boot 4 und Spring AI 2.0.
- Java 25
- Maven 3.9+
curl -s -o spring-init.zip "https://start.spring.io/starter.zip?\
type=maven-project&language=java&bootVersion=4.0.6\
&groupId=com.example&artifactId=helloworld\
&packageName=com.example.helloworld&javaVersion=25\
&dependencies=configuration-processor"
unzip spring-init.zipSpring Initializr liefert ein fertiges Maven-Projekt mit mvnw, .gitignore und
einer leeren HelloworldApplication.java.
Zwei Ergänzungen gegenüber dem generierten Stand:
a) start-class in <properties> eintragen (für AOT-fähiges Packaging):
<properties>
<java.version>25</java.version>
<start-class>com.example.helloworld.HelloworldApplication</start-class>
</properties>b) MCP-Server-Starter hinzufügen (Spring AI WebFlux / SSE-Transport):
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
<version>2.0.0-M8</version>
</dependency>c) Spring Milestones Repository (da M8 noch kein GA-Release ist):
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>Der spring-boot-starter aus dem Initializr-Template wird durch
spring-ai-starter-mcp-server-webflux ersetzt — der Starter zieht
WebFlux, Reactor und den MCP-Protokollstack selbst mit.
MCP-Tools sind einfache Spring-Beans, deren Methoden mit @Tool annotiert
werden. Die description erscheint im MCP-Toolkatalog und wird vom
KI-Modell für die Tool-Auswahl genutzt.
@Service
public class HelloWorldTools {
@Tool(description = "Returns a greeting message for the given name")
public String greet(String name) {
return "Hello, %s! Welcome to the MCP Hello World Server.".formatted(name);
}
@Tool(description = "Returns the current server time as ISO-8601 string")
public String serverTime() {
return java.time.Instant.now().toString();
}
}Spring AI benötigt einen ToolCallbackProvider-Bean, der dem MCP-Server
mitteilt, welche Tools exportiert werden sollen:
@Bean
public ToolCallbackProvider helloWorldTools(HelloWorldTools tools) {
return MethodToolCallbackProvider.builder().toolObjects(tools).build();
}spring.application.name=helloworld
spring.ai.mcp.server.name=hello-world-mcp
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=ASYNC
server.port=8080type=ASYNCaktiviert den reaktiven SSE-Transport (passend zu WebFlux).nameundversionerscheinen im MCP-Handshake.
./mvnw spring-boot:runDer Server lauscht auf http://localhost:8080.
./curl-test.shDas Script durchläuft den kompletten MCP-Protokollablauf:
- Öffnet eine SSE-Verbindung zu
/sseund liest den Session-Endpoint aus dem Stream - Sendet
initialize(Handshake mit Protokollversion) - Sendet
notifications/initialized(Bestätigung) - Ruft
tools/listauf — zeigt alle registrierten Tools - Ruft
tools/call greetmitname=Worldauf - Ruft
tools/call serverTimeauf
Beispielausgabe:
Connecting to http://localhost:8080/sse ...
Session endpoint: /mcp/message?sessionId=003c8063-07bb-49a3-ac42-95e048a10f3a
[initialize]
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"completions": {},
"logging": {},
"prompts": { "listChanged": true },
"resources": { "subscribe": false, "listChanged": true },
"tools": { "listChanged": true }
},
"serverInfo": {
"name": "hello-world-mcp",
"version": "1.0.0"
}
}
}
[notifications/initialized] sent
[tools/list]
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "greet",
"description": "Returns a greeting message for the given name",
"inputSchema": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
}
},
{
"name": "serverTime",
"description": "Returns the current server time as ISO-8601 string",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
}
]
}
}
Verfügbare Tools:
- greet: Returns a greeting message for the given name
- serverTime: Returns the current server time as ISO-8601 string
[tools/call greet]
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [{ "type": "text", "text": "\"Hello, World! Welcome to the MCP Hello World Server.\"" }],
"isError": false
}
}
=> "Hello, World! Welcome to the MCP Hello World Server."
[tools/call serverTime]
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [{ "type": "text", "text": "\"2026-06-04T08:10:42.098489232Z\"" }],
"isError": false
}
}
=> "2026-06-04T08:10:42.098489232Z"
Der Server-URL kann über die Umgebungsvariable MCP_SERVER überschrieben werden:
MCP_SERVER=http://myserver:9090 ./curl-test.shcurl -N http://localhost:8080/sse