Skip to content

Commit 6c29016

Browse files
committed
Add pagination to list
1 parent ee01081 commit 6c29016

File tree

5 files changed

+75
-23
lines changed

5 files changed

+75
-23
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.List;
1212
import java.util.Locale;
1313
import java.util.Objects;
14+
import java.util.stream.Stream;
1415
import software.amazon.smithy.java.aws.servicebundle.bundler.AwsServiceBundler;
1516
import software.amazon.smithy.mcp.bundle.api.Registry;
1617
import software.amazon.smithy.mcp.bundle.api.model.Bundle;
@@ -51,8 +52,8 @@ public String name() {
5152
}
5253

5354
@Override
54-
public List<RegistryEntry> listMcpBundles() {
55-
return availableMcpBundles;
55+
public Stream<RegistryEntry> listMcpBundles() {
56+
return availableMcpBundles.stream();
5657
}
5758

5859
@Override

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ osdetector = "1.7.3"
1616
accp = "2.4.1" # Amazon Corretto Crypto Provider
1717
jreleaser = "1.19.0"
1818
picocli = "4.7.7"
19+
jline = "3.30.4"
1920
graalvm-native = "0.11.0"
2021
shadow = "8.3.8"
2122

@@ -46,6 +47,8 @@ netty-all = {module = "io.netty:netty-all", version.ref = "netty"}
4647
# CLI related dependencies
4748
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
4849
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
50+
jline-terminal = { module = "org.jline:jline-terminal", version.ref = "jline" }
51+
jline-reader = { module = "org.jline:jline-reader", version.ref = "jline" }
4952

5053
# Test dependencies
5154
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit5" }

mcp/mcp-bundle-api/src/main/java/software/amazon/smithy/mcp/bundle/api/Registry.java

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

66
package software.amazon.smithy.mcp.bundle.api;
77

8-
import java.util.List;
8+
import java.util.stream.Stream;
99
import software.amazon.smithy.mcp.bundle.api.model.Bundle;
1010
import software.amazon.smithy.mcp.bundle.api.model.BundleMetadata;
1111

@@ -39,7 +39,7 @@ public BundleMetadata getBundleMetadata() {
3939

4040
String name();
4141

42-
List<RegistryEntry> listMcpBundles();
42+
Stream<RegistryEntry> listMcpBundles();
4343

4444
Bundle getMcpBundle(String id);
4545

mcp/mcp-cli/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ dependencies {
2020
implementation(project(":codecs:json-codec", configuration = "shadow"))
2121
implementation(libs.picocli)
2222
annotationProcessor(libs.picocli.codegen)
23+
implementation(libs.jline.terminal)
24+
implementation(libs.jline.reader)
2325
api(project(":mcp:mcp-cli-api"))
2426
api(project(":mcp:mcp-schemas"))
2527
implementation(libs.smithy.utils)

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

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77

88
import static picocli.CommandLine.Command;
99

10+
import java.util.Map;
11+
import org.jline.terminal.Terminal;
12+
import org.jline.terminal.TerminalBuilder;
1013
import picocli.CommandLine;
1114
import picocli.CommandLine.Option;
1215
import picocli.CommandLine.Spec;
1316
import software.amazon.smithy.java.mcp.cli.ExecutionContext;
1417
import software.amazon.smithy.java.mcp.cli.SmithyMcpCommand;
1518
import software.amazon.smithy.java.mcp.cli.model.Config;
1619
import software.amazon.smithy.java.mcp.cli.model.GenericToolBundleConfig;
20+
import software.amazon.smithy.java.mcp.cli.model.McpBundleConfig;
1721
import software.amazon.smithy.java.mcp.cli.model.SmithyModeledBundleConfig;
1822
import software.amazon.smithy.mcp.bundle.api.Registry;
1923

@@ -38,25 +42,7 @@ protected void execute(ExecutionContext context) {
3842
.string("@|bold,underline Registry MCP Servers:|@"));
3943
System.out.println();
4044

41-
// Display registry bundles
42-
for (Registry.RegistryEntry entry : registry.listMcpBundles()) {
43-
var bundle = entry.getBundleMetadata();
44-
var installedBundle = installedBundles.get(bundle.getId());
45-
//If there is a local bundle with the same name, prefer that.
46-
boolean isInstalled = installedBundle != null;
47-
boolean hasLocalOverride = isInstalled && switch (installedBundle.getValue()) {
48-
case SmithyModeledBundleConfig config -> config.isLocal();
49-
case GenericToolBundleConfig config -> config.isLocal();
50-
default -> false;
51-
};
52-
String tag = null;
53-
if (hasLocalOverride) {
54-
tag = "locally-overriden";
55-
} else if (isInstalled) {
56-
tag = "installed";
57-
}
58-
printBundleInfo(commandLine, bundle.getId(), bundle.getName(), bundle.getDescription(), tag);
59-
}
45+
displayRegistryBundlesPaginated(registry, installedBundles, commandLine);
6046

6147
var localBundles = context.config()
6248
.getToolBundles()
@@ -97,6 +83,46 @@ protected String registryToUse(Config config) {
9783
return registryName;
9884
}
9985

86+
private void displayRegistryBundlesPaginated(
87+
Registry registry,
88+
Map<String, McpBundleConfig> installedBundles,
89+
CommandLine commandLine
90+
) {
91+
var registryIterator = registry.listMcpBundles().iterator();
92+
int displayedCount = 0;
93+
final int pageSize = 10;
94+
95+
while (registryIterator.hasNext()) {
96+
if (displayedCount > 0 && displayedCount % pageSize == 0) {
97+
System.out.println("Press down arrow for more...");
98+
if (!waitForDownArrow()) {
99+
break;
100+
}
101+
}
102+
103+
var entry = registryIterator.next();
104+
var bundle = entry.getBundleMetadata();
105+
var installedBundle = installedBundles.get(bundle.getId());
106+
107+
boolean isInstalled = installedBundle != null;
108+
boolean hasLocalOverride = isInstalled && switch (installedBundle.getValue()) {
109+
case SmithyModeledBundleConfig config -> config.isLocal();
110+
case GenericToolBundleConfig config -> config.isLocal();
111+
default -> false;
112+
};
113+
114+
String tag = null;
115+
if (hasLocalOverride) {
116+
tag = "locally-overriden";
117+
} else if (isInstalled) {
118+
tag = "installed";
119+
}
120+
121+
printBundleInfo(commandLine, bundle.getId(), bundle.getName(), bundle.getDescription(), tag);
122+
displayedCount++;
123+
}
124+
}
125+
100126
private void printBundleInfo(
101127
CommandLine commandLine,
102128
String bundleId,
@@ -116,4 +142,24 @@ private void printBundleInfo(
116142
System.out.println(description);
117143
System.out.println();
118144
}
145+
146+
private boolean waitForDownArrow() {
147+
try (Terminal terminal = TerminalBuilder.builder()
148+
.system(true)
149+
.build()) {
150+
terminal.enterRawMode();
151+
int ch = terminal.reader().read();
152+
153+
if (ch == 27) {
154+
int bracket = terminal.reader().read();
155+
if (bracket == 91) {
156+
int arrow = terminal.reader().read();
157+
return arrow == 66;
158+
}
159+
}
160+
return false;
161+
} catch (Exception e) {
162+
return false;
163+
}
164+
}
119165
}

0 commit comments

Comments
 (0)