# mcp-demo **Repository Path**: zidafone/mcp-demo ## Basic Information - **Project Name**: mcp-demo - **Description**: 使用AI技术的网站 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-04-03 - **Last Updated**: 2025-04-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MCP 官方 Java SDK 示例 MCP(Model Context Protocol)是一个强大的协议,用于模型与上下文的交互。本文将通过一个完整的 Java 示例来展示如何使用 MCP 官方 SDK 构建客户端和服务器应用程序。 ## 项目概述 我们的示例项目包含以下主要代码文件: 1. `MyServer.java` - MCP 服务器实现 2. `MyClient.java` - MCP 客户端实现 3. `pom.xml` - Maven 项目配置 4. `logback.xml` - 日志配置 ## 环境配置 项目的 Maven 依赖非常简单: ```xml io.modelcontextprotocol.sdk mcp 0.8.1 ch.qos.logback logback-classic 1.4.11 ``` 项目使用 Java 17,并配置了必要的插件以确保 UTF-8 编码支持和依赖打包。 ## MCP 服务器实现 `MyServer.java` 展示了如何创建一个基本的 MCP 服务器,提供工具、资源和提示功能。 ### 服务器初始化 ```java // 设置系统默认编码为UTF-8,确保正确处理中文字符 System.setProperty("file.encoding", "UTF-8"); // 创建基于标准输入输出的传输提供者,用于服务器通信 StdioServerTransportProvider transportProvider = new StdioServerTransportProvider(new ObjectMapper()); // 创建并配置MCP同步服务器 McpSyncServer syncServer = McpServer.sync(transportProvider) .serverInfo("my-server", "1.0.0") // 设置服务器标识和版本 .capabilities(ServerCapabilities.builder() .resources(true, true) // 启用资源读写功能 .tools(true) // 启用工具功能 .prompts(true) // 启用提示功能 .logging() // 启用日志功能 .build()) .build(); ``` ### 添加计算器工具 服务器实现了一个简单的计算器工具,支持加减乘除四种基本运算: ```java private static void addCalculatorTool(McpSyncServer syncServer) throws JsonProcessingException { // 创建工具的JSON Schema定义 String schema = createSchema(); // 创建工具规范,包含工具定义和处理逻辑 McpServerFeatures.SyncToolSpecification syncToolSpecification = new McpServerFeatures.SyncToolSpecification( new Tool("calculator", "Basic calculator", schema), (exchange, arguments) -> { List result = new ArrayList<>(); try { // 从参数中提取操作类型和操作数 String operation = (String) arguments.get("operation"); double a = ((Number) arguments.get("a")).doubleValue(); double b = ((Number) arguments.get("b")).doubleValue(); // 根据操作类型执行相应的计算 double calculationResult = 0; switch (operation) { case "add": calculationResult = a + b; break; // ... 其他操作 ... } result.add(new TextContent("计算结果: " + calculationResult)); } catch (Exception e) { // 处理计算过程中的异常 result.add(new TextContent("计算错误: " + e.getMessage())); return new CallToolResult(result, true); } return new CallToolResult(result, false); }); syncServer.addTool(syncToolSpecification); } ``` ### 添加资源和提示 服务器还提供了资源访问和提示生成功能: ```java private static void addExampleResource(McpSyncServer syncServer) { // 创建资源规范,包含资源定义和访问处理逻辑 McpServerFeatures.SyncResourceSpecification syncResourceSpecification = new McpServerFeatures.SyncResourceSpecification( // 定义资源的基本信息:URI、名称、描述和内容类型 new Resource("custom://resource", "示例资源", "这是一个示例资源", "text/plain", null), (exchange, request) -> { // 处理资源读取请求 List contents = new ArrayList<>(); String content = "这是资源内容示例"; contents.add(new TextResourceContents("custom://resource/content", "text/plain", content)); return new ReadResourceResult(contents); }); syncServer.addResource(syncResourceSpecification); } ``` ```java private static void addGreetingPrompt(McpSyncServer syncServer) { // 创建提示规范,包含提示定义和处理逻辑 McpServerFeatures.SyncPromptSpecification syncPromptSpecification = new McpServerFeatures.SyncPromptSpecification( // 定义提示的基本信息和参数 new Prompt("greeting", "生成问候语", new ArrayList<>(Arrays.asList( new PromptArgument("name", "用户名称", true)))), (exchange, request) -> { // 处理提示请求 List messages = new ArrayList<>(); // 处理用户名称,确保正确处理UTF-8编码 String name; try { name = new String(((String) request.arguments().get("name")).getBytes("UTF-8"), StandardCharsets.UTF_8); } catch (UnsupportedEncodingException e) { name = (String) request.arguments().get("name"); } if (name == null || name.isEmpty()) { name = "访客"; } // 创建对话消息序列 // ... return new GetPromptResult("为用户" + name + "生成的问候语", messages); }); syncServer.addPrompt(syncPromptSpecification); } ``` ## MCP 客户端实现 `MyClient.java` 展示了如何创建 MCP 客户端并与服务器交互。 ### 客户端初始化 ```java private static McpSyncClient initializeClient() { // 创建客户端传输层 ServerParameters params = ServerParameters.builder("java") .args("-Dfile.encoding=UTF-8", "-jar", "C:\\_Data\\git-project\\website-ai\\target\\ai-demo-0.0.1-SNAPSHOT.jar") .build(); // ... 其他参数配置 ... McpClientTransport transport = new StdioClientTransport(params); // 创建同步客户端 McpSyncClient client = io.modelcontextprotocol.client.McpClient.sync(transport) .requestTimeout(Duration.ofSeconds(1000)) .capabilities(ClientCapabilities.builder() .roots(true) // 启用根目录支持 .sampling() // 启用采样支持 .build()) .sampling(request -> { // 简单的采样处理器实现 System.out.println("收到采样请求: " + request); return CreateMessageResult.builder() .role(Role.ASSISTANT) .message("这是一个示例响应") .build(); }) .build(); // 初始化连接 System.out.println("正在初始化MCP客户端..."); client.initialize(); System.out.println("MCP客户端初始化完成"); return client; } ``` ### 与服务器交互 客户端实现了多种与服务器交互的方法: #### 列出和调用工具 ```java private static void listTools(McpSyncClient client) { System.out.println("\n获取可用工具列表:"); ListToolsResult tools = client.listTools(); tools.tools().forEach(tool -> { System.out.println("工具名称: " + tool.name()); System.out.println("工具描述: " + tool.description()); System.out.println("工具Schema: " + tool.inputSchema()); System.out.println("-------------------"); }); } private static void callCalculatorTool(McpSyncClient client) { System.out.println("\n调用计算器工具:"); CallToolResult calcResult = client.callTool( new CallToolRequest("calculator", Map.of("operation", "add", "a", 2, "b", 3)) ); System.out.println("计算结果: "); calcResult.content().forEach(content -> { if (content instanceof TextContent) { System.out.println(((TextContent) content).text()); } }); } ``` #### 访问资源 ```java private static void listResources(McpSyncClient client) { System.out.println("\n获取可用资源列表:"); ListResourcesResult resources = client.listResources(); resources.resources().forEach(resource -> { System.out.println("资源URI: " + resource.uri()); System.out.println("资源名称: " + resource.name()); System.out.println("资源描述: " + resource.description()); System.out.println("资源类型: " + resource.mimeType()); System.out.println("-------------------"); }); } private static void readResource(McpSyncClient client) { ListResourcesResult resources = client.listResources(); if (!resources.resources().isEmpty()) { Resource firstResource = resources.resources().get(0); System.out.println("\n读取资源: " + firstResource.uri()); ReadResourceResult resourceResult = client.readResource( new ReadResourceRequest(firstResource.uri()) ); System.out.println("资源内容: "); resourceResult.contents().forEach(content -> { if (content instanceof TextResourceContents) { System.out.println(((TextResourceContents) content).text()); } }); } } ``` #### 使用提示 ```java private static void listPrompts(McpSyncClient client) { System.out.println("\n获取可用提示列表:"); ListPromptsResult prompts = client.listPrompts(); prompts.prompts().forEach(prompt -> { System.out.println("提示名称: " + prompt.name()); System.out.println("提示描述: " + prompt.description()); System.out.println("提示参数: "); prompt.arguments().forEach(arg -> { System.out.println(" - " + arg.name() + (arg.required() ? " (必需)" : " (可选)") + ": " + arg.description()); }); System.out.println("-------------------"); }); } private static void useGreetingPrompt(McpSyncClient client) { if (client.listPrompts().prompts().stream().anyMatch(prompt -> prompt.name().equals("greeting"))) { System.out.println("\n使用问候提示:"); GetPromptResult promptResult = client.getPrompt( new GetPromptRequest("greeting", Map.of("name", "张三")) ); System.out.println("提示结果: " + promptResult.description()); System.out.println("消息: "); promptResult.messages().forEach(message -> { System.out.println("角色: " + message.role()); if (message.content() instanceof TextContent) { System.out.println("内容: " + ((TextContent) message.content()).text()); } System.out.println("-------------------"); }); } } ``` #### 根目录管理 ```java private static void addRootDirectory(McpSyncClient client) { System.out.println("\n添加根目录:"); client.addRoot(new Root("file:///tmp", "临时目录")); System.out.println("根目录已添加"); // 通知服务器根目录列表已更改 client.rootsListChangedNotification(); System.out.println("已通知服务器根目录列表变更"); } ``` ## 运行项目 要运行此示例项目,首先需要编译并打包: ```bash mvn clean package ``` 然后可以分别启动服务器和客户端: ```bash # 启动服务器 java -jar target/ai-demo-0.0.1-SNAPSHOT.jar # 在另一个终端启动客户端 java -cp target/ai-demo-0.0.1-SNAPSHOT.jar com.qidafang.demo.mcp.MyClient ``` ## 总结 通过这个示例,我们展示了如何使用 MCP Java SDK 构建功能完整的客户端和服务器应用程序。MCP 协议提供了丰富的功能,包括: 1. 工具调用 - 允许客户端调用服务器提供的工具 2. 资源访问 - 提供对服务器资源的读取 3. 提示生成 - 支持参数化的提示模板 4. 根目录管理 - 允许客户端管理文件系统访问 这个示例可以作为开发更复杂 MCP 应用的起点,您可以根据自己的需求扩展功能。 希望这个示例能帮助您更好地理解和使用 MCP Java SDK!