fix(LocalRunnerClient): support read MetaActionInfo according to desc files when an MCP Client with described tools registered by CommonMcp

This commit is contained in:
2026-01-16 21:28:45 +08:00
parent c5f6c4e0ae
commit fb5cabc747

View File

@@ -61,6 +61,9 @@ public class LocalRunnerClient extends RunnerClient {
private final String MCP_SERVER_PATH; private final String MCP_SERVER_PATH;
private final String MCP_DESC_PATH; private final String MCP_DESC_PATH;
private final String MCP_NAME_DESC = "mcp-desc";
private final String MCP_NAME_DYNAMIC = "mcp-dynamic";
/** /**
* 存储包括 DescMcp、DynamicActionMcp、CommonMcp 在内的所有 MCP Server 对应的客户端 * 存储包括 DescMcp、DynamicActionMcp、CommonMcp 在内的所有 MCP Server 对应的客户端
* <br/> * <br/>
@@ -119,7 +122,7 @@ public class LocalRunnerClient extends RunnerClient {
private void registerCommonMcp() throws IOException { private void registerCommonMcp() throws IOException {
val ctx = new WatchContext(Path.of(MCP_SERVER_PATH), FileSystems.getDefault().newWatchService()); val ctx = new WatchContext(Path.of(MCP_SERVER_PATH), FileSystems.getDefault().newWatchService());
val common = new LocalWatchEventProcessor.Common(existedMetaActions, mcpClients, ctx); val common = new LocalWatchEventProcessor.Common(existedMetaActions, mcpClients, mcpClients.get(MCP_NAME_DESC), ctx);
new LocalWatchServiceBuild.BuildRegistry(ctx) new LocalWatchServiceBuild.BuildRegistry(ctx)
.initialLoad(common.buildLoad()) .initialLoad(common.buildLoad())
.registerCreate(common.buildCreate()) .registerCreate(common.buildCreate())
@@ -141,7 +144,7 @@ public class LocalRunnerClient extends RunnerClient {
.build(); .build();
registerDescMcpWatch(); registerDescMcpWatch();
log.info("DescMcp 文件监听注册完毕"); log.info("DescMcp 文件监听注册完毕");
registerMcpClient("mcp-desc", pair.clientSide(), 10); registerMcpClient(MCP_NAME_DESC, pair.clientSide(), 10);
log.info("DescMcp 注册完毕"); log.info("DescMcp 注册完毕");
} }
@@ -173,7 +176,7 @@ public class LocalRunnerClient extends RunnerClient {
// 后续的动态更新通过对应的 event 事件触发 // 后续的动态更新通过对应的 event 事件触发
registerDynamicActionMcpWatch(); registerDynamicActionMcpWatch();
log.info("DynamicActionMcp 文件监听注册完毕"); log.info("DynamicActionMcp 文件监听注册完毕");
registerMcpClient("dynamic-action", pair.clientSide(), 10); registerMcpClient(MCP_NAME_DYNAMIC, pair.clientSide(), 10);
log.info("DynamicActionMcp 注册完毕"); log.info("DynamicActionMcp 注册完毕");
} }
@@ -1069,15 +1072,17 @@ public class LocalRunnerClient extends RunnerClient {
private final Map<String, McpSyncClient> mcpClients; private final Map<String, McpSyncClient> mcpClients;
private final Map<File, McpConfigFileRecord> mcpConfigFileCache = new HashMap<>(); private final Map<File, McpConfigFileRecord> mcpConfigFileCache = new HashMap<>();
private final McpSyncClient descClient;
@SuppressWarnings("BooleanMethodIsAlwaysInverted") @SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean normalFile(File file) { private boolean normalFile(File file) {
return file.exists() && file.isFile() && file.getName().endsWith(".json"); return file.exists() && file.isFile() && file.getName().endsWith(".json");
} }
private Common(ConcurrentHashMap<String, MetaActionInfo> existedMetaActions, Map<String, McpSyncClient> mcpClients, WatchContext ctx) { private Common(ConcurrentHashMap<String, MetaActionInfo> existedMetaActions, Map<String, McpSyncClient> mcpClients, McpSyncClient descClient, WatchContext ctx) {
super(existedMetaActions, ctx); super(existedMetaActions, ctx);
this.mcpClients = mcpClients; this.mcpClients = mcpClients;
this.descClient = descClient;
} }
/** /**
@@ -1098,7 +1103,7 @@ public class LocalRunnerClient extends RunnerClient {
try { try {
for (McpSchema.Tool tool : client.listTools().tools()) { for (McpSchema.Tool tool : client.listTools().tools()) {
val metaActionInfo = buildMetaActionInfo(tool); val metaActionInfo = buildMetaActionInfo(id, tool);
existedMetaActions.put(id + "::" + tool.name(), metaActionInfo); existedMetaActions.put(id + "::" + tool.name(), metaActionInfo);
} }
mcpClients.put(id, client); mcpClients.put(id, client);
@@ -1113,8 +1118,32 @@ public class LocalRunnerClient extends RunnerClient {
} }
/**
* 构建 MetaActionInfo
*
* @param id MCP Client id
* @param tool 待构建 MetaActionInfo 的 MCP Tool
* @return MetaActionInfo 信息
*/
private @NotNull MetaActionInfo buildMetaActionInfo(String id, McpSchema.Tool tool) {
// 先检查是否存在对应的描述文件
val toolName = tool.name(); //格式: mcpName::toolName
for (McpSchema.Resource resource : descClient.listResources().resources()) {
val resourceName = resource.name();
if (resourceName.equals(toolName) && resourceName.split("::")[0].equals(id)) {
val resourceContent = descClient.readResource(resource).contents().getFirst();
if (resourceContent instanceof McpSchema.TextResourceContents r) {
try {
return JSONObject.parseObject(r.text(), MetaActionInfo.class);
} catch (Exception e) {
log.error("序列化描述文件资源失败", e);
log.error("序列化描述文件资源失败, uri: {}", r.uri());
log.error("序列化描述文件资源失败, text: {}", r.text());
}
}
}
}
private @NotNull MetaActionInfo buildMetaActionInfo(McpSchema.Tool tool) {
MetaActionInfo info = new MetaActionInfo(); MetaActionInfo info = new MetaActionInfo();
info.setDescription(tool.description()); info.setDescription(tool.description());
Map<String, Object> outputSchema = tool.outputSchema(); Map<String, Object> outputSchema = tool.outputSchema();