news 2025/12/27 9:34:19

Spring AI 当中对应 MCP 的操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring AI 当中对应 MCP 的操作

或者在企业级中, 有多个智能应用,想将通用的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>

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/17 22:49:34

有了开源的 MySQL,为什么还要选择 PostgreSQL?

近年来&#xff0c;随着信创推进与数据库自主可控需求提升&#xff0c;PostgreSQL 凭借其开源、稳定、功能强大的特性&#xff0c;已成为国产数据库创新的首选技术底座。国内多家头部科技企业纷纷基于 PostgreSQL 深度定制&#xff0c;打造出满足自身业务需求的分布式、云原生或…

作者头像 李华
网站建设 2025/12/17 22:45:43

端到端自动驾驶仿真新范式:aiSim如何解决智驾测试的“灾难性挑战“

1 引言&#xff1a;从模块化到端到端的智驾革命随着智能驾驶技术快速发展&#xff0c;端到端解决方案正成为行业新趋势。与传统规则驱动的模块化方案相比&#xff0c;学习驱动的端到端方案具备更强的泛化能力、全面优化优势和持续学习能力。然而&#xff0c;这种变革对仿真测试…

作者头像 李华
网站建设 2025/12/17 22:45:26

【优化】避免繁琐设置字符编码,简单C/C++中文处理方法

字符串字面量在C/C中的中文处理 一、字符串字面量的本质 在C/C中&#xff0c;字符串字面量是存储在静态内存区域的字符数组。其基本形式为&#xff1a; const char* str "中文字符";但直接使用窄字符&#xff08;char&#xff09;处理中文时&#xff0c;常因编码问题…

作者头像 李华
网站建设 2025/12/17 22:45:26

牛客周赛 Round 111

设一个数组 &#xfffd; { 2 , 3 , 4 , 3 , 5 , 1 } b{2,3,4,3,5,1}&#xff0c;则 &#xfffd; ( &#xfffd; ) 2 3 4 5 14 L(b)234514&#xff0c; &#xfffd; ( &#xfffd; ) 1 5 6 R(b)156。 小芳希望小红构造一个长为 &#xfffd; …

作者头像 李华
网站建设 2025/12/17 22:44:00

定性与定量考核的结合

在现代企业管理中&#xff0c;如何科学、公正地评估员工绩效&#xff0c;始终是一个核心议题。要实现全面而准确的评估&#xff0c;关键在于将定量考核的客观性与定性考核的深刻性有效结合。 单纯的定量考核&#xff08;“计件”&#xff09;提供了“做什么”的客观数据&#x…

作者头像 李华
网站建设 2025/12/23 18:42:28

如何衡量团队产出效率

在现代组织中&#xff0c;团队的产出效率直接决定企业的竞争力与执行力。**要科学衡量团队产出效率&#xff0c;核心在于建立多维度的指标体系&#xff0c;将成果、过程与协作因素综合评估&#xff0c;以实现对绩效的量化与优化。**单纯用“工作量”或“加班时间”衡量团队贡献…

作者头像 李华