【大模型应用】MCP 概念详解 及 Java 项目使用
MCP:AI工具的标准化接口协议 MCP(Model Context Protocol)是由Anthropic开发的开放协议,旨在为大型语言模型提供标准化访问外部工具的方式。其核心功能包括: 架构设计:采用客户端-服务器模式,通过SSE/WebSocket实现双向通信。客户端展示工具列表并执行调用,服务器提供具体工具能力。 核心组件: 工具(Tools):定义明确的函数接口 资源(Resource
第一部分:MCP 深度解析 - AI 的“USB 标准”
1. 什么是 MCP?
MCP (Model Context Protocol) 是由 Anthropic 主导开发的一种开放协议,旨在为大语言模型(LLM)提供一种标准化、安全的方式来访问外部工具、数据和服务。
- 核心比喻:MCP 之于 AI 应用,犹如 USB 之于电脑。它定义了一套通用的“接口”和“协议”,允许模型(如Claude、GPT)即插即用地与各种外部资源(数据库、API、文件系统等)进行交互,而无需为每个工具编写特定的集成代码。
- 要解决的问题:
- 集成碎片化:每个AI应用都需要重复编写连接外部工具(如SQL数据库、JIRA、GitHub)的代码,工作量大且难以维护。
- 安全性:直接授予AI模型访问生产系统的权限存在巨大风险。
- 能力限制:模型的上下文窗口有限,无法直接处理大量外部数据。
2. 为什么 MCP 如此重要?
MCP 是构建下一代 “AI原生” 应用的基础设施,它实现了模型(大脑) 与工具(手脚) 的彻底解耦。
- 对模型提供商(Anthropic, OpenAI等):无需不断为模型内置更多功能,只需让模型学会使用MCP协议,即可无限扩展其能力。
- 对开发者:可以专注于开发好用的工具(MCP Server),而无需关心模型层面的集成。一次开发,所有兼容MCP的模型和应用(如Claude Console、Cline)都能使用。
- 对企业:可以安全、可控地将内部系统(数据库、CRM、ERP)暴露给AI使用,极大提升自动化能力。
3. MCP 的核心组件与工作原理
MCP 采用客户端-服务器(Client-Server) 架构,通过双向通信(如SSE、WebSocket)进行交互。
-
MCP Client(客户端):
- 通常是AI应用或模型界面(如Claude Code编辑器、Cursor编辑器、未来可能支持MCP的ChatGPT)。
- 职责:建立与Server的连接,向模型展示可用的工具列表,并根据模型的决策调用Server上的工具,最后将结果返回给模型/用户。
-
MCP Server(服务器):
- 工具能力的提供者。一个Server可以提供一种或多种工具(例如,一个SQL Server提供
sql_query
工具;一个文件系统Server提供read_file
,list_files
工具)。 - 职责:启动后向Client注册自己提供的工具列表(包括名称、描述、参数schema),并等待Client的调用请求。执行具体的业务逻辑(如执行SQL查询、读取文件、调用JIRA API)并将结果返回给Client。
- 工具能力的提供者。一个Server可以提供一种或多种工具(例如,一个SQL Server提供
-
Session:
- Client和Server之间建立的一个持久连接会话,在整个会话期内保持通信。
-
工具(Tools):
- Server提供的具体能力,本质是一个个函数。每个工具都有明确的名称、描述和参数定义(遵循JSON Schema)。模型的“思考”过程就包括选择正确的工具并提供正确的参数。
-
资源(Resources):
- 一种特殊的工具,用于提供静态数据(如一个文件的内容、一个数据库表的结构定义)。Client可以预先加载资源内容到模型的上下文中,帮助模型更好地做出决策。
第二部分:MCP 底层通信协议分析
MCP 协议本质上是一系列定义好的 JSON-RPC 2.0 消息,通过 SSE (Server-Sent Events) 或 WebSocket 传输。
1. 协议流程与关键消息
2. 传输方式
- SSE (Server-Sent Events):
- 特点:基于HTTP,单向(Server->Client)流式通信。MCP巧妙地利用了两条SSE连接实现双向通信(Client->Server通过普通HTTP POST)。
- 优点:简单,兼容性好,易于调试。
- WebSocket:
- 特点:真正的全双工通信协议。
- 优点:延迟更低,通信效率更高,是更现代的选择。
第三部分:Java 项目中的 MCP 应用与实践
Java生态在MCP中主要扮演 MCP Server 提供者的角色,即用Java编写各种工具服务。
方案一:使用 Java 开发 MCP Server(推荐)
这是最核心的应用方式。你可以用Java为你公司的内部系统(数据库、CRM、内部API)构建MCP Server,从而让AI安全地使用这些系统。
1. 技术栈选择:
- 核心库:目前MCP官方库主要针对Node.js/Python。Java开发者需要手动实现MCP协议。
- HTTP Server/SSE:使用 Spring Boot 提供HTTP端点并处理SSE连接。
WebClient
和SseEmitter
是得力工具。 - JSON处理:Jackson 用于序列化/反序列化MCP的JSON-RPC消息。
- 依赖注入:Spring Framework 用于管理工具执行所需的Bean(如
DataSource
,RestTemplate
)。
2. 实现步骤:
a. 定义工具接口(以SQL查询为例)
/**
* MCP Tool 的抽象表示
*/
@Data
public class SQLQueryTool implements McpTool {
private final String name = "sql_query";
private final String description = "Execute a SELECT SQL query against the company data warehouse and get the results. Do not perform INSERT/UPDATE/DELETE.";
// 使用JSON Schema定义参数结构
private final ObjectNode inputSchema = createInputSchema();
private ObjectNode createInputSchema() {
// 使用Jackson构建JSON Schema
return JsonNodeFactory.instance.objectNode()
.put("type", "object")
.set("properties", JsonNodeFactory.instance.objectNode()
.set("query", JsonNodeFactory.instance.objectNode()
.put("type", "string")
.put("description", "The SELECT SQL query to execute")));
}
}
b. 实现MCP Server的核心控制器
@RestController
@RequestMapping("/mcp")
@Slf4j
public class McpServerController {
@Autowired
private SQLService sqlService; // 你的业务服务
private final Map<String, McpTool> tools = Map.of(
"sql_query", new SQLQueryTool()
);
// 处理SSE连接初始化
@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handleSseConnection() {
SseEmitter emitter = new SseEmitter(0L); // 无超时
// 1. 发送 "initialize" 请求(略)
// 2. 发送 "tools/list" 通知
sendToolsList(emitter);
return emitter;
}
private void sendToolsList(SseEmitter emitter) {
try {
ObjectNode message = JsonNodeFactory.instance.objectNode();
message.put("jsonrpc", "2.0");
message.put("method", "tools/list");
message.set("params", JsonNodeFactory.instance.objectNode()
.set("tools", JsonNodeFactory.instance.arrayNode()
.addAll(tools.values().stream()
.map(tool -> JsonNodeFactory.instance.objectNode()
.put("name", tool.getName())
.put("description", tool.getDescription())
.set("inputSchema", tool.getInputSchema()))
.collect(Collectors.toList()))));
emitter.send(SseEmitter.event().data(message.toString()));
} catch (IOException e) {
log.error("Failed to send tools list", e);
}
}
// 处理来自Client的HTTP POST请求(工具调用)
@PostMapping("/call")
public ResponseEntity<String> handleToolCall(@RequestBody JsonNode request) {
String method = request.path("method").asText();
JsonNode params = request.path("params");
if ("tools/call".equals(method)) {
String toolName = params.path("name").asText();
JsonNode arguments = params.path("arguments");
if ("sql_query".equals(toolName)) {
String query = arguments.path("query").asText();
if (!isSafeQuery(query)) {
return ResponseEntity.badRequest().body("{\"error\": \"Only SELECT queries are allowed.\"}");
}
try {
// 执行安全的查询
List<Map<String, Object>> result = sqlService.executeSafeQuery(query);
// 构建成功的JSON-RPC响应
ObjectNode successResponse = buildSuccessResponse(request.path("id"), result);
return ResponseEntity.ok(successResponse.toString());
} catch (Exception e) {
// 构建错误的JSON-RPC响应
ObjectNode errorResponse = buildErrorResponse(request.path("id"), -32000, e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse.toString());
}
}
}
// ... 处理其他method
return ResponseEntity.notFound().build();
}
private boolean isSafeQuery(String query) {
// 实现简单的SQL安全检查:只允许SELECT开头的查询
String trimmedQuery = query.trim().toLowerCase();
return trimmedQuery.startsWith("select");
}
}
c. 实现工具执行服务
@Service
public class SQLService {
@Autowired
private JdbcTemplate jdbcTemplate; // Spring JDBC
public List<Map<String, Object>> executeSafeQuery(String query) {
// 使用JdbcTemplate执行查询,返回List<Map>格式,便于JSON序列化
return jdbcTemplate.query(query, new ColumnMapRowMapper());
}
}
方案二:Java 作为 MCP Client(桥接模式)
在某些场景下,你可能需要用Java编写一个MCP Client,作为你现有Java应用和MCP生态之间的桥接器。
应用场景:
- 你有一个传统的Java Web应用,你想为其添加AI辅助功能。
- 你的Java应用充当Client,连接到一个或多个MCP Server(如Python写的文件操作Server),然后将获取到的上下文信息发送给OpenAI/Anthropic的API。
简化示例:
@Component
public class McpClientBridge {
private final WebClient webClient;
public McpClientBridge(@Value("${mcp.server.url}") String serverUrl) {
this.webClient = WebClient.builder().baseUrl(serverUrl).build();
}
public Flux<String> streamSqlQueryResult(String userRequest) {
// 1. 连接到MCP Server,获取工具列表 (模拟LLM的决策过程)
// 2. 假设我们决定调用 sql_query 工具
String query = "SELECT * FROM sales WHERE quarter = 'Q3'"; // 应由LLM生成,这里简化
ObjectNode callRequest = JsonNodeFactory.instance.objectNode()
.put("jsonrpc", "2.0")
.put("id", 1)
.put("method", "tools/call")
.set("params", JsonNodeFactory.instance.objectNode()
.put("name", "sql_query")
.set("arguments", JsonNodeFactory.instance.objectNode()
.put("query", query)));
// 3. 调用工具并获取结果
return webClient.post()
.uri("/call")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(callRequest.toString())
.retrieve()
.bodyToMono(String.class)
.flatMapMany(response -> {
// 4. 解析响应,将结果流式返回给调用者(或发送给LLM API)
JsonNode jsonNode = JsonUtils.toJsonNode(response);
String result = jsonNode.path("result").path("content").asText();
return Flux.just("查询结果:", result);
});
}
}
第四部分:生产级考量与最佳实践
-
安全性第一:
- 输入验证与净化:对工具参数进行严格校验(如SQL注入检查、路径遍历攻击检查)。
- 权限控制:MCP Server应实现身份认证和授权,不同用户/模型只能访问被允许的工具和数据。
- 网络隔离:将MCP Server部署在独立的网络区域,仅开放必要的端口。
-
错误处理与鲁棒性:
- 为所有工具调用实现全面的异常捕获和友好的错误信息返回。
- 使用熔断器模式(Resilience4j)防止MCP Server故障导致主应用雪崩。
- 为MCP连接设置合理的超时和重试机制。
-
性能与可观测性:
- 日志记录:详细记录所有工具调用的请求、响应和耗时,用于审计和调试。
- 指标监控:使用Micrometer暴露Metrics(QPS、延迟、错误率),并接入Prometheus+Grafana。
- 资源管理:对于耗时长的工具操作,考虑支持异步调用和状态查询。
-
开发体验:
- 为你的Java MCP Server编写详细的文档,说明其提供的工具和用法。
- 可以考虑提供测试客户端,方便开发者调试工具。
总结
MCP 是连接AI模型与现实世界的桥梁,它通过标准化协议解决了工具集成的核心痛点。对于Java开发者而言,当前最大的价值在于用Java构建强大、安全、可靠的企业级MCP Server,将内部系统的能力安全地暴露给AI。
行动建议:
- 评估场景:识别你公司内部哪些系统(数据库、知识库、ITSM系统)最需要被AI访问。
- 原型开发:使用Spring Boot为一个简单工具(如员工目录查询、订单状态查询)实现MCP Server。
- 安全评审:对原型进行严格的安全评审。
- 逐步推广:在安全可控的前提下,逐步扩大MCP Server的应用范围。
虽然Java在MCP生态中起步稍晚,但其在企业级应用开发中的统治地位,使其成为构建生产环境MCP Server的绝佳选择。随着MCP协议的日益普及,Java开发者在这一领域将大有可为。
更多推荐
所有评论(0)