引言
MCP(Model Context Protocol,模型上下文协议)是 Anthropic 推出的开放协议,旨在标准化 AI 模型与外部工具、数据源的集成方式。本文将深入解析 MCP 协议的原理和实战应用。
什么是 MCP
MCP 定义了一套标准化的接口规范,使得 AI 模型能够:
- 发现和调用外部工具
- 访问结构化数据
- 执行特定领域的操作
核心概念
1 2 3 4
| ┌─────────────┐ MCP Protocol ┌─────────────┐ │ AI Model │ ◄──────────────────► │ MCP Tool │ │ (Client) │ │ (Server) │ └─────────────┘ └─────────────┘
|
MCP 协议架构
1. 协议分层
1 2 3
| 应用层:Tool Definition、Resource Access 传输层:JSON-RPC 2.0 传输层:Stdio / SSE / HTTP
|
2. 核心组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public interface MCPTool {
String getName();
String getDescription();
String getInputSchema();
ToolResult execute(Map<String, Object> arguments); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| @Component public class WeatherTool implements MCPTool { @Autowired private WeatherService weatherService; @Override public String getName() { return "get_weather"; } @Override public String getDescription() { return "获取指定城市的天气信息"; } @Override public String getInputSchema() { return """ { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" }, "date": { "type": "string", "description": "日期,格式:YYYY-MM-DD" } }, "required": ["city"] } """; } @Override public ToolResult execute(Map<String, Object> arguments) { String city = (String) arguments.get("city"); String date = (String) arguments.getOrDefault("date", "today"); try { WeatherInfo weather = weatherService.query(city, date); return ToolResult.success(weather.toString()); } catch (Exception e) { return ToolResult.error("查询天气失败: " + e.getMessage()); } } }
|
SpringAI 集成 MCP
1. 依赖配置
1 2 3 4
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp</artifactId> </dependency>
|
2. MCP Server 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Configuration public class MCPConfig { @Bean public MCPServer mcpServer(List<MCPTool> tools) { MCPServer server = new MCPServer(); for (MCPTool tool : tools) { server.registerTool(tool); } return server; } @Bean public McpSyncServer mcpSyncServer(MCPServer server) { StdioServerTransport transport = new StdioServerTransport(); return McpSyncServer.create(server, transport); } }
|
3. 客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| @Service public class MCPClientService { @Autowired private ChatModel chatModel; public String chatWithTools(String userMessage) { List<ToolDefinition> tools = Arrays.asList( ToolDefinition.builder() .name("get_weather") .description("获取指定城市的天气信息") .inputSchema(""" { "type": "object", "properties": { "city": {"type": "string"}, "date": {"type": "string"} }, "required": ["city"] } """) .build(), ToolDefinition.builder() .name("search_database") .description("查询数据库") .inputSchema(""" { "type": "object", "properties": { "sql": {"type": "string"} }, "required": ["sql"] } """) .build() ); Prompt prompt = new Prompt( userMessage, ToolCallingChatOptions.builder() .toolDefinitions(tools) .build() ); ChatResponse response = chatModel.call(prompt); if (response.hasToolCalls()) { List<ToolCall> toolCalls = response.getToolCalls(); return executeToolCalls(toolCalls); } return response.getResult().getOutput().getContent(); } }
|
实际应用场景
1. 智能运维助手
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Component public class DevOpsAssistant { @Autowired private MCPClient mcpClient;
public String analyzeError(String errorLog) { String prompt = """ 分析以下系统错误日志,并提供解决方案: %s 你可以使用以下工具: 1. search_logs - 搜索相关日志 2. query_metrics - 查询系统指标 3. check_config - 检查配置文件 """.formatted(errorLog); return mcpClient.chat(prompt); } }
|
2. 数据库查询助手
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @Component public class DatabaseQueryTool implements MCPTool { @Autowired private JdbcTemplate jdbcTemplate; @Override public String getName() { return "execute_query"; } @Override public String getDescription() { return "执行 SQL 查询并返回结果"; } @Override public ToolResult execute(Map<String, Object> arguments) { String sql = (String) arguments.get("sql"); if (!isSafeSQL(sql)) { return ToolResult.error("不安全的 SQL 语句"); } try { List<Map<String, Object>> results = jdbcTemplate.queryForList(sql); return ToolResult.success(JSON.toJSONString(results)); } catch (Exception e) { return ToolResult.error("查询失败: " + e.getMessage()); } } private boolean isSafeSQL(String sql) { String lowerSQL = sql.toLowerCase(); return !lowerSQL.contains("drop") && !lowerSQL.contains("delete") && !lowerSQL.contains("update") && lowerSQL.trim().startsWith("select"); } }
|
MCP 与 Function Calling 对比
| 特性 |
MCP |
Function Calling |
| 标准化 |
是,开放协议 |
各厂商独立实现 |
| 工具发现 |
支持动态发现 |
需预定义 |
| 传输方式 |
Stdio/SSE/HTTP |
HTTP |
| 生态系统 |
正在发展 |
已成熟 |
| 跨平台 |
支持 |
依赖厂商 |
最佳实践
1. 工具设计原则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
public class ToolBestPractices { public ToolResult execute(Map<String, Object> args) { if (!args.containsKey("required_param")) { return ToolResult.error("缺少必需参数: required_param"); } if (!(args.get("count") instanceof Integer)) { return ToolResult.error("count 必须是整数"); } } }
|
2. 安全性考虑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Component public class SecureMCPExecutor {
public ToolResult executeWithAuth(MCPTool tool, Map<String, Object> args, UserContext user) { if (!hasPermission(user, tool.getName())) { return ToolResult.error("无权使用该工具"); } Map<String, Object> sanitizedArgs = sanitizeArgs(args); return tool.execute(sanitizedArgs); } private Map<String, Object> sanitizeArgs(Map<String, Object> args) { return args; } }
|
总结
MCP 协议为 AI 工具集成提供了标准化方案,主要优势:
- 标准化接口:统一工具定义和调用方式
- 动态发现:支持运行时工具发现
- 跨平台:不依赖特定 AI 厂商
- 可扩展:易于添加新工具
随着生态的发展,MCP 有望成为 AI 工具集成的标准协议。
本文基于 SpringAI MCP 模块实践,探索 AI 工具标准化集成方案