开发者

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

目录
  • 一、MCP 协议简介
  • 二、环境准备
  • 三、构建 MCP 服务端
    • 1、最简单的 SSE 服务
    • 2、多端点服务
    • 3、动态管理工具
    • 4、STDIO 服务
  • 四、构建 MCP 客户端
    • 1、基本客户端调用
    • 2、集成到AI模型
  • 五、高级特性
    • 1、三种原语内容
    • 2、代理模式
    • 3、与Web API互通
  • 六、生产环境注意事项
    • 1、鉴权设计:使用过滤器保护MCP端点
    • 2、客户端配置
    • 3、断线重连:客户端默认支持断线重连,可通过心跳机制保持连接
  • 七、总结

    一、MCP 协议简介

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

    MCP 的核心优势在于:

    • 支持多种通讯方式(stdio/SSE/Streaming)
    • 支持服务发现(客户端可查询服务端点提供的接口)
    • 与 AI 生态无缝集成(可直接作为大模型的工具使用)

    MCP 架构示意图:

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

    二、环境准备

    首先在项目中添加 Java MCP 关键依赖:

    <dependency>
        <groupId>org.noear</groupId>
        <artifactId>solon-ai-mcp</artifactId>
        <version>最新版本</version>
    </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 服务

    @McpServerEndpoint(sseEndpoint = "/mcp/sse")
    public class SimpleMcpServejsr {
        @ToolMapping(description = "问候服务")
        public String hello(@Param(name="name", description = "用户名") String name) {
            return "你好, " + name;
        }
    }
    public class App {
        public static void main(String[] args) {
            Solon.start(App.class, args);
        }
    }

    2、多端点服务

    // 金融工具服务
    @McpServerEndpoint(name="finance-tools", sseEndpoint = "/finance/sse")
    public class FinanceTools {
        @ToolMapping(description = "计算复利")
        public double compoundInterest(
                @Param(description = "本金") double principal,
                @Param(description = "年利率") double rate,
                @Param(description = "年数") int years) {
            return principal * Math.pow(1 + rate, years);
        }
    }
    // 教育工具服务
    @McpServerEndpoint(name="edu-tools", sseEndpoint = "/edu/sse")
    public class EducationTools {
        @ToolMapping(description = "生成数学题")
        public String generateMathProblem(
                @Param(description = "难度级别") String level) {
            if("easy".equals(level)) {
                return "3 + 5 = ?";
            } else {
                return "∫(x^2)dx from 0 to 1 = ?";
            }
        }
    }

    3、动态管理工具

    @Controller
    public class ToolManager {
        @Inject("finance-tools")
        McpServerEndpointProvider financeEndpoint;
        @Mapping("/tool/add")
        public void addTool() {
            financeEndpoint.addTool(new FunctionToolDesc("calculateTax")
                .doHandle(params -> {
                    double income = (double)params.get("incom编程客栈e");
                    return income * 0.2; // 简单计算20%税
                }));
            financeEndpoint.notifyToolsListChanged();
        }
        @Mapping("/tool/remove")
        public void removeTool() {
            financeEndpoint.removeTool("calculateTax");
            financeEndpoint.notifyToolsListChanged();
        }
    }

    4、STDIO 服务

    @McpServerEndpoint(channel = McpChannel.STDIO)
    public class StdioCalculator {
        @ToolMapping(description = "加法计算")
        public int add(@Param int a, @Param int b) {
            return a + b;
        }
        @ToolMapping(description = "减法计算")
        public int subtract(@Param int a, @Param int b) {
            return a - b;
        }
    }

    注意:STDIO 服务不能开启控制台日志,否则会污染协议流。

    四、构建 MCP 客户端

    1、基本客户端调用

    public class McpClientDemo {
        public static void main(String[] args) {
            // 连接SSE服务
            McpClientToolProvider sseClient = McpClientToolProvider.builder()
                .apiUrl("http://localhost:8080/mcp/sse")
                .build();
            String greeting = sseClient.callToolAsText("hello", Map.of("name", "张三"));
            System.out.println(greeting);
            // 连接STDIO服务
            McpClientToolProvider stdioClient = McpClientToolProvider.builder()
                .channel(McpChannel.STDIO)
                .serverParameters(McpServerParameters.builder("java")
                    .args("-jar", "path/to/stdio-service.jar")
                    .build())
                .build();
            int sum = stdioClient.callToolAsText("add", Map.of("a", 5, "b", 3));
            System.out.println("5 + 3 = " + sum);
        }
    }

    2、集成到AI模型

    @Configuration
    public class AiConfig {
        @Bean
        public ChatModel chatModel(
                @Inject("${solon.ai.chat.config}") ChatConfig chatConfig,
                @Inject("mcp-weather") McpClientToolProvider toolProvider) {
            return ChatModel.of(chatConfig)
                .defaultToolsAdd(toolProvider.getTools())
                .build();
        }
        @Bean("mcp-weather")
        public McpClientToolProvider weatherToolProvider() {
            return McpClientToolProvider.builder()
                .apiUrl("http://weather-service/mcp/sse")
                .build();
        }
    }
    @Service
    public class WeatherService {
        @Inject
        ChatModel chatModel;
        public String askWeather(String question) {
            ChatResponse response = chatModel.prompt(question).call();
            return response.getContent();
        }
    }

    五、高级特性

    1、三种原语内容

    @McpServerEndpoint(sseEndpoint = "/mcp/sse")
    public class FullFeatureServer {
        // 工具服务
        @ToolMapping(description = "汇率转换")
        public double exchangeRate(
                @Param(description = "源货币") String from,
                @Param(description = "目标货币") String to) {
            // 实现汇率转换逻辑
            return 6.5;
        }
        // 资源服务
        @ResourceMapping(uri = "config://app-info", 
                       description = "获取应用信息")
        public String getAppInfo() {
            return "AppName: WeatherService, Version: 1.0.0";
        }
        // 提示语服务
        @PromptMapping(description = "生成天气报告提示")
        public Collection<ChatMessage> weatherReportPrompt(
                @Param(description = "城市名称") String city) {
            return Arrays.asList(
                ChatMessage.ofSystem("你是一个天气报告助手"),
                ChatMessage.ofUser("请生成" + city + "的天气报告")
            );
        }
    }

    2、代理模式

    // 将STDIO服务代理为SSE服务
    @McpServerEndpoint(sseEndpoint = "/proxy/sse")
    public class StdioToSseProxy implements ToolProvider {
        private McpClientProvider stdioClient = McpClientProvider.builder()
            .channel(McpChannel.STDIO)
            .serverParameters(ServerParphpameters.builder("java")
                .args("-jar", "path/to/stdio-service.jar")
                .build())
            .build();
        @Override
        public Collection<FunctionTool> getTools() {
            return stdioClient.getTools();
        }
    }
    // 将SSE服务代理为STDIO服务
    @McpServerEndpoint(channel = McpChannel.STDIO)
    public class SseToStdioProxy implements ToolProvider {
        private McpClientProvider sseClient = McpClientProvider.builder()
            .apiUrl("http://remote-service/mcp/sse")
            .build();
        @Override
        public Collection<FunctionTool> getTools() {
            return sseClient.getTools();
        }
    }

    3、与Web API互通

    @Controller
    @McpServerEndpoint(sseEndpoint = "/mcp/sse")
    public class HybridService {
        // 同时作为Web API和MCP工具
        @ToolMapping(description = "查询库存")
        @Mapping("/api/inventory")
        public int getInventory(
                @Param(description = "产品ID") String productId,
                @Header("Authorization") String auth) {
            // 验证逻辑...
            return 100; // 示例库存
        }
        // 纯Web API
        @Mapping("/api/info")
        public String getInfo() {
            return "Service Info";
        }
        /js/ 纯MCP工具
        @ToolMapping(description = "计算折扣")
        public double calculateDiscount(
                @Param(description = "原价") double price,
                @Param(description = "会员等级") String level) {
            if("VIP".equals(level)) {
                return price * 0.8;
            }
            return price;
        }
    }

    六、生产环境注意事项

    1、鉴权设计:使用过滤器保护MCP端点

    @Component
    public class McpAuthFilter implements Filter {
        @Override
        public void doFilter(Context ctx, FilterChain chain) throws Throwable {
            if (ctx.pathNew().startsWith("/mcp/")) {
                String apiKey = ctx.header("X-API-KEY");
                if(!validateApiKey(apiKey)) {
                    ctx.status(401);
                    return;
                }
            }
            chain.doFilter(ctx);
        }
    }

    2、客户端配置

    McpClientToolProvider.builder()
        .apiUrl("http://service/mcp/sse")
        .apiKey("your-api-key")
        .httpTimeout(HttpTimeout.builder()
            .connectTimeout(Duration.ofSeconds(5))
            .readTimeout(Duration.ofSeconds(30))
            .build())
        .requestTimeout(Duration.ofSeconds(20))
        .build();

    3、断线重连:客户端默认支持断线重连,可通过心跳机制保持连接

    @McpServerEndpoint(sseEndpoint = "/mcp/sse", heartbeatInterval = "60s")
    public class HeartbeatService {
        // ...
    }

    七、总结

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

    • 可以创建多种类型的服务端点(SSE/STDIO)
    • 支持动态添加和移除工具
    • 可与 Web API 无缝集成
    • 支持代理模式实现协议转换
    • 提供完整的鉴权和配置方案

    MCP 协议特别适合需要与 AI 系统集成的场景,能够将现有服务快速暴露给大模型使用,同时也支持传统的程序间调用。其灵活的通讯方式(进程内/远程)和原语支持(工具/提示/资源)使其成为构建现代分布式系统的有力工具。

    在实际项目中,可以根据需求选择 SSE 或 STDIO 通讯方式,或者结合两者使用代理模式。对于需要与 AI 集成的场景,MCP 提供的工具服务描述机制能够大大简化集成工作。

    到此这篇关于Java MCP 实战:构建跨进程与远程的工具服务的文章就介绍到这了,更多相关Java MCP&GJolbLLlVPnbsp;实战:构建跨进程与远程的工具服务内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜