Spring Boot Starter for building Model Context Protocol (MCP) servers with auto-configuration, annotation-based tool/resource/prompt definitions, and support for STDIO, SSE, and Streamable-HTTP transports
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Spring Boot starter for building Model Context Protocol (MCP) servers with auto-configuration, annotation-based definitions, and multiple transport protocols.
| Aspect | Details |
|---|---|
| Package | org.springframework.ai:spring-ai-starter-mcp-server |
| Type | Maven Spring Boot Starter |
| Language | Java |
| Protocols | STDIO, SSE, Streamable-HTTP, Stateless |
| Server Types | Synchronous (SYNC), Asynchronous (ASYNC) |
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>@SpringBootApplication
public class MyMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(MyMcpServerApplication.class, args);
}
}
@Component
public class MyTools {
@McpTool(name = "add", description = "Add two numbers")
public int add(
@McpToolParam(description = "First number", required = true) int a,
@McpToolParam(description = "Second number", required = true) int b) {
return a + b;
}
}spring.ai.mcp.server.stdio=true
spring.ai.mcp.server.name=my-mcp-server
spring.ai.mcp.server.version=1.0.0| Annotation | Purpose | Example |
|---|---|---|
@McpTool | Define executable tool | @McpTool(name = "calc") |
@McpResource | Define resource | @McpResource(uri = "config://{key}") |
@McpPrompt | Define prompt template | @McpPrompt(name = "greeting") |
@McpComplete | Define completion | @McpComplete(prompt = "city") |
| Protocol | Use Case | Configuration |
|---|---|---|
| STDIO | CLI tools | spring.ai.mcp.server.stdio=true |
| SSE | Web apps (default) | spring.ai.mcp.server.protocol=SSE |
| Streamable | HTTP streaming | spring.ai.mcp.server.protocol=STREAMABLE |
| Stateless | Scalable deployments | spring.ai.mcp.server.protocol=STATELESS |
| Type | Execution Model | Return Types |
|---|---|---|
| SYNC | Blocking operations | Primitives, Objects, MCP types |
| ASYNC | Reactive operations | Mono<T>, Flux<T> |
// Annotations
import org.springaicommunity.mcp.annotation.McpTool;
import org.springaicommunity.mcp.annotation.McpToolParam;
import org.springaicommunity.mcp.annotation.McpResource;
import org.springaicommunity.mcp.annotation.McpPrompt;
import org.springaicommunity.mcp.annotation.McpArg;
// Context
import org.springaicommunity.mcp.server.McpSyncRequestContext;
import org.springaicommunity.mcp.server.McpAsyncRequestContext;
// Schema Types
import org.springaicommunity.mcp.schema.McpSchema.*;
// Spring
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Bean;@McpTool(name = "divide", description = "Divide two numbers")
public CallToolResult divide(
@McpToolParam(description = "Numerator", required = true) double a,
@McpToolParam(description = "Denominator", required = true) double b) {
if (b == 0) {
return CallToolResult.builder()
.addTextContent("Error: Division by zero")
.isError(true)
.build();
}
return CallToolResult.builder()
.addTextContent("Result: " + (a / b))
.build();
}@McpTool(name = "process", description = "Process with progress")
public String process(McpSyncRequestContext context,
@McpToolParam(description = "Data") String data) {
context.info("Starting");
context.progress(0);
// Work...
context.progress(50);
// More work...
context.progress(100);
return "Done";
}@McpResource(
uri = "config://{key}",
name = "Configuration",
description = "Get config value")
public String getConfig(String key) {
return configService.get(key);
}# Server basics
spring.ai.mcp.server.enabled=true
spring.ai.mcp.server.name=mcp-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=SYNC # or ASYNC
# Transport
spring.ai.mcp.server.stdio=false
spring.ai.mcp.server.protocol=SSE # SSE, STREAMABLE, STATELESS
# Capabilities
spring.ai.mcp.server.capabilities.tool=true
spring.ai.mcp.server.capabilities.resource=true
spring.ai.mcp.server.capabilities.prompt=true
spring.ai.mcp.server.capabilities.completion=true
# Timeouts
spring.ai.mcp.server.request-timeout=20s| Problem | Solution |
|---|---|
| Tool not discovered | Ensure class is @Component and method is public |
| Connection fails | Check transport config and port availability |
| Schema generation fails | Use supported types or explicit CallToolRequest |
| Context unavailable | Verify stateful protocol (not STATELESS) |