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>

具体的示例参考:

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;
} @Override
public 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 client
McpClientProvider 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());
}
}

jFinal 使用 SolonMCP 开发 MCP(拥抱新潮流)的更多相关文章

  1. unity3D实际的原始视频游戏开发系列讲座12之U3D的2D为了开发实战的新方法

     U3D的2D为了开发实战的新方法 (Unity3d-4.x的打飞机2D游戏开发新的方法应用 ) 大纲介绍:不使用NGUI和TK2d插件,   使用 U3D内置强大的最大的工具. 开发过程设计到例 ...

  2. Android开发艺术探索——新的征程,程序人生路漫漫!

    Android开发艺术探索--新的征程,程序人生路漫漫! 偶尔写点东西分享,但是我还是比较喜欢写笔记,看书,群英传看完了,是学到了点东西,开始看这本更加深入Android的书籍了,不知道适不适合自己, ...

  3. 【视频】使用fiddler开发工具进行新架构页面本地调试

    [视频]使用fiddler开发工具进行新架构页面本地调试,视频没录制好,有些部分比较模糊...

  4. cocos2d-x -3.81+win7+vs2013开发环境创建新的项目

    cocos2d-x -3.81+win7+vs2013开发环境创建新的项目 1.准备阶段 (1) vs2013下载及安装 (2)cocos2d-x 3.8.1下载及解压 (3)python下载及安装( ...

  5. BGV作为拥抱新时代的DeFi项目,是否有能力超越YFI?

    随着今年11月DeFi蓝筹股们的集体反弹,市场变化让投资者明白,不能再死守诸如COMP和MKR的古典DeFi了,只有拥抱新时代的DeFi们才有赚钱的可能,不要和钱过不去.经过9-10月的回调,11月的 ...

  6. 活字格发布新版本,插件公开,引领Web开发新潮流

    日前,活字格Web 应用生成平台发布V4.0版本,首次公开插件机制,强大的扩展性和系统集成能力,引起业内瞩目. 活字格是由西安葡萄城自主研发的 Web 应用生成平台,提供易用的类Excel可视化设计器 ...

  7. SuperMap iClient 7C——网络客户端GIS开发平台 产品新特性

    SuperMap iClient 7C是空间信息和服务的可视化交互开发平台,是SuperMap服务器系列产品的统一客户端.产品基于统一的架构体系,面向Web端和移动端提供了多种类型的SDK开发包,帮助 ...

  8. UWP开发随笔——UWP新控件!AutoSuggestBox!

    摘要 要开发一款优秀的application,控件肯定是必不可少的,uwp就为开发者提供了各种各样的系统控件,AutoSuggestBox就是uwp极具特色的控件之一,也是相对于之前win8.1的ua ...

  9. iOS7开发中的新特性

        iOS7到现在已经发布了有一段时间了.相信你现在已经了解了它那些开创性的视觉设计,已经了解了它的新的API,比如说SpirteKit,UIKit Dynamics以及TextKit,作为开发者 ...

  10. 03-移动端开发教程-CSS3新特性(下)

    1. CSS3动画 1.1 过渡的缺点 transition的优点在于简单易用,但是它有几个很大的局限. transition需要事件触发,所以没法在网页加载时自动发生. transition是一次性 ...

随机推荐

  1. 异步导入导出Excel方案

    一.异步导出Excel文件 1.设计思想 用户无需在当前页面等待导出结果,点击导出按钮后服务端即可返回前端提示用户导出处理中请到下载中心查看结果. 具体业务文件导出实现由后台异步处理导出文件到腾讯CO ...

  2. Processing (Java) 中实现2D任意图形的鼠标悬停检测 · 2D射线检测 · 模拟按钮 · 点击事件

    引言 如果使用Processing开发应用,画面中需要设定一些按钮,而且这些按钮是不规则图形样式,甚至是以一张图片形式呈现,如何判定其轮廓,定义悬停事件.点击事件是非常核心的算法需求.本文浅析这一问题 ...

  3. 给react native 添加transform translateY动画报错:Transform with key of "translateY" must be a number:{translateY“:0}

    初学react native,想实现一个相机扫描功能时,报错,报错描述如标题 这是我的主要逻辑代码 const fadeAnim = useRef(new Animated.Value(0)).cur ...

  4. Vue3生命周期钩子函数深度解析:从源码到实战的万字指南

    一.Vue3生命周期革新特性 相较于Vue2,Vue3通过Composition API带来了更灵活的生命周期管理方式.通过onBeforeMount等函数注册钩子时,实际是通过injectHook方 ...

  5. ubuntu 22.04 deskop 无法打开terminal

    系统语言设置的问题,改为汉语即可

  6. selenium自动化测试+OCR-获取图片页面小说

    随着爬虫技术的发展,反爬虫技术也越来越高. 目前有些网站通过自定义字体库的方式实现反爬,主要表现在页面数据显示正常,但是页面获取到的实际数据是别的字符或者是一个编码.这种反爬需要解析网站自己的字体库, ...

  7. SpringSecurity5(11-跨域配置)

    SpringBoot跨域处理 @CrossOrigin(局部跨域) 作用在方法上 @RestController public class IndexController { @CrossOrigin ...

  8. MySQL-redo log 和 binlog

    redo log部分 为什么需要redo log? 简单的说,如果每次更新数据库的操作,都去更新磁盘的话,开销是很大的.通过引入redo log日志,其中记录了每次更新的操作明细,在系统不繁忙的时候, ...

  9. Math类、System类--java进阶day05

    1.Math类 Math类里所有方法都被static修饰,说明它是一个工具类,不需要创建对象,直接类名调用 2.Math方法展示 . 3.System类 SYstem方法展示 1.currentTim ...

  10. Windows 系统授权服务信息

    cmd 中输入命令 slmgr.vbs /dlv 后查看输出信息 据说,OEM和RETAIL可以正常升级到Windows10,并永久激活