历史文章

Spring AI:对接DeepSeek实战
Spring AI:对接官方 DeepSeek-R1 模型 —— 实现推理效果
Spring AI:ChatClient实现对话效果
Spring AI:使用 Advisor 组件 - 打印请求大模型出入参日志
Spring AI:ChatMemory 实现聊天记忆功能
Spring AI:本地安装 Ollama 并运行 Qwen3 模型
Spring AI:提示词工程
Spring AI:提示词工程 - Prompt 角色分类(系统角色与用户角色)
Spring AI:基于 “助手角色” 消息实现聊天记忆功能
Spring AI:结构化输出 - 大模型响应内容
Spring AI:Docker 安装 Cassandra 5.x(限制内存占用)&& CQL
Spring AI:整合 Cassandra - 实现聊天消息持久化
Spring AI:多模态 AI 大模型
Spring AI:文生图:调用通义万相 AI 大模型
Spring AI:文生音频 - cosyvoice-V2
Spring AI:文生视频 - wanx2.1-i2v-plus
Spring AI:上手体验工具调用(Tool Calling)

MCP 介绍

在这里插入图片描述
在上篇文章 中,我们已经了解什么是 Function Call, 并在 Spring AI 项目中实践了一波,让 AI 大模型能够实时获取当前日期,以及天气情况。本小节中,我们再来了解一下更高级的 MCP 功能。

什么是 MCP?

MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 公司于 2024 年提出的开放标准协议,旨在解决大语言模型(LLM)与外部工具和数据源的高效、安全交互问题。它通过标准化接口,让AI模型能像使用 “USB接口” 一样,连接各类外部资源,如数据库、第三方 API、文件系统等等,从而突破静态训练数据的限制,实现动态任务执行。

其优势如下:

  • 生态互操作性 :任何支持 MCP 的大模型,均可接入现有工具生态圈,官方和社区现已提供超 1100 个 MCP 服务,覆盖 GitHub、Slack、AWS 等平台,避免 “重复造轮子”;

  • 动态上下文管理: 支持多轮对话状态保持。例如当用户要求 “分析上周销售数据并对比去年同期” 时,MCP 能自动关联历史查询上下文,无需重复说明时间范围;

  • 企业级安全设计: 通过会话加密和权限分级(如限制人事部门访问其他部门的数据),解决敏感数据暴露的风险;

  • 降低开发成本: 开发者只需开发一次 MCP 服务,即可让所有兼容模型调用, 无需多次开发

应用场景

下面列举一些 MCP 的应用场景:

在这里插入图片描述

MCP 架构

MCP 采用经典的 “客户端-服务端” 架构,如下图所示:

在这里插入图片描述

  • Host 主机:通常为 AI 应用,比如 Cursor,Trae 等代码编辑器或其他应用。主机负责接收用户的问题与指令,再调用 AI 大模型,当大模型觉得需要调用外部工具时,Host 主机会主动调用 MCP 客户端。
  • MCP 客户端:客户端通常内置于主机中,负责与 MCP 服务端建立连接、发送请求和接收请求。我们可以把 MCP 客户端理解为公司 “前台小姐姐”,为外来人员提供服务,有啥事都可以咨询她,由她将任务转交给不同部门去处理。
  • MCP 服务端:MCP 服务器可以看做是一个 “工具箱” 或 “数据源”,供 MCP 客户端来调用,例如访问文件系统、数据库查询、操作浏览器等等。MCP 服务器负责执行具体的操作,如调用工具或访问数据,再将结果返回给 MCP 客户端。

通过上图,Host 主机通过 MCP 客户端,可以分别同多个 MCP 服务端进行通信,每次连接都使用统一的 MCP 协议,由于统一了标准协议,当我们想让 AI 大模型接入一种新的 “工具”,只需再启动一个对应的 MCP 服务器并连接该 “工具” 提供的接口即可,非常方便,主机本身不需要做大的改动。另外,多个 MCP 服务器可以同时运行,当大模型觉得自己无法完成某项任务时,就可以让这些 MCP 服务器来协助。

举个栗子,我们向主机提问 “我的 E:/ 盘下,有哪些文件?”,比如 Cursor 编辑器,整体的处理流程大致如下:

1、我们向 Cursor 提问;
2、Cursor 调用大模型来分析我们的问题,由大模型决定是否需要访问本地文件系统;
3、若需要,主机内置的 MCP 客户端被激活,与本地文件系统的 MCP 服务器建立连接;
4、MCP 客户端向 MCP 服务端发送请求,想要获取 E:/ 盘下的文件列表;
5、本地文件系统 MCP 服务器执行访问操作,获取文件列表,并将结果返回给 MCP 客户端;
6、MCP 客户端再将结果发送给 AI 大模型;
7、AI 大模型再以自然语言的方式,告诉我们最终结果;

和 Fucntion Call 的区别

你可能疑问,MCP 和 Function Call 有啥区别呢?它两属于不同的技术手段,区别大致如下:
在这里插入图片描述

  • 定义上:MCP 是一种标准化协议,为 AI 大模型与外部系统之间的交互,提供了规范化的接口,有点类似于 “USB 接口” ,能够连接不同的外接设备,如键盘、鼠标、音箱等等。它能让不同的系统之间能够高效的数据传输与工具调用;而 Function Call 是大语言模型本身提供的一种能力,通过预定义函数,当用户提问后,AI 大模型理解用户的提示词,并判断是否需要调用这些预定义的函数。
  • 技术实现上:MCP 采用了 “客户端-服务端” 架构,标准化处理 MCP 客户端与 MCP 服务端之间的通信,包括请求、响应等等。此架构能够更好的应用复杂的网络环境,和多元化的场景需求;而 Function Call 实现相对简单,它在大模型运行时环境直接执行,但需要开发者提前将函数定义好,并提交给 AI 大模型。
  • 功能与应用场景:MCP 能够处理复杂、异步的任务,例如,你可以将公司内部的系统,封装成 MCP 服务提供调用;而 Function Call 则更适合处理简单、低延迟的任务,例如获取天气数据、实时翻译等。
  • 整合方式:MCP 服务一般由第三方提供好,我们只需要对接即可,无需额外编写代码;而 Function Call 则需要自己编写预定义函数,并提交给 AI 大模型。

整合 MCP Client: 调用高德地图 MCP 服务

尝试在 Spring AI 项目中整合 MCP Client 客户端,并调用高德地图官方提供的 MCP Server 服务,实现一些小案例 —— 比如让 AI 大模型推荐最近 1000m 内,好评率较高的烧烤店。

MCP.so 介绍

MCP.so(官网:https://mcp.so/zh )是全球领先的MCP(Model Context Protocol,模型上下文协议)服务器资源平台,专注于提供 MCP 服务的导航、托管与调试功能。其核心定位是成为连接 AI 模型与外部工具/数据源的标准化枢纽,推动AI应用开发的效率与可扩展性,目前已收录 1万+ 的 MCP 服务。

在这里插入图片描述
进入 MCP.so 官网后,在 Featrued 精选菜单下,可以找到高德地图官方提供的 MCP Server,它包含的工具包括:

1、生成专属地图:将出行规划导入高德地图,生成专属地图;
2、导航到目的地:根据用户传入经纬度,启动导航;
3、打车:根据用户输入起终经纬度坐标,发起打车请求;
4、地理编码:将详细的结构化地址转换为经纬度坐标;
5、逆地理编码:将一个高德经纬度坐标转换为行政区划地址信息;
6、IP 定位:IP 定位根据用户输入的 IP 地址,定位 IP 的所在位置;
7、天气查询:根据城市名称或者标准adcode查询指定城市的天气;
8、骑行路径规划:用于规划骑行通勤方案,规划时会考虑天桥、单行线、封路等情况。最大支持 500km 的骑行路线规划;
9、周边搜索:根据用户传入关键词以及坐标,搜索出规定半径范围内的 POI 地点;

TIP: 关于高德地图 MCP Server 更多功能,可阅读官方文档:https://lbs.amap.com/api/mcp-server/summary 。

申请 API Key

在使用高德 MCP 服务之前,需要登录到高德开发平台:https://lbs.amap.com/ ,注册一个用户,完成认证后登录到后台:

在这里插入图片描述

如上图所示,操作如下:

①:创建新应用;
②:填写应用名称,如 “小马智能”;
③:选择应用类型,这里选择 “工具”,然后点击新建

在这里插入图片描述
应用新建成功后,操作如下:

①:添加 Key;
②:填写 Key 名称,如 “小马智能”;
③:勾选服务平台,这里选择 “Web服务”;
④:勾选 “阅读并同意协议” 后,点击提交;
⑤:复制 Key 值,等会需要用到;

添加依赖

接着,编辑 pom.xml 文件,添加 MCP Client 客户端依赖:

<!-- MCP Client -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>

添加配置

在 MCP.so 网站中,点击进入高德地图 MCP 服务的详情页中,如下图所示, 复制右边的配置:

在这里插入图片描述
在 /resources 目录下,新建一个 mcp-servers-config.json 配置文件,文件名可以随意命名:

将刚刚复制的配置项添加进去。因为咱们是 Windows 系统,无法直接使用 npx 命令,所以配置项需要稍作修改,如下:

{
  "mcpServers": {
    "amap-maps": {
      "command": "cmd",
      "args": [
        "/c",
        "npx",
        "-y",
        "@amap/amap-maps-mcp-server"
      ],
      "env": {
        "AMAP_MAPS_API_KEY": "填写你申请的高德地图 API Key"
      }
    }
  }
}

解释一下:

  • 根对象 mcpServers: 定义一组 MCP 服务器配置;
  • 服务标识 amap-maps: 服务名称,表示这是针对 高德地图(AMap) 的配置。
      • command: 指定要运行的基本命令。这里使用的是 cmd(Windows 命令提示符)。
      • args: 是一个数组,包含传递给命令的参数。在这个例子中:
          • /c 表示执行后面的命令然后终止。
          • npx 是 Node.js 的一个工具,用于执行 npm 包中的命令。注意,需要确保你的电脑已安装好 Node.js。
          • -y 是 npx 的一个选项,表示如果遇到提示(比如是否安装包)都自动回答 yes。
          • @amap/amap-maps-mcp-server是要通过 npx 运行的包,即高德地图的 MCP 服务包。
  • env: 是一个环境变量对象,用于设置运行时的环境变量。
      • AMAP_MAPS_API_KEY: 需要填写用户申请的高德地图API Key。

然后,编辑 application.yml 配置文件,添加配置项如下:

spring:
  // 省略...
  ai:
    // 省略...
    mcp:
      client:
        stdio:
          servers-configuration: classpath:/mcp-servers-config.json # 指定 MCP 服务的配置文件路径
        toolcallback:
          enabled: true # 开启 MCP 客户端的工具回调(Tool Callback)功能

配置 ChatClient

编辑 ChatClientConfig 配置类,将 MCP 工具配置上

@Configuration
public class ChatClientConfig {

    @Resource
    private ChatMemory chatMemory;

    /**
     * 初始化 ChatClient 客户端
     * @param chatModel
     * @return
     */
    @Bean
    public ChatClient chatClient(DeepSeekChatModel chatModel, ToolCallbackProvider tools) {
        return ChatClient.builder(chatModel)
                .defaultToolCallbacks(tools) // MCP
//                .defaultSystem("请你扮演一个智能客服")
                .defaultAdvisors(new SimpleLoggerAdvisor(), // 添加 Spring AI 内置的日志记录功能
//                                 new MyLoggerAdvisor(), // 添加自定义的日志打印 Advisor
                                MessageChatMemoryAdvisor.builder(chatMemory).build()
                        )
                .build();
    }
}
	

新增 Controller 控制器

然后,为了方便等会测试,我们在 /controller 包下,新建一个 McpChatClientController 控制器,声明接口 /mcp/ai/generateStream , 代码如下:

@RestController
@RequestMapping("/mcp/ai")
public class McpChatClientController {

    @Resource
    private ChatClient chatClient;

    /**
     * 流式对话
     * @param message
     * @return
     */
    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<AIResponse> generateStream(@RequestParam(value = "message") String message,
                                           @RequestParam(value = "chatId") String chatId) {

        // 流式输出
        return chatClient.prompt()
                .user(message) // 提示词
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
                .stream()
                .chatResponse()
                .mapNotNull(chatResponse -> {
                        Generation generation = chatResponse.getResult();
                        String text = generation.getOutput().getText();
                        return AIResponse.builder().v(text).build();
                });

    }

}

测试

重启后端项目,观察控制台日志:

在这里插入图片描述
若包含提示信息 Amap Maps MCP Server running on stdio, 则表示 MCP 服务对接成功了。

我们可以测试下如下场景:

xxxxx 这个 IP 的具体位置在哪里
深圳今天的天气怎么样
我的坐标是东经xxx,北纬xxxx,附近 1000m 有什么好评率较高的烧烤店,推荐一下。需要附带上门店的图片,以 markdown 图片格式展示出来
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐