3232import io .helidon .codegen .RoundContext ;
3333import io .helidon .codegen .classmodel .ClassModel ;
3434import io .helidon .codegen .classmodel .Method ;
35+ import io .helidon .codegen .classmodel .Parameter ;
3536import io .helidon .codegen .spi .CodegenExtension ;
3637import io .helidon .common .types .AccessModifier ;
3738import io .helidon .common .types .Annotation ;
4445import io .helidon .common .types .TypeNames ;
4546import io .helidon .common .types .TypedElementInfo ;
4647
48+ import static io .helidon .common .types .TypeNames .LIST ;
4749import static io .helidon .extensions .mcp .codegen .McpJsonSchemaCodegen .addSchemaMethodBody ;
4850import static io .helidon .extensions .mcp .codegen .McpJsonSchemaCodegen .getDescription ;
4951import static io .helidon .extensions .mcp .codegen .McpTypes .CONSUMER_REQUEST ;
9698
9799final class McpCodegen implements CodegenExtension {
98100 private static final TypeName GENERATOR = TypeName .create (McpCodegen .class );
99- private static final ResolvedType STRING_LIST = ResolvedType .create (TypeName .builder (TypeNames . LIST )
101+ private static final ResolvedType STRING_LIST = ResolvedType .create (TypeName .builder (LIST )
100102 .addTypeArgument (TypeNames .STRING )
101103 .build ());
102104
@@ -148,12 +150,25 @@ private void process(RoundContext roundCtx, TypeInfo type) {
148150
149151 serverClassModel .addField (delegate -> delegate
150152 .accessModifier (AccessModifier .PRIVATE )
151- .isFinal (true )
152- .name ("delegate" )
153153 .type (type .typeName ())
154- .addContent ("new " )
155- .addContent (type .typeName ())
156- .addContent ("()" ));
154+ .name ("delegate" ));
155+
156+ serverClassModel .addImport ("io.helidon.service.registry.GlobalServiceRegistry" );
157+
158+ serverClassModel .addConstructor (constructor -> {
159+ constructor .accessModifier (AccessModifier .PUBLIC );
160+ constructor .addContentLine ("try {" )
161+ .addContent ("delegate = GlobalServiceRegistry.registry().get(" )
162+ .addContent (type .typeName ())
163+ .addContentLine (".class);" )
164+ .decreaseContentPadding ()
165+ .addContentLine ("} catch (Exception e) {" )
166+ .addContent ("delegate = " )
167+ .addContent ("new " )
168+ .addContent (type .typeName ())
169+ .addContentLine ("();" )
170+ .addContentLine ("}" );
171+ });
157172
158173 generateTools (generatedType , serverClassModel , type );
159174 generatePrompts (generatedType , serverClassModel , type );
@@ -440,10 +455,15 @@ private void addResourceMethod(Method.Builder builder, String uri, ClassModel.Bu
440455 if (TypeNames .STRING .equals (parameter .typeName ())) {
441456 parameters .add (parameter .elementName ());
442457 builder .addContent ("String " )
443- .addContent (parameter .elementName ())
458+ .addContent ("encoded_" + parameter .elementName ())
444459 .addContent (" = request.parameters().get(\" " )
445460 .addContent (parameter .elementName ())
446461 .addContentLine ("\" ).asString().orElse(\" \" );" );
462+ builder .addContent ("String " )
463+ .addContent (parameter .elementName ())
464+ .addContent (" = io.helidon.common.uri.UriPath.create(" )
465+ .addContent ("encoded_" + parameter .elementName ())
466+ .addContentLine (").path();" );
447467 }
448468 }
449469 }
@@ -620,7 +640,7 @@ private void addPromptArgumentsMethod(Method.Builder builder, TypedElementInfo e
620640 .returnType (LIST_MCP_PROMPT_ARGUMENT );
621641
622642 for (TypedElementInfo param : element .parameterArguments ()) {
623- if (MCP_FEATURES . equals (param .typeName ())) {
643+ if (isIgnoredSchemaElement (param .typeName ())) {
624644 continue ;
625645 }
626646 String builderName = "builder" + index ++;
@@ -812,6 +832,22 @@ private void addToolMethod(Method.Builder builder, ClassModel.Builder classModel
812832 .addContentLine ("().orElse(null);" );
813833 continue ;
814834 }
835+ if (isList (param .typeName ())) {
836+ TypeName typeArg = param .typeName ().typeArguments ().getFirst ();
837+ addToListMethod (classModel , typeArg );
838+
839+ if (!parametersLocalVar ) {
840+ addParametersLocalVar (builder , classModel );
841+ parametersLocalVar = true ;
842+ }
843+ parameters .add (param .elementName ());
844+ builder .addContent ("var " )
845+ .addContent (param .elementName ())
846+ .addContent (" = toList(parameters.get(\" " )
847+ .addContent (param .elementName ())
848+ .addContentLine ("\" ).asList().orElse(null));" );
849+ continue ;
850+ }
815851 if (!parametersLocalVar ) {
816852 addParametersLocalVar (builder , classModel );
817853 parametersLocalVar = true ;
@@ -975,6 +1011,23 @@ private void addSubscriberMethod(Method.Builder builder, TypedElementInfo elemen
9751011 .addContentLine ("};" );
9761012 }
9771013
1014+ private void addToListMethod (ClassModel .Builder classModel , TypeName type ) {
1015+ Method .Builder method = Method .builder ();
1016+ TypeName typeList = TypeName .create ("java.util.List<" + type + ">" );
1017+ TypeName parameterList = TypeName .create ("java.util.List<" + MCP_PARAMETERS + ">" );
1018+ method .name ("toList" )
1019+ .isStatic (true )
1020+ .accessModifier (AccessModifier .PRIVATE )
1021+ .returnType (typeList );
1022+ method .addParameter (Parameter .builder ().name ("list" ).type (parameterList ).build ());
1023+ method .addContentLine ("return list == null ? List.of()" );
1024+ method .increaseContentPadding ();
1025+ method .addContentLine (": list.stream().map(p -> p.as(" + type + ".class))" );
1026+ method .increaseContentPadding ();
1027+ method .addContentLine (".map(p -> p.get()).toList();" );
1028+ classModel .addMethod (method .build ());
1029+ }
1030+
9781031 private boolean isBoolean (TypeName type ) {
9791032 return TypeNames .PRIMITIVE_BOOLEAN .equals (type ) || TypeNames .BOXED_BOOLEAN .equals (type );
9801033 }
@@ -994,6 +1047,10 @@ private boolean isNumber(TypeName type) {
9941047 || TypeNames .PRIMITIVE_DOUBLE .equals (type );
9951048 }
9961049
1050+ private boolean isList (TypeName type ) {
1051+ return type .equals (TypeNames .LIST ) && type .typeArguments ().size () == 1 ;
1052+ }
1053+
9971054 private TypeName createClassName (TypeName generatedType , TypedElementInfo element , String suffix ) {
9981055 return TypeName .builder ()
9991056 .className (element .findAnnotation (MCP_NAME )
0 commit comments