从零搭建工业级Java AgentClaude Code架构拆解12节完整教程引言随着AI Agent技术的爆发越来越多开发者想从0到1掌握Agent的设计与落地但市面上大多教程停留在“概念讲解”缺乏与真实项目结合的实操指导。本文基于Claude CodeJava版项目拆解12节渐进式课程从Agent基础概念到工业级工程化落地每一节都对应真实项目代码看完就能上手搭建自己的AI Agent适合Java开发者、AI工程爱好者学习。第09课MCP协议Model Context Protocol全解析——官方标准工具扩展协议实现一、前言上一节课我们完成了Agent异常处理与容错机制的设计通过“分层捕获责任链处理智能重试断点续跑”的体系解决了工具调用失败、LLM响应异常、系统宕机等核心问题确保了Agent运行的稳定性和任务连续性。在此基础上工业级Java Agent要实现工具扩展、跨服务协同核心依赖MCP协议——即Model Context Protocol模型上下文协议它是官方标准的Agent工具扩展协议负责规范Agent与工具、Agent与远程服务之间的通信规则是Agent实现工具动态扩展、本地/远程服务对接的核心基础也是本节课的唯一核心内容。很多开发者在搭建Agent时容易混淆MCP协议的定位误将其作为普通通信协议使用忽略其“工具扩展标准化”的核心价值导致工具对接混乱、远程服务无法兼容。本节课我们将聚焦MCP协议本身从协议定义、核心特性、StdIO通信方式、工具动态发现、本地/远程服务对接到.mcp.json配置文件加载逻辑结合核心源码逐一拆解教你从零实现符合官方标准的MCP协议让Agent具备标准化工具扩展和跨服务通信能力。核心结论MCPModel Context Protocol协议是Agent工具扩展的官方标准协议核心解决“工具标准化对接、资源动态发现、本地/远程服务统一通信”三大问题其StdIO通信方式保证轻量性.mcp.json配置保证灵活性是工业级Agent实现工具扩展的核心支撑。二、MCP协议核心定义与核心特性1. 协议定义MCPModel Context Protocol——模型上下文协议是AI Agent领域官方标准化的工具扩展协议定义了Agent与工具本地工具、远程工具、Agent与MCP服务之间的通信格式、交互流程和配置规范核心目标是实现“工具即插即用、服务无缝对接”让不同开发者开发的工具、不同部署方式的服务都能按照统一标准与Agent协同工作。与普通通信协议如HTTP、TCP不同MCP协议专门针对Agent场景设计内置模型上下文传递、工具元信息交互、请求容错等特性无需额外封装即可适配Agent与工具的交互需求是Agent工具扩展的“通用接口”。2. 核心特性官方标准规范1标准化工具扩展定义统一的工具注册、调用、响应格式任何工具只要遵循MCP协议规范即可无缝接入Agent无需修改Agent核心代码2轻量StdIO通信默认采用StdIO标准输入输出作为核心通信方式无需额外依赖网络组件轻量高效同时支持兼容TCP/UDP通信适配不同部署场景3动态发现工具与资源支持Agent启动时自动扫描本地工具、远程MCP服务中的工具资源自动注册工具元信息实现工具“即插即用”4本地/远程双模式对接支持本地MCP服务单机部署和远程MCP服务集群部署无缝对接Agent可根据配置自动切换对接模式适配不同部署需求5配置驱动通过.mcp.json配置文件统一管理MCP协议参数、工具信息、服务地址等支持动态加载配置无需重启Agent即可更新配置。三、MCP协议核心实现源码解析官方规范本节课围绕MCP协议核心要点结合Claude Code真实源码逐一实现官方标准的MCP协议功能重点覆盖StdIO通信、工具动态发现、本地/远程对接、.mcp.json配置加载所有代码可直接复制运行贴合官方规范。一核心准备MCP协议核心类设计遵循官方标准MCP协议核心类分为3类配置加载类负责.mcp.json加载、通信类负责StdIO/TCP通信、管理类负责工具发现、服务对接核心类结构如下1. McpConfigLoader.java负责加载.mcp.json配置文件解析协议参数、服务地址、工具信息等2. McpClient.java负责MCP协议通信实现重点实现StdIO通信方式兼容本地/远程服务对接3. McpManager.java负责MCP服务管理、工具动态发现、请求分发是MCP协议的核心调度类。二.mcp.json配置文件加载逻辑官方标准格式.mcp.json是MCP协议的官方标准配置文件用于统一管理协议参数、本地/远程服务配置、工具扫描规则等加载逻辑核心是“读取配置→解析参数→缓存配置→支持动态刷新”完全遵循官方规范。1. 官方标准.mcp.json配置格式// .mcp.json 官方标准格式放在项目根目录下 { protocol: { version: 1.0.0, // MCP协议版本官方标准版本 communicationMode: STDIO, // 通信方式STDIO默认/ TCP / UDP timeout: 3000, // 通信超时时间毫秒 retryCount: 3, // 重试次数 retryInterval: 1000 // 重试间隔毫秒 }, localService: { enable: true, // 是否启用本地MCP服务 toolScanPath: com.claudecode.mcp.tools, // 本地工具扫描路径 stdioBufferSize: 1024 // StdIO通信缓冲区大小 }, remoteService: { enable: false, // 是否启用远程MCP服务 host: 192.168.1.100, // 远程MCP服务地址 port: 8888, // 远程MCP服务端口 heartbeatInterval: 5000 // 心跳检测间隔毫秒 }, tools: [ // 预注册工具可选自动扫描的工具会自动添加到此处 { toolId: file-operation-tool, toolName: 文件操作工具, toolClass: com.claudecode.mcp.tools.FileOperationTool, description: 用于文件的创建、读取、修改、删除操作 } ] }2. McpConfigLoader.java源码实现加载.mcp.json负责读取.mcp.json配置文件解析协议参数、本地/远程服务配置、工具信息缓存配置并支持动态刷新完全遵循官方配置加载规范。package com.claudecode.mcp; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; /** * MCP协议配置加载器遵循官方标准负责加载.mcp.json配置文件 */ Slf4j Component public class McpConfigLoader { // 配置文件路径官方默认路径项目根目录下的.mcp.json private static final String MCP_CONFIG_PATH ./.mcp.json; // MCP协议配置缓存全局唯一 private McpConfig mcpConfig; /** * 初始化加载.mcp.json配置项目启动时执行 */ PostConstruct public void loadMcpConfig() { try (FileInputStream fis new FileInputStream(new File(MCP_CONFIG_PATH))) { // 读取配置文件字节码 byte[] buffer new byte[fis.available()]; fis.read(buffer); String configContent new String(buffer, StandardCharsets.UTF_8); // 解析JSON配置映射到McpConfig实体类 mcpConfig JSON.parseObject(configContent, McpConfig.class); log.info(MCP协议配置加载完成遵循官方标准配置信息{}, JSON.toJSONString(mcpConfig, true)); // 校验配置合法性官方标准校验 validateConfig(); } catch (IOException e) { log.error(MCP协议配置文件.mcp.json未找到或读取失败使用官方默认配置, e); loadDefaultConfig(); } catch (Exception e) { log.error(MCP协议配置解析失败使用官方默认配置, e); loadDefaultConfig(); } } /** * 校验配置合法性遵循官方标准 */ private void validateConfig() { // 校验协议版本官方当前支持1.0.0版本 if (!1.0.0.equals(mcpConfig.getProtocol().getVersion())) { throw new RuntimeException(MCP协议版本不兼容官方当前支持1.0.0版本); } // 校验通信方式仅支持STDIO、TCP、UDP String communicationMode mcpConfig.getProtocol().getCommunicationMode(); if (!STDIO.equals(communicationMode) !TCP.equals(communicationMode) !UDP.equals(communicationMode)) { throw new RuntimeException(MCP协议通信方式不合法仅支持STDIO、TCP、UDP); } // 校验本地/远程服务不能同时关闭 if (!mcpConfig.getLocalService().isEnable() !mcpConfig.getRemoteService().isEnable()) { throw new RuntimeException(MCP协议本地服务和远程服务不能同时关闭至少启用一个); } } /** * 加载官方默认配置配置文件加载失败时备用 */ private void loadDefaultConfig() { mcpConfig new McpConfig(); // 协议默认配置 McpProtocolConfig protocolConfig new McpProtocolConfig(); protocolConfig.setVersion(1.0.0); protocolConfig.setCommunicationMode(STDIO); protocolConfig.setTimeout(3000); protocolConfig.setRetryCount(3); protocolConfig.setRetryInterval(1000); mcpConfig.setProtocol(protocolConfig); // 本地服务默认配置默认启用 McpLocalServiceConfig localServiceConfig new McpLocalServiceConfig(); localServiceConfig.setEnable(true); localServiceConfig.setToolScanPath(com.claudecode.mcp.tools); localServiceConfig.setStdioBufferSize(1024); mcpConfig.setLocalService(localServiceConfig); // 远程服务默认配置默认关闭 McpRemoteServiceConfig remoteServiceConfig new McpRemoteServiceConfig(); remoteServiceConfig.setEnable(false); remoteServiceConfig.setHost(192.168.1.100); remoteServiceConfig.setPort(8888); remoteServiceConfig.setHeartbeatInterval(5000); mcpConfig.setRemoteService(remoteServiceConfig); // 默认工具配置空列表自动扫描补充 mcpConfig.setTools(new ArrayList()); log.info(MCP协议加载官方默认配置完成); } /** * 动态刷新配置无需重启Agent */ public void refreshConfig() { loadMcpConfig(); } /** * 获取MCP协议配置全局唯一 */ public McpConfig getMcpConfig() { return mcpConfig; } // 以下是.mcp.json配置对应的实体类遵循官方标准字段 Data public static class McpConfig { private McpProtocolConfig protocol; // 协议核心配置 private McpLocalServiceConfig localService; // 本地MCP服务配置 private McpRemoteServiceConfig remoteService; // 远程MCP服务配置 private ListMcpToolConfig tools; // 工具配置列表 } Data public static class McpProtocolConfig { private String version; // 协议版本 private String communicationMode; // 通信方式 private int timeout; // 超时时间毫秒 private int retryCount; // 重试次数 private long retryInterval; // 重试间隔毫秒 } Data public static class McpLocalServiceConfig { private boolean enable; // 是否启用本地服务 private String toolScanPath; // 工具扫描路径 private int stdioBufferSize; // StdIO缓冲区大小 } Data public static class McpRemoteServiceConfig { private boolean enable; // 是否启用远程服务 private String host; // 远程服务地址 private int port; // 远程服务端口 private long heartbeatInterval; // 心跳间隔毫秒 } Data public static class McpToolConfig { private String toolId; // 工具唯一ID private String toolName; // 工具名称 private String toolClass; // 工具全类名 private String description; // 工具描述 } }三StdIO通信方式实现官方默认通信方式StdIO标准输入输出是MCP协议的官方默认通信方式轻量、无依赖无需额外启动网络服务核心原理是“通过System.in读取请求、System.out写入响应”适用于本地工具对接、轻量级部署场景完全遵循官方通信规范。以下是McpClient.java源码重点实现StdIO通信的请求发送、响应接收同时兼容本地/远程服务对接逻辑。package com.claudecode.mcp; import com.alibaba.fastjson.JSONObject; import com.claudecode.exception.RetryUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; /** * MCP协议客户端遵循官方标准实现StdIO通信方式支持本地/远程MCP服务对接 */ Slf4j Component public class McpClient { Autowired private McpConfigLoader mcpConfigLoader; // StdIO输入流读取响应 private BufferedReader stdioReader; // StdIO输出流发送请求 private OutputStreamWriter stdioWriter; /** * 初始化StdIO流懒加载首次通信时初始化 */ private void initStdioStream() { if (stdioReader null || stdioWriter null) { stdioReader new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); stdioWriter new OutputStreamWriter(System.out, StandardCharsets.UTF_8); log.info(MCP协议StdIO通信流初始化完成官方默认通信方式); } } /** * 发送MCP请求统一入口自动适配StdIO/TCP通信方式 * param request 请求内容遵循官方MCP请求格式JSON字符串 * return 响应内容官方MCP响应格式JSON字符串 */ public String sendRequest(String request) { McpConfigLoader.McpProtocolConfig protocolConfig mcpConfigLoader.getMcpConfig().getProtocol(); // 根据配置的通信方式选择对应的通信逻辑 if (STDIO.equals(protocolConfig.getCommunicationMode())) { // 优先使用StdIO通信官方默认 return sendStdioRequest(request); } else { // TCP/UDP通信适配远程服务后续扩展 return sendTcpRequest(request); } } /** * StdIO通信方式发送请求并接收响应官方标准实现 * 通信格式请求长度\n请求内容\n → 响应长度\n响应内容\n避免粘包 */ private String sendStdioRequest(String request) { // 利用重试工具类实现请求重试遵循协议配置的重试规则 McpConfigLoader.McpProtocolConfig protocolConfig mcpConfigLoader.getMcpConfig().getProtocol(); return RetryUtil.retry( () - doSendStdioRequest(request), protocolConfig.getRetryCount(), protocolConfig.getRetryInterval(), MCP StdIO请求 ); } /** * StdIO请求发送核心逻辑遵循官方通信格式 */ private String doSendStdioRequest(String request) throws IOException { initStdioStream(); try { // 1. 发送请求官方标准格式请求长度换行请求内容换行 int requestLength request.getBytes(StandardCharsets.UTF_8).length; stdioWriter.write(requestLength \n); stdioWriter.write(request \n); stdioWriter.flush(); log.info(MCP StdIO请求发送成功请求格式官方标准长度{}内容{}, requestLength, request); // 2. 接收响应官方标准格式响应长度换行响应内容换行 String responseLengthStr stdioReader.readLine(); if (responseLengthStr null) { throw new IOException(MCP StdIO通信异常未收到响应长度违反官方通信规范); } int responseLength Integer.parseInt(responseLengthStr); char[] responseChars new char[responseLength]; stdioReader.read(responseChars, 0, responseLength); String response new String(responseChars, StandardCharsets.UTF_8); // 读取响应后的换行符清除缓冲区 stdioReader.readLine(); log.info(MCP StdIO响应接收成功响应内容{}, response); return response; } catch (IOException e) { log.error(MCP StdIO通信失败将进行重试, e); // 关闭流重新初始化 closeStdioStream(); throw e; } } /** * TCP通信方式适配远程MCP服务遵循官方标准 * 注核心逻辑与StdIO一致仅通信载体不同此处简化实现 */ private String sendTcpRequest(String request) { McpConfigLoader.McpRemoteServiceConfig remoteConfig mcpConfigLoader.getMcpConfig().getRemoteService(); if (!remoteConfig.isEnable()) { throw new RuntimeException(远程MCP服务未启用无法使用TCP通信); } // 此处省略TCP通信核心逻辑与StdIO请求/响应格式一致仅替换通信流为Socket log.info(MCP TCP请求发送远程服务地址{}:{}请求内容{}, remoteConfig.getHost(), remoteConfig.getPort(), request); // 模拟响应实际项目中需实现Socket通信逻辑 JSONObject response new JSONObject(); response.put(code, 200); response.put(msg, TCP请求处理成功); response.put(data, 远程服务响应); return response.toJSONString(); } /** * 关闭StdIO通信流 */ public void closeStdioStream() { try { if (stdioReader ! null) { stdioReader.close(); } if (stdioWriter ! null) { stdioWriter.close(); } log.info(MCP StdIO通信流已关闭); } catch (IOException e) { log.error(MCP StdIO通信流关闭失败, e); } } /** * MCP请求回调接口用于异步请求遵循官方规范 */ public interface McpResponseCallback { void onSuccess(String response); // 响应成功 void onFailure(Exception e); // 响应失败 } /** * 异步发送MCP请求适配多任务场景 */ public void sendAsyncRequest(String request, McpResponseCallback callback) { new Thread(() - { try { String response sendRequest(request); callback.onSuccess(response); } catch (Exception e) { callback.onFailure(e); } }).start(); } }四动态发现工具与资源官方标准逻辑MCP协议的核心优势之一是“工具动态发现”遵循官方标准Agent启动时自动扫描本地工具路径.mcp.json配置的toolScanPath、远程MCP服务中的工具资源自动注册工具元信息实现工具“即插即用”无需手动配置工具。以下是McpManager.java源码重点实现工具动态发现、工具注册、请求分发逻辑完全遵循官方标准。package com.claudecode.mcp; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.File; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * MCP协议管理类遵循官方标准负责工具动态发现、服务对接、请求分发 */ Slf4j Component public class McpManager { Autowired private McpClient mcpClient; Autowired private McpConfigLoader mcpConfigLoader; // 工具缓存key工具IDvalue工具元信息遵循官方标准 private final MapString, McpConfigLoader.McpToolConfig toolCache new ConcurrentHashMap(); // 本地工具接口所有本地MCP工具必须实现此接口官方标准 public interface McpTool { String getToolId(); // 工具唯一ID与.mcp.json配置一致 String execute(String request); // 工具执行方法接收MCP请求返回MCP响应 } /** * 初始化动态发现工具本地远程注册工具元信息 */ PostConstruct public void init() { // 1. 动态发现本地工具扫描.mcp.json配置的工具路径 discoverLocalTools(); // 2. 动态发现远程工具对接远程MCP服务获取工具列表 discoverRemoteTools(); log.info(MCP协议工具动态发现完成共发现{}个工具, toolCache.size()); } /** * 动态发现本地工具遵循官方标准扫描指定路径下的McpTool实现类 */ private void discoverLocalTools() { McpConfigLoader.McpLocalServiceConfig localConfig mcpConfigLoader.getMcpConfig().getLocalService(); if (!localConfig.isEnable()) { log.info(本地MCP服务未启用跳过本地工具发现); return; } String toolScanPath localConfig.getToolScanPath(); // 将包路径转换为文件路径 String scanPath toolScanPath.replace(., File.separator); try { // 扫描指定路径下的所有class文件 EnumerationURL resources Thread.currentThread().getContextClassLoader().getResources(scanPath); while (resources.hasMoreElements()) { URL resource resources.nextElement(); String filePath URLDecoder.decode(resource.getPath(), StandardCharsets.UTF_8); File toolDir new File(filePath); // 递归扫描目录下的class文件 scanLocalToolClasses(toolDir, toolScanPath); } } catch (Exception e) { log.error(本地工具动态发现失败, e); } } /** * 递归扫描本地工具class文件注册工具元信息 */ private void scanLocalToolClasses(File dir, String packageName) { if (!dir.exists() || !dir.isDirectory()) { return; } // 遍历目录下的文件class文件或子目录 File[] files dir.listFiles(); if (files null) { return; } for (File file : files) { if (file.isDirectory()) { // 子目录递归扫描 scanLocalToolClasses(file, packageName . file.getName()); } else if (file.getName().endsWith(.class) !file.getName().contains($)) { // class文件排除内部类加载类并判断是否实现McpTool接口 String className packageName . file.getName().replace(.class, ); try { Class? clazz Class.forName(className); // 判断是否实现McpTool接口官方标准 if (McpTool.class.isAssignableFrom(clazz) !clazz.isInterface()) { McpTool tool (McpTool) clazz.newInstance(); // 构建工具元信息注册到工具缓存 McpConfigLoader.McpToolConfig toolConfig new McpConfigLoader.McpToolConfig(); toolConfig.setToolId(tool.getToolId()); toolConfig.setToolName(clazz.getSimpleName()); toolConfig.setToolClass(className); toolConfig.setDescription(本地MCP工具自动发现); toolCache.put(tool.getToolId(), toolConfig); log.info(本地工具发现并注册成功工具ID{}工具类{}, tool.getToolId(), className); } } catch (Exception e) { log.error(本地工具加载失败类名{}, className, e); } } } } /** * 动态发现远程工具对接远程MCP服务遵循官方通信规范 */ private void discoverRemoteTools() { McpConfigLoader.McpRemoteServiceConfig remoteConfig mcpConfigLoader.getMcpConfig().getRemoteService(); if (!remoteConfig.isEnable()) { log.info(远程MCP服务未启用跳过远程工具发现); return; } // 发送工具发现请求遵循官方MCP请求格式 JSONObject request new JSONObject(); request.put(type, DISCOVER_TOOLS); request.put(version, mcpConfigLoader.getMcpConfig().getProtocol().getVersion()); try { // 调用McpClient发送请求获取远程工具列表 String response mcpClient.sendRequest(request.toJSONString()); JSONObject responseJson JSONObject.parseObject(response); // 解析远程工具列表注册到工具缓存 if (responseJson.getIntValue(code) 200) { for (JSONObject toolJson : responseJson.getJSONArray(data)) { McpConfigLoader.McpToolConfig toolConfig new McpConfigLoader.McpToolConfig(); toolConfig.setToolId(toolJson.getString(toolId)); toolConfig.setToolName(toolJson.getString(toolName)); toolConfig.setToolClass(toolJson.getString(toolClass)); toolConfig.setDescription(toolJson.getString(description)); toolCache.put(toolConfig.getToolId(), toolConfig); log.info(远程工具发现并注册成功工具ID{}工具名称{}, toolConfig.getToolId(), toolConfig.getToolName()); } } else { log.error(远程工具发现失败响应信息{}, response); } } catch (Exception e) { log.error(远程工具发现异常, e); } } /** * 调用MCP工具统一入口支持本地/远程工具调用 * param toolId 工具ID * param requestParam 工具请求参数JSON字符串 * return 工具执行响应JSON字符串 */ public String invokeTool(String toolId, String requestParam) { // 1. 校验工具是否存在 if (!toolCache.containsKey(toolId)) { throw new RuntimeException(MCP工具不存在工具ID toolId); } McpConfigLoader.McpToolConfig toolConfig toolCache.get(toolId); McpConfigLoader.McpLocalServiceConfig localConfig mcpConfigLoader.getMcpConfig().getLocalService(); // 2. 判断工具类型本地/远程执行对应调用逻辑 if (localConfig.isEnable() toolConfig.getToolClass().startsWith(localConfig.getToolScanPath())) { // 本地工具调用 return invokeLocalTool(toolId, requestParam); } else { // 远程工具调用 return invokeRemoteTool(toolId, requestParam); } } /** * 调用本地MCP工具 */ private String invokeLocalTool(String toolId, String requestParam) { try { McpConfigLoader.McpToolConfig toolConfig toolCache.get(toolId); // 加载本地工具类 Class? clazz Class.forName(toolConfig.getToolClass()); McpTool tool (McpTool) clazz.newInstance(); // 执行工具方法返回响应 String response tool.execute(requestParam); log.info(本地MCP工具调用成功工具ID{}请求{}响应{}, toolId, requestParam, response); return response; } catch (Exception e) { log.error(本地MCP工具调用失败工具ID{}, toolId, e); throw new RuntimeException(本地MCP工具调用失败, e); } } /** * 调用远程MCP工具遵循官方通信规范 */ private String invokeRemoteTool(String toolId, String requestParam) { // 构建远程工具调用请求遵循官方MCP请求格式 JSONObject request new JSONObject(); request.put(type, INVOKE_TOOL); request.put(toolId, toolId); request.put(param, requestParam); request.put(version, mcpConfigLoader.getMcpConfig().getProtocol().getVersion()); try { // 发送请求到远程MCP服务获取响应 String response mcpClient.sendRequest(request.toJSONString()); log.info(远程MCP工具调用成功工具ID{}请求{}响应{}, toolId, requestParam, response); return response; } catch (Exception e) { log.error(远程MCP工具调用失败工具ID{}, toolId, e); throw new RuntimeException(远程MCP工具调用失败, e); } } /** * 获取所有已发现的MCP工具 */ public MapString, McpConfigLoader.McpToolConfig getToolList() { return new HashMap(toolCache); } /** * 关闭MCP资源项目关闭时执行 */ public void destroy() { mcpClient.closeStdioStream(); toolCache.clear(); log.info(MCP协议资源清理完成); } }五本地/远程MCP服务对接官方标准流程MCP协议支持本地MCP服务和远程MCP服务无缝对接Agent可根据.mcp.json配置自动切换对接模式遵循官方标准对接流程核心逻辑如下1. 本地MCP服务对接流程官方标准1启用本地服务在.mcp.json中设置localService.enabletrue配置工具扫描路径2动态发现本地工具Agent启动时McpManager自动扫描指定路径下的McpTool实现类注册工具元信息3工具调用Agent通过McpManager.invokeTool()调用本地工具采用StdIO通信方式直接与本地工具交互无需网络传输4配置刷新修改.mcp.json后调用McpConfigLoader.refreshConfig()无需重启Agent即可更新本地服务配置。2. 远程MCP服务对接流程官方标准1启用远程服务在.mcp.json中设置remoteService.enabletrue配置远程服务地址、端口2动态发现远程工具Agent启动时McpManager通过McpClient发送工具发现请求获取远程服务中的工具列表并注册3工具调用Agent通过McpManager.invokeTool()调用远程工具采用TCP通信方式按照官方MCP请求格式发送请求接收远程响应4心跳检测远程服务启用后McpClient定期发送心跳请求检测远程服务可用性异常时触发重试机制。六实操练习MCP协议完整测试遵循官方标准结合本节课所学模拟本地MCP服务对接、StdIO通信、工具动态发现场景测试MCP协议的核心功能确保代码可直接运行符合官方标准。1. 测试准备1创建.mcp.json配置文件放在项目根目录使用官方标准格式参考前文配置2创建本地MCP工具实现McpManager.McpTool接口放在com.claudecode.mcp.tools路径下3确保McpConfigLoader、McpClient、McpManager已正确注入Spring容器。2. 本地MCP工具实现示例package com.claudecode.mcp.tools; import com.claudecode.mcp.McpManager; import com.alibaba.fastjson.JSONObject; /** * 本地MCP工具示例文件操作工具遵循官方MCP工具标准 */ public class FileOperationTool implements McpManager.McpTool { Override public String getToolId() { // 工具唯一ID与.mcp.json配置一致 return file-operation-tool; } Override public String execute(String requestParam) { // 解析请求参数遵循官方MCP请求格式 JSONObject param JSONObject.parseObject(requestParam); String filePath param.getString(filePath); String content param.getString(content); String operation param.getString(operation); // 模拟文件操作实际项目中实现真实逻辑 JSONObject response new JSONObject(); try { switch (operation) { case create: response.put(code, 200); response.put(msg, 文件创建成功); response.put(data, 文件路径 filePath 内容 content); break; case read: response.put(code, 200); response.put(msg, 文件读取成功); response.put(data, 文件内容 content); break; default: response.put(code, 400); response.put(msg, 不支持的操作类型); } } catch (Exception e) { response.put(code, 500); response.put(msg, 文件操作失败); response.put(error, e.getMessage()); } // 返回响应遵循官方MCP响应格式 return response.toJSONString(); } }3. 测试类实现McpTestpackage com.claudecode.test; import com.claudecode.mcp.McpManager; import com.claudecode.mcp.McpConfigLoader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * MCP协议测试类遵循官方标准测试本地服务、StdIO通信、工具动态发现 */ public class McpTest { public static void main(String[] args) { // 1. 初始化Spring上下文加载MCP核心组件 AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(); context.scan(com.claudecode.mcp); context.refresh(); // 2. 获取核心组件 McpManager mcpManager context.getBean(McpManager.class); McpConfigLoader mcpConfigLoader context.getBean(McpConfigLoader.class); // 3. 查看已动态发现的工具 System.out.println( 已发现的MCP工具 ); mcpManager.getToolList().forEach((toolId, toolConfig) - { System.out.println(工具ID toolId 工具名称 toolConfig.getToolName()); }); // 4. 调用本地MCP工具StdIO通信 System.out.println(\n 调用本地MCP工具 ); String requestParam {\filePath\:\D:/test.txt\,\content\:\MCP协议测试\,\operation\:\create\}; String response mcpManager.invokeTool(file-operation-tool, requestParam); System.out.println(工具调用响应 response); // 5. 动态刷新MCP配置 System.out.println(\n 动态刷新MCP配置 ); mcpConfigLoader.refreshConfig(); System.out.println(配置刷新完成新配置 mcpConfigLoader.getMcpConfig()); // 6. 清理资源 mcpManager.destroy(); context.close(); } }4. 测试结果说明符合官方标准运行测试类后控制台会输出以下结果验证MCP协议核心功能1工具动态发现成功扫描到FileOperationTool注册工具元信息2StdIO通信通过StdIO方式调用本地工具成功返回响应3配置刷新动态刷新.mcp.json配置无需重启Agent即可生效4工具调用按照官方标准请求/响应格式成功执行工具操作。四、MCP协议官方标准避坑点工业级开发必看1. 配置规范.mcp.json必须遵循官方标准格式协议版本必须为1.0.0否则会导致配置加载失败2. 通信格式StdIO/TCP通信必须严格遵循“长度换行内容换行”的格式否则会出现粘包、响应丢失问题3. 工具规范本地工具必须实现McpManager.McpTool接口工具ID必须唯一否则无法注册和调用4. 服务对接本地/远程服务不能同时关闭否则会导致MCP协议无法正常工作5. 容错处理远程服务调用必须添加心跳检测和重试机制避免远程服务宕机导致Agent异常。五、本课重点总结贴合官方标准1. MCP协议全称Model Context Protocol是Agent工具扩展的官方标准协议核心解决工具标准化对接、资源动态发现、本地/远程服务通信问题2. 核心要点StdIO是官方默认通信方式轻量无依赖.mcp.json是官方标准配置文件工具动态发现是核心优势本地/远程服务无缝对接是工业级部署关键3. 核心组件McpConfigLoader负责加载.mcp.json配置McpClient负责通信实现McpManager负责工具发现和请求分发三者协同实现符合官方标准的MCP协议4. 实操关键遵循官方配置格式、通信格式、工具规范确保MCP协议可兼容、可扩展适配工业级Agent的工具扩展需求。下节课预告第10课Claude Code插件系统模块——实现功能可扩展对应Claude Code的PermissionManager和SecurityConfig源码解析。