当前位置: 首页 > ops >正文

jFinal 使用 SolonMCP 开发 MCP(拥抱新潮流)

MCP 官方的 java-sdk 目前只支持 java17+。直接基于 mcp-java-sdk 也比较复杂。使用 SolonMCP,可以基于 java8 开发(像 MVC 的开发风格),且比较简单。

1、SolonMCP 简介

SolonMCP(全称:solon-ai-mcp)是 solon 的一个扩展。支持内嵌到 jfinal,vert.x,springboot2,springboot3 等框架使用。

Maven 主要依赖包:

<dependency><groupId>org.noear</groupId><artifactId>solon-ai-mcp</artifactId>
</dependency>

具体的示例参考:

  • https://gitee.com/opensolon/solon-ai-mcp-embedded-examples/tree/main/solon-ai-embedded-jfinal
  • https://gitee.com/opensolon/solon-ai-mcp-embedded-examples/tree/main/solon-ai-embedded-jfinal-newstyle

2、MCP 服务端开发

2.1、添加入口类 webapp.HelloApp(比较空,注意下 mcpServerConfig)

MCP 内部是基于响应式的,需要开启异步支持。

public class HelloApp extends JFinalConfig {public static void main(String[] args) {UndertowServer.create(HelloApp.class).setDevMode(false).setPort(8080).onDeploy((cl, di) -> {di.getFilters().get("jfinal").setAsyncSupported(true); //注意这个,要开启异步支持}).start();}public void configConstant(Constants me) {me.setDevMode(false);}public void configRoute(Routes me) {}public void configEngine(Engine me) {}public void configPlugin(Plugins me) {me.add(mcpServerConfig);}public void configInterceptor(Interceptors me) {}public void configHandler(Handlers me) {me.add(mcpServerConfig);}private McpServerConfig mcpServerConfig = new McpServerConfig();
}
2.2、添加 webapp.mcpserver.McpServerConfig(实现 Handler、IPlugin 接口)

实现 IPlugin 对接 Solon 的生命周期。实现 Handler 对接 mcp 的请求处理。

public class McpServerConfig extends Handler implements IPlugin {public boolean start() {Solon.start(McpServerConfig.class, new String[]{"--cfg=mcpserver.yml"});return true;}public boolean stop() {if (Solon.app() != null) {Solon.stopBlock(false, Solon.cfg().stopDelay());}return true;}@Overridepublic void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {if (target.startsWith("/mcp/")) {Context ctx = new SolonServletContext(request, response);try {//Solon处理(可能是空处理)Solon.app().tryHandle(ctx);if (isHandled != null && isHandled.length > 0) {isHandled[0] = true;}} catch (Throwable e) {ctx.errors = e;throw e;} finally {ContextUtil.currentRemove();}} else {if (next != null) {next.handle(target, request, response, isHandled);}}}
}
2.3、添加 webapp.mcpserver.tool.McpServer(实现 Handler、IPlugin 接口)

这里是重点了,添加 mcp server 端点(支持多个端点)

@McpServerEndpoint(sseEndpoint = "/mcp/sse")
public class McpServer {//// 建议开启编译参数:-parameters (否则,最好再配置参数的 name)//@ToolMapping(description = "查询天气预报")public String getWeather(@Param(description = "城市位置") String location) {return "晴,14度";}@ResourceMapping(uri = "config://app-version", description = "获取应用版本号")public String getAppVersion() {return "v3.2.0";}@ResourceMapping(uri = "db://users/{user_id}/email", description = "根据用户ID查询邮箱")public String getEmail(@Param(description = "用户Id") String user_id) {return user_id + "@example.com";}@PromptMapping(description = "生成关于某个主题的提问")public Collection<ChatMessage> askQuestion(@Param(description = "主题") String topic) {return Arrays.asList(ChatMessage.ofUser("请解释一下'" + topic + "'的概念?"));}
}
2.4、编译后运行

或者开发时,直接运行 HelloApp:main 方法

3、MCP 客户端开发

客户端简单些

public class McpClientTest {public static void main(String[] args) throws Exception {McpClientProvider toolProvider = McpClientProvider.builder().apiUrl("http://localhost:8080/mcp/sse").build();//工具调用Map<String, Object> map = Collections.singletonMap("location", "杭州");String rst = toolProvider.callToolAsText("getWeather", map).getContent();System.out.println(rst);assert "晴,14度".equals(rst);//资源读取resourceContent = toolProvider.readResourceAsText("config://app-version").getContent();System.out.println(resourceContent);}
}

4、MCP 客户端作为 LLM(ChatModel) 的工具集使用

也比较简单。使用 ollama 做为 llm 提供者,方便本地测试。

public class McpClientTest {private static final String apiUrl = "http://127.0.0.1:11434/api/chat";private static final String provider = "ollama";private static final String model = "qwen2.5:1.5b"; //"llama3.2";//deepseek-r1:1.5b;public static void main(String[] args) throws Exception {//构建 mcp clientMcpClientProvider toolProvider = McpClientProvider.builder().apiUrl("http://localhost:8080/mcp/sse").build();//构建 llm 接口ChatModel chatModel = ChatModel.of(apiUrl).provider(provider).model(model).defaultToolsAdd(toolProvider) //添加默认工具(这是 mcp client).build();//请求ChatResponse resp = chatModel.prompt("杭州今天的天气怎么样?").call();System.out.println(resp.getMessage());}
}
http://www.xdnf.cn/news/5916.html

相关文章:

  • .NET8关于ORM的一次思考
  • ELF文件详解
  • 基于 PLC 的轮式服务机器人研究
  • 数据归属地信息库在广告营销中的应用
  • Docker 环境安装(2025最新版)
  • 【认知思维】验证性偏差:认知陷阱的识别与克服
  • FlashInfer - Kernel Generator(内核生成器)
  • RDD 算子 - 转换算子 2
  • 【Python爬虫 !!!!!!政府招投标数据爬虫项目--医疗实例项目文档(提供源码!!!)!!!学会Python爬虫轻松赚外快】
  • #跟着若城学鸿蒙# HarmonyOS NEXT学习之AlphabetIndexer组件详解
  • C语言while循环的用法(非常详细,附带实例)
  • AbstractQueuedSynchronizer之AQS
  • 使用WebStorm打断点调试Vue项目
  • 相对论速度叠加公式与双曲正切
  • 如何创建企业微信应用,如何给企业微信发送消息
  • 【Docker】Docker环境下快速部署Ollama与Open-WebUI:详细指南
  • Qiankun在vue3+vite+ts使用
  • 最优化方法Python计算:有约束优化应用——线性可分问题支持向量机
  • 车载网关作为车辆网络系统的核心枢纽
  • 算法竞赛相关 Java 二分模版
  • 课题推荐——低成本地磁导航入门,附公式推导和MATLAB例程运行演示
  • XILINX-配置(引脚复用)
  • 【Nova UI】十六、打造组件库之滚动条组件(中):探秘滑块的计算逻辑
  • JavaScript进阶(九)
  • 定时器(两种)
  • 芋道(yudao-cloud)项目,后端接口报401-账号未登录解决方案
  • deepseek梳理java高级开发工程师微服务面试题
  • AD PCB布线的常用命令
  • EasyOps®5月热力焕新:三大核心模块重构效能边界
  • LeetCode LCR 016. 无重复字符的最长子串 (Java)