或者在企业级中, 有多个智能应用,想将通用的tools公共化
怎么办?
可以把tools单独抽取出来, 由应用程序读取外部的tools。 那关键是怎么读呢? 怎么解析呢? 如果每个提供商各用一种规则你能想象有多麻烦! 所以MCP就诞生了, 他指定了标准规则, 以jsonrpc2.0的方式进行通讯。
那问题又来了, 以什么方式通讯呢? http? rpc? stdio? mcp提供了sse和stdio这2种方式。
使用
Streamable http目前springai1.0版本不支持(因为Streamable http 是 spring ai 1.0 之后说明的) 我们先掌握SSE和STDIO
分别说下STDIO和SSE的方式:
STDIO更适合客户端桌面应用和辅助工具
SSE更适合web应用 、业务有关的公共tools
MCP STDIO 输出配置实操
MCP Server
现成共用MCP Server
现在有很多MCP 服务 给大家提供一个网站:MCP Server(MCP 服务器)
那MCP有了, 怎么调用呢? 这里介绍2种使用方式:
MCP Client
通过工具
CherryStudio、Cursor 、Claude Desktop、Cline 等等很多, 这里不一一演示, 不会的话自己找个文章, 工具使用都很简单!
以Cline为例: 他是Vscode的插件
安装VSCode
安装插件:
配置cline的模型:
配置cline的mcpserver
{
"mcpServers": {
"baidu-map": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@baidumap/mcp-server-baidu-map"
],
"env": {
"BAIDU_MAP_API_KEY": "LEyBQxG9UzR9C1GZ6zDHsFDVKvBem2do"
}
},
"filesystem": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/tuling/Desktop"
]
},
"mcp-server-weather": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=",
"-jar",
"D:\\ideaworkspace\\git_pull\\tuling-flight-booking_all\\mcp-stdio-server\\target\\mcp-stdio-server-xs-1.0.jar"
]
}
}
}
开启cline权限
6.测试:
通过 Spring AI 接入 第三方的 MCP Server
依赖
<!--既支持sse\也支持Stdio-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>
2 配置
spring:
ai:
mcp:
client:
# 连接超时时间设置
request-timeout: 60000
stdio: # 设置 sse 输出方式
# 配置Mcp 方式2: 将 mcp的配置 单独放在一个 Json 文件当中读取,推荐,利用维护
# classpath 是指:项目resources
servers-configuration: classpath:/mcp-servers-config.json
# 配置MCP 方式2: 直接将 mcp 配置全局配置文件中(mcp 配置太多不利于维护)
# connections:
# server1:
# command: /path/to/server
# args:
# - --port=8080
# - --mode=production
# env:
# API_KEY: your-api-key
# DEBUG: "true"
mcp-servers-config.json:
获取Baidu地图key: 控制台 | 百度地图开放平台
{
"mcpServers": {
"baidu-map": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@baidumap/mcp-server-baidu-map"
],
"env": {
"BAIDU_MAP_API_KEY": "xxxx"
}
},
"filesystem": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/tuling/Desktop"
]
},
"mcp-server-weather": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=",
"-jar",
"D:\\xxx\\target\\mcp-stdio-server-xs-1.0.jar"
]
}
}
}
{
"mcpServers": {
// 外部第三方的
"baidu-map": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@baidumap/mcp-server-baidu-map"
],
"env": {
"BAIDU_MAP_API_KEY": "xxxx"
}
},
// 外部第三方的
"filesystem": {
"command": "cmd", // 指明使用 cmd 命令执行
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/tuling/Desktop"
]
},
// 自定义的 mcp 服务
"mcp-server-weather": { // 对应的项目名 application的 name
"command": "java", // 指明通过 java 命令执行,java 解析可以直接识别到
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=", // 清空控制台,不然会输入很多信息
"-jar", // -jar 启动 Spring Boot
"D:\\xxx\\target\\mcp-stdio-server-xs-1.0.jar" // 自定义的mcp服务的jar路径
]
}
}
}
绑定到Chatclient
/**
* @description: 智能航空助手:
*/
@RestController
@CrossOrigin
public class OpenAiController {
private final ChatClient chatClient;
public OpenAiController(
DashScopeChatModel dashScopeChatModel,
// 配置引入 外部 mcp tools
ToolCallbackProvider mcpTools) {
this.chatClient =ChatClient.builder(dashScopeChatModel)
.defaultToolCallbacks(mcpTools) // 将外部的 mcop tools 对大模型进行绑定,这里是构造器的绑定,不是单个对话的绑定
.build();
}
@CrossOrigin
@GetMapping(value = "/ai/generateStreamAsString", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> generateStreamAsString(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
Flux<String> content = chatClient.prompt()
.user(message)
.stream()
.content();
return content;
}
# 调试日志
logging:
level:
io:
modelcontextprotocol:
client: DEBUG
spec: DEBUG
使用 Spring AI 接入 自定义MCP Server
创建一个spring ai项目
依赖
<!--mcp-server -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<!--spring ai 包管理依赖 -->
<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>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
添加工具
@Service
public class UserToolService {
Map<String,Double> userScore = Map.of(
"xushu",99.0,
"zhangsan",2.0,
"lisi",3.0);
@Tool(description = "获取用户分数")
public String getScore(String username) { // 也可以添加上 @ToolParam(description=“” )告诉大模型这个参数的描述是做什么的
if(userScore.containsKey(userName)){
return userScore.get(userName).toString();
}
return "未检索到当前用户"+userName;
}
}
暴露工具
@Bean // 将我们编写的 tools 对外的UserToolService 绑定上去
public ToolCallbackProvider weatherTools(UserToolService userToolService) {
return MethodToolCallbackProvider.builder().toolObjects(userToolService).build();
}
配置
spring:
main:
banner-mode: off
ai:
mcp:
server:
name: my-weather-server
version: 0.0.1
# 注意:您必须禁用横幅和控制台日志记录,以允许 STDIO 传输!!工作 banner-mode: off
打包 mvn package
此时target/生成了jar则成功!
在我们需要的用到我们自定义的 mcp 的项目当中,加上我们自行定义的 MCP 服务。如下,我们是将其统一放到了一个配置的 json 文件当中。去了
{
"mcpServers": {
// 外部第三方的
"baidu-map": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@baidumap/mcp-server-baidu-map"
],
"env": {
"BAIDU_MAP_API_KEY": "xxxx"
}
},
// 外部第三方的
"filesystem": {
"command": "cmd", // 指明使用 cmd 命令执行
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/tuling/Desktop"
]
},
// 自定义的 mcp 服务
"mcp-server-weather": { // 对应的项目名 application的 name
"command": "java", // 指明通过 java 命令执行,java 解析可以直接识别到
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=", // 清空控制台,不然会输入很多信息
"-jar", // -jar 启动 Spring Boot
"D:\\xxx\\target\\mcp-stdio-server-xs-1.0.jar" // 自定义的mcp服务的jar路径
]
}
}
}
MCP SSE 输出配置实操(推荐 Web)
MCP Server
这种方式需要将部署为Web服务
依赖
<!--mcp服务器核心依赖— 响应式-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
<!-- 这个 SSE 是需要 Web 的 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
定义外部工具
@Service
public class UserToolService {
Map<String,Double> userScore = Map.of(
"xushu",99.0,
"zhangsan",2.0,
"lisi",3.0);
@Tool(description = "获取用户分数")
public String getScore(String username) {
if(userScore.containsKey(username)){
return userScore.get(username).toString();
}
return "未检索到当前用户";
}
}
暴露工具
@Bean
public ToolCallbackProvider weatherToolCallbackProvider(WeatherService weatherService,
UserToolService userToolService) {
return MethodToolCallbackProvider.builder().toolObjects(userToolService).build();
}
配置(需要用 web 启动)
server:
port: 8088
MCP Client
将上面 通过 SSE 方式创建的自定义 MCP Server 配置进来
添加依赖
<!--既支持sse\也支持Stdio-->
<dependency>
<groupId>org.springframework.ai</groupId>