Model Context Protocol (MCP) 模型上下文协议

一、引言

在当今生成式 AI 快速发展的时代,大型语言模型(LLM)如 GPT、Claude 等已经在自然语言理解、文本生成和对话交互等方面展现了惊人的能力。然而,LLM 本身只能依赖于训练数据和提示(Prompt)来生成回答,无法直接访问或操作外部系统、数据库、文件、第三方 API 等资源。为了让 LLM 能够在必要时获取更准确、更实时、更专业的上下文信息,并执行实际操作,Anthropic 提出了**模型上下文协议(Model Context Protocol,简称 MCP)**这一开放标准,用以规范 LLM 与各种数据源和工具的交互方式。MCP 的目标是为 AI 应用提供一个类似“USB-C 接口”的统一协议,让开发者只需一次集成,便可轻松连接到任意 MCP 服务器,从而让 AI 模型访问多种数据源与功能。

本篇博客将深入探讨 MCP 的设计初衷、核心概念、技术架构,以及在 Java/Spring 生态中如何通过 Spring AI MCP 客户端与服务端实现对 MCP 的集成与应用。我们将通过多个案例演示如何快速搭建 MCP 客户端与 MCP 服务端,包括本地文件系统、SQLite 数据库、天气查询等场景,并讨论安全性、可扩展性与最佳实践。最后,展望 MCP 在未来生成式 AI 生态中的发展趋势与挑战。


二、为什么需要模型上下文协议

  1. 弥补 LLM 的固有局限
    LLM 虽然在通用语言任务上表现卓越,但其内部参数仅包含训练时所见的数据,无法实时访问新的信息或执行精确计算。传统做法需要在 Prompt 中硬编码外部调用逻辑,既繁琐又难以维护。MCP 提供了一种标准化的调用机制,让模型在需要时通过协议获取外部上下文或触发操作,从而提升回答的准确性与实用性。
  2. 简化多源集成成本
    在没有统一协议前,不同的数据源和工具通常需要各自的 SDK 或 API 进行集成,导致接入成本高、维护复杂。MCP 定义了通用的 JSON-RPC 2.0 消息格式和能力协商机制,使得开发者只需实现符合 MCP 规范的服务器或客户端,就能与任意 MCP 生态中的其他组件互通。
  3. 支持复杂智能体与工作流
    随着 Agent 式 AI 的兴起,智能体往往需要在对话中结合多种能力:查询数据库、检索文档、调用业务系统、发送邮件等。MCP 通过定义工具(Tools)、资源(Resources)和提示(Prompts)等概念,为构建多步骤、跨系统的复杂工作流提供了坚实的协议基础。

三、MCP 的核心概念与架构

3.1 协议规范(Protocol Specification)

MCP 基于 JSON-RPC 2.0,定义了客户端(MCP Client)与服务器(MCP Server)之间的消息格式、请求/响应结构以及错误处理机制。它通过状态化连接,允许在同一会话中进行多次请求和响应,并支持能力协商(Capability Negotiation),以确保客户端和服务器都能了解对方支持的功能版本。

3.2 核心角色
  • MCP Client:在 AI 应用端(通常嵌入在 LLM 服务或 Agent 框架中)的实现,负责根据用户请求或模型指令构建 JSON-RPC 调用,并将其发送给 MCP Server。Anthropic 提供了多种语言的 SDK(Python、TypeScript、Java 等),简化客户端开发。
  • MCP Server:在外部系统端的实现,接收并解析客户端请求,与实际的数据源或工具交互,将结果封装为符合 MCP 协议的 JSON 响应返回给客户端。MCP Server 可以访问本地文件、数据库、Web API 或其他服务。
  • Transport Layer:MCP 支持多种传输方式,目前主要有基于 stdio 的进程间通信和基于 SSE(Server-Sent Events)的 HTTP 长连接。stdio 方式适用于本地嵌入式部署,SSE 方式则支持跨网络、分布式调用。
3.3 功能模块
  • 工具(Tools):客户端可调用的函数或方法,例如查询天气、执行数据库查询、文件读写等。
  • 资源(Resources):结构化的数据集合,模型可用于检索或过滤,如文档库、知识图谱等。
  • 提示(Prompts):可复用的消息模板,帮助构建对话上下文或工作流步骤。

这些模块通过 MCP 协议进行描述与发现,客户端在初始化时可查询服务器提供的工具列表,并在对话中根据需要发起相应调用。


四、Spring AI MCP 集成概览

为了让 Java/Spring 开发者能够快速使用 MCP,Spring AI 提供了 spring-ai-mcp 工件,支持在 Spring Boot 应用中以最少的配置完成 MCP Client 和 MCP Server 的集成。

4.1 引入依赖

在 Maven 项目中添加:

<dependency>
  <groupId>org.springframework.experimental</groupId>
  <artifactId>spring-ai-mcp</artifactId>
  <version>0.2.0</version>
</dependency>

同时由于该工件位于 Spring Milestone 仓库,需要在 pom.xml 中添加:

<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/libs-milestone-local</url>
    <snapshots><enabled>false</enabled></snapshots>
  </repository>
</repositories>

对于 Gradle 项目,则在 build.gradle 中加入:

dependencies {
  implementation 'org.springframework.experimental:spring-ai-mcp:0.2.0'
}

4.2 MCP Client 初始化

Spring AI MCP 提供 McpClient 用于与 MCP Server 建立连接并发起调用。以下示例展示了如何通过 stdio 方式启动 Brave Search MCP 服务,并将其注册为 Spring AI ChatClient 的工具:

// 配置启动参数:使用 npx 启动 @modelcontextprotocol/server-brave-search
var stdioParams = ServerParameters.builder("npx")
        .args("-y", "@modelcontextprotocol/server-brave-search")
        .addEnvVar("BRAVE_API_KEY", System.getenv("BRAVE_API_KEY"))
        .build();

// 创建同步 MCP 客户端
var mcpClient = McpClient.using(new StdioClientTransport(stdioParams)).sync();

// 初始化连接
var init = mcpClient.initialize();
System.out.println("MCP Initialized: " + init);

// 将 MCP 工具转换为 Spring AI Function
var functionCallbacks = mcpClient.listTools(null)
        .tools()
        .stream()
        .map(tool -> new McpFunctionCallback(mcpClient, tool))
        .toArray(McpFunctionCallback[]::new);

// 构建 ChatClient 并注入 MCP 工具
var chatClient = chatClientBuilder
        .defaultFunctions(functionCallbacks)
        .build();

// 与模型交互示例
String response = chatClient
        .prompt("Does Spring AI support the Model Context Protocol? Please provide some references.")
        .call()
        .content();

System.out.println("Assistant: " + response);

以上代码演示了如何在 Spring Boot 应用中,通过 MCP 客户端与外部 MCP Server 建立连接,并将其作为函数回调(Function Callback)注册到 ChatClient,使得 LLM 在对话中能够动态调用 Brave Search 服务获取搜索结果。


五、案例 1:通过 MCP 访问本地文件系统

在许多场景下,我们需要让智能体能够查询或修改本地文件,以便利用文件内容作为对话上下文或存储模型生成的结果。以下示例展示了如何使用 MCP 将本地文件系统作为 MCP Server 暴露给 LLM:

5.1 环境准备
  1. 安装 npx:确保本地安装了 npm。

    npm install -g npx
    
    
  2. 下载示例源码

    git clone https://github.com/springaialibaba/spring-ai-alibaba-examples.git
    cd spring-ai-alibaba-examples/spring-ai-alibaba-mcp-example/filesystem
    
    
  3. 设置环境变量

    export AI_DASHSCOPE_API_KEY=<your-api-key>
    
    
  4. 构建并运行示例

    ./mvnw clean install
    ./mvnw spring-boot:run
    
    
5.2 示例架构
  • MCP Server(filesystem):通过 @modelcontextprotocol/server-filesystem 包,将本地目录作为文件系统服务端。客户端通过 stdio 与之通信。
  • MCP Client:在 Spring Boot 应用中,使用 StdioClientTransport 与 McpClient 建立连接,并将文件系统工具注册到 ChatClient。
  • ChatClient:将 MCP 工具注入后,与 LLM 交互时,模型可调用 readFilewriteFile 等方法操作文件。
5.3 关键代码
// MCP 客户端 Bean
@Bean(destroyMethod = "close")
public McpSyncClient mcpClient() {
    var stdioParams = ServerParameters.builder("npx")
            .args("-y", "@modelcontextprotocol/server-filesystem", "./data")
            .build();
    var mcpClient = McpClient.sync(new StdioServerTransport(stdioParams),
            Duration.ofSeconds(10), new ObjectMapper());
    var init = mcpClient.initialize();
    System.out.println("Filesystem MCP Initialized: " + init);
    return mcpClient;
}

// Function Callbacks Bean
@Bean
public List<McpFunctionCallback> functionCallbacks(McpSyncClient mcpClient) {
    return mcpClient.listTools(null)
            .tools()
            .stream()
            .map(tool -> new McpFunctionCallback(mcpClient, tool))
            .toList();
}

// ChatClient Bean 注入 MCP 工具
@Bean
public ChatClient chatClient(ChatClient.Builder builder, List<McpFunctionCallback> callbacks) {
    return builder.defaultFunctions(callbacks.toArray(new McpFunctionCallback[0]))
                  .build();
}

在上述配置完成后,当用户在对话中询问“请读取 data 目录下的 config.json 并告诉我其中的配置项”时,LLM 会自动发起对 readFile 工具的调用,MCP Server 返回文件内容,最终模型给出具体的配置解析。


六、案例 2:通过 MCP 访问 SQLite 数据库

除了文件系统,数据库也是常见的数据源。我们可以使用 MCP 将 SQLite 数据库暴露为 MCP Server,让 LLM 以自然语言查询数据库。

6.1 环境准备
  1. 安装 UVX 通用包管理工具,运行 uvx install mcp-server-sqlite

  2. 下载示例源码并设置 API Key,同上。

  3. 构建并运行:

    ./mvnw clean install
    ./mvnw spring-boot:run
    
    
6.2 MCP Server 配置

使用 uvx 启动 mcp-server-sqlite

uvx run mcp-server-sqlite --db-path=./data/shop.db

服务启动后,会监听 stdio,等待 MCP Client 请求。

6.3 MCP Client Bean
@Bean(destroyMethod = "close")
public McpSyncClient mcpClient() {
    var stdioParams = ServerParameters.builder("uvx")
            .args("run", "mcp-server-sqlite", "--db-path=./data/shop.db")
            .build();
    var mcpClient = McpClient.sync(new StdioServerTransport(stdioParams),
            Duration.ofSeconds(10), new ObjectMapper());
    var init = mcpClient.initialize();
    System.out.println("SQLite MCP Initialized: " + init);
    return mcpClient;
}

6.4 自然语言查询示例
  • 用户:所有商品的价格总和是多少?
  • Assistant:LLM 自动调用 aggregate 工具执行 SELECT SUM(price) FROM products; 并返回 1642.8,最后生成回答:“所有商品的价格总和是 1642.8 元。”
  • 用户:告诉我价格高于平均值的商品。
  • Assistant:LLM 调用 query 工具执行两步操作:先查询平均价格,再查询高于平均的商品列表,最终以自然语言返回结果列表。

七、Spring AI MCP Server 端实现

除了客户端,Spring AI 也提供了 MCP Server Starter,使得在 Spring Boot 应用中快速暴露工具变得极为简单。

7.1 基于 stdio 的 MCP 服务端
依赖
<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>

配置(application.yml)
spring:
  main:
    web-application-type: none
  ai:
    mcp:
      server:
        stdio: true
        name: my-filesystem-server
        version: 0.1.0

实现工具类
@Service
public class FileSystemService {

    @Tool(description = "读取指定路径的文件内容")
    public String readFile(
            @ToolParameter(description = "文件路径,例如: data/config.json") String path) {
        try {
            return Files.readString(Paths.get(path));
        } catch (IOException e) {
            return "Error: " + e.getMessage();
        }
    }

    @Tool(description = "将内容写入指定路径的文件")
    public String writeFile(
            @ToolParameter(description = "文件路径,例如: data/output.txt") String path,
            @ToolParameter(description = "要写入的内容") String content) {
        try {
            Files.writeString(Paths.get(path), content);
            return "Write successful";
        } catch (IOException e) {
            return "Error: " + e.getMessage();
        }
    }
}

注册工具
@SpringBootApplication
public class McpServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }

    @Bean
    public ToolCallbackProvider fileSystemTools(FileSystemService service) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(service)
                .build();
    }
}

运行后,Spring Boot 应用将作为 MCP Server 进程,通过 stdio 与 MCP Client 通信,实现对文件系统工具的调用。


7.2 基于 SSE 的 MCP 服务端
依赖
<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

配置(application.yml)
server:
  port: 8080
spring:
  ai:
    mcp:
      server:
        name: my-sse-filesystem-server
        version: 0.1.0

工具实现与注册

与 stdio 方式相同,只需同时提供 WebClient.Builder Bean:

@Bean
public WebClient.Builder webClientBuilder() {
    return WebClient.builder();
}

运行后,MCP Server 将监听 HTTP 连接,支持多个客户端通过 SSE 长连接进行调用。


八、安全、性能与最佳实践

  1. 安全性:对敏感工具(如文件写入、数据库写入、外部 API 调用)需进行鉴权和审计;对客户端输入参数做严格校验;在 SSE 模式下,使用 HTTPS 并启用身份验证与授权。
  2. 性能:对耗时操作(大文件读写、复杂查询)可采用异步处理;合理设置超时时间;对于高并发场景,可水平扩展 MCP Server 实例。
  3. 版本管理:在协议升级或工具更新时,通过能力协商机制让客户端和服务器平滑过渡;在工具描述中添加 version 字段,便于模型和客户端了解工具版本。
  4. 监控与日志:记录 MCP 请求与响应日志;监控调用延迟和错误率;对于 stdio 模式,可将 stderr 重定向到集中式日志系统。
  5. 工具设计:每个工具方法应职责单一、参数明确;为参数添加详细描述,帮助模型正确生成调用;避免“万能”接口,防止模型生成复杂、错误的调用。

九、MCP 生态与未来展望

自 Anthropic 于 2024 年 11 月发布 MCP 以来,已有包括 Replit、Codeium、Sourcegraph 等多家厂商和开源社区项目接入 MCP 生态,构建了代码搜索、文档检索、知识库、开发者助手等多种 Agent 应用 。

未来,随着更多语言的 SDK 发布、标准规范的完善以及社区最佳实践的沉淀,MCP 有望成为生成式 AI 应用的事实标准,助力开发者更高效地构建智能体、工作流和交互式应用。同时,安全、可扩展性、可组合性等方面也将成为生态发展的重点研究方向。


十、总结

模型上下文协议(MCP)为 LLM 应用提供了一个统一、标准化的接口,使其能够在对话或工作流中随时访问和操作外部数据源与工具。通过 JSON-RPC 2.0 协议、能力协商机制和多种传输层实现,MCP 打破了不同系统间的集成壁垒,简化了多源集成成本。

在 Java/Spring 生态中,借助 Spring AI MCP,我们可以轻松地将本地文件系统、数据库、第三方 API 等资源暴露给 LLM,并在 ChatClient 中将其注册为函数回调,实现“智能体”式的交互与自动化操作。

随着 MCP 生态的不断壮大与成熟,未来生成式 AI 应用将在多领域多场景中得到更广泛的应用,推动智能体技术向更高的可用性、可靠性和安全性发展。希望本文能帮助读者全面了解 MCP 的原理、实现和最佳实践,快速上手并在实际项目中落地应用。


本文部分示例改编自 Anthropic 官方博客、Model Context Protocol 官网及社区文章。