Spring AI MCP入门:手写一个Jdbc MCP Server
目前网上能看到的MCP Server基本上都是基于Python或者nodejs ,虽然也有Java版本的MCP SDK,但是鲜有基于Java开发的。 不过尽管如此,作为Java开发中的顶级框架Spring已经基于MCP SDK在进行Spring AI框架开发了,不过目前还没有正式发布,本文将使用Spring AI MCP做一个简单的查询数据库的MCP Server。
引入依赖
目前为止Spring AI MCP相关依赖最新的版本号是1.0.0-M7,我试了通过SSE的方式访问是不通的,如果有人测试访问是通的,麻烦给我留个言。sdtio的方式没有试过,感兴趣的可以试一下。
所以本文还是基于1.0.0-M6的版本,具体依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>site.sunlong</groupId>
<artifactId>jdbc-mcp-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jdbc-mcp-server</name>
<description>jdbc-mcp-server</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M6</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
从传输协议角度,spring-ai-mcp-server 相关依赖分为两类:
- STDIO(标准输入输出) : 主要用于本地或进程内通信,通过标准输入输出流与客户端交互。对应的依赖为
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
- 基于 Web 的 SSE(Server-Sent Events): 通过 HTTP/SSE 协议提供服务,适合 Web 环境或需要通过 HTTP 接口与客户端通信的场景。SSE 依赖又分为两类,区别在于 webflux 是非阻塞模型、响应式编程:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
配置文件:
spring.ai.mcp.server.name=jdbc-mcp-server
# 是否使用 stdio 传输协议,默认false
spring.ai.mcp.server.stdio=false
spring.data.jdbc.dialect=mysql
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_practice?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
写工具
依赖和配置都准备好了以后,剩下的就是动手开发了。写工具分两步,编写工具和注册工具。
- 使用@Tool注解编写工具
- @Tool 注解标记这个方法是一个工具,通过 description 属性告诉大模型这个工具是做什么的,其实就是提示词,大模型会根据自己的理解调用这个工具,所以这个描述很重要。
- @ToolParam:从名字可以看出来,就是工具调用时需要传什么参数
@Service
public class JdbcQueryService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Tool(description = "查询数据库中所有的表")
public List<Map<String, Object>> queryAllTables(){
String sql = "SELECT TABLE_NAME , TABLE_COMMENT FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE()";
return jdbcTemplate.queryForList(sql);
}
@Tool(description = "查询数据库中的表的数据")
public List<Map<String, Object>> queryTable(@ToolParam(description = "表名") String tableName){
String sql = "SELECT * FROM " + tableName;
return jdbcTemplate.queryForList(sql);
}
}
- 注册工具
@Configuration
public class McpConfig {
@Bean
ToolCallbackProvider jdbcQueryTools(JdbcQueryService jdbcQueryService) {
return MethodToolCallbackProvider
.builder()
.toolObjects(jdbcQueryService)
.build();
}
}
启动服务端,控制台打印如下日志表明工具注入成功,我是写了2个工具,所以tools是2。
测试
客户端配置
启动之后就可以通过客户端调用MCP Server了,我这依旧使用Cherry Studio。
Cherry Studio中添加MCP 服务器
连接上之后可用工具列表就可以看到工具及描述了,同时在控制台也可以看到MCP 客户端传过来的信息:
Client initialize request - Protocol: 2024-11-05, Capabilities: ClientCapabilities[experimental=null, roots=null, sampling=null], Info: Implementation[name=Cherry Studio, version=1.2.1]
调用MCP 服务端
对话框界面选择MCP服务器 ,选择刚才添加的MCP 服务端,然后就可以进行对话了。
下面两个图是我对话的截图及大模型的输出,因为太长就只截图了部分界面,可以看到大模型的确是调用了工具并将数据库中有哪些表和该表的数据也给返回了。
查询数据库中所有的表
查询数据库中的表的数据
遇到的问题
因为还没有正式发布,所以会存在一些问题。
1. 连接超时 在客户端连接服务端时,总是提示超时,而且在调用时会特别慢,会超时连接很多次。
2. 会话发送失败 客户端连接过来之后发送会话会一直失败
总结
从我们的实现过程来看,实现一个MCP服务端并不复杂。 目前来说 MCP也是属于起步阶段,生态还有待完善,所以 Spring AI MCP也还不成熟,当然后面随着MCP的起飞,Spring AI MCP也会起飞的,所以让子弹再飞一会儿吧。
下一篇将介绍一下,Spring AI MCP Client 怎么入门使用。