Build a Model Context Protocol (MCP) Server and Client with Spring Boot 3
This tutorial walks through creating a Model Context Protocol (MCP) server and client using Spring Boot 3, covering dependencies, configuration, tool implementation, registration, and sample code to enable AI models to access external services like weather and IP information.
1. Introduction
Model Context Protocol (MCP) is a standardized protocol that lets large AI models connect easily to external data sources and tools, much like a universal USB‑C plug.
1.1 What is MCP
MCP abstracts the connection between AI models and external resources, allowing models to read/write files, simulate browser actions, or invoke other tools.
1.2 Why MCP is Needed
Provides a uniform interface so AI models can interact with various tools without custom integration code.
Breaks data silos by unifying access to disparate data sources.
1.3 Java and MCP Architecture
The architecture consists of a client/server layer, a session layer (McpSession), and a transport layer (McpTransport) that handles JSON‑RPC serialization.
2. Practical Example
2.1 Server Development
Add the following Maven dependencies:
<code><dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
</dependency></code>Configuration (application.yml):
<code>spring:
ai:
dashscope:
api-key: sk-xxxooo
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
chat:
options:
stream: true
model: qwen-turbo
---
spring:
ai:
mcp:
server:
enabled: true
name: ai_mcp_server
version: 1.0.0
type: ASYNC
sse-message-endpoint: /mcp/message</code>Implement two external tools:
<code>public class CommonTool {
@Tool(description = "获取当前天气预报")
WeatherResponse getCurrentWeather(WeatherRequest request) {
System.err.printf("准备查询【%s】天气预报%n", request.city());
RestClient client = RestClient.create(URI.create("https://api.vvhan.com"));
Map<?,?> result = client.get()
.uri("/api/weather?city={0}", request.city())
.retrieve()
.body(Map.class);
try {
return new WeatherResponse(new ObjectMapper().writeValueAsString(result));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Tool(description = "获取IP地址详细信息")
String getIpAddressInfo(String ip) {
System.err.printf("准备查询【%s】详细信息%n", ip);
RestClient client = RestClient.create(URI.create("https://api.vvhan.com"));
Map<?,?> result = client.get()
.uri("/api/ipInfo?ip={0}", ip)
.retrieve()
.body(Map.class);
try {
return new ObjectMapper().writeValueAsString(result);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}</code>Register the tools:
<code>@Configuration
public class ToolsConfig {
@Bean
ToolCallbackProvider tools() {
ToolCallback[] toolCallbacks = ToolCallbacks.from(new CommonTool());
return ToolCallbackProvider.from(toolCallbacks);
}
}</code>Start the server – the console will show the registered tools.
2.2 Client Development
Add client dependencies:
<code><dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M6.1</version>
</dependency></code>Client configuration:
<code>spring:
ai:
mcp:
client:
enable: true
name: ai-mcp-client
initialized: true
type: ASYNC
sse:
connections:
server1:
url: http://localhost:8888</code>Define a controller that uses the injected ToolCallbackProvider and ChatClient :
<code>@RestController
@RequestMapping("/tools")
public class ToolController {
private final ChatClient chatClient;
public ToolController(ChatClient.Builder aiClientBuilder, ToolCallbackProvider mcpTools) {
this.chatClient = aiClientBuilder.defaultTools(mcpTools).build();
}
@GetMapping("/weather")
public ResponseEntity<String> getCurrentWeather(String prompt) {
System.err.println(prompt);
String response = this.chatClient.prompt(prompt).call().content();
return ResponseEntity.ok(response);
}
@GetMapping("/ip")
public ResponseEntity<String> getIpAddressInfo(String prompt) {
System.err.println(prompt);
String response = this.chatClient.prompt(prompt).call().content();
return ResponseEntity.ok(response);
}
}</code>When the application starts, the client automatically discovers the two tools (weather and IP lookup) from the server.
After these steps, you can call the tools via the defined REST endpoints and see the AI model invoking the external services successfully.
Success!
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.