Spring AI MCP 实战:打通 AI 与外部服务的边界

2026-05-29· AI 应用开发· 0 次阅读· 阅读约 32 分钟

我们之前通过工具调用给 AI 应用加了不少能力,但每次加新功能都要写一堆代码。有没有更简单的方式?能不能像插 USB 一样,需要什么能力直接插上就能用?

MCP 就是来做这件事的。

本文先讲 MCP 的核心概念和原理,然后介绍三种使用方式,最后基于 Spring AI 框架实战开发 MCP 客户端和服务端,帮你掌握 MCP 的架构原理和最佳实践。

友情提示:由于 AI 技术更新速度很快,教程的部分细节可能会失效,请大家重点学习思路和方法,不要因为实操和教程不一致就过于担心,要学会自己阅读官方文档并查阅资料,多锻炼自己解决问题的能力。

一、需求分析

目前我们的咖啡店智能客服已经具备知识问答和工具调用能力。现在再加一个实用功能:当用户问“你们离我有多远”时,客服能根据用户的位置,计算出距离并推荐最近的门店。

怎么实现?

按照之前学习的知识,大概有三种思路:

  • 依赖大模型自身能力:大模型可以理解“距离”这个概念,但它不知道用户在哪,也不知道门店的具体位置。
  • 利用 RAG 知识库:把门店地址录入知识库,AI 可以查,但无法计算实时距离,也不知道用户当前位置。
  • 利用工具调用:开发一个根据用户位置查询附近门店并计算距离的工具,调用高德地图 API 获取真实数据。准确度高,但每次都要写工具。

第三种方案效果最好。但既然要调用第三方 API,为什么不能直接接入现成的服务?

这就是 MCP 要解决的问题——让地图服务直接提供给 AI 调用,咖啡店客服只需要接入,不用自己开发位置查询工具。

二、MCP 必知必会

2.1 什么是 MCP?

MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 在 2024 年 11 月提出的一种开放标准。它的核心目标是增强 AI 与外部系统的互操作能力,为 AI 模型连接外部数据源和工具提供标准化的方式

你可以把 MCP 想象成 AI 应用的 USB 接口。就像 USB 为设备连接外设提供了统一的插拔标准,MCP 为 AI 模型连接不同的数据源和工具提供了标准化的方法。如今 MCP 的市场影响力还在持续扩大,到 2026 年 3 月,其 SDK 月下载量已突破 9700 万次,主流 AI 提供商几乎都给予了正式支持。

MCP 主要解决三个问题:

  • 增强 AI 能力:AI 应用可以轻松接入别人提供的服务,实现网页搜索、数据库查询、第三方 API 调用等功能。
  • 统一标准:MCP 本身不提供服务,只是定义了一套规范。服务提供者和使用者都去遵守同一套标准,大幅降低开发者的理解和接入成本。
  • 打造服务生态:如果大家都把自己的能力做成标准化的 MCP 服务对外开放,就等于构建了一个服务市场,开发者可以按需选用,不用重复开发。目前已有超过 18000 个 MCP 服务可供使用。

标准可以造就生态。其实这并不新鲜了,前端同学可以想想NPN包,后端同学可以想想Maven仓库还有Docker镜像源,不懂编程的同学想想手机应用市场,应该就能理解了。

目前已经有不少 MCP 服务市场,开发者可以在这些平台上找到各种现成的 MCP 服务:

目前超过 18000 个 MCP 服务已经发布,覆盖了搜索、数据库、浏览器自动化、图片生成、地图等多个领域。其中绝大多数 MCP 服务市场主要提供本地下载 MCP 服务端代码并运行的方式,毕竟部署 MCP 服务也是需要成本的。

开源社区MCP市场:MCP.so

2.2 MCP 架构

MCP 采用经典的客户端-服务器架构,主要包含三个核心角色:

  • Host(主机) :希望访问 MCP 服务的程序,比如 Claude Desktop、IDE、AI 工具,或者部署在服务器上的你自己的项目。MCP Client 内嵌在 Host 中,负责与 Server 建立通信。
  • Client(客户端) :内嵌在主机中,负责和服务端建立连接并发送请求。它能自动匹配服务器的协议版本、确认可用功能、管理通信状态,还能发现和使用服务端提供的各种工具。
  • Server(服务端) :负责提供具体的工具、资源和功能。它处理客户端的请求,解析协议,执行对应的业务逻辑,然后把结果返回。

这种设计的核心好处是客户端和服务端完全解耦——不管服务端是用什么语言开发的,客户端都能调用,不同开发语言的开发者可以协作构建统一的 AI 生态。

2.3 SDK 三层架构

如果要在程序中使用 MCP 或开发 MCP 服务,需要引入 MCP 官方的 SDK。MCP Java SDK 的架构主要分为三层:

  1. 客户端/服务器层(Client/Server Layer) :提供 McpClientMcpServer 两个核心接口。McpClient 负责处理客户端操作,而 McpServer 管理服务端的协议操作。两者均通过 McpSession 进行通信管理。
  2. 会话层(Session Layer) :通过 DefaultMcpSession 的实现,管理通信模式与状态,保证消息的可靠传输。
  3. 传输层(Transport Layer) :负责 JSON-RPC 消息的序列化与反序列化,支持多种传输协议实现,如 Stdio、HTTP over SSE 等。这一层决定了数据如何通过网络或本地系统传输。

2.4 传输机制

MCP 的传输机制非常灵活,从网络协议栈的角度看,MCP 是应用层协议。从设计上主要分为数据层和传输层两个维度:数据层基于 JSON-RPC 2.0 标准,定义了工具调用、资源访问等操作的请求与响应消息结构;传输层则负责实际的数据传输工作。

MCP 支持两种传输机制:

  • Stdio(标准输入输出):通过进程间的标准输入输出流进行通信。适用于本地进程间通信,比如同一台机器上的客户端与服务器通信。不依赖网络协议,是操作系统直接提供的进程间通信机制。适合本地开发调试、轻量级工具和 IDE 插件的场景。
  • SSE(Server-Sent Events):客户端使用 HTTP POST 发送请求,服务器通过 SSE 流式返回响应。适用于远程网络通信,客户端与服务端分布在不同的主机上。基于 TCP 协议,适合部署在云端的远程服务和分布式系统。

客户端和服务端需要经过标准的连接建立流程之后,才能正常交换信息。如果选择 Stdio 传输,客户端通过命令行启动服务端子进程;如果选择 SSE 传输,客户端通过 HTTP 与远程服务端建立连接。无论哪种方式,双方都需要先完成协议版本协商和能力交换,然后才能开始正常的请求-响应通信。

客户端可以通过不同传输方式调用不同的 MCP 服务,可以是本地的,也可以是远程的,这种灵活性让 MCP 既能支持本地开发调试,也能支持云端生产环境的高并发部署。

2.5 核心概念

很多人以为 MCP 协议就只能提供工具给别人调用,但实际上 MCP 的能力远不止这些。按照官方定义,MCP 总共有 6 个核心概念。日常开发中最实用的是前三个:

  1. Resources(资源) :服务端可以向客户端提供各种数据,比如文本、文件、数据库记录、API 响应。资源是只读的,AI 可以基于这些资源来获得更丰富的上下文,但不能修改资源内容。
  2. Prompts(提示词) :服务端可以定义可复用的提示词模板和工作流,供客户端直接使用。它的作用是标准化常见的 AI 交互模式。
  3. Tools(工具) :这是 MCP 中最实用的特性。服务端把可调用的函数暴露给客户端,AI 模型可以执行计算、查询信息,或者和外部系统交互。
  4. Sampling(采样) :允许服务端通过客户端向 AI 模型发起生成请求(反向请求),实现复杂智能代理行为。
  5. Roots(根目录) :定义了服务器可以访问的文件系统位置,是 MCP 协议的安全机制,用于限制访问范围。
  6. Transports(传输) :也就是上面提到的 Stdio 和 SSE,负责实际的数据传输。

在 Spring AI 的 MCP 开发中,我们主要关注 Tools,其他概念了解即可。如果要进一步学习,可以去查阅官方文档。

三、Spring AI MCP 客户端开发

客户端的演示我们使用MCP.so平台的高德地图 MCP 工具为例:

3.1 引入依赖

Spring AI 提供了两种客户端 Starter,分别支持普通同步调用和响应式编程,可以根据实际需要选择合适的依赖。

  • spring-ai-starter-mcp-client:核心启动器,提供基于标准输入输出(Stdio)和基于 HTTP 的 SSE 传输支持,适合大多数场景。
  • spring-ai-starter-mcp-client-webflux:基于 WebFlux 的响应式 SSE 传输实现,适合需要异步流式处理或高并发的场景。
xml
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-client</artifactId>
  <version>1.0.0</version>
</dependency>

3.2 配置 MCP 服务

在项目 resources 目录下新建 mcp-servers.json 配置文件,定义需要使用的 MCP 服务:

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

这个配置告诉 Spring AI:

  • 我们要接入一个名为 amap-maps 的 MCP 服务
  • 通过 npx 命令启动这个服务(需要本地有 Node.js 环境)
  • -y 参数表示自动确认,@amap/amap-maps-mcp-server 是高德地图官方发布的 MCP 服务包名
  • 通过环境变量 AMAP_MAPS_API_KEY 传入你在高德开放平台申请的 API Key

关于 API Key:去高德开放平台注册账号,申请一个 Web 服务类型的 API Key,替换上面的占位符即可。

然后在 application.yml 中添加配置:

yaml
spring:
  ai:
    mcp:
      client:
        enabled: true
        stdio:
          servers-configuration: classpath:mcp-servers.json

3.3 在代码中使用

在 Spring Boot 启动时,Spring AI 的** MCP 自动配置 **会做以下几件事:

  1. 读取 mcp-servers.json 中的配置
  2. 通过 npx 命令启动高德 MCP 服务的子进程(通过 Stdio 通信)
  3. 建立客户端与这个子进程之间的连接
  4. 扫描服务端提供了哪些工具,把每个工具自动封装成 ToolCallback 对象
  5. 把所有这些 ToolCallback 收集起来,注入成一个 ToolCallbackProvider Bean

因此在业务代码中,只需要注入并使用它就行:

java
@Component
@Slf4j
public class CoffeeApp {

    private final ChatClient chatclient;

    @Autowired
    private VectorStore coffeeVectorStore;

    @Autowired
    private ToolCallbackProvider toolCallbackProvider;  //注入MCP工具


    private static final String SYSTEM_PROMPT = """                        
            你是“醒石咖啡”的智能客服助手。你的职责是友好、专业地回答顾客关于门店信息、饮品菜单、优惠活动、服务流程、投诉建议等常规问题。
                        
            回答原则:
            1. 优先使用知识库中的标准答案,若无法确定则主动建议顾客联系门店或查看官方小程序 https://blog.xinxinnote.tech。
            2. 对于员工内部制度(如奖惩、排班)、食品安全事故、法律纠纷等敏感问题,仅提供基础指引并转人工处理。
            3. 不编造任何超出已知范围的优惠、价格或库存信息。
            4. 保持礼貌、耐心,语气亲切但不过度热情。
                        
            禁止回答的内容:
            - 顾客的个人隐私信息(如身份证号、银行卡号)
            - 对竞争对手的负面评价
            - 超出咖啡店业务范围的问题(如医疗建议、投资理财)
                        
            当不确定时,统一回复:“您好,这个问题我需要帮您转接人工客服或您可到店咨询,感谢理解!”
            """;

    public CoffeeApp(ChatModel dashscopeChatModel) {
        //初始化具有记忆能力的ChatClient
        MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(new InMemoryChatMemoryRepository())
                .maxMessages(20)
                .build();

        this.chatclient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(SYSTEM_PROMPT)   //系统提示词
                .defaultAdvisors(
                        MessageChatMemoryAdvisor.builder(chatMemory).build(),
                        new MyLoggerAdvisor()
                )
                .build();
    }


    /**
     * 支持调用MCP能力
     *
     * @return
     */
    public String chatWithMcp(String message, String chatId) {
        ChatResponse chatResponse = chatclient.prompt()
                .user(message)
                .advisors(spec -> spec.param(ChatMemory.CONVERSATION_ID, chatId))
                .advisors(new MyLoggerAdvisor())  //开启日志
                .advisors(CustomRAGAdvisorFactory.createRagCustomAdvisor(coffeeVectorStore, null))
                .toolCallbacks(toolCallbackProvider)
                .call()
                .chatResponse();
        
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }
}

ToolCallbackProvider 已经被 Spring AI 自动扫描并注册好了。通过 .tools(toolCallbackProvider) 这一行,所有高德 MCP 服务提供的工具(比如附近搜索、地理编码、距离计算等)都被一次性注册给了 ChatClient。用户提问时,AI 模型会自主判断是否需要调用哪个工具来完成回答。

3.4 测试效果

写一个简单的测试来验证:

java
//测试代码
@SpringBootTest
class CoffeeAppTest {


    @Autowired
    private CoffeeApp coffeeApp;

    @Test
    void chatWithMcp() {
        String chatId = UUID.randomUUID().toString();
        String message = "你们店在上海哪个位置?离我这里有多远?我在虹桥火车站";
        String answer = coffeeApp.chatWithMcp(message, chatId);
        Assertions.assertNotNull(answer);
    }
}

AI 会这样处理流程:

  1. 分析问题,判断需要用到地图搜索工具
  2. 调用高德 MCP 服务提供的"附近搜索"工具,传入"虹桥火车站"作为位置参数和"咖啡店"作为搜索关键词
  3. 高德 MCP 服务通过 API Key 调用高德地图接口,返回咖啡店列表
  4. AI 把返回的 JSON 数据整理成友好的推荐语,返回给用户

整个过程不需要手动处理 HTTP 请求,不需要解析 JSON 响应,不需要写工具调用代码。MCP 服务把这一切都封装好了,Spring AI 负责对接,AI 负责决策。

四、Spring AI MCP 服务端开发

如果想把你自己写的工具暴露给其他人用,可以把工具封装成一个 MCP 服务,让别人也能通过标准协议接入。

4.1 引入依赖

Spring AI 提供了多种 MCP 服务端 Starter,根据应用场景选择:

  • spring-ai-starter-mcp-server:核心服务端启动器,提供 Stdio 传输支持,不需要额外的 Web 依赖。
  • spring-ai-starter-mcp-server-webmvc:基于 Spring MVC 的 SSE 传输实现,兼容传统的 Servlet 环境。
  • spring-ai-starter-mcp-server-webflux:基于 WebFlux 的响应式 SSE 传输实现,支持异步流式处理。

如果服务端需要接收客户端通过网络远程发起调用,建议使用 spring-ai-starter-mcp-server-webmvc;如果只需要在本机通过 Stdio 被调用,spring-ai-starter-mcp-server 就够用了。

xml
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

4.2 配置服务

application.yml 中添加 MCP 服务端配置:

yaml
spring:
  ai:
    mcp:
      server:
        name: webmvc-mcp-server
        version: 1.0.0
        stdio: false
        type: SYNC
        sse-endpoint: /sse                   # SSE 端点路径
        sse-message-endpoint: /mcp/message   # SSE 消息端点路径

4.3 开发服务

开发 MCP 服务端的方式跟之前开发工具调用几乎一样——直接用 @Tool 注解标记服务类中的方法。

java
@Slf4j
@Component
public class TimeTool {

    @Tool(description = "获取当前精确的日期和时间(包括年月日、时分秒)。当用户的问题涉及到现在、今天、当前时刻、倒计时、截止时间等需要基于当前时间进行计算的场景时,必须调用此工具进行计算")
    public String getCurrentTimeByZoneId(
        @ToolParam(description = "时区id,比如 Asia/Shanghai") String zoneId) {
        log.info("TimeTool.getTimeByZoneId 调用入参:{}", zoneId);
        ZoneId zid = ZoneId.of(zoneId);
        ZonedDateTime now = ZonedDateTime.now(zid);
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatTime = now.format(dtf);
        log.info("TimeTool.getTimeByZoneId 调用返回值:{}", formatTime);
        return formatTime;
    }
}

4.4 注册工具

在 Spring Boot 项目启动时,通过配置类注册 ToolCallbackProvider Bean:

java
@Configuration
public class MCPConfig {

    @Bean
    public ToolCallbackProvider getTimeByZoneId(TimeTool timeTool) {   
        return MethodToolCallbackProvider.builder()
        .toolObjects(timeTool)   // 注册工具
        .build();
    }
}

这样,别人就可以通过 Stdio 或 SSE 的方式接入你的 MCP 服务,调用你提供的工具了。如果使用 Stdio 传输,客户端会在本地启动一个新的子进程来运行你的服务端程序;如果使用 SSE 传输,客户端会通过 HTTP 远程调用。

我们只需要把服务端打包成可执行的 JAR,并告知客户端启动命令。客户端只需要在配置 JSON 中填入启动命令,就能像使用任何第三方 MCP 服务一样使用你提供的工具。

总结

MCP 从本质上解决了 AI 应用接入外部能力时的重复开发问题。它的核心价值可以概括为"一次开发,到处调用",让工具开发者专注于把一件事做精,让 AI 应用开发者只关心怎么用好这些能力。

回顾整个过程,在 Spring AI框架中使用 MCP 和开发 MCP 是一件比较容易的事情,实际开发中 MCP 服务已经都封装好了,Spring AI 负责对接,AI 负责决策。如果你想了解更多 MCP 的玩法,可以去 MCP.so、阿里百炼等服务市场逛逛,看看别人都提供了哪些现成的服务。也可以试试把自己写的工具通过 @Tool 注解包一下,注册成 MCP 服务,分享给更多人使用。

如果你想获取本文的完整代码仓库,欢迎关注我的公众号 AutowiredAI,后台回复「MCP实战」即可。如果配置过程中遇到任何问题,欢迎留言交流,我会尽力解答。

评论

评论功能即将上线,敬请期待...

🏷️ 文章标签

MCP 实战Spring AI工具调用AI 大模型基础AI 编排框架

©2026 EasyBlog 版权所有. Powered by Nuxt.