一、引言
在当今生成式 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 生态中的发展趋势与挑战。
二、为什么需要模型上下文协议
- 弥补 LLM 的固有局限
LLM 虽然在通用语言任务上表现卓越,但其内部参数仅包含训练时所见的数据,无法实时访问新的信息或执行精确计算。传统做法需要在 Prompt 中硬编码外部调用逻辑,既繁琐又难以维护。MCP 提供了一种标准化的调用机制,让模型在需要时通过协议获取外部上下文或触发操作,从而提升回答的准确性与实用性。 - 简化多源集成成本
在没有统一协议前,不同的数据源和工具通常需要各自的 SDK 或 API 进行集成,导致接入成本高、维护复杂。MCP 定义了通用的 JSON-RPC 2.0 消息格式和能力协商机制,使得开发者只需实现符合 MCP 规范的服务器或客户端,就能与任意 MCP 生态中的其他组件互通。 - 支持复杂智能体与工作流
随着 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 环境准备
-
安装 npx:确保本地安装了 npm。
npm install -g npx
-
下载示例源码:
git clone https://github.com/springaialibaba/spring-ai-alibaba-examples.git cd spring-ai-alibaba-examples/spring-ai-alibaba-mcp-example/filesystem
-
设置环境变量:
export AI_DASHSCOPE_API_KEY=<your-api-key>
-
构建并运行示例:
./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 交互时,模型可调用
readFile
、writeFile
等方法操作文件。
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 环境准备
-
安装 UVX 通用包管理工具,运行
uvx install mcp-server-sqlite
。 -
下载示例源码并设置 API Key,同上。
-
构建并运行:
./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 长连接进行调用。
八、安全、性能与最佳实践
- 安全性:对敏感工具(如文件写入、数据库写入、外部 API 调用)需进行鉴权和审计;对客户端输入参数做严格校验;在 SSE 模式下,使用 HTTPS 并启用身份验证与授权。
- 性能:对耗时操作(大文件读写、复杂查询)可采用异步处理;合理设置超时时间;对于高并发场景,可水平扩展 MCP Server 实例。
- 版本管理:在协议升级或工具更新时,通过能力协商机制让客户端和服务器平滑过渡;在工具描述中添加
version
字段,便于模型和客户端了解工具版本。 - 监控与日志:记录 MCP 请求与响应日志;监控调用延迟和错误率;对于 stdio 模式,可将 stderr 重定向到集中式日志系统。
- 工具设计:每个工具方法应职责单一、参数明确;为参数添加详细描述,帮助模型正确生成调用;避免“万能”接口,防止模型生成复杂、错误的调用。
九、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 官网及社区文章。