Skip to content

Commit 01031ce

Browse files
Merge pull request #47414 from phillip-kruger/chappie-mcp
Expose DevUI's capabilities as MCP functions
2 parents 369e31b + f6fc52d commit 01031ce

File tree

76 files changed

+3999
-1055
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3999
-1055
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.quarkus.runtime.annotations;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.ElementType.PARAMETER;
5+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
6+
7+
import java.lang.annotation.Documented;
8+
import java.lang.annotation.Retention;
9+
import java.lang.annotation.Target;
10+
11+
/**
12+
* Adds metadata to a JsonRPC method to control its behavior and appearance.
13+
*/
14+
@Retention(RUNTIME)
15+
@Target({ METHOD, PARAMETER })
16+
@Documented
17+
public @interface JsonRpcDescription {
18+
19+
/**
20+
* @return the description text
21+
*/
22+
String value();
23+
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.quarkus.runtime.annotations;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Documented;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Defines where the JsonRPC method should be available.
12+
*/
13+
@Retention(RUNTIME)
14+
@Target({ METHOD })
15+
@Documented
16+
public @interface JsonRpcUsage {
17+
Usage[] value();
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.quarkus.runtime.annotations;
2+
3+
import java.util.EnumSet;
4+
5+
public enum Usage {
6+
DEV_UI,
7+
DEV_MCP;
8+
9+
public static EnumSet<Usage> onlyDevUI() {
10+
return EnumSet.of(Usage.DEV_UI);
11+
}
12+
13+
public static EnumSet<Usage> onlyDevMCP() {
14+
return EnumSet.of(Usage.DEV_MCP);
15+
}
16+
17+
public static EnumSet<Usage> devUIandDevMCP() {
18+
return EnumSet.of(Usage.DEV_UI, Usage.DEV_MCP);
19+
}
20+
}

extensions/devui/deployment-spi/src/main/java/io/quarkus/devui/spi/AbstractDevUIBuildItem.java

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package io.quarkus.devui.spi;
22

3-
import java.util.List;
3+
import java.lang.invoke.MethodHandle;
44
import java.util.Map;
55
import java.util.Optional;
66
import java.util.stream.Collectors;
77

88
import io.quarkus.builder.item.MultiBuildItem;
99
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
1010
import io.quarkus.deployment.util.ArtifactInfoUtil;
11+
import io.quarkus.maven.dependency.ArtifactKey;
1112

1213
/**
1314
* For All DEV UI Build Item, we need to distinguish between the extensions, and the internal usage of Dev UI
@@ -16,30 +17,33 @@ public abstract class AbstractDevUIBuildItem extends MultiBuildItem {
1617

1718
private final Class<?> callerClass;
1819
private String extensionIdentifier = null;
19-
20+
private ArtifactKey artifactKey;
2021
private static final String DOT = ".";
21-
private final String customIdentifier;
22+
private final boolean isInternal;
2223

2324
public AbstractDevUIBuildItem() {
2425
this(null);
2526
}
2627

2728
public AbstractDevUIBuildItem(String customIdentifier) {
28-
this.customIdentifier = customIdentifier;
29-
30-
if (this.customIdentifier == null) {
29+
this.extensionIdentifier = customIdentifier;
30+
isInternal = customIdentifier == null;
31+
if (customIdentifier == null) {
3132
// Get the class that will be used to auto-detect the name
3233
StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
3334

34-
List<StackWalker.StackFrame> stackFrames = stackWalker.walk(frames -> frames.collect(Collectors.toList()));
35+
stackWalker.walk(frames -> frames.collect(Collectors.toList()));
3536

3637
Optional<StackWalker.StackFrame> stackFrame = stackWalker.walk(frames -> frames
3738
.filter(frame -> (!frame.getDeclaringClass().getPackageName().startsWith("io.quarkus.devui.spi")
38-
&& !frame.getDeclaringClass().getPackageName().startsWith("io.quarkus.devui.deployment")))
39+
&& !frame.getDeclaringClass().getPackageName().startsWith("io.quarkus.devui.deployment")
40+
&& !frame.getDeclaringClass().equals(MethodHandle.class)))
3941
.findFirst());
4042

4143
if (stackFrame.isPresent()) {
4244
this.callerClass = stackFrame.get().getDeclaringClass();
45+
if (this.callerClass == null)
46+
this.extensionIdentifier = DEV_UI;
4347
} else {
4448
throw new RuntimeException("Could not detect extension identifier automatically");
4549
}
@@ -48,26 +52,28 @@ public AbstractDevUIBuildItem(String customIdentifier) {
4852
}
4953
}
5054

51-
public String getExtensionPathName(CurateOutcomeBuildItem curateOutcomeBuildItem) {
52-
if (this.customIdentifier != null) {
53-
return customIdentifier;
54-
}
55-
if (this.callerClass == null) {
56-
return DEV_UI;
55+
public ArtifactKey getArtifactKey(CurateOutcomeBuildItem curateOutcomeBuildItem) {
56+
if (this.artifactKey == null) {
57+
if (callerClass != null) {
58+
Map.Entry<String, String> groupIdAndArtifactId = ArtifactInfoUtil.groupIdAndArtifactId(callerClass,
59+
curateOutcomeBuildItem);
60+
this.artifactKey = ArtifactKey.ga(groupIdAndArtifactId.getKey(), groupIdAndArtifactId.getValue());
61+
}
5762
}
63+
return this.artifactKey;
64+
}
5865

66+
public String getExtensionPathName(CurateOutcomeBuildItem curateOutcomeBuildItem) {
5967
if (this.extensionIdentifier == null) {
60-
61-
Map.Entry<String, String> groupIdAndArtifactId = ArtifactInfoUtil.groupIdAndArtifactId(callerClass,
62-
curateOutcomeBuildItem);
63-
this.extensionIdentifier = groupIdAndArtifactId.getKey() + DOT + groupIdAndArtifactId.getValue();
68+
ArtifactKey ak = getArtifactKey(curateOutcomeBuildItem);
69+
this.extensionIdentifier = ak.getGroupId() + DOT + ak.getArtifactId();
6470
}
6571

6672
return this.extensionIdentifier;
6773
}
6874

6975
public boolean isInternal() {
70-
return this.customIdentifier != null;
76+
return this.isInternal;
7177
}
7278

7379
public static final String DEV_UI = "devui";

extensions/devui/deployment-spi/src/main/java/io/quarkus/devui/spi/DevUIContent.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ public class DevUIContent {
1010
private final String fileName;
1111
private final byte[] template;
1212
private final Map<String, Object> data;
13+
private final Map<String, String> descriptions;
1314

1415
private DevUIContent(DevUIContent.Builder builder) {
1516
this.fileName = builder.fileName;
1617
this.template = builder.template;
1718
this.data = builder.data;
19+
this.descriptions = builder.descriptions;
1820
}
1921

2022
public String getFileName() {
@@ -29,6 +31,10 @@ public Map<String, Object> getData() {
2931
return data;
3032
}
3133

34+
public Map<String, String> getDescriptions() {
35+
return descriptions;
36+
}
37+
3238
public static Builder builder() {
3339
return new Builder();
3440
}
@@ -37,6 +43,7 @@ public static class Builder {
3743
private String fileName;
3844
private byte[] template;
3945
private Map<String, Object> data;
46+
private Map<String, String> descriptions;
4047

4148
private Builder() {
4249
this.data = new HashMap<>();
@@ -69,6 +76,11 @@ public Builder addData(String key, Object value) {
6976
return this;
7077
}
7178

79+
public Builder descriptions(Map<String, String> descriptions) {
80+
this.descriptions = descriptions;
81+
return this;
82+
}
83+
7284
public DevUIContent build() {
7385
if (fileName == null) {
7486
throw new RuntimeException(

extensions/devui/deployment-spi/src/main/java/io/quarkus/devui/spi/buildtime/BuildTimeAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* Define a action that can be executed against the deployment classpath in runtime
1111
* This means a call will still be make with Json-RPC to the backend, but fall through to this action
1212
*/
13+
@Deprecated
1314
public class BuildTimeAction {
1415

1516
private final String methodName;

0 commit comments

Comments
 (0)