使用Java实现MCP(模型上下文协议)完整指南

该文章已生成可运行项目,

使用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达到生产级别,还需要考虑:

  1. 安全性: 添加认证授权机制
  2. 监控: 集成指标收集和日志追踪
  3. 容错: 实现重试机制和熔断器
  4. 配置化: 支持外部配置文件
  5. 文档: 提供完整的API文档

这个Java MCP实现为构建企业级AI应用提供了坚实的基础框架,开发者可以根据具体业务需求进行进一步的定制和扩展。

本文章已经生成可运行项目
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值