前言
在了解**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的大体工作逻辑如下图:
一些说明
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架构的图片:
一些说明
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,启动服务
测试
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,启动服务
结果
Langflow
Langflow需要配置MCP sse的Tool组件,如图:
Dify
Dify需要安装MCP sse的Tool,且要求版本在1.0.0+以上。如图
总结
0,MCP源于function calling。
1,MCP是给function calling提供的一种标准化和规划化的协议。统一协议,统一标准。大模型的实际触发还是走的function calling。
2,MCP需要注意三个元语:**Tool(工具),Resource(资源),Prompt(提示模板)**。
3,MCP社区开发了大量统一的MCP Server,不过MCP概念尚未普及,主流的开放平台还未兼容MCP协议,需要自己包装和开发。