From d614ac0b159ee09b4f96b66eab57164fffd63133 Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Wed, 24 Dec 2025 21:36:39 +0800 Subject: [PATCH] feat(LocalRunnerClient): support initializing in-process dynamic action MCP Server --- Partner-Main/pom.xml | 6 ++++ .../core/action/runner/LocalRunnerClient.java | 31 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Partner-Main/pom.xml b/Partner-Main/pom.xml index ec937cf1..f9e3db57 100644 --- a/Partner-Main/pom.xml +++ b/Partner-Main/pom.xml @@ -56,6 +56,12 @@ 0.5.0 test + + work.slhaf + Partner-Common + 0.5.0 + compile + diff --git a/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java b/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java index 29afdbec..b158fa92 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java +++ b/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java @@ -10,6 +10,8 @@ import io.modelcontextprotocol.client.transport.ServerParameters; import io.modelcontextprotocol.client.transport.StdioClientTransport; import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer; import io.modelcontextprotocol.json.McpJsonMapper; +import io.modelcontextprotocol.server.McpServer; +import io.modelcontextprotocol.server.McpStatelessAsyncServer; import io.modelcontextprotocol.spec.McpClientTransport; import io.modelcontextprotocol.spec.McpSchema; import lombok.Data; @@ -17,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; +import work.slhaf.partner.common.mcp.InProcessMcpTransport; import work.slhaf.partner.core.action.entity.McpData; import work.slhaf.partner.core.action.entity.MetaAction; import work.slhaf.partner.core.action.entity.MetaActionInfo; @@ -29,7 +32,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -46,14 +48,32 @@ import static work.slhaf.partner.common.Constant.Path.TMP_ACTION_DIR_LOCAL; public class LocalRunnerClient extends RunnerClient { private final Map mcpClients = new HashMap<>(); + /** + * 动态生成的行动程序都将挂载至该 McpServer + */ + private McpStatelessAsyncServer dynamicActionMcpServer; public LocalRunnerClient(ConcurrentHashMap existedMetaActions, ExecutorService executor, @Nullable String actionWatchPath) { super(existedMetaActions, executor); ActionWatchService watchService = new ActionWatchService(actionWatchPath); watchService.launch(); + registerDynamicActionMcp(); setupShutdownHook(); } + private void registerDynamicActionMcp() { + InProcessMcpTransport.Pair pair = InProcessMcpTransport.pair(); + McpSchema.ServerCapabilities serverCapabilities = McpSchema.ServerCapabilities.builder() + .tools(true) + .resources(true, true) + .build(); + dynamicActionMcpServer = McpServer.async(pair.serverSide()) + .capabilities(serverCapabilities) + .jsonMapper(McpJsonMapper.getDefault()) + .build(); + registerMcpClient("dynamic-action", pair.clientSide(), 10); + } + @Override protected RunnerResponse doRun(MetaAction metaAction) { RunnerResponse response; @@ -219,13 +239,18 @@ public class LocalRunnerClient extends RunnerClient { /** * 该部分主要发生在扫描到新的MCP Server描述文件时出现的注册逻辑 * - * @param id MCP Client 的 id + * @param id MCP Client 的 id * @param mcpClientTransportParams MCP Server 的参数 */ private void registerMcpClient(String id, McpClientTransportParams mcpClientTransportParams) { McpClientTransport clientTransport = createTransport(mcpClientTransportParams); + int timeout = mcpClientTransportParams.timeout; + registerMcpClient(id, clientTransport, timeout); + } + + private void registerMcpClient(String id, McpClientTransport clientTransport, int timeout) { McpSyncClient client = McpClient.sync(clientTransport) - .requestTimeout(Duration.ofSeconds(mcpClientTransportParams.timeout)) + .requestTimeout(Duration.ofSeconds(timeout)) .clientInfo(new McpSchema.Implementation(id, "PARTNER")) // 行动程序(现 MCP Tool)的描述文本将直接由resources返回 // 原因: ToolChange 发送的内容侧重调用,缺少可承担描述文本的字段