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());}
}