使用Java实现MCP(模型上下文协议)完整指南
本文详细介绍了如何使用Java构建一个完整的MCP(Model Context Protocol)服务器和客户端,为大型语言模型与外部工具和数据源提供安全高效的连接方案。
什么是MCP?
MCP(Model Context Protocol)是由Anthropic提出的一种开放协议,旨在标准化大型语言模型与外部数据源、工具和服务之间的连接方式。它类似于传统软件开发中的API协议,但专门为AI应用场景设计。
MCP的核心优势
- 标准化: 提供统一的工具调用和数据访问接口
- 安全性: 通过明确的权限控制保护敏感数据
- 可扩展性: 支持自定义工具和资源的动态注册
- 跨平台: 协议无关具体编程语言和运行环境
项目架构设计
在开始编码之前,我们先规划整个项目的架构:
mcp-java-demo/
├── 传输层 (Transport)
│ ├── 标准输入输出 (Stdio)
│ └── HTTP/SSE (未来扩展)
├── 协议层 (Protocol)
│ ├── 消息格式 (JSON-RPC 2.0)
│ ├── 请求/响应模型
│ └── 错误处理
├── 服务层 (Server)
│ ├── 方法路由
│ ├── 工具管理
│ └── 资源管理
└── 客户端 (Client)
├── 连接管理
└── 异步调用
环境准备
技术栈要求
- Java 11+
- Maven 3.6+
- Jackson (JSON处理)
- SLF4J (日志)
项目初始化
首先创建Maven项目结构:
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mcp-java-demo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jackson.version>2.15.2</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
</dependencies>
</project>
核心协议实现
消息基类设计
/**
* MCP消息基类
* 遵循JSON-RPC 2.0规范
*/
public abstract class McpMessage {
private String jsonrpc = "2.0";
private String id;
// getters and setters
}
请求消息模型
/**
* MCP请求消息
* 用于客户端向服务器发起方法调用
*/
public class McpRequest extends McpMessage {
private String method;
private Map<String, Object> params;
// 示例:创建工具调用请求
public static McpRequest createToolCall(String toolName, Map<String, Object> arguments) {
McpRequest request = new McpRequest();
request.setMethod("tools/call");
request.setParams(Map.of(
"name", toolName,
"arguments", arguments
));
return request;
}
}
响应消息模型
/**
* MCP响应消息
* 包含调用结果或错误信息
*/
public class McpResponse extends McpMessage {
private Object result;
private McpError error;
public static class McpError {
private int code;
private String message;
// 常见错误码
public static final int PARSE_ERROR = -32700;
public static final int INVALID_REQUEST = -32600;
public static final int METHOD_NOT_FOUND = -32601;
public static final int INVALID_PARAMS = -32602;
public static final int INTERNAL_ERROR = -32603;
}
}
传输层实现
传输接口抽象
/**
* 传输层接口
* 支持多种通信方式
*/
public interface McpTransport {
void send(McpMessage message) throws IOException;
McpMessage receive() throws IOException;
void close() throws IOException;
boolean isConnected();
}
标准输入输出传输
/**
* 标准输入输出传输实现
* 适用于进程间通信
*/
public class StdioTransport implements McpTransport {
private final BufferedReader reader;
private final PrintWriter writer;
private final ObjectMapper objectMapper;
public StdioTransport() {
this(System.in, System.out);
}
@Override
public void send(McpMessage message) throws IOException {
String json = objectMapper.writeValueAsString(message);
writer.println(json);
}
@Override
public McpMessage receive() throws IOException {
String line = reader.readLine();
return line != null ? objectMapper.readValue(line, McpMessage.class) : null;
}
}
MCP服务器核心实现
服务器主类
/**
* MCP服务器核心实现
* 处理消息路由、方法调用和资源管理
*/
public class McpServer {
private final McpTransport transport;
private final Map<String, Function<Map<String, Object>, Object>> methods;
private boolean running = false;
public McpServer(McpTransport transport) {
this.transport = transport;
this.methods = new HashMap<>();
initializeStandardMethods();
registerDemoTools();
}
/**
* 初始化标准MCP方法
*/
private void initializeStandardMethods() {
registerMethod("initialize", this::handleInitialize);
registerMethod("tools/list", this::handleToolsList);
registerMethod("tools/call", this::handleToolsCall);
registerMethod("resources/list", this::handleResourcesList);
registerMethod("resources/read", this::handleResourcesRead);
}
/**
* 注册演示工具
*/
private void registerDemoTools() {
// 计算器工具
registerTool("calculate", Map.of(
"operation", Map.of("type", "string", "enum", List.of("add", "subtract", "multiply", "divide")),
"a", Map.of("type", "number"),
"b", Map.of("type", "number")
));
// 天气查询工具
registerTool("get_weather", Map.of(
"city", Map.of("type", "string")
));
// 网页搜索工具
registerTool("search_web", Map.of(
"query", Map.of("type", "string")
));
}
/**
* 启动服务器主循环
*/
public void start() throws IOException {
running = true;
sendInitialize();
while (running && transport.isConnected()) {
McpMessage message = transport.receive();
if (message == null) break;
handleMessage(message);
}
}
}
初始化处理
/**
* 处理客户端初始化请求
* 返回服务器能力和支持的工具列表
*/
private Object handleInitialize(Map<String, Object> params) {
@SuppressWarnings("unchecked")
Map<String, Object> clientCapabilities = (Map<String, Object>) params.get("capabilities");
Map<String, Object> serverCapabilities = new HashMap<>();
serverCapabilities.put("tools", Map.of("listChanged", true));
serverCapabilities.put("resources", Map.of("listChanged", true));
// 构建工具列表
List<Map<String, Object>> tools = new ArrayList<>();
tools.add(createToolSchema("calculate", "数学计算器",
"执行基本的数学运算", Map.of(
"operation", "运算类型: add, subtract, multiply, divide",
"a", "第一个数字",
"b", "第二个数字"
)));
tools.add(createToolSchema("get_weather", "天气查询",
"获取指定城市的天气信息", Map.of(
"city", "城市名称"
)));
return Map.of(
"protocolVersion", "2024-11-05",
"capabilities", serverCapabilities,
"serverInfo", Map.of(
"name", "Java MCP Demo Server",
"version", "1.0.0"
),
"tools", tools
);
}
工具调用实现
/**
* 处理工具调用请求
* 根据工具名称路由到具体的处理器
*/
private Object handleToolsCall(Map<String, Object> params) {
String name = (String) params.get("name");
@SuppressWarnings("unchecked")
Map<String, Object> arguments = (Map<String, Object>) params.get("arguments");
switch (name) {
case "calculate":
return handleCalculateTool(arguments);
case "get_weather":
return handleWeatherTool(arguments);
case "search_web":
return handleSearchTool(arguments);
default:
throw new RuntimeException("未知工具: " + name);
}
}
/**
* 计算器工具实现
*/
private Object handleCalculateTool(Map<String, Object> arguments) {
String operation = (String) arguments.get("operation");
double a = ((Number) arguments.get("a")).doubleValue();
double b = ((Number) arguments.get("b")).doubleValue();
double result;
switch (operation) {
case "add": result = a + b; break;
case "subtract": result = a - b; break;
case "multiply": result = a * b; break;
case "divide":
if (b == 0) throw new RuntimeException("除数不能为零");
result = a / b;
break;
default: throw new RuntimeException("不支持的操作: " + operation);
}
return Map.of(
"content", List.of(Map.of(
"type", "text",
"text", String.format("计算结果: %.2f %s %.2f = %.2f", a,
getOperationSymbol(operation), b, result)
))
);
}
/**
* 天气查询工具实现
*/
private Object handleWeatherTool(Map<String, Object> arguments) {
String city = (String) arguments.get("city");
// 模拟天气数据 - 实际应用中可接入真实天气API
String[] conditions = {"晴", "多云", "小雨", "阴", "晴朗"};
String condition = conditions[Math.abs(city.hashCode()) % conditions.length];
int temperature = 15 + (Math.abs(city.hashCode()) % 20);
int humidity = 30 + (Math.abs(city.hashCode()) % 50);
return Map.of(
"content", List.of(Map.of(
"type", "text",
"text", String.format(
"%s天气状况:\n- 天气: %s\n- 温度: %d°C\n- 湿度: %d%%\n- 更新时间: %s",
city, condition, temperature, humidity,
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
)
))
);
}
客户端实现
客户端主类
/**
* MCP客户端
* 提供便捷的API与MCP服务器交互
*/
public class McpClient {
private final McpServer server;
public McpClient() {
this(new StdioTransport());
}
public McpClient(McpTransport transport) {
this.server = new McpServer(transport);
}
/**
* 启动客户端
*/
public void start() throws IOException {
System.err.println("启动MCP客户端...");
server.start();
}
/**
* 调用远程工具
*/
public CompletableFuture<McpResponse> callTool(String toolName, Map<String, Object> arguments) {
Map<String, Object> params = new HashMap<>();
params.put("name", toolName);
params.put("arguments", arguments);
return server.sendRequest("tools/call", params);
}
/**
* 读取资源
*/
public CompletableFuture<McpResponse> readResource(String uri) {
return server.sendRequest("resources/read", Map.of("uri", uri));
}
}
演示运行器
/**
* MCP演示运行器
* 展示如何使用MCP客户端调用各种工具
*/
public class McpDemoRunner {
public static void main(String[] args) {
try {
System.out.println("🚀 启动MCP Java演示程序\n");
McpServer server = new McpServer(new StdioTransport());
// 在后台启动服务器
Thread serverThread = new Thread(() -> {
try {
server.start();
} catch (Exception e) {
System.err.println("服务器错误: " + e.getMessage());
}
});
serverThread.setDaemon(true);
serverThread.start();
// 等待服务器初始化
Thread.sleep(2000);
// 运行演示
runDemo(server);
} catch (Exception e) {
System.err.println("演示程序错误: " + e.getMessage());
e.printStackTrace();
}
}
private static void runDemo(McpServer server) throws Exception {
System.out.println("📋 开始测试MCP工具调用\n");
// 1. 测试计算器工具
testCalculator(server);
// 2. 测试天气查询工具
testWeather(server);
// 3. 测试网页搜索工具
testWebSearch(server);
// 4. 测试资源读取
testResourceReading(server);
System.out.println("\n✅ 所有测试完成!");
}
private static void testCalculator(McpServer server) throws Exception {
System.out.println("1. 🧮 测试计算器工具");
Map<String, Object> args = Map.of(
"operation", "multiply",
"a", 12.5,
"b", 4.2
);
CompletableFuture<McpResponse> future = server.sendRequest("tools/call",
Map.of("name", "calculate", "arguments", args));
McpResponse response = future.get(5, TimeUnit.SECONDS);
if (response.getError() == null) {
@SuppressWarnings("unchecked")
Map<String, Object> result = (Map<String, Object>) response.getResult();
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) result.get("content");
System.out.println(" 结果: " + content.get(0).get("text"));
} else {
System.out.println(" 错误: " + response.getError().getMessage());
}
}
private static void testWeather(McpServer server) throws Exception {
System.out.println("2. 🌤️ 测试天气查询工具");
Map<String, Object> args = Map.of("city", "上海");
CompletableFuture<McpResponse> future = server.sendRequest("tools/call",
Map.of("name", "get_weather", "arguments", args));
McpResponse response = future.get(5, TimeUnit.SECONDS);
if (response.getError() == null) {
@SuppressWarnings("unchecked")
Map<String, Object> result = (Map<String, Object>) response.getResult();
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) result.get("content");
System.out.println(" 结果: " + content.get(0).get("text"));
} else {
System.out.println(" 错误: " + response.getError().getMessage());
}
}
// 其他测试方法...
}
构建和运行
使用Maven构建
# 编译项目
mvn clean compile
# 运行演示
mvn exec:java -Dexec.mainClass="com.example.mcp.McpDemoRunner"
# 打包可执行JAR
mvn clean package
创建启动脚本
#!/bin/bash
# run-demo.sh
echo "构建MCP Java演示程序..."
mvn clean compile
echo "运行演示..."
mvn exec:java -Dexec.mainClass="com.example.mcp.McpDemoRunner"
echo "演示完成!"
实际应用场景
场景1: AI助手集成
// 将MCP服务器集成到AI助手应用中
public class AiAssistantIntegration {
private McpClient mcpClient;
public AiAssistantIntegration() {
this.mcpClient = new McpClient();
}
public String processUserQuery(String query) {
// 分析用户意图并调用相应的MCP工具
if (query.contains("天气")) {
String city = extractCity(query);
return getWeatherInfo(city);
} else if (query.contains("计算")) {
return performCalculation(query);
}
return "抱歉,我暂时无法处理这个请求";
}
private String getWeatherInfo(String city) {
try {
CompletableFuture<McpResponse> future = mcpClient.callTool("get_weather",
Map.of("city", city));
McpResponse response = future.get(10, TimeUnit.SECONDS);
// 解析并格式化响应
return formatWeatherResponse(response);
} catch (Exception e) {
return "获取天气信息失败: " + e.getMessage();
}
}
}
场景2: 数据管道集成
// 使用MCP构建数据处理管道
public class DataPipeline {
private McpServer mcpServer;
public void setupDataTools() {
// 注册数据处理工具
mcpServer.registerMethod("data/transform", this::handleDataTransform);
mcpServer.registerMethod("data/validate", this::handleDataValidation);
mcpServer.registerMethod("data/export", this::handleDataExport);
}
private Object handleDataTransform(Map<String, Object> params) {
// 实现数据转换逻辑
String data = (String) params.get("data");
String format = (String) params.get("format");
// 执行转换操作
String transformed = transformData(data, format);
return Map.of(
"content", List.of(Map.of(
"type", "text",
"text", transformed
))
);
}
}
性能优化建议
1. 连接池管理
/**
* MCP连接池
* 管理多个MCP服务器连接
*/
public class McpConnectionPool {
private final List<McpClient> connections;
private final int poolSize;
public McpConnectionPool(int poolSize) {
this.poolSize = poolSize;
this.connections = new ArrayList<>();
initializeConnections();
}
public McpClient getConnection() {
// 实现连接负载均衡
return connections.get(ThreadLocalRandom.current().nextInt(poolSize));
}
}
2. 异步批处理
/**
* 批量工具调用处理器
* 提高多个工具调用的效率
*/
public class BatchToolProcessor {
private final McpClient client;
private final ExecutorService executor;
public CompletableFuture<List<McpResponse>> processBatch(
List<Map<String, Object>> toolCalls) {
List<CompletableFuture<McpResponse>> futures = toolCalls.stream()
.map(call -> client.callTool(
(String) call.get("name"),
(Map<String, Object>) call.get("arguments")))
.collect(Collectors.toList());
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
}
}
总结
通过本文的完整实现,我们构建了一个功能齐全的Java MCP框架,具备以下特点:
核心特性
- ✅ 完整的JSON-RPC 2.0协议支持
- ✅ 标准输入输出传输层
- ✅ 动态工具注册和调用
- ✅ 资源管理和访问
- ✅ 异步请求处理
- ✅ 完善的错误处理
扩展能力
- 🔧 支持自定义工具开发
- 🔧 可扩展的传输层
- 🔧 灵活的配置管理
- 🔧 性能监控和优化
生产就绪建议
要让这个Demo达到生产级别,还需要考虑:
- 安全性: 添加认证授权机制
- 监控: 集成指标收集和日志追踪
- 容错: 实现重试机制和熔断器
- 配置化: 支持外部配置文件
- 文档: 提供完整的API文档
这个Java MCP实现为构建企业级AI应用提供了坚实的基础框架,开发者可以根据具体业务需求进行进一步的定制和扩展。
816

被折叠的 条评论
为什么被折叠?



