Java?MCP?實戰(zhàn)之如何構(gòu)建跨進程與遠程的工具服務(wù)
一、MCP 協(xié)議簡介
MCP(Model Context Protocol,模型上下文協(xié)議)是由Anthropic推出的一種開放標(biāo)準(zhǔn)協(xié)議,旨在為大語言模型(LLM)與外部數(shù)據(jù)源、工具和服務(wù)提供標(biāo)準(zhǔn)化、安全的集成方式。支持進程間(通過 stdio)和遠程(通過 HTTP SSE/Streaming)通訊。它專為 AI 開發(fā)設(shè)計,可以方便地提供 Tool(工具服務(wù))、Prompt(提示語服務(wù))和 Resource(資源服務(wù))三種原語內(nèi)容。
MCP 的核心優(yōu)勢在于:
- 支持多種通訊方式(stdio/SSE/Streaming)
- 支持服務(wù)發(fā)現(xiàn)(客戶端可查詢服務(wù)端點提供的接口)
- 與 AI 生態(tài)無縫集成(可直接作為大模型的工具使用)
MCP 架構(gòu)示意圖:

二、環(huán)境準(zhǔn)備
首先在項目中添加 Java MCP 關(guān)鍵依賴:
<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
三、構(gòu)建 MCP 服務(wù)端
1、最簡單的 SSE 服務(wù)
@McpServerEndpoint(sseEndpoint = "/mcp/sse")
public class SimpleMcpServer {
@ToolMapping(description = "問候服務(wù)")
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、多端點服務(wù)
// 金融工具服務(wù)
@McpServerEndpoint(name="finance-tools", sseEndpoint = "/finance/sse")
public class FinanceTools {
@ToolMapping(description = "計算復(fù)利")
public double compoundInterest(
@Param(description = "本金") double principal,
@Param(description = "年利率") double rate,
@Param(description = "年數(shù)") int years) {
return principal * Math.pow(1 + rate, years);
}
}
// 教育工具服務(wù)
@McpServerEndpoint(name="edu-tools", sseEndpoint = "/edu/sse")
public class EducationTools {
@ToolMapping(description = "生成數(shù)學(xué)題")
public String generateMathProblem(
@Param(description = "難度級別") String level) {
if("easy".equals(level)) {
return "3 + 5 = ?";
} else {
return "∫(x^2)dx from 0 to 1 = ?";
}
}
}3、動態(tài)管理工具
@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("income");
return income * 0.2; // 簡單計算20%稅
}));
financeEndpoint.notifyToolsListChanged();
}
@Mapping("/tool/remove")
public void removeTool() {
financeEndpoint.removeTool("calculateTax");
financeEndpoint.notifyToolsListChanged();
}
}4、STDIO 服務(wù)
@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 服務(wù)不能開啟控制臺日志,否則會污染協(xié)議流。
四、構(gòu)建 MCP 客戶端
1、基本客戶端調(diào)用
public class McpClientDemo {
public static void main(String[] args) {
// 連接SSE服務(wù)
McpClientToolProvider sseClient = McpClientToolProvider.builder()
.apiUrl("http://localhost:8080/mcp/sse")
.build();
String greeting = sseClient.callToolAsText("hello", Map.of("name", "張三"));
System.out.println(greeting);
// 連接STDIO服務(wù)
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、三種原語內(nèi)容
@McpServerEndpoint(sseEndpoint = "/mcp/sse")
public class FullFeatureServer {
// 工具服務(wù)
@ToolMapping(description = "匯率轉(zhuǎn)換")
public double exchangeRate(
@Param(description = "源貨幣") String from,
@Param(description = "目標(biāo)貨幣") String to) {
// 實現(xiàn)匯率轉(zhuǎn)換邏輯
return 6.5;
}
// 資源服務(wù)
@ResourceMapping(uri = "config://app-info",
description = "獲取應(yīng)用信息")
public String getAppInfo() {
return "AppName: WeatherService, Version: 1.0.0";
}
// 提示語服務(wù)
@PromptMapping(description = "生成天氣報告提示")
public Collection<ChatMessage> weatherReportPrompt(
@Param(description = "城市名稱") String city) {
return Arrays.asList(
ChatMessage.ofSystem("你是一個天氣報告助手"),
ChatMessage.ofUser("請生成" + city + "的天氣報告")
);
}
}2、代理模式
// 將STDIO服務(wù)代理為SSE服務(wù)
@McpServerEndpoint(sseEndpoint = "/proxy/sse")
public class StdioToSseProxy implements ToolProvider {
private McpClientProvider stdioClient = McpClientProvider.builder()
.channel(McpChannel.STDIO)
.serverParameters(ServerParameters.builder("java")
.args("-jar", "path/to/stdio-service.jar")
.build())
.build();
@Override
public Collection<FunctionTool> getTools() {
return stdioClient.getTools();
}
}
// 將SSE服務(wù)代理為STDIO服務(wù)
@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 = "產(chǎn)品ID") String productId,
@Header("Authorization") String auth) {
// 驗證邏輯...
return 100; // 示例庫存
}
// 純Web API
@Mapping("/api/info")
public String getInfo() {
return "Service Info";
}
// 純MCP工具
@ToolMapping(description = "計算折扣")
public double calculateDiscount(
@Param(description = "原價") double price,
@Param(description = "會員等級") String level) {
if("VIP".equals(level)) {
return price * 0.8;
}
return price;
}
}六、生產(chǎn)環(huán)境注意事項
1、鑒權(quán)設(shè)計:使用過濾器保護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 {
// ...
}七、總結(jié)
通過本文,我們學(xué)習(xí)了如何使用 Java 和 Solon MCP 構(gòu)建強大的工具服務(wù):
- 可以創(chuàng)建多種類型的服務(wù)端點(SSE/STDIO)
- 支持動態(tài)添加和移除工具
- 可與 Web API 無縫集成
- 支持代理模式實現(xiàn)協(xié)議轉(zhuǎn)換
- 提供完整的鑒權(quán)和配置方案
MCP 協(xié)議特別適合需要與 AI 系統(tǒng)集成的場景,能夠?qū)F(xiàn)有服務(wù)快速暴露給大模型使用,同時也支持傳統(tǒng)的程序間調(diào)用。其靈活的通訊方式(進程內(nèi)/遠程)和原語支持(工具/提示/資源)使其成為構(gòu)建現(xiàn)代分布式系統(tǒng)的有力工具。
在實際項目中,可以根據(jù)需求選擇 SSE 或 STDIO 通訊方式,或者結(jié)合兩者使用代理模式。對于需要與 AI 集成的場景,MCP 提供的工具服務(wù)描述機制能夠大大簡化集成工作。
到此這篇關(guān)于Java MCP 實戰(zhàn):構(gòu)建跨進程與遠程的工具服務(wù)的文章就介紹到這了,更多相關(guān)Java MCP 實戰(zhàn):構(gòu)建跨進程與遠程的工具服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)的不同圖片居中剪裁生成同一尺寸縮略圖功能示例
這篇文章主要介紹了Java實現(xiàn)的不同圖片居中剪裁生成同一尺寸縮略圖功能,涉及java針對圖片的讀取、屬性修改等相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
Java SpringMVC的@RequestMapping注解使用及說明
這篇文章主要介紹了Java SpringMVC的@RequestMapping注解使用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
java使用poi讀取doc和docx文件的實現(xiàn)示例
這篇文章主要介紹了java使用poi讀取doc和docx文件的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

