mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(RunnerClient): redesign existedMetaActions update strategy
Context: Resource-change events cannot reliably represent tool changes. The previous approach attempted to externalize descriptive content into files, but the meta attribute of McpSchema.Tool can provide this information.
This commit is contained in:
@@ -18,6 +18,8 @@ import io.modelcontextprotocol.spec.McpSchema;
|
|||||||
import io.modelcontextprotocol.spec.McpStatelessServerTransport;
|
import io.modelcontextprotocol.spec.McpStatelessServerTransport;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.publisher.Sinks;
|
import reactor.core.publisher.Sinks;
|
||||||
import work.slhaf.partner.core.action.entity.McpData;
|
import work.slhaf.partner.core.action.entity.McpData;
|
||||||
@@ -88,27 +90,37 @@ public abstract class RunnerClient {
|
|||||||
// ResourcesChange 事件传递的 Resource 可以由 Client 读取内容
|
// ResourcesChange 事件传递的 Resource 可以由 Client 读取内容
|
||||||
// 预计在 Server 侧,收到客户端发送的新的行动程序信息,该信息由客户端处补充后,将其放置在指定位置
|
// 预计在 Server 侧,收到客户端发送的新的行动程序信息,该信息由客户端处补充后,将其放置在指定位置
|
||||||
// 并写入描述文件、发起 ResourcesChange 事件
|
// 并写入描述文件、发起 ResourcesChange 事件
|
||||||
.resourcesChangeConsumer(resources -> updateExistedMetaActions(id, resources))
|
.toolsChangeConsumer(tools -> updateExistedMetaActions(id, tools))
|
||||||
.build();
|
.build();
|
||||||
mcpClients.put(id, client);
|
mcpClients.put(id, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateExistedMetaActions(String id, List<McpSchema.Resource> resources) {
|
private void updateExistedMetaActions(String id, @UnknownNullability List<McpSchema.Tool> tools) {
|
||||||
synchronized (existedMetaActions) {
|
for (McpSchema.Tool tool : tools) {
|
||||||
McpSyncClient client = mcpClients.get(id);
|
MetaActionInfo info = buildMetaActionInfo(tool);
|
||||||
for (McpSchema.Resource resource : resources) {
|
String actionKey = id + "::" + tool.name();
|
||||||
McpSchema.ReadResourceResult resourceResult = client.readResource(resource);
|
synchronized (existedMetaActions) {
|
||||||
for (McpSchema.ResourceContents resourceContent : resourceResult.contents()) {
|
existedMetaActions.put(actionKey, info);
|
||||||
// 忽略非文本类型,行动描述信息只会以文本形式存在
|
|
||||||
if (resourceContent instanceof McpSchema.TextResourceContents content) {
|
|
||||||
MetaActionInfo metaActionInfo = JSONObject.parseObject(content.text(), MetaActionInfo.class);
|
|
||||||
existedMetaActions.put(id + "::" + resource.name(), metaActionInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static @NotNull MetaActionInfo buildMetaActionInfo(McpSchema.Tool tool) {
|
||||||
|
MetaActionInfo info = new MetaActionInfo();
|
||||||
|
info.setDescription(tool.description());
|
||||||
|
Map<String, Object> outputSchema = tool.outputSchema();
|
||||||
|
info.setResponseSchema(outputSchema == null ? JSONObject.of() : JSONObject.from(outputSchema));
|
||||||
|
info.setParams(tool.inputSchema().properties());
|
||||||
|
|
||||||
|
JSONObject meta = JSONObject.from(tool.meta());
|
||||||
|
info.setIo(meta.getBoolean("io"));
|
||||||
|
info.setPreActions(meta.getList("pre", String.class));
|
||||||
|
info.setPostActions(meta.getList("post", String.class));
|
||||||
|
info.setStrictDependencies(meta.getBoolean("strict"));
|
||||||
|
info.setTags(meta.getList("tag", String.class));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
private McpClientTransport createTransport(McpServerParams mcpServerParams) {
|
private McpClientTransport createTransport(McpServerParams mcpServerParams) {
|
||||||
return switch (mcpServerParams) {
|
return switch (mcpServerParams) {
|
||||||
case InProcessMcpServerParams params -> {
|
case InProcessMcpServerParams params -> {
|
||||||
|
|||||||
@@ -46,6 +46,22 @@ public class RunnerClientTest {
|
|||||||
System.out.println(query.toString());
|
System.out.println(query.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void schemaTest() {
|
||||||
|
TestRunnerClient testClient = new TestRunnerClient();
|
||||||
|
RunnerClient.StdioMcpServerParams params = new RunnerClient.StdioMcpServerParams(20, "uvx", Map.of("http_proxy", "http://127.0.0.1:7897", "https_proxy", "http://127.0.0.1:7897"), List.of("mcp-server-fetch"));
|
||||||
|
testClient.registerMcpClient("test", params);
|
||||||
|
McpSyncClient client = testClient.mcpClients.values().stream().toList().getFirst();
|
||||||
|
List<McpSchema.Tool> tools = client.listTools().tools();
|
||||||
|
System.out.println("\r\n ------ \r\n");
|
||||||
|
McpSchema.Tool first = tools.getFirst();
|
||||||
|
Map<String, Object> paramsSchema = first.inputSchema().properties();
|
||||||
|
System.out.println(paramsSchema.toString());
|
||||||
|
System.out.println("\r\n ------ \r\n");
|
||||||
|
Map<String, Object> outputSchema = first.outputSchema();
|
||||||
|
System.out.println(outputSchema);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void inProcessMcpTransportTest() {
|
void inProcessMcpTransportTest() {
|
||||||
RunnerClient.InProcessMcpTransport.Pair pair = RunnerClient.InProcessMcpTransport.pair();
|
RunnerClient.InProcessMcpTransport.Pair pair = RunnerClient.InProcessMcpTransport.pair();
|
||||||
|
|||||||
Reference in New Issue
Block a user