找回密码
 立即注册
首页 业界区 业界 Java MCP 实战:构建跨进程与远程的工具服务 ...

Java MCP 实战:构建跨进程与远程的工具服务

椎蕊 12 小时前
一、MCP 协议简介

MCP(Model Context Protocol,模型上下文协议)是由Anthropic推出的一种开放标准协议,旨在为大语言模型(LLM)与外部数据源、工具和服务提供标准化、安全的集成方式。支持进程间(通过 stdio)和远程(通过 HTTP SSE/Streaming)通讯。它专为 AI 开发设计,可以方便地提供 Tool(工具服务)、Prompt(提示语服务)和 Resource(资源服务)三种原语内容。
MCP 的核心优势在于:

  • 支持多种通讯方式(stdio/SSE/Streaming)
  • 支持服务发现(客户端可查询服务端点提供的接口)
  • 与 AI 生态无缝集成(可直接作为大模型的工具使用)
MCP 架构示意图:
1.png
二、环境准备

首先在项目中添加 Java MCP 关键依赖:
  1. <dependency>
  2.     <groupId>org.noear</groupId>
  3.     solon-ai-mcp</artifactId>
  4.     <version>最新版本</version>
  5. </dependency>
复制代码
支持 java8, java11, java17, java21, java24 。支持 solon,springboot,vert.x,jFinal 等框架集成。完整的示例参考:

  • https://gitee.com/solonlab/solon-ai-mcp-embedded-examples
  • https://gitcode.com/solonlab/solon-ai-mcp-embedded-examples
  • https://github.com/solonlab/solon-ai-mcp-embedded-examples
三、构建 MCP 服务端

1、最简单的 SSE 服务
  1. @McpServerEndpoint(sseEndpoint = "/mcp/sse")
  2. public class SimpleMcpServer {
  3.     @ToolMapping(description = "问候服务")
  4.     public String hello(@Param(name="name", description = "用户名") String name) {
  5.         return "你好, " + name;
  6.     }
  7. }
  8. public class App {
  9.     public static void main(String[] args) {
  10.         Solon.start(App.class, args);
  11.     }
  12. }
复制代码
2、多端点服务
  1. // 金融工具服务
  2. @McpServerEndpoint(name="finance-tools", sseEndpoint = "/finance/sse")
  3. public class FinanceTools {
  4.     @ToolMapping(description = "计算复利")
  5.     public double compoundInterest(
  6.             @Param(description = "本金") double principal,
  7.             @Param(description = "年利率") double rate,
  8.             @Param(description = "年数") int years) {
  9.         return principal * Math.pow(1 + rate, years);
  10.     }
  11. }
  12. // 教育工具服务
  13. @McpServerEndpoint(name="edu-tools", sseEndpoint = "/edu/sse")
  14. public class EducationTools {
  15.     @ToolMapping(description = "生成数学题")
  16.     public String generateMathProblem(
  17.             @Param(description = "难度级别") String level) {
  18.         if("easy".equals(level)) {
  19.             return "3 + 5 = ?";
  20.         } else {
  21.             return "∫(x^2)dx from 0 to 1 = ?";
  22.         }
  23.     }
  24. }
复制代码
3、动态管理工具
  1. @Controller
  2. public class ToolManager {
  3.     @Inject("finance-tools")
  4.     McpServerEndpointProvider financeEndpoint;
  5.    
  6.     @Mapping("/tool/add")
  7.     public void addTool() {
  8.         financeEndpoint.addTool(new FunctionToolDesc("calculateTax")
  9.             .doHandle(params -> {
  10.                 double income = (double)params.get("income");
  11.                 return income * 0.2; // 简单计算20%税
  12.             }));
  13.         financeEndpoint.notifyToolsListChanged();
  14.     }
  15.    
  16.     @Mapping("/tool/remove")
  17.     public void removeTool() {
  18.         financeEndpoint.removeTool("calculateTax");
  19.         financeEndpoint.notifyToolsListChanged();
  20.     }
  21. }
复制代码
4、STDIO 服务
  1. @McpServerEndpoint(channel = McpChannel.STDIO)
  2. public class StdioCalculator {
  3.     @ToolMapping(description = "加法计算")
  4.     public int add(@Param int a, @Param int b) {
  5.         return a + b;
  6.     }
  7.    
  8.     @ToolMapping(description = "减法计算")
  9.     public int subtract(@Param int a, @Param int b) {
  10.         return a - b;
  11.     }
  12. }
复制代码
注意:STDIO 服务不能开启控制台日志,否则会污染协议流。
四、构建 MCP 客户端

1、基本客户端调用
  1. public class McpClientDemo {
  2.     public static void main(String[] args) {
  3.         // 连接SSE服务
  4.         McpClientToolProvider sseClient = McpClientToolProvider.builder()
  5.             .apiUrl("http://localhost:8080/mcp/sse")
  6.             .build();
  7.         
  8.         String greeting = sseClient.callToolAsText("hello", Map.of("name", "张三"));
  9.         System.out.println(greeting);
  10.         
  11.         // 连接STDIO服务
  12.         McpClientToolProvider stdioClient = McpClientToolProvider.builder()
  13.             .channel(McpChannel.STDIO)
  14.             .serverParameters(McpServerParameters.builder("java")
  15.                 .args("-jar", "path/to/stdio-service.jar")
  16.                 .build())
  17.             .build();
  18.             
  19.         int sum = stdioClient.callToolAsText("add", Map.of("a", 5, "b", 3));
  20.         System.out.println("5 + 3 = " + sum);
  21.     }
  22. }
复制代码
2、集成到AI模型
  1. @Configuration
  2. public class AiConfig {
  3.     @Bean
  4.     public ChatModel chatModel(
  5.             @Inject("${solon.ai.chat.config}") ChatConfig chatConfig,
  6.             @Inject("mcp-weather") McpClientToolProvider toolProvider) {
  7.         
  8.         return ChatModel.of(chatConfig)
  9.             .defaultToolsAdd(toolProvider.getTools())
  10.             .build();
  11.     }
  12.    
  13.     @Bean("mcp-weather")
  14.     public McpClientToolProvider weatherToolProvider() {
  15.         return McpClientToolProvider.builder()
  16.             .apiUrl("http://weather-service/mcp/sse")
  17.             .build();
  18.     }
  19. }
  20. @Service
  21. public class WeatherService {
  22.     @Inject
  23.     ChatModel chatModel;
  24.    
  25.     public String askWeather(String question) {
  26.         ChatResponse response = chatModel.prompt(question).call();
  27.         return response.getContent();
  28.     }
  29. }
复制代码
五、高级特性

1、三种原语内容
  1. @McpServerEndpoint(sseEndpoint = "/mcp/sse")
  2. public class FullFeatureServer {
  3.     // 工具服务
  4.     @ToolMapping(description = "汇率转换")
  5.     public double exchangeRate(
  6.             @Param(description = "源货币") String from,
  7.             @Param(description = "目标货币") String to) {
  8.         // 实现汇率转换逻辑
  9.         return 6.5;
  10.     }
  11.    
  12.     // 资源服务
  13.     @ResourceMapping(uri = "config://app-info",
  14.                    description = "获取应用信息")
  15.     public String getAppInfo() {
  16.         return "AppName: WeatherService, Version: 1.0.0";
  17.     }
  18.    
  19.     // 提示语服务
  20.     @PromptMapping(description = "生成天气报告提示")
  21.     public Collection<ChatMessage> weatherReportPrompt(
  22.             @Param(description = "城市名称") String city) {
  23.         return Arrays.asList(
  24.             ChatMessage.ofSystem("你是一个天气报告助手"),
  25.             ChatMessage.ofUser("请生成" + city + "的天气报告")
  26.         );
  27.     }
  28. }
复制代码
2、代理模式
  1. // 将STDIO服务代理为SSE服务
  2. @McpServerEndpoint(sseEndpoint = "/proxy/sse")
  3. public class StdioToSseProxy implements ToolProvider {
  4.     private McpClientProvider stdioClient = McpClientProvider.builder()
  5.         .channel(McpChannel.STDIO)
  6.         .serverParameters(ServerParameters.builder("java")
  7.             .args("-jar", "path/to/stdio-service.jar")
  8.             .build())
  9.         .build();
  10.    
  11.     @Override
  12.     public Collection<FunctionTool> getTools() {
  13.         return stdioClient.getTools();
  14.     }
  15. }
  16. // 将SSE服务代理为STDIO服务
  17. @McpServerEndpoint(channel = McpChannel.STDIO)
  18. public class SseToStdioProxy implements ToolProvider {
  19.     private McpClientProvider sseClient = McpClientProvider.builder()
  20.         .apiUrl("http://remote-service/mcp/sse")
  21.         .build();
  22.    
  23.     @Override
  24.     public Collection<FunctionTool> getTools() {
  25.         return sseClient.getTools();
  26.     }
  27. }
复制代码
3、与Web API互通
  1. @Controller
  2. @McpServerEndpoint(sseEndpoint = "/mcp/sse")
  3. public class HybridService {
  4.     // 同时作为Web API和MCP工具
  5.     @ToolMapping(description = "查询库存")
  6.     @Mapping("/api/inventory")
  7.     public int getInventory(
  8.             @Param(description = "产品ID") String productId,
  9.             @Header("Authorization") String auth) {
  10.         // 验证逻辑...
  11.         return 100; // 示例库存
  12.     }
  13.    
  14.     // 纯Web API
  15.     @Mapping("/api/info")
  16.     public String getInfo() {
  17.         return "Service Info";
  18.     }
  19.    
  20.     // 纯MCP工具
  21.     @ToolMapping(description = "计算折扣")
  22.     public double calculateDiscount(
  23.             @Param(description = "原价") double price,
  24.             @Param(description = "会员等级") String level) {
  25.         if("VIP".equals(level)) {
  26.             return price * 0.8;
  27.         }
  28.         return price;
  29.     }
  30. }
复制代码
六、生产环境注意事项

1、鉴权设计:使用过滤器保护MCP端点
  1. @Component
  2. public class McpAuthFilter implements Filter {
  3.     @Override
  4.     public void doFilter(Context ctx, FilterChain chain) throws Throwable {
  5.         if (ctx.pathNew().startsWith("/mcp/")) {
  6.             String apiKey = ctx.header("X-API-KEY");
  7.             if(!validateApiKey(apiKey)) {
  8.                 ctx.status(401);
  9.                 return;
  10.             }
  11.         }
  12.         chain.doFilter(ctx);
  13.     }
  14. }
复制代码
2、客户端配置
  1. McpClientToolProvider.builder()
  2.     .apiUrl("http://service/mcp/sse")
  3.     .apiKey("your-api-key")
  4.     .httpTimeout(HttpTimeout.builder()
  5.         .connectTimeout(Duration.ofSeconds(5))
  6.         .readTimeout(Duration.ofSeconds(30))
  7.         .build())
  8.     .requestTimeout(Duration.ofSeconds(20))
  9.     .build();
复制代码
3、断线重连:客户端默认支持断线重连,可通过心跳机制保持连接
  1. @McpServerEndpoint(sseEndpoint = "/mcp/sse", heartbeatInterval = "60s")
  2. public class HeartbeatService {
  3.     // ...
  4. }
复制代码
七、总结

通过本文,我们学习了如何使用 Java 和 Solon MCP 构建强大的工具服务:

  • 可以创建多种类型的服务端点(SSE/STDIO)
  • 支持动态添加和移除工具
  • 可与 Web API 无缝集成
  • 支持代理模式实现协议转换
  • 提供完整的鉴权和配置方案
MCP 协议特别适合需要与 AI 系统集成的场景,能够将现有服务快速暴露给大模型使用,同时也支持传统的程序间调用。其灵活的通讯方式(进程内/远程)和原语支持(工具/提示/资源)使其成为构建现代分布式系统的有力工具。
在实际项目中,可以根据需求选择 SSE 或 STDIO 通讯方式,或者结合两者使用代理模式。对于需要与 AI 集成的场景,MCP 提供的工具服务描述机制能够大大简化集成工作。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册