1010
1111import java .util .ArrayList ;
1212import java .util .List ;
13+ import java .util .Map ;
1314
1415import javax .lang .model .element .ExecutableElement ;
1516
@@ -435,14 +436,8 @@ public List<String> generateMcpDefinitionMethod(boolean kt) {
435436 String sizeArg = (sizeStr .isEmpty () || sizeStr .equals ("-1" )) ? "null" : sizeStr + "L" ;
436437
437438 // --- NESTED ANNOTATION EXTRACTION ---
438- // We parse the string representation of the annotation to avoid massive APT ElementVisitor
439- // boilerplate.
440- // It looks like: @...McpAnnotations(audience={"USER"}, priority=1.0, lastModified="2024")
441439 String annotationsArg = "null" ;
442- String rawAnnotations =
443- extractAnnotationValue ("io.jooby.annotation.mcp.McpResource" , "annotations" );
444-
445- boolean hasAnnotations = rawAnnotations .contains ("priority=" );
440+ var annotation = parseResourceAnnotation ();
446441
447442 var isTemplate = isMcpResourceTemplate ();
448443 var specType = isTemplate ? "ResourceTemplate" : "Resource" ;
@@ -459,32 +454,15 @@ public List<String> generateMcpDefinitionMethod(boolean kt) {
459454 " {" ));
460455
461456 // Build the Kotlin ResourceAnnotations object if present
462- if (hasAnnotations ) {
463- annotationsArg = "annotations" ;
464- String audienceList =
465- rawAnnotations .contains ("USER" ) && rawAnnotations .contains ("ASSISTANT" )
466- ? "listOf(io.modelcontextprotocol.spec.McpSchema.Role.USER,"
467- + " io.modelcontextprotocol.spec.McpSchema.Role.ASSISTANT)"
468- : (rawAnnotations .contains ("USER" )
469- ? "listOf(io.modelcontextprotocol.spec.McpSchema.Role.USER)"
470- : (rawAnnotations .contains ("ASSISTANT" )
471- ? "listOf(io.modelcontextprotocol.spec.McpSchema.Role.ASSISTANT)"
472- : "emptyList()" ));
473-
474- String priority = rawAnnotations .replaceAll (".*priority=([0-9.]+).*" , "$1" );
475- var lastMod =
476- rawAnnotations .contains ("lastModified=" )
477- ? string (rawAnnotations .replaceAll (".*lastModified=\" ([^\" ]+)\" .*" , "$1" ))
478- : "null" ;
479-
480- buffer .add (statement (indent (6 ), "val audience = " , audienceList ));
457+ if (annotation != null ) {
458+ buffer .add (statement (indent (6 ), "val audience = " , "listOf(" , annotation .audience , "" ));
481459 buffer .add (
482460 statement (
483461 indent (6 ),
484462 "val annotations = io.modelcontextprotocol.spec.McpSchema.Annotations(audience, " ,
485- priority ,
463+ annotation . priority ,
486464 ", " ,
487- lastMod ,
465+ annotation . lastModified ,
488466 ")" ));
489467 }
490468
@@ -539,33 +517,25 @@ public List<String> generateMcpDefinitionMethod(boolean kt) {
539517 "Spec() {" ));
540518
541519 // Build the Java ResourceAnnotations object if present
542- if (hasAnnotations ) {
520+ if (annotation != null ) {
543521 annotationsArg = "annotations" ;
544- String audienceList =
545- rawAnnotations .contains ("USER" ) && rawAnnotations .contains ("ASSISTANT" )
546- ? "java.util.List.of(io.modelcontextprotocol.spec.McpSchema.Role.USER,"
547- + " io.modelcontextprotocol.spec.McpSchema.Role.ASSISTANT)"
548- : (rawAnnotations .contains ("USER" )
549- ? "java.util.List.of(io.modelcontextprotocol.spec.McpSchema.Role.USER)"
550- : (rawAnnotations .contains ("ASSISTANT" )
551- ? "java.util.List.of(io.modelcontextprotocol.spec.McpSchema.Role.ASSISTANT)"
552- : "java.util.Collections.emptyList()" ));
553-
554- String priority = rawAnnotations .replaceAll (".*priority=([0-9.]+).*" , "$1" );
555- var lastMod =
556- rawAnnotations .contains ("lastModified=" )
557- ? string (rawAnnotations .replaceAll (".*lastModified=\" ([^\" ]+)\" .*" , "$1" ))
558- : "null" ;
559-
560- buffer .add (statement (indent (6 ), "var audience = " , audienceList , semicolon (kt )));
522+
523+ buffer .add (
524+ statement (
525+ indent (6 ),
526+ "var audience = " ,
527+ "java.util.List.of(" ,
528+ annotation .audience ,
529+ ")" ,
530+ semicolon (kt )));
561531 buffer .add (
562532 statement (
563533 indent (6 ),
564534 "var annotations = new"
565535 + " io.modelcontextprotocol.spec.McpSchema.Annotations(audience, " ,
566- priority ,
536+ annotation . priority ,
567537 "D, " ,
568- lastMod ,
538+ annotation . lastModified ,
569539 ")" ,
570540 semicolon (kt )));
571541 }
@@ -940,5 +910,39 @@ private boolean hasOutputSchema() {
940910 && !isMcpClass ;
941911 }
942912
943- private record McpAnnotation (String name , String value ) {}
913+ private McpAnnotation parseResourceAnnotation () {
914+ String rawAnnotations =
915+ extractAnnotationValue ("io.jooby.annotation.mcp.McpResource" , "annotations" );
916+
917+ boolean hasAnnotations = rawAnnotations .contains ("priority=" );
918+
919+ if (!hasAnnotations ) {
920+ return null ;
921+ }
922+
923+ var audienceList = new ArrayList <String >();
924+ var annotationMap =
925+ Map .of (
926+ "USER" ,
927+ "io.modelcontextprotocol.spec.McpSchema.Role.USER" ,
928+ "ASSISTANT" ,
929+ "io.modelcontextprotocol.spec.McpSchema.Role.ASSISTANT" );
930+ for (var entry : annotationMap .entrySet ()) {
931+ if (rawAnnotations .contains (entry .getKey ())) {
932+ audienceList .add (entry .getValue ());
933+ }
934+ }
935+ if (audienceList .isEmpty ()) {
936+ audienceList .add (annotationMap .get ("USER" ));
937+ }
938+ var priority = rawAnnotations .replaceAll (".*priority=([0-9.]+).*" , "$1" );
939+ var lastMod =
940+ rawAnnotations .contains ("lastModified=" )
941+ ? string (rawAnnotations .replaceAll (".*lastModified=\" ([^\" ]+)\" .*" , "$1" ))
942+ : "null" ;
943+
944+ return new McpAnnotation (String .join (", " , audienceList ), lastMod .toString (), priority );
945+ }
946+
947+ private record McpAnnotation (String audience , String lastModified , String priority ) {}
944948}
0 commit comments