MCP 原理及 Java 开发指南
Categories: AI
目的:帮助 Java / Spring Boot 开发者快速理解 MCP 的设计动机、协议细节、以及 如何在 Spring AI 中落地。
为什么需要 MCP?
MCP 助力开发者在 LLM 之上构建智能体和复杂工作流。由于 LLM 需要频繁与外部数据和工具集成,MCP 提供了以下核心价值:
- 开箱即用的集成能力:提供丰富的预置集成方案,LLM 可直接接入使用
- 灵活的供应商切换:支持在不同 LLM 服务商之间无缝迁移
- 安全最佳实践:内置数据安全防护机制,确保基础设施安全可控
MCP 用 JSON‑RPC 2.0 + 能力发现 的模式,把「模型 ↔ 应用 ↔ 工具」之间的交互标准化,实现 一次接入,多处复用。
MCP 协议就好比 USB 接口,USB 设备可以通过 USB Hub 连接到不同的计算机上,而不需要重新设计接口。
- 我们在电脑上可以同时使用多个 USB 设备(鼠标、键盘、硬盘、游戏手柄),这些 USB 设备有不同的功能,只要实现了标准的 USB 接口协议即可。
- 电脑可以类比成 LLM,USB Hub 可以类比成 MCP Server,USB 设备可以类比成 Tool、Resource、Prompt 等。
- 通过 MCP 协议,LLM 可以通过 USB Hub 访问不同的 USB 设备,从而扩展出各种各样的能力(发邮件、打电话、地图旅行规划、订票)。
从某种程度上说,MCP 就像是设计模式中的命令(Command)模式 + 外观(Facade)模式。
基本概念
关键术语

- MCP 主机:需要通过 MCP 访问数据的程序,如 Claude Desktop、IDE 或 AI 工具
- MCP 客户端:与服务器保持 1:1 连接的协议客户端
- MCP 服务器:通过标准化的模型上下文协议暴露特定能力的轻量级程序
- 本地数据源:MCP 服务器可以安全访问的计算机文件、数据库和服务
- 远程服务:MCP 服务器可以通过互联网连接的外部系统(例如通过 API)
分层架构
┌────────────────────────────┐
│ Client / Server API 层 │ ← McpClient / McpServer
├────────────────────────────┤
│ Session 会话层 │ ← 会话 & 状态管理
├────────────────────────────┤
│ Transport 传输层 │ ← Stdio / SSE / WebSocket / gRPC
└────────────────────────────┘
MCP 采用分层架构设计,每一层都有其特定的职责:
- Client / Server API 层
- 提供 McpClient 和 McpServer 接口
- 处理高层业务逻辑和协议交互
- 负责能力发现和工具调用
- Session 会话层
- 管理客户端和服务器之间的会话状态
- 处理会话的生命周期(初始化、运行、关闭)
- 维护会话上下文和状态信息
- Transport 传输层
- 提供多种传输机制支持:
- Stdio:标准输入输出,适合本地进程间通信
- SSE (Server-Sent Events):单向服务器推送
- WebSocket:全双工通信
- gRPC:高性能 RPC 框架
- 处理底层通信细节和协议转换
- 提供多种传输机制支持:
这种分层设计使得 MCP 具有:
- 良好的可扩展性:可以轻松添加新的传输机制
- 清晰的职责分离:各层专注于自己的功能
- 灵活的部署方式:支持多种通信场景
传输机制
| 传输 | 场景 | 特点 |
|---|---|---|
| Stdio | 本地 CLI / 子进程 | 零网络开销,启动快 |
| HTTP + SSE | 微服务 / Web 应用 | POST 请求 + SSE 推流,部署友好 |
| 自定义 | WebSocket / gRPC | 只需实现 Transport 接口即可 |
Java Spring AI 集成实践
使用 Spring AI 开发,详细说明可以参考官网文档。
MCP 分为 Stdio 和 SSE 两种传输方式,下面的例子使用 SSE 方式,最简化开发一个发票助手 MCP,并展示如何通过模型自动调用这个 MCP。
POM 依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
配置示例 application.properties
spring.main.banner-mode=off
# logging.pattern.console=
spring.ai.mcp.server.name=my-invoice-server
spring.ai.mcp.server.version=0.0.1
详细的配置参数及默认值可以参考官方文档:Spring AI / Model Context Protocol (MCP) / MCP Server Boot Starters。
暴露 Tool
这里就模拟一个非常简单的功能,仅拼装对应参数,返回发票链接。
@Service
public class InvoiceService {
@Tool(description = "获取发票链接")
public String getInvoiceUrl(@ToolParam(required = true, description = "发票 id") String invoiceId) {
return "https://www.example.com/invoice/" + invoiceId;
}
}
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider invoiceTools(InvoiceService invoiceService) {
return MethodToolCallbackProvider.builder().toolObjects(invoiceService).build();
}
}
启动服务
执行 java -jar mcp-server.jar 启动服务,默认监听 8080 端口。
在 MCP client 中配置 mcp.setting
cursor、VS code 中的 cline 插件都算是 MCP client。本文展示 cline 插件如何配置。

cline_mcp_setting.json 增加如下配置:
{
"mcpServers": {
"invoice-local": {
"url": "http://localhost:8080/sse",
"autoApprove": [
"getInvoiceUrl"
]
}
}
}
我们可以看到对应的 getInvoiceUrl 方法已经被自动注册到 MCP Server 中。

使用 MCP!
在 cline 中输入问题:“我有一个发票 id 是 123456,发票链接是多少?”,可以看到模型会自动判断是否需要调用 MCP Server 中的 getInvoiceUrl 方法,并拼装参数,获取结果。

说明
- JDK 版本必须 >= 17
- Spring Boot 版本必须 >= 3.2
- Spring AI 底层使用 modelcontextprotocol / java-sdk
- MCP 协议等都在快速发展中,上面的代码示例仅供参考,具体实现可能会有所不同
完整配置示例
Application.java:
package com.example.mcp;
import org.springframework.ai.mcp.server.tool.ToolCallbackProvider;
import org.springframework.ai.mcp.server.tool.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
/**
* 注册所有 Tools
*/
@Bean
public ToolCallbackProvider toolCallbackProvider(
DatabaseTools databaseTools,
FileTools fileTools,
HttpTools httpTools
) {
return MethodToolCallbackProvider.builder()
.toolObjects(databaseTools, fileTools, httpTools)
.build();
}
/**
* WebClient for HTTP tools
*/
@Bean
public WebClient webClient() {
return WebClient.builder()
.defaultHeader("User-Agent", "MCP-Server/1.0")
.build();
}
}
application.yml:
spring:
application:
name: mcp-server-demo
ai:
mcp:
server:
name: "Enterprise MCP Server"
version: "1.0.0"
description: "Comprehensive MCP server with database, file, and HTTP capabilities"
server:
port: 8080
logging:
level:
org.springframework.ai.mcp: DEBUG
com.example.mcp: DEBUG
MCP Client 配置与使用
Claude Desktop 配置
Claude Desktop 是最早支持 MCP 的应用之一。配置文件位置:
macOS:
~/Library/Application\ Support/Claude/claude_desktop_config.json
Windows:
%APPDATA%\Claude\claude_desktop_config.json
配置示例:
{
"mcpServers": {
"enterprise-server": {
"command": "java",
"args": [
"-jar",
"/path/to/mcp-server.jar"
],
"env": {
"SERVER_PORT": "8080"
}
},
"database-server": {
"url": "http://localhost:8080/sse",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
Cursor IDE 配置
Cursor 通过 .cursor/mcp.json 文件配置 MCP 服务器:
{
"mcpServers": {
"local-dev": {
"command": "java",
"args": ["-jar", "mcp-server.jar"],
"env": {
"WORKSPACE_ROOT": "${workspaceFolder}"
}
},
"remote-api": {
"url": "https://api.example.com/mcp/sse",
"autoApprove": ["read_file", "list_directory"]
}
}
}
Cline/Continue 配置
VS Code 插件 Cline 的配置文件:~/.cline/mcp_settings.json
{
"mcpServers": {
"development": {
"url": "http://localhost:8080/sse",
"autoApprove": [
"query_database",
"read_file",
"list_directory"
],
"alwaysAllow": ["get_table_schema"]
}
}
}
实际使用示例
场景 1:数据库查询
用户: 查询用户表中所有活跃用户的数量
AI: 我会帮你查询数据库。
[调用 query_database]
参数: sql = "SELECT COUNT(*) as count FROM users WHERE status = 'active'"
结果: {"rowCount": 1, "rows": [{"count": 1234}]}
AI: 当前有 1,234 个活跃用户。
场景 2:文件操作
用户: 帮我创建一个 README.md 文件,包含项目介绍
AI: 好的,我会创建 README 文件。
[调用 write_file]
参数:
path = "README.md"
content = "# Project Name\n\nThis is a comprehensive guide..."
create_dirs = true
AI: README.md 文件已创建成功!
场景 3:代码审查
用户: 使用 code-review prompt 审查这段代码
AI: 我会使用专业的代码审查模板。
[调用 code-review prompt]
参数:
language = "Java"
code = "public class User { ... }"
focus_areas = "安全性和性能"
AI: [提供详细的代码审查反馈...]
最佳实践
安全考虑
- 输入验证
public class SecurityValidator {
public static void validateSqlQuery(String sql) {
// 防止 SQL 注入
String lowerSql = sql.toLowerCase();
String[] dangerousKeywords = {
"drop", "delete", "update", "insert",
"truncate", "alter", "create"
};
for (String keyword : dangerousKeywords) {
if (lowerSql.contains(keyword)) {
throw new SecurityException(
"不允许的 SQL 操作: " + keyword
);
}
}
}
public static Path validatePath(Path basePath, String userPath) {
Path resolved = basePath.resolve(userPath).normalize();
// 防止路径遍历攻击
if (!resolved.startsWith(basePath)) {
throw new SecurityException(
"路径超出允许范围: " + userPath
);
}
return resolved;
}
}
- 权限控制
@Configuration
public class McpSecurityConfig {
@Bean
public McpAuthorizationManager authorizationManager() {
return new McpAuthorizationManager() {
@Override
public boolean canExecuteTool(String toolName, Principal user) {
// 基于用户角色的权限控制
return switch (toolName) {
case "query_database" ->
user.hasRole("DATA_ANALYST");
case "write_file" ->
user.hasRole("DEVELOPER");
default -> true;
};
}
};
}
}
- API 速率限制
@Aspect
@Component
public class RateLimitAspect {
private final RateLimiter rateLimiter =
RateLimiter.create(10.0); // 每秒 10 个请求
@Around("@annotation(Tool)")
public Object rateLimit(ProceedingJoinPoint joinPoint)
throws Throwable {
if (!rateLimiter.tryAcquire()) {
throw new RateLimitException(
"请求过于频繁,请稍后再试"
);
}
return joinPoint.proceed();
}
}
性能优化
- 结果缓存
@Service
public class CachedDatabaseTools {
@Cacheable(value = "tableSchema", key = "#tableName")
public TableSchema getTableSchema(String tableName) {
// 缓存表结构,避免重复查询
return databaseService.getSchema(tableName);
}
@Cacheable(
value = "queryResults",
key = "#sql",
condition = "#sql.toLowerCase().startsWith('select')"
)
public QueryResult executeQuery(String sql) {
return databaseService.execute(sql);
}
}
- 异步处理
@Service
public class AsyncFileTools {
@Tool(description = "异步搜索文件")
public CompletableFuture<List<String>> searchFilesAsync(
@ToolParam(name = "pattern") String pattern
) {
return CompletableFuture.supplyAsync(() -> {
// 耗时的文件搜索操作
return fileService.search(pattern);
});
}
}
- 连接池管理
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
// 优化连接池配置
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
return new HikariDataSource(config);
}
}
错误处理
统一异常处理:
@ControllerAdvice
public class McpExceptionHandler {
@ExceptionHandler(SecurityException.class)
public ResponseEntity<ErrorResponse> handleSecurityException(
SecurityException ex
) {
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body(new ErrorResponse(
"SECURITY_ERROR",
ex.getMessage()
));
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ErrorResponse> handleValidationException(
IllegalArgumentException ex
) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(new ErrorResponse(
"VALIDATION_ERROR",
ex.getMessage()
));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(
Exception ex
) {
log.error("Unexpected error", ex);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse(
"INTERNAL_ERROR",
"服务暂时不可用,请稍后重试"
));
}
}
record ErrorResponse(
String code,
String message
) {}
监控与日志
@Aspect
@Component
public class McpMonitoringAspect {
@Around("@annotation(tool)")
public Object monitorToolExecution(
ProceedingJoinPoint joinPoint,
Tool tool
) throws Throwable {
String toolName = tool.name();
long startTime = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
// 记录成功的工具调用
log.info(
"Tool executed: {} | Duration: {}ms",
toolName, duration
);
// 发送指标到监控系统
metricsService.recordToolExecution(
toolName, duration, "success"
);
return result;
} catch (Exception ex) {
long duration = System.currentTimeMillis() - startTime;
// 记录失败的工具调用
log.error(
"Tool failed: {} | Duration: {}ms | Error: {}",
toolName, duration, ex.getMessage()
);
metricsService.recordToolExecution(
toolName, duration, "failure"
);
throw ex;
}
}
}
典型应用场景
1. IDE 智能助手
功能描述: 在 IDE 中提供代码生成、重构、调试等智能辅助功能。
实现示例:
@Service
public class IdeTools {
@Tool(description = "生成单元测试")
public String generateUnitTest(
@ToolParam(name = "source_code") String sourceCode,
@ToolParam(name = "test_framework") String framework
) {
// 分析源代码
CodeAnalysis analysis = codeAnalyzer.analyze(sourceCode);
// 生成测试代码
return testGenerator.generate(analysis, framework);
}
@Tool(description = "代码重构建议")
public List<RefactoringSuggestion> suggestRefactoring(
@ToolParam(name = "code") String code
) {
return refactoringService.analyzePotentialImprovements(code);
}
}
2. 企业数据分析
功能描述: 提供自然语言到 SQL 的转换,支持数据可视化。
@Service
public class DataAnalyticsTools {
@Tool(description = "自然语言查询")
public QueryResult nlQuery(
@ToolParam(name = "question") String question
) {
// 将自然语言转换为 SQL
String sql = nlToSqlConverter.convert(question);
log.info("Generated SQL: {}", sql);
// 执行查询
return databaseService.executeQuery(sql);
}
@Tool(description = "生成数据可视化")
public ChartConfig generateChart(
@ToolParam(name = "data") List<Map<String, Object>> data,
@ToolParam(name = "chart_type") String chartType
) {
return chartGenerator.generate(data, chartType);
}
}
3. 文档生成与管理
@Service
public class DocumentationTools {
@Tool(description = "生成 API 文档")
public String generateApiDocs(
@ToolParam(name = "swagger_spec") String swaggerSpec
) {
return apiDocGenerator.generate(swaggerSpec);
}
@Tool(description = "更新用户手册")
public UpdateResult updateUserManual(
@ToolParam(name = "section") String section,
@ToolParam(name = "content") String content
) {
Path manualPath = docsPath.resolve("user-manual.md");
return documentService.updateSection(manualPath, section, content);
}
}
4. DevOps 自动化
@Service
public class DevOpsTools {
@Tool(description = "部署应用")
public DeploymentResult deploy(
@ToolParam(name = "environment") String environment,
@ToolParam(name = "version") String version
) {
return deploymentService.deploy(environment, version);
}
@Tool(description = "查看日志")
public List<LogEntry> getLogs(
@ToolParam(name = "service") String service,
@ToolParam(name = "lines") int lines
) {
return logService.getTailLogs(service, lines);
}
@Tool(description = "检查服务健康状态")
public HealthStatus checkHealth(
@ToolParam(name = "service") String service
) {
return healthCheckService.check(service);
}
}
生态系统与工具
官方工具
- MCP Inspector - 调试和测试 MCP 服务器
- 网址: https://github.com/modelcontextprotocol/inspector
- 功能: 实时查看工具调用、测试 prompts、监控资源
- MCP CLI - 命令行工具
npm install -g @modelcontextprotocol/cli mcp test http://localhost:8080/sse
社区服务器
访问 mcp.so 浏览 1000+ 社区 MCP 服务器:
- 数据库: PostgreSQL, MySQL, MongoDB, Redis
- 云服务: AWS, Azure, GCP
- 开发工具: GitHub, GitLab, Jira
- 通信: Slack, Discord, Email
- 数据处理: Pandas, NumPy, Excel
客户端支持
| 客户端 | 支持程度 | 配置方式 |
|---|---|---|
| Claude Desktop | ✅ 完整支持 | JSON 配置文件 |
| Cursor | ✅ 完整支持 | .cursor/mcp.json |
| Cline (VS Code) | ✅ 完整支持 | 插件配置 |
| Continue | ✅ 完整支持 | config.json |
| Zed | ✅ 实验性支持 | 内置配置 |
常见问题
Q: MCP 与 OpenAI Function Calling 有什么区别?
A: MCP 是一个开放协议,不绑定特定 AI 提供商。Function Calling 是 OpenAI 特定的实现。MCP 支持更丰富的能力(Tools, Resources, Prompts),而 Function Calling 主要聚焦于函数调用。
Q: stdio 和 SSE 传输方式如何选择?
A:
- stdio: 适合本地命令行工具,零网络开销,启动快
- SSE: 适合 Web 服务,支持远程访问,易于部署和扩展
Q: MCP 服务器如何处理长时间运行的任务?
A: 建议使用异步模式:
@Tool(description = "异步任务")
public TaskId startAsyncTask(
@ToolParam(name = "input") String input
) {
// 返回任务 ID
return taskService.submit(input);
}
@Tool(description = "查询任务状态")
public TaskStatus getTaskStatus(
@ToolParam(name = "task_id") String taskId
) {
return taskService.getStatus(taskId);
}
Q: 如何调试 MCP 服务器?
A:
- 使用 MCP Inspector 工具
- 启用详细日志:
logging.level.org.springframework.ai.mcp=DEBUG - 使用 Postman 测试 SSE 端点
- 添加监控和追踪
Q: MCP 服务器的性能瓶颈在哪里?
A: 常见瓶颈:
- 数据库连接池不足
- 未使用缓存
- 同步阻塞操作
- 大数据传输
优化建议见”性能优化”章节。
未来展望
即将到来的特性
- 细粒度权限控制
- 基于工具的 ACL
- 资源级别的访问控制
- 审计日志
- 多模态支持
- 图像分析工具
- 音频处理
- 视频内容理解
- 增强的上下文管理
- 会话状态持久化
- 跨工具上下文共享
- 智能缓存策略
- 更好的可观测性
- 内置追踪和指标
- 性能分析工具
- 实时监控面板
技术演进方向
- 协议版本 2.0: 更高效的二进制传输
- 边缘计算: 在浏览器中运行 MCP 服务器
- 联邦学习: 跨服务器的知识共享
- AI Agent 框架: 与 LangChain, AutoGPT 等深度集成
生态发展
- 企业采用: 更多企业级 MCP 服务器
- 标准化: 行业标准和最佳实践
- 认证体系: MCP 服务器质量认证
- 市场生态: MCP 服务器市场和交易平台
参考资源
官方资源
- MCP 官方网站: https://modelcontextprotocol.io
- MCP 规范: https://spec.modelcontextprotocol.io
- MCP GitHub: https://github.com/modelcontextprotocol
- MCP 服务器目录: https://mcp.so/servers
Spring AI 相关
- Spring AI 文档: https://docs.spring.io/spring-ai/reference/
- MCP 集成指南: https://docs.spring.io/spring-ai/reference/api/mcp/
- 示例仓库: https://github.com/spring-projects/spring-ai-examples
- Spring AI MCP Server Starter: https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html
技术规范
- JSON-RPC 2.0: https://www.jsonrpc.org/specification
- Server-Sent Events: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
- OpenAPI 3.0: https://swagger.io/specification/
社区资源
- MCP Discord: https://discord.gg/modelcontextprotocol
- MCP Reddit: https://reddit.com/r/mcp
- Stack Overflow: 标签
model-context-protocol - YouTube 教程: 搜索 “MCP Tutorial”
相关项目
- Java SDK: https://github.com/modelcontextprotocol/java-sdk
- TypeScript SDK: https://github.com/modelcontextprotocol/typescript-sdk
- Python SDK: https://github.com/modelcontextprotocol/python-sdk
- MCP Inspector: https://github.com/modelcontextprotocol/inspector