首页 > 教程攻略 > ai教程 >【AI Agent 全栈开发】MCP

【AI Agent 全栈开发】MCP

来源:互联网 时间:2026-06-10 07:23:35

先说几个核心判断:AI应用生态发展到今天,优化提示词和Tool Calling已经帮我们突破了很多语言模型的边界,但如果仔细想想,工具一多、场景一复杂,老路子就开始吃力了——接口不统一、模型得硬编码工具定义……这些问题就像厨房里堆满了不同制式的厨具,每个都得单独学怎么用。好在,MCP(模型上下文协议)来了。

前言

如今,AI应用越来越依赖与外部系统的交互。我们从最开始的提示词工程,一步步走到Tool Calling——让模型自己决定要不要调用工具、调哪个工具。但现实是,随着工具数量的增长,传统的Tool Calling实现方式开始暴露出几个扎堆的挑战:工具接口格式不统一,模型需要硬编码工具定义……说实话,这些痛点如果不解决,后面每加一个新工具都得改代码,想想就头疼。

正是为了收拾这个烂摊子,MCP应运而生。

什么是MCP

MCP(Model Context Protocol)模型上下文协议,说白了,它不是要替代Tool Calling,而是给Tool Calling搭一个统一的、可扩展的跨平台基础设施。用一句话概括:

MCP就是Tool Calling的管理者

  • Tool Calling

    :模型决定要不要叫工具,叫哪个工具。
  • MCP

    :规定工具怎么描述、怎么发起调用、怎么传递结果。

有了MCP,AI只需学会一种通信格式,剩下的翻译工作全交给MCP Server。就像是给所有厨具统一配上了标准接口,厨房再乱也能高效运转。

MCP Ja va SDK架构

MCP Ja va SDK提供了Ja va端的完整实现,支持同步和异步两种通信模式,让AI模型和工具之间能按标准化方式握手。

  • Client/Server

    :请求的发起者和接收者,就像顾客和后厨。
  • Session

    :管理会话生命周期,相当于订单管理系统。
  • Transport

    :消息传递的方式,好比手机订餐加上骑手送餐。

Transport传输协议

MCP Ja va SDK支持多种“通信方式”,让AI应用(客户端)能灵活地与各种工具服务(服务器)对话。目前支持三种传输方式:

  1. 基于Stdio的进程间通信传输协议

    :通过标准输入/输出(stdin和stdout)在两个程序之间传消息,直接高效。
  2. 基于Ja va HttpClient的SSE客户端传输协议

    :用Ja va HttpClient发起HTTP请求,接收服务端持续推送的事件流。
  3. WebFlux SSE客户端传输协议

    :基于WebFlux的非阻塞响应式模型处理SSE流,适合高并发场景。

MCP Server

MCP Server是协议的具体服务端实现,对外提供特定功能。你可以直接去MCP Server社区查找你需要的功能——那里聚集了大量技术爱好者,资源很丰富。几个常用的社区入口:GitHub MCP Registry、MCP Flow、火山引擎MCP广场。不过要注意,这些社区里有些服务可能需要注册或API Key,具体按官方文档来。

MCP Client

有了服务端,怎么在代码里调用?这就需要MCP Client出场了。它连接开发环境和远程MCP Server,不同客户端对MCP协议的支持程度不一样,可以根据自己的需求选合适的。

MCP使用

在使用MCP Client之前,通常得先跑一个或多个MCP Server实例。很多MCP Server通过npx或uv命令启动,所以运行环境要提前配好。下面是一个典型的配置,以百度地图MCP Server为例:

{
  "mcpServers": {
    "baidu-map": {
      "command": "npx",
      "args": ["-y", "@baidumap/mcp-server-baidu-map"],
      "env": {
        "BAIDU_MAP_API_KEY": "xxx"
      }
    }
  }
}

配置好后,在Cursor里就能直接看到MCP Server的效果:

除了Cursor这类客户端,我们也能通过Spring AI代码来接入。以Spring AI Alibaba为例,先引入依赖,然后在配置文件中指定MCP Server的地址和超时时间:

spring:
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}
    mcp:
      client:
        request-timeout: 60000
        stdio:
          servers-configuration: classpath:/mcp/mcp-servers-config.json

同时,将百度地图的配置写入mcp/mcp-servers-config.json

{
  "mcpServers": {
    "baidu-map": {
      "command": "npx.cmd",
      "args": ["-y", "@baidumap/mcp-server-baidu-map"],
      "env": {
        "BAIDU_MAP_API_KEY": "你的Key"
      }
    }
  }
}

然后在Controller里注入ToolCallbackProvider,它会自动把MCP Server的工具注册给AI模型:

@RestController
@RequestMapping("/chat")
public class ChatController {
    private ChatClient chatClient;

    public ChatController(DashScopeChatModel chatModel, ToolCallbackProvider toolCallbackProvider) {
        this.chatClient = ChatClient.builder(chatModel)
                .defaultToolCallbacks(toolCallbackProvider)
                .build();
    }

    @RequestMapping("/generate")
    public String generate(String message) {
        return chatClient.prompt().user(message).call().content();
    }
}

ToolCallbackProvider是Spring AI中用来向AI模型注册可用工具的核心接口。只要MCP配置进来,它就能自动调用,完美解决了传统Tool Calling中各工具接口不同的问题,实现动态工具组合。

自定义MCP Server

我们知道MCP有两种通信方式:Stdio和Streamable HTTP。早先用的是SSE,但在2025年3月26日的协议更新后,官方用更强大的Streamable HTTP取代了SSE(解决了SSE连接容易断开的痛点)。不过为了兼容旧版本,这里仍保留SSE的实现说明。

使用Stdio自定义MCP Server

先写一个天气查询服务:

@Service
@Slf4j
public class WeatherService {
    private final Map weatherCache = new ConcurrentHashMap<>();

    public WeatherService() {
        weatherCache.put("北京", new WeatherInfo("晴转多云", "22~28", "南风2级", "78"));
        weatherCache.put("上海", new WeatherInfo("小雨", "18~24", "东风3级", "52"));
        weatherCache.put("广州", new WeatherInfo("晴朗", "25~33", "微风", "45"));
        weatherCache.put("深圳", new WeatherInfo("多云", "24~30", "东北风2级", "60"));
    }

    @Tool(description = "查询指定城市的天气信息,返回天气状况、温度范围、风力、空气质量")
    public String queryWeather(@ToolParam(description = "城市名称,如:北京、上海、广州、深圳") String city) {
        log.info("[HTTP MCP] queryWeather 调用,城市: {}", city);
        if (!weatherCache.containsKey(city)) {
            return String.format("未找到「%s」的天气信息,支持的城市:%s", city, weatherCache.keySet());
        }
        WeatherInfo info = weatherCache.get(city);
        return String.format("""
                            

相关下载