Skip to content

Commit 3fe46ad

Browse files
committed
Introduce id into the bundle metadata and other minor fixes
1 parent df4999a commit 3fe46ad

File tree

8 files changed

+116
-79
lines changed

8 files changed

+116
-79
lines changed

aws/aws-mcp-cli-commands/src/main/java/software/amazon/smithy/java/aws/mcp/cli/commands/CreateAwsServiceBundle.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ protected Bundle getNewBundle(CreateAwsServiceBundleInput input) {
5555
.smithyBundle(SmithyMcpBundle.builder()
5656
.bundle(bundleBuilder.build().bundle())
5757
.metadata(BundleMetadata.builder()
58+
.id(input.id)
5859
.name(input.name)
5960
.description(input.description)
6061
.build())

mcp/mcp-bundle-api/src/main/resources/META-INF/smithy/mcpbundle.smithy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ structure CommonBundleConfig {
1919
}
2020

2121
structure BundleMetadata {
22+
// Do not mark required for backward compatibility.
23+
id: String
24+
2225
@required
2326
name: String
2427

mcp/mcp-cli-api/model/main.smithy

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ $version: "2"
22

33
namespace smithy.mcp.cli
44

5+
use software.amazon.smithy.mcp.bundle.api#BundleMetadata
6+
57
structure Config {
68
toolBundles: McpBundleConfigs
79

@@ -36,8 +38,8 @@ structure CommonToolConfig {
3638

3739
@default(false)
3840
local: PrimitiveBoolean
39-
40-
description: String
41+
42+
metadata: BundleMetadata
4143
}
4244

4345
map Registries {

mcp/mcp-cli-api/src/main/java/software/amazon/smithy/java/mcp/cli/AbstractCreateBundle.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ public abstract static class CreateBundleInput {
1818
defaultValue = "false")
1919
boolean overwrite;
2020

21-
@Option(names = {"-n", "--name"}, description = "Name to assign to the MCP server. Eg: (aws-dynamodb-mcp)",
21+
@Option(names = {"--id"},
22+
description = "Id to assign to the MCP server. This id needs to end in mcp. Eg: (aws-dynamodb-mcp)",
2223
required = true)
24+
public String id;
25+
26+
@Option(names = {"--name"}, description = "Name for this MCP server. Eg: (Pipelines MCP Server)")
2327
public String name;
2428

25-
@Option(names = {"-d", "--description"}, description = "Description of this mcp server", required = true)
29+
@Option(names = {"-d", "--description"}, description = "Description of this mcp server.", required = true)
2630
public String description;
2731

2832
@ArgGroup
@@ -42,15 +46,22 @@ public static class JsonInput {
4246
protected void execute(ExecutionContext context) throws Exception {
4347
var input = getInput();
4448
var config = context.config();
45-
if (!input.overwrite && config.getToolBundles().containsKey(input.name)) {
46-
throw new IllegalArgumentException("Tool bundle " + input.name
49+
if (!input.overwrite && config.getToolBundles().containsKey(input.id)) {
50+
throw new IllegalArgumentException("Tool bundle " + input.id
4751
+ " already exists. Either choose a new name or pass --overwrite to overwrite the existing tool bundle");
4852
}
4953

54+
if (input.name == null) {
55+
input.name = input.id;
56+
}
57+
if (input.description == null) {
58+
input.description = "[" + input.id + "]" + " MCP Server";
59+
}
60+
5061
var bundle = getNewBundle(input);
51-
ConfigUtils.addMcpBundle(config, input.name, bundle, true);
52-
ConfigUtils.createWrapperAndUpdateClientConfigs(input.name, bundle, config, input.clientsInput);
53-
System.out.println("Successfully created bundle " + input.name);
62+
ConfigUtils.addMcpBundle(config, input.id, bundle, true);
63+
ConfigUtils.createWrapperAndUpdateClientConfigs(input.id, bundle, config, input.clientsInput);
64+
System.out.println("Successfully created bundle " + input.id);
5465
}
5566

5667
protected abstract T getInput();

mcp/mcp-cli-api/src/main/java/software/amazon/smithy/java/mcp/cli/ClientsInput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ public final class ClientsInput {
1515

1616
@Option(names = "--print-client-config",
1717
description = "If specified will not edit the client configs and only print to console.")
18-
public Boolean print;
18+
public boolean print = false;
1919
}

mcp/mcp-cli-api/src/main/java/software/amazon/smithy/java/mcp/cli/ConfigUtils.java

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ public static Config loadOrCreateConfig() throws IOException {
144144
return config;
145145
}
146146

147-
public static Path getBundleFileLocation(String bundleName) {
148-
return BUNDLE_DIR.resolve(bundleName + ".json");
147+
public static Path getBundleFileLocation(String id) {
148+
return BUNDLE_DIR.resolve(id + ".json");
149149
}
150150

151151
/**
@@ -188,47 +188,47 @@ private static void addMcpBundleConfig(Config existingConfig, String name, McpBu
188188
updateConfig(newConfig);
189189
}
190190

191-
public static Bundle getMcpBundle(String bundleName) {
191+
public static Bundle getMcpBundle(String id) {
192192
try {
193193
return Bundle.builder()
194-
.deserialize(JSON_CODEC.createDeserializer(Files.readAllBytes(getBundleFileLocation(bundleName))))
194+
.deserialize(JSON_CODEC.createDeserializer(Files.readAllBytes(getBundleFileLocation(id))))
195195
.build();
196196
} catch (IOException e) {
197197
throw new RuntimeException(e);
198198
}
199199
}
200200

201-
public static void removeMcpBundle(Config currentConfig, String bundleName) throws IOException {
201+
public static void removeMcpBundle(Config currentConfig, String id) throws IOException {
202202
var builder = currentConfig.toBuilder();
203203
var newBundles = new LinkedHashMap<>(currentConfig.getToolBundles());
204-
newBundles.remove(bundleName);
204+
newBundles.remove(id);
205205
builder.toolBundles(newBundles);
206206
var newConfig = builder.build();
207207
updateConfig(newConfig);
208-
var bundleFile = getBundleFileLocation(bundleName);
208+
var bundleFile = getBundleFileLocation(id);
209209
Files.deleteIfExists(bundleFile);
210210
// Remove wrapper script if it exists
211-
removeWrapperScript(bundleName);
211+
removeWrapperScript(id);
212212
}
213213

214-
public static void addToClientConfigs(Config config, String name, Set<String> clients, McpServerConfig serverConfig)
214+
public static void addToClientConfigs(Config config, String id, Set<String> clients, McpServerConfig serverConfig)
215215
throws IOException {
216-
updateClientConfigs(config, name, clients, serverConfig);
216+
updateClientConfigs(config, id, clients, serverConfig);
217217
}
218218

219-
public static void removeFromClientConfigs(Config config, String name, Set<String> clients) throws IOException {
220-
updateClientConfigs(config, name, clients, null);
219+
public static void removeFromClientConfigs(Config config, String id, Set<String> clients) throws IOException {
220+
updateClientConfigs(config, id, clients, null);
221221
}
222222

223-
private static void updateClientConfigs(Config config, String name, Set<String> clients, McpServerConfig newConfig)
223+
private static void updateClientConfigs(Config config, String id, Set<String> clients, McpServerConfig newConfig)
224224
throws IOException {
225225
var clientConfigsToUpdate = getClientConfigsToUpdate(config, clients);
226226
boolean isDelete = newConfig == null;
227227
for (var clientConfigs : clientConfigsToUpdate) {
228228
var filePath = Path.of(clientConfigs.getFilePath());
229229
if (Files.notExists(filePath)) {
230230
System.out.printf("Skipping updating Mcp config file for %s as the file path '%s' does not exist.",
231-
name,
231+
id,
232232
filePath);
233233
continue;
234234
}
@@ -243,11 +243,11 @@ private static void updateClientConfigs(Config config, String name, Set<String>
243243

244244
var map = new LinkedHashMap<>(currentMcpConfig.getMcpServers());
245245
if (isDelete) {
246-
if (map.remove(name) == null) {
246+
if (map.remove(id) == null) {
247247
continue;
248248
}
249249
} else {
250-
map.put(name, Document.of(newConfig));
250+
map.put(id, Document.of(newConfig));
251251
}
252252
var newMcpConfig = McpServersClientConfig.builder().mcpServers(map).build();
253253
Files.write(filePath,
@@ -283,10 +283,10 @@ private static Set<ClientConfig> getClientConfigsToUpdate(Config config, Set<Str
283283
return clientConfigsToUpdate;
284284
}
285285

286-
private static void writeMcpBundle(String toolBundleName, Bundle bundle)
286+
private static void writeMcpBundle(String id, Bundle bundle)
287287
throws IOException {
288288
var serializedBundle = toJson(bundle);
289-
Files.write(getBundleFileLocation(toolBundleName),
289+
Files.write(getBundleFileLocation(id),
290290
serializedBundle,
291291
StandardOpenOption.TRUNCATE_EXISTING,
292292
StandardOpenOption.CREATE);
@@ -297,35 +297,35 @@ public static McpBundleConfig addMcpBundle(Config config, String toolBundleName,
297297
return addMcpBundle(config, toolBundleName, bundle, false);
298298
}
299299

300-
public static McpBundleConfig addMcpBundle(Config config, String toolBundleName, Bundle bundle, boolean isLocal)
300+
public static McpBundleConfig addMcpBundle(Config config, String id, Bundle bundle, boolean isLocal)
301301
throws IOException {
302302
var location = Location.builder()
303-
.fileLocation(ConfigUtils.getBundleFileLocation(toolBundleName).toString())
303+
.fileLocation(ConfigUtils.getBundleFileLocation(id).toString())
304304
.build();
305305
var builder = McpBundleConfig.builder();
306306
switch (bundle.getValue()) {
307307
case SmithyMcpBundle smithyBundle -> builder.smithyModeled(SmithyModeledBundleConfig.builder()
308-
.name(toolBundleName)
309-
.description(smithyBundle.getMetadata().getDescription())
308+
.name(id)
309+
.metadata(smithyBundle.getMetadata())
310310
.bundleLocation(location)
311311
.local(isLocal)
312312
.build());
313313
case GenericBundle genericBundle -> {
314314
install(genericBundle.getInstall());
315315
builder.genericConfig(
316316
GenericToolBundleConfig.builder()
317-
.name(toolBundleName)
317+
.name(id)
318318
.local(isLocal)
319319
.bundleLocation(location)
320-
.description(genericBundle.getMetadata().getDescription())
320+
.metadata(genericBundle.getMetadata())
321321
.build());
322322
}
323323
default -> throw new IllegalStateException("Unexpected bundle type: " + bundle.type());
324324
}
325325

326326
var mcpBundleConfig = builder.build();
327-
writeMcpBundle(toolBundleName, bundle);
328-
addMcpBundleConfig(config, toolBundleName, mcpBundleConfig);
327+
writeMcpBundle(id, bundle);
328+
addMcpBundleConfig(config, id, mcpBundleConfig);
329329
return mcpBundleConfig;
330330
}
331331

@@ -384,9 +384,9 @@ private static String captureProcessOutput(Process process) throws IOException {
384384
}
385385
}
386386

387-
public static void createWrapperScript(String bundleName) throws IOException {
388-
Path scriptPath = SHIMS_DIR.resolve(bundleName);
389-
String scriptContent = createScriptContent(bundleName);
387+
public static void createWrapperScript(String id) throws IOException {
388+
Path scriptPath = SHIMS_DIR.resolve(id);
389+
String scriptContent = createScriptContent(id);
390390

391391
Files.writeString(scriptPath, scriptContent, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
392392
scriptPath.toFile().setExecutable(true);
@@ -400,8 +400,8 @@ private static String createScriptContent(String bundleName) {
400400
}
401401
}
402402

403-
public static void removeWrapperScript(String bundleName) throws IOException {
404-
Path scriptPath = SHIMS_DIR.resolve(bundleName);
403+
public static void removeWrapperScript(String id) throws IOException {
404+
Path scriptPath = SHIMS_DIR.resolve(id);
405405
Files.deleteIfExists(scriptPath);
406406
}
407407

@@ -502,22 +502,22 @@ private static void printUnixPathInstructions(String shimsDirStr) {
502502
}
503503

504504
public static void createWrapperAndUpdateClientConfigs(
505-
String name,
505+
String id,
506506
Bundle bundle,
507507
Config config,
508508
ClientsInput input
509509
) throws IOException {
510510
boolean shouldCreateWrapper = true;
511511
List<String> args = List.of();
512-
String command = name;
512+
String command = id;
513513
if (bundle.getValue() instanceof GenericBundle genericBundle && genericBundle.isExecuteDirectly()) {
514514
command = genericBundle.getRun().getExecutable();
515515
args = genericBundle.getRun().getArgs();
516516
shouldCreateWrapper = false;
517517
}
518518

519519
if (shouldCreateWrapper) {
520-
createWrapperScript(name);
520+
createWrapperScript(id);
521521
ensureMcpServersDirInPath();
522522
}
523523

@@ -537,11 +537,11 @@ public static void createWrapperAndUpdateClientConfigs(
537537
}
538538

539539
if (print) {
540-
System.out.println("You can add the following to your MCP Servers config to use " + name);
540+
System.out.println("You can add the following to your MCP Servers config to use " + id);
541541
var serializedConfig = ByteBufferUtils.getBytes(JSON_CODEC.serialize(newClientConfig));
542542
System.out.println(new String(serializedConfig, StandardCharsets.UTF_8));
543543
} else {
544-
addToClientConfigs(config, name, clientConfigs, newClientConfig);
544+
addToClientConfigs(config, id, clientConfigs, newClientConfig);
545545
}
546546
}
547547
}

mcp/mcp-cli/src/main/java/software/amazon/smithy/java/mcp/cli/commands/InstallBundle.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import java.io.IOException;
1111
import java.util.Set;
12-
import picocli.CommandLine.Mixin;
12+
import picocli.CommandLine.ArgGroup;
1313
import picocli.CommandLine.Option;
1414
import picocli.CommandLine.Parameters;
1515
import software.amazon.smithy.java.mcp.cli.ClientsInput;
@@ -28,7 +28,7 @@ public class InstallBundle extends SmithyMcpCommand {
2828
@Parameters(description = "Names of the MCP bundles to install.")
2929
Set<String> names;
3030

31-
@Mixin
31+
@ArgGroup
3232
ClientsInput clientsInput;
3333

3434
@Override

0 commit comments

Comments
 (0)