|
17 | 17 | import java.nio.file.StandardOpenOption; |
18 | 18 | import java.util.Comparator; |
19 | 19 | import java.util.HashMap; |
| 20 | +import java.util.LinkedHashMap; |
20 | 21 | import java.util.ServiceLoader; |
| 22 | +import java.util.Set; |
21 | 23 | import java.util.concurrent.TimeUnit; |
22 | 24 | import java.util.stream.Collectors; |
23 | 25 | import software.amazon.smithy.java.core.schema.SerializableStruct; |
| 26 | +import software.amazon.smithy.java.io.ByteBufferUtils; |
24 | 27 | import software.amazon.smithy.java.json.JsonCodec; |
| 28 | +import software.amazon.smithy.java.mcp.cli.model.ClientConfig; |
25 | 29 | import software.amazon.smithy.java.mcp.cli.model.Config; |
26 | 30 | import software.amazon.smithy.java.mcp.cli.model.GenericToolBundleConfig; |
27 | 31 | import software.amazon.smithy.java.mcp.cli.model.Location; |
28 | 32 | import software.amazon.smithy.java.mcp.cli.model.McpBundleConfig; |
| 33 | +import software.amazon.smithy.java.mcp.cli.model.McpServerConfig; |
| 34 | +import software.amazon.smithy.java.mcp.cli.model.McpServersClientConfig; |
29 | 35 | import software.amazon.smithy.java.mcp.cli.model.SmithyModeledBundleConfig; |
30 | 36 | import software.amazon.smithy.mcp.bundle.api.model.Bundle; |
31 | 37 | import software.amazon.smithy.mcp.bundle.api.model.ExecSpec; |
@@ -149,6 +155,79 @@ public static Bundle getMcpBundle(String bundleName) { |
149 | 155 | } |
150 | 156 | } |
151 | 157 |
|
| 158 | + public static void removeMcpBundle(Config currentConfig, String bundleName) throws IOException { |
| 159 | + var builder = currentConfig.toBuilder(); |
| 160 | + var newBundles = new LinkedHashMap<>(currentConfig.getToolBundles()); |
| 161 | + newBundles.remove(bundleName); |
| 162 | + builder.toolBundles(newBundles); |
| 163 | + var newConfig = builder.build(); |
| 164 | + updateConfig(newConfig); |
| 165 | + var bundleFile = getBundleFileLocation(bundleName); |
| 166 | + Files.deleteIfExists(bundleFile); |
| 167 | + } |
| 168 | + |
| 169 | + public static void addToClientConfigs(Config config, String name, Set<String> clients, McpServerConfig serverConfig) |
| 170 | + throws IOException { |
| 171 | + updateClientConfigs(config, name, clients, serverConfig); |
| 172 | + } |
| 173 | + |
| 174 | + public static void removeFromClientConfigs(Config config, String name, Set<String> clients) throws IOException { |
| 175 | + updateClientConfigs(config, name, clients, null); |
| 176 | + } |
| 177 | + |
| 178 | + private static void updateClientConfigs(Config config, String name, Set<String> clients, McpServerConfig newConfig) |
| 179 | + throws IOException { |
| 180 | + var clientConfigsToUpdate = getClientConfigsToUpdate(config, clients); |
| 181 | + boolean isDelete = newConfig == null; |
| 182 | + for (var clientConfigs : clientConfigsToUpdate) { |
| 183 | + var filePath = Path.of(clientConfigs.getFilePath()); |
| 184 | + if (Files.notExists(filePath)) { |
| 185 | + System.out.printf("Skipping updating Mcp config file for %s as the file path '%s' does not exist.", |
| 186 | + name, |
| 187 | + filePath); |
| 188 | + continue; |
| 189 | + } |
| 190 | + var currentConfig = Files.readAllBytes(filePath); |
| 191 | + McpServersClientConfig currentMcpConfig; |
| 192 | + if (currentConfig.length == 0) { |
| 193 | + if (isDelete) { |
| 194 | + continue; |
| 195 | + } |
| 196 | + currentMcpConfig = McpServersClientConfig.builder().build(); |
| 197 | + } else { |
| 198 | + currentMcpConfig = |
| 199 | + McpServersClientConfig.builder() |
| 200 | + .deserialize(JSON_CODEC.createDeserializer(currentConfig)) |
| 201 | + .build(); |
| 202 | + } |
| 203 | + var map = new LinkedHashMap<>(currentMcpConfig.getMcpServers()); |
| 204 | + if (isDelete) { |
| 205 | + if (map.remove(name) == null) { |
| 206 | + continue; |
| 207 | + } |
| 208 | + } else { |
| 209 | + map.put(name, newConfig); |
| 210 | + } |
| 211 | + var newMcpConfig = McpServersClientConfig.builder().mcpServers(map).build(); |
| 212 | + Files.write(filePath, |
| 213 | + ByteBufferUtils.getBytes(JSON_CODEC.serialize(newMcpConfig)), |
| 214 | + StandardOpenOption.TRUNCATE_EXISTING); |
| 215 | + } |
| 216 | + } |
| 217 | + |
| 218 | + private static Set<ClientConfig> getClientConfigsToUpdate(Config config, Set<String> clients) { |
| 219 | + Set<ClientConfig> clientConfigsToUpdate; |
| 220 | + if (!clients.isEmpty()) { |
| 221 | + clientConfigsToUpdate = config.getClientConfigs() |
| 222 | + .stream() |
| 223 | + .filter(c -> clients.contains(c.getName())) |
| 224 | + .collect(Collectors.toUnmodifiableSet()); |
| 225 | + } else { |
| 226 | + clientConfigsToUpdate = Set.copyOf(config.getClientConfigs()); |
| 227 | + } |
| 228 | + return clientConfigsToUpdate; |
| 229 | + } |
| 230 | + |
152 | 231 | private static void addMcpBundle(Config config, String toolBundleName, CliBundle mcpBundleConfig) |
153 | 232 | throws IOException { |
154 | 233 | var serializedBundle = toJson(mcpBundleConfig.mcpBundle()); |
|
0 commit comments