searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Spring AI MCP技术试用

2025-03-24 02:11:27
2
0

前言

在了解**Model Context Protocol(MCP)**前,首先需要先了解function calling,一般也理解为Tool Use。

为什么会有function calling?

大模型有几个问题:

1)没有最新的信息,因为训练的数据是某个时间点之前的,属于历史数据。

2)没有真正的逻辑能力,因为大模型返回的结果是基于训练数据的统计规律和概率匹配,而非严格的逻辑推理或形式化证明,即使加上了Jason Wei大佬提出的 ​链式思维(Chain of Thought,CoT​) 将大问题拆成小问题,以一定的逻辑顺序解决问题,但实质还是数据驱动的模式匹配,而非真正的认知推理。对于复杂的数学逻辑问题还是较为吃力。

3)大模型没与真实世界沟通的桥梁,就像人脑没有双手只能思考不能办事。

基于上述的一些问题,业内提出了Function Calling的概念,缓解了上述的问题,比如通过Function Calling访问最新的数据和私有的数据,为解决复杂的数据逻辑计算,可以通过tools use去调用专业的数学库,因为打通了和现实世界沟通的桥梁,大模型能做很多实际的现实工作。Function Calling的大体工作逻辑如下图:
企业微信截图_17425640135364.png

一些说明

1,首先会开发好一个外部可调用的API function,这个服务可以是做Math复杂数据计算的工具,或是具体的业务操作,或是外部的最新数据源访问等等能力。

2,这个function会定义为一个Tool,然后会有Prompt提示词一起注册到大模型中,让模型明白这个Tool是干啥的。

3,用户发起调用后,大模型按用户的要求选择function,并按情况填充function的参数请求API返回结果。

4,在大模型获得function返回的结果后,按提示词渲染和组装结果返回给用户。

这里会有一个问题,那就是不同的功能,不同的场景需要按情况开发不同的function,每个开发者或组织都会有自己的function,不一样的规划不一样的格式。因此,MCP的主要目的就是这个,统一协议,统一标准。 官方文档说明如下:

Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories,
MCP provides a standardized way to connect AI models to different data sources and tools.

关键字: like a USB-C (不能每个手机厂商都自己的接口吧~), standardized(标准化的;规范化的) 。简言之,MCP是给function calling提供的一种标准化和规划化的协议。

MCP技术是什么

上文已经说的很清楚了,MCP是给function call提供的一种标准化和规划化的协议。下面是官方MCP架构的图片:
企业微信截图_17425642514428.png

一些说明

1,不需要理解太复杂,主要注意三个元语:Tool(工具),Resource(资源),Prompt(提示模板)。

Tool(工具):允许服务器公开可执行的函数,这些函数可由客户端调用并由 LLM 使用来执行操作。使服务器能够向客户端暴露可执行的功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。

Resource(资源):服务器提供给客户端的任何类型的只读数据。包括不限于:文件内容、数据库记录、图片、日志等等。

Prompt(提示模板):这个才开始有点难理解,其实就是动态提示词,可以通过外部给AI模型沟通的“导航仪”,告诉模型“做什么”,明确“如何做”,确保输出更精准。

2,​理解了MCP之前的RAG(Retrieval-Augmented Generation检索增强生成)技术,Tool Use等需要和大模型交互的功能均统一可以使用MCP对接,而不需要单独的能力​。

3,上图的有些术语,MCP 客户端(MCP Clients),MCP 服务器(MCP Servers),本地资源(Local Resources),远程资源(Remote Resources)。

MCP 客户端(MCP Clients):发起请求的AI应用程序,比如聊天机器人,Agent。

MCP 服务器(MCP Servers):为 MCP客户端提供Tools,Resource和Prompt的服务。

本地资源(Local Resources):可供 MCP 服务器安全访问的资源,如文件,数据库。

远程资源(Remote Resources):MCP 服务器可以连接到的远程资源,如通过API提供的数据,比如天气,股票,新闻热点。

Demo实现

官方文档提供了Python ,Typescript,Java,kotlin这4中语音的SDK。这里使用大家比较熟悉的Java Spring AI MCP简单试用下Tools能力。

代码

详细例子可以查看SpringAI MCP 官方文档 。首先要求JDK版本至少为17。

# 1,maven依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-bom</artifactId>
    <version>${spring-ai.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
 
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
</dependency>
 
# 2,初始化
@SpringBootApplication
public class McpserverApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(McpserverApplication.class, args);
    }
 
    @Bean
    public ToolCallbackProvider wechatTools(WeChatService weChatService,EmailService emailService) {
        return MethodToolCallbackProvider.builder().toolObjects(weChatService,emailService).build();
    }
 
    public record TextInput(String input) {
    }
 
    @Bean
    public ToolCallback toUpperCase() {
        return FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase())
                .inputType(TextInput.class)
                .description("Put the text to upper case")
                .build();
    }
}
 
# 3,开发Tools
 
//--邮件Tool
@Service
public class EmailService {
 
    @Resource
    private EmailConfig emailConfig;
 
    @Tool(description = "使用邮件工具给target发送邮件")
    public String postEmailMsg(@ToolParam(description = "target目标邮箱") String target,
                               @ToolParam(description = "发送内容") String content) {
        List<String> to = new ArrayList<>();
        to.add(target);
        String subject = "AI MCP邮箱测试";
        boolean flag = EmailUtils.send(emailConfig, to, subject, content,
                emailConfig.getContentType(), null);
        System.out.println("邮箱发送结果flag=" + flag + "\n,target=" + target + "\n,content=" + content);
        return "send email result:" + flag;
    }
}
 
//--企微机器人Tool
@Service
public class WeChatService {
 
    @Value("${wechat.reboot.url}")
    private String wechatRebootUrl;
 
    @Tool(description = "给微信群推送内容为content的消息")
    public String postWeChatMsg(@ToolParam String content) {
 
        RestClient restClient = RestClient.create();
 
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("msgtype", "text");
 
        Map<String, Object> contentBody = new HashMap<>();
        contentBody.put("content", content);
        requestBody.put("text", contentBody);
 
        // 发送 POST 请求
        var responseTmp = restClient.post()
                .uri(wechatRebootUrl)
                .header(Headers.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .body(requestBody).retrieve();
 
        System.out.println("wechat发送结果" + responseTmp.toString());
        return responseTmp.toString();
    }
}
 
 
# 4,配置文件
server.port=8113
 
# Server identification
spring.ai.mcp.server.name=aiagent-demo-server
spring.ai.mcp.server.version=0.0.1
 
# Server type (SYNC/ASYNC)
spring.ai.mcp.server.type=SYNC
 
# mcp有两种通讯方式stdio(内部进程通讯)和Server-Sent Events (SSE 服务器发送事件),
spring.ai.mcp.server.stdio=false
spring.ai.mcp.server.sse-message-endpoint=/mcp/message
spring.ai.mcp.server.enabled=true
 
# Change notifications
spring.ai.mcp.server.resource-change-notification=true
spring.ai.mcp.server.tool-change-notification=true
spring.ai.mcp.server.prompt-change-notification=true
 
# Logging (required for STDIO transport)
spring.main.banner-mode=off
logging.file.name=../logs/server.log
 
# 5,启动服务

企业微信截图_17425643895271.png

测试

client调用

客户端调用代码同样使用SpringAI,较为简单,具体参考官方文档例子。

# 1,maven依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
 
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
 
# 2,初始化
@SpringBootApplication
public class McpclientApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(McpclientApplication.class, args);
    }
 
    @Value("${ai.user.input}")
    private String userInput;
 
    @Bean
    public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools,
                                                 ConfigurableApplicationContext context) {
        return args -> {
            var chatClient = chatClientBuilder
                    .defaultTools(tools)
                    .build();
            System.out.println("\n>>> QUESTION: " + userInput);
            System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
            context.close();
        };
    }
}
 
# 3,配置文件
server.port=8114
 
spring.main.web-application-type=none
 
spring.ai.ollama.base-url=${ollama服务的IP}:11434
spring.ai.ollama.chat.options.model=qwen2.5:14b
spring.ai.ollama.chat.options.temperature=0.7
 
spring.ai.mcp.client.sse.connections.server1.url=${mcp server的IP}:8113
 
ai.user.input=简单说明下RAG结束并发送到邮箱xxx@chinatelecom.cn
 
# 4,启动服务

结果
企业微信截图_17425644798304.png

企业微信截图_17425644977765.png

Langflow

Langflow需要配置MCP sse的Tool组件,如图:
企业微信截图_17425645174792.png

企业微信截图_17425645318907.png

企业微信截图_17425645445854.png

Dify

Dify需要安装MCP sse的Tool,且要求版本在1.0.0+以上。如图
企业微信截图_1742564563581.png

企业微信截图_17425645848525.png

总结

0,MCP源于function calling。

1,​MCP是给function calling提供的一种标准化和规划化的协议。统一协议,统一标准。大模型的实际触发还是走的function calling​。

2,MCP需要注意三个元语:​**Tool(工具),Resource(资源),Prompt(提示模板)**​。

3,MCP社区开发了大量统一的MCP Server,不过MCP概念尚未普及,主流的开放平台还未兼容MCP协议,需要自己包装和开发。

0条评论
0 / 1000
wanghg11
16文章数
2粉丝数
wanghg11
16 文章 | 2 粉丝
原创

Spring AI MCP技术试用

2025-03-24 02:11:27
2
0

前言

在了解**Model Context Protocol(MCP)**前,首先需要先了解function calling,一般也理解为Tool Use。

为什么会有function calling?

大模型有几个问题:

1)没有最新的信息,因为训练的数据是某个时间点之前的,属于历史数据。

2)没有真正的逻辑能力,因为大模型返回的结果是基于训练数据的统计规律和概率匹配,而非严格的逻辑推理或形式化证明,即使加上了Jason Wei大佬提出的 ​链式思维(Chain of Thought,CoT​) 将大问题拆成小问题,以一定的逻辑顺序解决问题,但实质还是数据驱动的模式匹配,而非真正的认知推理。对于复杂的数学逻辑问题还是较为吃力。

3)大模型没与真实世界沟通的桥梁,就像人脑没有双手只能思考不能办事。

基于上述的一些问题,业内提出了Function Calling的概念,缓解了上述的问题,比如通过Function Calling访问最新的数据和私有的数据,为解决复杂的数据逻辑计算,可以通过tools use去调用专业的数学库,因为打通了和现实世界沟通的桥梁,大模型能做很多实际的现实工作。Function Calling的大体工作逻辑如下图:
企业微信截图_17425640135364.png

一些说明

1,首先会开发好一个外部可调用的API function,这个服务可以是做Math复杂数据计算的工具,或是具体的业务操作,或是外部的最新数据源访问等等能力。

2,这个function会定义为一个Tool,然后会有Prompt提示词一起注册到大模型中,让模型明白这个Tool是干啥的。

3,用户发起调用后,大模型按用户的要求选择function,并按情况填充function的参数请求API返回结果。

4,在大模型获得function返回的结果后,按提示词渲染和组装结果返回给用户。

这里会有一个问题,那就是不同的功能,不同的场景需要按情况开发不同的function,每个开发者或组织都会有自己的function,不一样的规划不一样的格式。因此,MCP的主要目的就是这个,统一协议,统一标准。 官方文档说明如下:

Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories,
MCP provides a standardized way to connect AI models to different data sources and tools.

关键字: like a USB-C (不能每个手机厂商都自己的接口吧~), standardized(标准化的;规范化的) 。简言之,MCP是给function calling提供的一种标准化和规划化的协议。

MCP技术是什么

上文已经说的很清楚了,MCP是给function call提供的一种标准化和规划化的协议。下面是官方MCP架构的图片:
企业微信截图_17425642514428.png

一些说明

1,不需要理解太复杂,主要注意三个元语:Tool(工具),Resource(资源),Prompt(提示模板)。

Tool(工具):允许服务器公开可执行的函数,这些函数可由客户端调用并由 LLM 使用来执行操作。使服务器能够向客户端暴露可执行的功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。

Resource(资源):服务器提供给客户端的任何类型的只读数据。包括不限于:文件内容、数据库记录、图片、日志等等。

Prompt(提示模板):这个才开始有点难理解,其实就是动态提示词,可以通过外部给AI模型沟通的“导航仪”,告诉模型“做什么”,明确“如何做”,确保输出更精准。

2,​理解了MCP之前的RAG(Retrieval-Augmented Generation检索增强生成)技术,Tool Use等需要和大模型交互的功能均统一可以使用MCP对接,而不需要单独的能力​。

3,上图的有些术语,MCP 客户端(MCP Clients),MCP 服务器(MCP Servers),本地资源(Local Resources),远程资源(Remote Resources)。

MCP 客户端(MCP Clients):发起请求的AI应用程序,比如聊天机器人,Agent。

MCP 服务器(MCP Servers):为 MCP客户端提供Tools,Resource和Prompt的服务。

本地资源(Local Resources):可供 MCP 服务器安全访问的资源,如文件,数据库。

远程资源(Remote Resources):MCP 服务器可以连接到的远程资源,如通过API提供的数据,比如天气,股票,新闻热点。

Demo实现

官方文档提供了Python ,Typescript,Java,kotlin这4中语音的SDK。这里使用大家比较熟悉的Java Spring AI MCP简单试用下Tools能力。

代码

详细例子可以查看SpringAI MCP 官方文档 。首先要求JDK版本至少为17。

# 1,maven依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-bom</artifactId>
    <version>${spring-ai.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
 
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
</dependency>
 
# 2,初始化
@SpringBootApplication
public class McpserverApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(McpserverApplication.class, args);
    }
 
    @Bean
    public ToolCallbackProvider wechatTools(WeChatService weChatService,EmailService emailService) {
        return MethodToolCallbackProvider.builder().toolObjects(weChatService,emailService).build();
    }
 
    public record TextInput(String input) {
    }
 
    @Bean
    public ToolCallback toUpperCase() {
        return FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase())
                .inputType(TextInput.class)
                .description("Put the text to upper case")
                .build();
    }
}
 
# 3,开发Tools
 
//--邮件Tool
@Service
public class EmailService {
 
    @Resource
    private EmailConfig emailConfig;
 
    @Tool(description = "使用邮件工具给target发送邮件")
    public String postEmailMsg(@ToolParam(description = "target目标邮箱") String target,
                               @ToolParam(description = "发送内容") String content) {
        List<String> to = new ArrayList<>();
        to.add(target);
        String subject = "AI MCP邮箱测试";
        boolean flag = EmailUtils.send(emailConfig, to, subject, content,
                emailConfig.getContentType(), null);
        System.out.println("邮箱发送结果flag=" + flag + "\n,target=" + target + "\n,content=" + content);
        return "send email result:" + flag;
    }
}
 
//--企微机器人Tool
@Service
public class WeChatService {
 
    @Value("${wechat.reboot.url}")
    private String wechatRebootUrl;
 
    @Tool(description = "给微信群推送内容为content的消息")
    public String postWeChatMsg(@ToolParam String content) {
 
        RestClient restClient = RestClient.create();
 
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("msgtype", "text");
 
        Map<String, Object> contentBody = new HashMap<>();
        contentBody.put("content", content);
        requestBody.put("text", contentBody);
 
        // 发送 POST 请求
        var responseTmp = restClient.post()
                .uri(wechatRebootUrl)
                .header(Headers.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .body(requestBody).retrieve();
 
        System.out.println("wechat发送结果" + responseTmp.toString());
        return responseTmp.toString();
    }
}
 
 
# 4,配置文件
server.port=8113
 
# Server identification
spring.ai.mcp.server.name=aiagent-demo-server
spring.ai.mcp.server.version=0.0.1
 
# Server type (SYNC/ASYNC)
spring.ai.mcp.server.type=SYNC
 
# mcp有两种通讯方式stdio(内部进程通讯)和Server-Sent Events (SSE 服务器发送事件),
spring.ai.mcp.server.stdio=false
spring.ai.mcp.server.sse-message-endpoint=/mcp/message
spring.ai.mcp.server.enabled=true
 
# Change notifications
spring.ai.mcp.server.resource-change-notification=true
spring.ai.mcp.server.tool-change-notification=true
spring.ai.mcp.server.prompt-change-notification=true
 
# Logging (required for STDIO transport)
spring.main.banner-mode=off
logging.file.name=../logs/server.log
 
# 5,启动服务

企业微信截图_17425643895271.png

测试

client调用

客户端调用代码同样使用SpringAI,较为简单,具体参考官方文档例子。

# 1,maven依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
 
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
 
# 2,初始化
@SpringBootApplication
public class McpclientApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(McpclientApplication.class, args);
    }
 
    @Value("${ai.user.input}")
    private String userInput;
 
    @Bean
    public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools,
                                                 ConfigurableApplicationContext context) {
        return args -> {
            var chatClient = chatClientBuilder
                    .defaultTools(tools)
                    .build();
            System.out.println("\n>>> QUESTION: " + userInput);
            System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
            context.close();
        };
    }
}
 
# 3,配置文件
server.port=8114
 
spring.main.web-application-type=none
 
spring.ai.ollama.base-url=${ollama服务的IP}:11434
spring.ai.ollama.chat.options.model=qwen2.5:14b
spring.ai.ollama.chat.options.temperature=0.7
 
spring.ai.mcp.client.sse.connections.server1.url=${mcp server的IP}:8113
 
ai.user.input=简单说明下RAG结束并发送到邮箱xxx@chinatelecom.cn
 
# 4,启动服务

结果
企业微信截图_17425644798304.png

企业微信截图_17425644977765.png

Langflow

Langflow需要配置MCP sse的Tool组件,如图:
企业微信截图_17425645174792.png

企业微信截图_17425645318907.png

企业微信截图_17425645445854.png

Dify

Dify需要安装MCP sse的Tool,且要求版本在1.0.0+以上。如图
企业微信截图_1742564563581.png

企业微信截图_17425645848525.png

总结

0,MCP源于function calling。

1,​MCP是给function calling提供的一种标准化和规划化的协议。统一协议,统一标准。大模型的实际触发还是走的function calling​。

2,MCP需要注意三个元语:​**Tool(工具),Resource(资源),Prompt(提示模板)**​。

3,MCP社区开发了大量统一的MCP Server,不过MCP概念尚未普及,主流的开放平台还未兼容MCP协议,需要自己包装和开发。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0