本文基于Spring AI Alibaba 1.0.0-M5.1 的示例讲解Spring AI (1.0.0-M5前)的实验性内容MCP(Model Context Protocol)组件。
Spring AI Alibaba官方文档:Spring AI Alibaba 模型上下文协议
介绍
模型上下文协议,规范应用程序如何向LLM提供上下文,实际上是通过统一的方式(JSON-RPC消息格式),将MCP Server (数据/工具提供者)和MCP Client进行通信
MCP Server多数是基于TypeScript/Python开发的,Spring AI提供了Java和Spring的集成,分模块架构
-
Spring AI application : Spring AI应用,例如ChatClient
-
Spring MCP Client: Spring AI下的MCP客户端
-
MCP Server: MCP服务
-
Local DataSource: 本地数据源
-
Remote Server: 远程服务
在阿里官方的文档中,提供了集成了隐私浏览器Brave的search API的MCP Server与Spring AI ChatClient的注册示例。Brave的计划有2000/月的免费方案,也有3🔪/1000次的付费方案。
官方示例
使用Spring AI MCP访问本地文件系统
该示例可以通过 MCP 查询或更新本地文件系统,并以文件系统中的数据作为上下文与模型交互。
前提准备
1. 安装 npx (Node Package eXecute): 首先确保本地机器安装了 npm,然后运行如下命令:
npm install -g npx
2. 如果使用官方的示例项目代码,请查看官方的仓库:Spring ai alibaba mcp example
3. 如果在你自己的项目里尝试,请确保添加了以下依赖(Maven)
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId
<version>1.0.0-M5.1</version>
</dependency>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
由于在Spring AI 1.0.0-M5版本中,MCP为实验性内容,还需要额外引入该依赖:
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-ai-mcp</artifactId>
<version>0.3.0</version>
</dependency>
代码
主要需要配置的组成模块分为三部分:
MCP Client:与MCP Server通信的关键组件
Function Callbacks:MCP专属的Function calling
ChatClient:Spring AI封装的LLM交互类,可视为单个智能体
1. 声明Function Callbacks
像所有工具方法那样,提供给ChatClient前,我们先声明好该Mcp提供了啥工具,此处使用的是McpFunctionCallback,这是spring-ai-mcp对FunctionCallback接口的实现类:
@Bean
public List<McpFunctionCallback> functionCallbacks(McpSyncClient mcpClient) {
return mcpClient.listTools(null)
.tools()
.stream()
.map(tool -> new McpFunctionCallback(mcpClient, tool))
.toList();
}
通过listTools方法,可以拿到MCPClient提供的所有工具,(更详细的内容详情请见源码解析),将McpClient提供的工具类配置为McpFunctionCallback类,并作为列表返回。
2. 声明ChatClient
在声明ChatClient时,和function calling几乎一模一样,提供给chatClient即可
var chatClient = chatClientBuilder
.defaultFunctions(functionCallbacks)
.build();
3. 初始化McpClient [关键]
每个提供服务的MCP Server的参数不太一样,但是启动的流程通过Spring AI MCP transport基本上统一了
@Bean(destroyMethod = "close")
public McpSyncClient mcpClient() {
// based on
// https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem
var stdioParams = ServerParameters.builder("npx")
.args("-y", "@modelcontextprotocol/server-filesystem", getFilePath())
.build();
var mcpClient = McpClient.using(new StdioClientTransport(stdioParams))
.requestTimeout(Duration.ofSeconds(10)).sync();
var init = mcpClient.initialize();
System.out.println("MCP Initialized: " + init);
return mcpClient;
}
// 定位本地文件系统路径
private static String getFilePath() {
String path = System.getenv("MCP_FILE_DIRECTORY_PATH");// 这里通过启动时设置的环境变量,如果没有,默认使用getDbPath方法提供的当前工作目录
return StringUtils.isEmpty(path) ? getDbPath() : path;
}
private static String getDbPath() {
return Paths.get(System.getProperty("user.dir")).toString();
}
步骤为先使用transport的ServerParameters类构建好参数并运行npx进程,然后新建McpClient与该服务进行连接,将mcpclient注册为bean交给Spring管理生命周期。
4. 使用
@Bean
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,
List<McpFunctionCallback> functionCallbacks, ConfigurableApplicationContext context) {
return args -> {
var chatClient = chatClientBuilder
.defaultFunctions(functionCallbacks.toArray(new McpFunctionCallback[0]))
.build();
System.out.println("Running predefined questions with AI model responses:\n");
// Question 1
String question1 = "你能解释一下 spring-ai-mcp-overview. txt 文件的内容吗?";
System.out.println("QUESTION: " + question1);
System.out.println("ASSISTANT: " + chatClient.prompt(question1).call().content());
// Question 2
String question2 = "请总结 spring-ai-mcp-overview. txt 文件的内容,并将其存储为 Markdown 格式的新 summary.md?";
System.out.println("\nQUESTION: " + question2);
System.out.println("ASSISTANT: " +
chatClient.prompt(question2).call().content());
context.close();//通过context关闭Springboot应用
};
}
可以发现,注入chatClient后,将提示词给予它,它就会和调用其他function callings一样,调用mcp的function callbacks,并返回操作的结果。
通过以上配置,该chatClient就具备了借助Mcp Client与MCP服务通信的能力。Spring AI Alibaba还提供了一个构建MCP服务访问SQLite的示例,详情请查看官方示例仓库。