SpringAI的Model Context Protocol(MCP)是一个强大的工具集成框架,它允许开发者将各种功能封装成可调用的工具,并通过标准化协议与AI模型进行交互。作为一名长期从事Java开发的工程师,我在实际项目中发现MCP特别适合构建需要AI增强能力的服务端应用。
MCP服务端主要支持三种通信模式:
这三种模式各有优势,开发者可以根据具体需求选择。下面我将通过四个实际案例,详细讲解如何构建不同类型的MCP服务端。
首先创建一个基础的Spring Boot项目,添加以下关键依赖:
xml复制<properties>
<java.version>17</java.version>
<spring-ai.version>1.1.2</spring-ai.version>
</properties>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这里使用SpringAI 1.1.2版本,需要Java 17或更高版本。MCP服务端核心依赖是spring-ai-starter-mcp-server。
核心工具类需要完成两个功能:
java复制@Service
public class WeatherService {
private final String KEY;
private final RestClient restClient;
public WeatherService() {
this.restClient = RestClient.builder().build();
this.KEY = System.getenv("AMAP_KEY");
}
@Tool(description = "根据城市名称查询对应的城市编码")
public String getAdCode(@ToolParam(description = "查询的城市,比如: 北京") String keywords) {
// 实现细节...
}
@Tool(description = "根据城市编码查询对应城市的天气信息")
public String getWeather(@ToolParam(description = "查询的城市编码,比如: 110101") String adCode) {
// 实现细节...
}
}
关键点说明:
@Tool注解标记这是一个MCP工具@ToolParam描述参数用途在启动类中注册工具:
java复制@SpringBootApplication
public class Application {
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder()
.toolObjects(weatherService)
.build();
}
}
测试时可以使用Cherry Studio工具,配置如下JSON:
json复制{
"mcpServers": {
"weather-server": {
"command": "java",
"args": [
"-Dfile.encoding=UTF-8",
"-Dsun.jnu.encoding=UTF-8",
"-jar",
"path/to/your.jar"
],
"env": {
"AMAP_KEY": "your_api_key"
}
}
}
}
注意事项:
- 高德API有调用频率限制,生产环境需要添加缓存
- 错误处理要完善,考虑网络超时等情况
- API密钥不要硬编码在代码中
SSE服务端需要不同的starter:
xml复制<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
<version>${spring-ai.version}</version>
</dependency>
配置文件设置:
properties复制server.port=8086
spring.ai.mcp.server.protocol=sse
spring.ai.mcp.server.sse-endpoint=/sse
翻译服务需要考虑多语言支持:
java复制@Service
public class TranslationService {
@Tool(description = "将句子或词从一种语言翻译为另一种语言")
public String translate(
@ToolParam(description = "需要翻译的句子或词") String text,
@ToolParam(description = "句子当前语言标识") Language languageFrom,
@ToolParam(description = "将要翻译的语言标识") Language languageTo) {
// 实现细节...
}
public enum Language {
ZH("zh", "中文"),
EN("en", "英语"),
// 其他语言...
}
}
百度翻译API需要签名验证,关键签名方法:
java复制private Map<String, String> buildTranslateParams(String query, String from, String to) throws Exception {
Map<String, String> params = new HashMap<>();
params.put("q", query);
params.put("from", from);
params.put("to", to);
params.put("appid", appId);
String salt = String.valueOf(System.currentTimeMillis());
params.put("salt", salt);
params.put("sign", md5(appId + query + salt + securityKey));
return params;
}
测试时注意:
优化建议:
添加邮件相关依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置SMTP:
properties复制spring.mail.host=smtp.163.com
spring.mail.port=465
spring.mail.username=your@163.com
spring.mail.password=your_password
spring.mail.properties.mail.smtp.ssl.enable=true
支持多种邮件格式:
java复制@Service
public class EmailService {
@Tool(description = "给指定邮箱发送邮件信息")
public String sendSimpleEmail(
@ToolParam(description = "收件人邮箱") String[] to,
@ToolParam(description = "邮件主题") String subject,
@ToolParam(description = "邮件正文") String content,
@ToolParam(description = "邮件类型") EmailType emailType) {
// 实现细节...
}
public enum EmailType {
MARKDOWN, HTML, TEXT
}
}
Markdown转HTML使用Flexmark:
java复制public static String convertToHtml(String markdownStr) {
MutableDataSet dataSet = new MutableDataSet();
return HtmlRenderer.builder(dataSet).build()
.render(Parser.builder(dataSet).build()
.parse(markdownStr));
}
使用Docker快速部署:
bash复制docker pull searxng/searxng:latest
mkdir -p ./searxng/config/ ./searxng/data/
docker run --name searxng -d \
-p 8888:8080 \
-v "./config/:/etc/searxng/" \
-v "./data/:/var/cache/searxng/" \
docker.io/searxng/searxng:latest
配置修改config/settings.yml:
yaml复制server:
base_url: "http://localhost:8888/"
secret_key: "your_secret_key"
search:
formats:
- json
java复制@Service
public class SearXNGService {
@Tool(description = "根据关键字联网搜索")
public String search(@ToolParam(description = "搜索关键字") String keyword) {
String url = "/search?q=" + keyword
+ "&format=json&engines=bing&categories=general&language=zh-CN";
Response response = restClient.get().uri(url).retrieve().body(Response.class);
// 结果处理...
}
}
症状:工具在Cherry Studio中不可见
排查步骤:
@Tool注解是否正确使用症状:工具能注册但调用失败
排查步骤:
症状:响应缓慢或超时
优化建议:
在实际项目中,我发现SpringAI MCP最大的优势在于它的灵活性。通过标准化的协议,我们可以轻松集成各种功能,同时保持与AI模型的无缝交互。特别是在需要快速原型开发的场景中,这种架构可以大大缩短开发周期。