跳转到内容

JeecgBoot MCP 协议接入与工具管理

JeecgBoot MCP 协议接入与工具管理

学习目标

通过本章学习,你将能够:

  • 理解 JeecgBoot 如何通过 langchain4j-mcp 接入三种 MCP 传输模式
  • 掌握 MCP 工具同步与连接生命周期管理
  • 了解 MCP 与自定义 REST API 插件的统一分类设计
  • 掌握 MCP 工具在企业级 AI 应用中的集成方案

前置知识

本章涉及 MCP 协议的通用原理,建议先阅读:

下文假设你已理解上述概念,直接聚焦 JeecgBoot 的具体实现。


项目实践

三种传输模式实现

基于 langchain4j-mcp,JeecgBoot 实现了三种 MCP 传输模式:

传输模式实现类适用场景
HTTP SSEHttpMcpTransport远程 MCP Server,SSE 流式响应
Streamable HTTPStreamableHttpMcpTransport新一代 MCP HTTP 标准
StdioStdioMcpTransport本地进程 MCP

传输模式在 AiragMcp 实体的 type 字段中配置:

AiragMcp 实体
├── name # MCP 服务名称
├── category # "mcp" 或 "plugin"
├── type # "sse" | "streamableHttp" | "stdio"
├── endpoint # 服务端点(URL 或命令)
├── headers # 请求头(JSON,如认证信息)
├── tools # 同步后的工具列表(JSON)
├── synced # 同步状态(0=未同步,1=已同步)
└── status # 启用/禁用

MCP 工具同步流程

当用户在界面中新增或编辑 MCP Server 后,平台自动同步工具列表:

用户保存 MCP 配置
根据 type 创建对应 Transport
构建临时 McpClient(DefaultMcpClient)
调用 tools/list 获取工具列表
转换为 AiragMcp.tools(JSON 格式存储)
synced = 1
关闭临时 McpClient(释放连接)

同步内容:每个工具的名称、描述、参数 schema(JSON Schema 格式),这些信息后续用于构建 langchain4j 的 ToolSpecification

连接生命周期管理:McpToolProviderWrapper

这是 JeecgBoot 中一个关键的设计模式。McpToolProvider 本身不暴露连接引用,导致调用方无法在使用后关闭连接。

解决方案:使用包装器模式保存连接引用:

// 伪代码:McpToolProviderWrapper
class McpToolProviderWrapper {
private final McpToolProvider mcpToolProvider;
private final McpClient mcpClient; // 保存连接引用
McpToolProviderWrapper(endpoint, headers, allowSensitive) {
McpTransport transport = createTransport(type, endpoint, headers);
this.mcpClient = McpClient.builder()
.transport(transport)
.build();
this.mcpToolProvider = McpToolProvider.builder()
.mcpClient(mcpClient)
.allowSensitive(allowSensitive)
.build();
}
void close() {
mcpClient.closeAll(); // 关闭 MCP 连接
}
}

使用场景

// 每次聊天独立创建 MCP 连接
void buildPlugins(AIChatParams params) {
for (String pluginId : pluginIds) {
AiragMcp mcp = airagMcpMapper.selectById(pluginId);
McpToolProviderWrapper wrapper = buildMcpToolProviderWrapper(...);
mcpToolProviderWrappers.add(wrapper); // 保存引用
mcpToolProviders.add(wrapper.getMcpToolProvider());
}
params.setMcpToolProviderWrappers(mcpToolProviderWrappers);
}
// 聊天完成/异常后关闭
void sendWithDefault(...) {
final AIChatParams finalParams = aiChatParams;
chatStream.onCompleteResponse(response -> {
finalParams.closeMcpConnections(); // 正常完成时关闭
}).onError(error -> {
finalParams.closeMcpConnections(); // 异常时也关闭
});
}

不关闭的后果:每次聊天创建新的 MCP 连接而不关闭 → 连接泄漏 → MCP Server 连接数耗尽 → 后续请求全部失败。

MCP 与 REST API 插件统一分类

平台将两种工具源统一为一个管理界面:

类别category 值工具构建方式
MCP Server"mcp"McpToolProvider(langchain4j 标准)
REST API 插件"plugin"PluginToolBuilder(自定义 ToolSpecification + ToolExecutor)

统一效果:AI 应用在选择工具时,不需要区分是 MCP 还是 REST API,统一通过 pluginIds 列表引用。

REST API 插件构建

对于非 MCP 的自定义 REST API,平台通过 PluginToolBuilder 构建工具:

PluginToolBuilder.buildTools
Map<ToolSpecification, ToolExecutor> buildTools(AiragMcp plugin, HttpServletRequest request) {
JSONArray toolsArray = JSON.parseArray(plugin.getTools());
for (JSONObject toolDef : toolsArray) {
// 从工具定义构建 ToolSpecification
ToolSpecification spec = ToolSpecification.builder()
.name(toolDef.getString("name"))
.description(toolDef.getString("description"))
.parameters(buildJsonSchema(toolDef.getJSONArray("parameters")))
.build();
// 构建执行器(HTTP 调用)
ToolExecutor executor = (args, context) -> {
String url = buildUrl(plugin.getEndpoint(), toolDef.getString("path"));
return httpClient.post(url, args, plugin.getHeaders());
};
tools.put(spec, executor);
}
return tools;
}

敏感节点安全控制

MCP 工具可能暴露敏感操作(如数据库写入、用户管理)。平台通过 allowSensitiveNodes 配置控制:

McpToolProvider.builder()
.mcpClient(mcpClient)
.allowSensitiveNodes(aiRagConfigBean.getAllowSensitiveNodes()) // YAML 配置
.build();

AiRagConfigBean 中可配置允许的敏感操作白名单,不在白名单中的 MCP 工具不会被注册到 AI 聊天中。


问题与规避

陷阱表现对策
MCP Server 不可达时同步失败synced 保持为 0,用户看不到工具列表前端显示灰色”同步失败”状态,提供重试按钮
连接泄漏多次聊天后 MCP Server 连接数持续增长使用 McpToolProviderWrapper 确保每次聊天结束后关闭
工具名冲突多个 MCP Server 提供同名工具工具注册时使用 mcpName_toolName 前缀(langchain4j 默认行为)
旧数据兼容旧版 MCP 记录没有 category 字段兼容逻辑:if (category 为空) category = "mcp"

设计取舍

每次聊天新建连接 vs 连接池

JeecgBoot 选择:每次聊天新建 MCP 连接,完成后关闭。

方案优势代价
每次新建实现简单,隔离性好(不同聊天互不影响)频繁创建连接有开销
连接池复用连接,延迟低连接池管理复杂,需要处理超时、失效、并发

对于低频使用场景(用户不会每秒发起多次 MCP 调用),每次新建是合理的简单方案。如果平台规模扩大,可升级为连接池。

MCP 同步 vs 运行时发现

JeecgBoot 选择:先同步工具列表到数据库,聊天时使用缓存的工具定义。

方案优势代价
同步存储聊天时无需连接 MCP Server,降低延迟MCP Server 工具变更后需重新同步
运行时发现始终使用最新工具列表每次聊天都需连接 MCP Server 拉取工具列表

同步方案在聊天延迟和工具实时性之间选择了前者,因为 MCP 工具变更通常由管理员主动操作,可配合手动触发同步。


参考来源