fix(LocalRunnerClient): support cleaning non-existing MCP Servers' tools while MCP configuration files changed in CommonMcp

This commit is contained in:
2026-01-16 21:48:17 +08:00
parent fb5cabc747
commit c793851107
2 changed files with 42 additions and 6 deletions

View File

@@ -1269,13 +1269,13 @@ public class LocalRunnerClient extends RunnerClient {
private void checkAndReload(boolean trustCache) {
/*
for each file cannot present all mcp configurations,
we need to load all at once, and then compare them with existed records.
we will record existing mcp paramsCacheMap and id-params map for which is changed.
for each file cannot present all mcp configurations,
we need to load all at once, and then compare them with existed records.
we will record existing mcp paramsCacheMap and id-params map for which is changed.
recording changedMap only cannot figure out which mcp was deleted,
so existingMcpIdSet attr is required
*/
recording changedMap only cannot figure out which mcp was deleted,
so existingMcpIdSet attr is required
*/
val changedMap = new HashMap<String, McpClientTransportParams>();
val existingMcpIdSet = new HashSet<String>();
@@ -1349,6 +1349,8 @@ public class LocalRunnerClient extends RunnerClient {
// new mcp clients and outdated clients has been updated in above logic
// this part focus on removing non-existing mcp
mcpClients.keySet().removeIf(id -> !existingMcpIdSet.contains(id));
// clear relevant tools' action info
existedMetaActions.keySet().removeIf(id -> !existingMcpIdSet.contains(id.split("::")[0]));
}
private boolean fileChanged(File file, McpConfigFileRecord fileRecord) {

View File

@@ -701,6 +701,40 @@ public class LocalRunnerClientTest {
}
}
@Test
void testCommonMcpRemoveEntryFromConfig(@TempDir Path tempDir) throws IOException, InterruptedException {
ConcurrentHashMap<String, MetaActionInfo> existedMetaActions = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
new LocalRunnerClient(existedMetaActions, executor, tempDir.toString());
try {
Path mcpDir = tempDir.resolve("action").resolve("mcp");
Files.createDirectories(mcpDir);
Path configFile = mcpDir.resolve("servers.json");
String config = buildCommonMcpConfig(
buildStdioServerEntry("mcp-deepwiki", "mcp-deepwiki@latest"),
buildStdioServerEntry("playwright", "@playwright/mcp@latest")
);
writeCommonMcpConfig(configFile, config);
waitForCondition(() -> hasActionKey(existedMetaActions, key -> key.startsWith("mcp-deepwiki::")), 20000);
waitForCondition(() -> hasActionKey(existedMetaActions, key -> key.startsWith("playwright::")), 20000);
Assertions.assertTrue(hasActionKey(existedMetaActions, key -> key.startsWith("mcp-deepwiki::")));
Assertions.assertTrue(hasActionKey(existedMetaActions, key -> key.startsWith("playwright::")));
String updatedConfig = buildCommonMcpConfig(
buildStdioServerEntry("mcp-deepwiki", "mcp-deepwiki@latest")
);
writeCommonMcpConfig(configFile, updatedConfig);
waitForCondition(() -> !hasActionKey(existedMetaActions, key -> key.startsWith("playwright::")), 20000);
Assertions.assertFalse(hasActionKey(existedMetaActions, key -> key.startsWith("playwright::")));
Assertions.assertTrue(hasActionKey(existedMetaActions, key -> key.startsWith("mcp-deepwiki::")));
} finally {
executor.shutdownNow();
}
}
@Test
void testCommonMcpInvalidJsonRecovery(@TempDir Path tempDir) throws IOException, InterruptedException {
ConcurrentHashMap<String, MetaActionInfo> existedMetaActions = new ConcurrentHashMap<>();