MCP(Model Context Protocol)本质是标准化的 LLM 工具调用交互规范,核心目标是让 AI 工具(如 Claude Desktop、IDE 插件)安全、高效地调用封装了本地 / 远程资源的 “能力服务”,其实现逻辑与 Function Call 一致,但更强调 “通信协议标准化” 和 “多场景适配(本地 / 远程)”。

MCP 是一个开放协议,它标准化了应用程序如何向大语言模型(LLMs)提供上下文。

MCP 核心角色

MCP 的实现依赖 5 个核心角色,各角色分工明确,共同完成 “工具调用” 闭环:

角色

核心职责

示例

MCP 主机(Host)

发起工具调用需求的 “业务方”,即 MCP 能力的使用者

Trae、Claude Desktop、IDE 插件、AI 问答工具

MCP 客户端(Client)

遵循 MCP 协议的 “通信代理”,负责与 MCP 服务器建立连接、传递调用请求、接收结果

基于 stdio/SSE 的 Spring AI 客户端

MCP 服务器(Server)

封装 “工具能力” 的 “服务提供方”,暴露可调用的工具(如天气查询、数据库访问)

本地嵌入式服务、远程 HTTP 服务

本地数据源

MCP 服务器可安全访问的本地资源(避免 Host 直接操作)

本地文件、MySQL 数据库、本地 API

远程服务

MCP 服务器可调用的外部互联网服务

天气 API(OpenMeteo)、支付接口

MCP 两种实现方式

  1. 基于 stdio(标准输入输出)
    • 适用场景:嵌入式、单机部署,客户端直接启动服务端子进程。
    • 特点:轻量、无网络依赖,适合本地工具(如文件读取、系统命令)。
    • 实现关键
      • 服务端需设置 spring.main.web-application-type=none
      • 启动参数包含 -Dspring.ai.mcp.server.stdio=true
      • 客户端通过 StdioClientTransport 管理子进程 。
  1. 基于 SSE(Server-Sent Events)
    • 适用场景:远程服务、多客户端共享、云原生部署。
    • 特点:基于 HTTP/HTTPS,可跨网络调用,支持负载均衡。
    • 实现关键
      • 服务端作为 WebFlux 应用运行在指定端口(如 8080)
      • 客户端通过 WebFluxSseClientTransport 连接

两种方式在业务逻辑层完全一致——都通过 @Tool 注解暴露方法

MCP 客户端实现

客户端的核心是 “按协议与服务器通信”,分为本地 stdio 模式(同一机器,子进程交互)和远程 SSE 模式(跨机器,HTTP 交互),两者实现差异集中在 “连接方式” 和 “配置”。

本地 stdio 模式(适合嵌入式场景)

核心特点

客户端与服务器在同一台机器,客户端通过 “启动服务器子进程”,用标准输入输出流(stdio)通信,无需网络,延迟低。

实现步骤

  1. 添加依赖(Spring AI MCP 客户端 starter)
<!-- 本地stdio模式依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
  1. 配置服务器(application.yml + JSON 配置文件)
    • application.yml:指定服务器配置文件路径,或直接配置启动命令
spring:
  ai:
    dashscope:  # 若调用远程LLM(如通义千问),配置API密钥
      api-key: ${DASH_SCOPE_API_KEY}
    mcp:
      client:
        stdio:
          # 方式1:指定服务器配置文件(推荐,分离配置)
          servers-configuration: classpath:/mcp-servers-config.json
          # 方式2:直接配置(适合简单场景)
          # connections:
          #   server1:
          #     command: java
          #     args: [-jar, /path/to/mcp-server.jar]
    • mcp-servers-config.json:定义服务器启动参数(如命令、JVM 参数)
{
  "mcpServers": {
    "weather-server": {  # 服务器名称(自定义)
      "command": "java",  # 启动命令
      "args": [
        "-Dspring.ai.mcp.server.stdio=true",  # 启用stdio模式
        "-Dspring.main.web-application-type=none",  # 禁用Web服务(本地子进程)
        "-jar",
        "/path/to/weather-mcp-server.jar"  # 服务器Jar包路径
      ],
      "env": {}  # 可选:环境变量(如数据库密码)
    }
  }
}
  1. 代码实现:构建 ChatClient,注入 MCP 工具
@SpringBootApplication
public class McpStdioClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpStdioClientApplication.class, args);
    }

    // 注入工具和ChatClient,执行查询
    @Bean
    public CommandLineRunner runTool(
            ChatClient.Builder chatClientBuilder,
            ToolCallbackProvider tools,  // MCP工具自动注入
            ConfigurableApplicationContext context) {
        return args -> {
            // 1. 构建支持MCP工具的ChatClient
            ChatClient chatClient = chatClientBuilder
                    .defaultTools(tools)  // 注入MCP服务器的工具(如天气查询)
                    .build();

            // 2. 调用工具:查询北京天气(触发MCP客户端向服务器发请求)
            String userQuery = "北京的天气如何?";
            System.out.println(">>> 问题:" + userQuery);
            String result = chatClient.prompt(userQuery).call().content();
            System.out.println(">>> 结果:" + result);

            context.close();
        };
    }
}

远程 SSE 模式(适合多客户端共享场景)

核心特点

服务器独立部署(如远程服务器、云服务),客户端通过Server-Sent Events(SSE) 协议(HTTP 长连接)与服务器通信,支持多客户端同时调用。

实现步骤

  1. 添加依赖(支持 SSE 的 MCP 客户端 starter)
<!-- 远程SSE模式依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
  1. 配置服务器(仅需指定远程 URL)
spring:
  ai:
    dashscope:
      api-key: ${DASH_SCOPE_API_KEY}
    mcp:
      client:
        sse:
          connections:
            weather-server:  # 服务器名称
              url: http://localhost:8080  # 远程MCP服务器地址(SSE服务端口)
  1. 代码实现:与 stdio 模式完全一致(协议透明化)
@SpringBootApplication
public class McpSseClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpSseClientApplication.class, args);
    }

    @Bean
    public CommandLineRunner runTool(
            ChatClient.Builder chatClientBuilder,
            ToolCallbackProvider tools,
            ConfigurableApplicationContext context) {
        return args -> {
            // 代码与stdio模式完全相同,Spring AI自动处理SSE通信
            ChatClient chatClient = chatClientBuilder.defaultTools(tools).build();
            String result = chatClient.prompt("北京天气?").call().content();
            System.out.println(">>> SSE模式结果:" + result);

            context.close();
        };
    }
}

MCP 服务器实现

服务器的核心是 “将能力封装为可调用的工具”,通过@Tool注解标记方法,让客户端自动发现并调用,同样支持 stdio 和 SSE 两种部署模式。

本地 stdio 模式(嵌入式服务器)

核心特点

作为客户端的 “子进程” 启动,无独立端口,禁用 Web 服务,适合本地资源访问(如本地文件、数据库)。

实现步骤:
  1. 添加依赖(stdio 模式服务器 starter)
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
  1. 配置服务器(禁用 Web,启用 stdio)
spring:
  main:
    web-application-type: none  # 关键:禁用Web服务(嵌入式子进程)
    banner-mode: off  # 关闭启动日志(减少干扰)
  ai:
    mcp:
      server:
        stdio: true  # 启用stdio模式
        name: weather-stdio-server  # 服务器名称(客户端需匹配)
        version: 0.0.1  # 版本号(用于兼容性判断)
  1. 封装工具:用@Tool标记可调用方法
// 服务类:封装天气查询能力(调用远程天气API)
@Service
public class WeatherToolService {
    private final WebClient webClient;

    // 注入WebClient,用于调用远程天气API
    public WeatherToolService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("https://api.open-meteo.com/v1").build();
    }

    /**
     * 工具1:根据经纬度查天气预报
     * @Tool:标记为MCP工具,description供客户端识别功能
     * @ToolParameter:描述参数,帮助客户端传递正确值
     */
    @Tool(description = "根据经纬度获取实时天气预报(温度、风速)")
    public String getWeather(
            @ToolParameter(description = "纬度,示例:39.9042(北京)") String latitude,
            @ToolParameter(description = "经度,示例:116.4074(北京)") String longitude) {
        try {
            // 调用远程天气API
            String apiResult = webClient.get()
                    .uri(uri -> uri.path("/forecast")
                            .queryParam("latitude", latitude)
                            .queryParam("longitude", longitude)
                            .queryParam("current", "temperature_2m,wind_speed_10m")
                            .build())
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();

            // 格式化结果(实际项目需解析JSON)
            return "北京天气:\n" + apiResult;
        } catch (Exception e) {
            return "查询失败:" + e.getMessage();
        }
    }

    /** 工具2:根据经纬度查空气质量(模拟数据) */
    @Tool(description = "根据经纬度获取空气质量(PM2.5、AQI)")
    public String getAirQuality(
            @ToolParameter(description = "纬度") String latitude,
            @ToolParameter(description = "经度") String longitude) {
        return "北京空气质量:\nPM2.5: 15 μg/m³(优)\nAQI: 42";
    }
}
  1. 注册工具:让服务器识别并暴露工具
@SpringBootApplication
public class McpStdioServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpStdioServerApplication.class, args);
    }

    // 注册工具:将WeatherToolService中的@Tool方法暴露给客户端
    @Bean
    public ToolCallbackProvider weatherTools(WeatherToolService weatherToolService) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(weatherToolService)  // 传入工具类实例
                .build();
    }
}

远程 SSE 模式(独立服务器)

核心特点

作为独立 Web 服务启动(有端口),支持多客户端远程调用,适合共享能力(如团队内共用的数据库查询工具)。

实现步骤

  1. 添加依赖(同 stdio 模式,需 WebFlux 支持 SSE)
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
  1. 配置服务器(指定端口,启用 SSE)
server:
  port: 8080  # 独立服务端口(客户端需配置此地址)
spring:
  ai:
    mcp:
      server:
        name: weather-sse-server  # 服务器名称
        version: 0.0.1
        # 无需配置stdio=true(默认启用SSE)
  1. 工具封装与注册:与 stdio 模式完全一致

工具类(WeatherToolService)和注册代码(ToolCallbackProvider)与 stdio 模式相同,Spring AI 自动通过 SSE 协议暴露工具。

  1. 启动服务器:独立运行
# 打包
mvn clean package -DskipTests
# 启动(独立进程)
java -jar target/weather-sse-server.jar

MCP 客户端与服务器交互流程

两种模式的交互逻辑差异集中在 “连接建立方式”,核心工具调用流程一致(请求→处理→响应)。

stdio 模式交互(本地子进程)

  1. 客户端启动时,读取mcp-servers-config.json,执行java -jar命令启动服务器子进程;
  2. 客户端通过 “标准输入流” 向服务器发送工具调用请求(如getWeather(latitude=39.9042, longitude=116.4074));
  3. 服务器执行@Tool方法,通过 “标准输出流” 将结果返回给客户端;
  4. 客户端将结果传递给 Host(如 AI 工具),生成最终回答。

SSE 模式交互(远程 HTTP)

  1. 客户端启动时,通过配置的http://localhost:8080建立 SSE 长连接;
  2. 客户端通过 HTTP 请求发送工具调用参数,服务器接收后执行@Tool方法;
  3. 服务器通过 SSE 流将结果推送给客户端(无需客户端轮询);
  4. 客户端接收结果,传递给 Host。

MCP 的本质

MCP 与 LLM 的 Function Call 核心目标一致(让 AI 调用外部工具),但 MCP 是更具象的 “交互协议规范”,两者差异如下:

维度

Function Call(如 OpenAI 函数调用)

MCP(模型上下文协议)

核心定位

工具调用能力(LLM 侧定义)

工具调用的 “通信 + 封装” 标准化规范

通信方式

依赖 LLM API(如 OpenAI API)

支持 stdio(本地)、SSE(远程)两种模式

能力封装

需手动定义函数 Schema

@Tool

注解自动封装,无需手动写 Schema

部署场景

多为远程 API 调用

支持本地嵌入式、远程共享两种场景

安全隔离

无明确隔离(Host 直接调用工具)

服务器隔离 Host 与数据源(Host 不直接操作本地资源)

结论:MCP 是 Function Call 的 “工业化实现”—— 它将 Function Call 的 “工具调用逻辑”,通过标准化协议(stdio/SSE)、注解式工具封装、多场景部署,变成可落地的工程方案。

Function Calling 是‘模型自己会用的工具’,MCP 是‘让模型安全、标准地连接万物的协议’

MCP 核心价值

  1. 标准化:终结了各家 Function Calling 的碎片化,提供统一接口。
  2. 解耦:LLM 应用与工具服务完全分离,便于独立开发、部署、升级。
  3. 安全可控:通过独立服务进程隔离敏感操作(如数据库访问)。
  4. 生态友好:任何人可开发 MCP Server,形成“AI 工具市场”。

MCP 落地最佳实践

  1. 工具设计
    • 每个@Tool方法仅做一件事(如 “查天气”“查空气质量” 分开),避免参数过多;
    • @ToolParameter详细描述参数(含示例),帮助 LLM 生成正确参数。
  1. 错误处理
    • 服务器工具方法必须捕获异常,返回 “用户可理解的错误信息”(如 “纬度格式错误,示例:39.9042”)。
  1. 部署选择
    • 本地资源访问(如本地文件、数据库)→ 选 stdio 模式(低延迟、安全);
    • 多客户端共享能力(如团队共用工具)→ 选 SSE 模式(方便部署、可扩展)
Logo

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

更多推荐