2121 * MCP server features specification that a particular server can choose to support.
2222 *
2323 * @author Dariusz Jędrzejczyk
24+ * @author Jihoon Kim
2425 */
2526public class McpServerFeatures {
2627
@@ -41,6 +42,7 @@ record Async(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities s
4142 List <McpServerFeatures .AsyncToolSpecification > tools , Map <String , AsyncResourceSpecification > resources ,
4243 List <McpSchema .ResourceTemplate > resourceTemplates ,
4344 Map <String , McpServerFeatures .AsyncPromptSpecification > prompts ,
45+ Map <CompletionRefKey , McpServerFeatures .AsyncCompletionSpecification > completions ,
4446 List <BiFunction <McpAsyncServerExchange , List <McpSchema .Root >, Mono <Void >>> rootsChangeConsumers ,
4547 String instructions ) {
4648
@@ -60,14 +62,16 @@ record Async(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities s
6062 List <McpServerFeatures .AsyncToolSpecification > tools , Map <String , AsyncResourceSpecification > resources ,
6163 List <McpSchema .ResourceTemplate > resourceTemplates ,
6264 Map <String , McpServerFeatures .AsyncPromptSpecification > prompts ,
65+ Map <CompletionRefKey , McpServerFeatures .AsyncCompletionSpecification > completions ,
6366 List <BiFunction <McpAsyncServerExchange , List <McpSchema .Root >, Mono <Void >>> rootsChangeConsumers ,
6467 String instructions ) {
6568
6669 Assert .notNull (serverInfo , "Server info must not be null" );
6770
6871 this .serverInfo = serverInfo ;
6972 this .serverCapabilities = (serverCapabilities != null ) ? serverCapabilities
70- : new McpSchema .ServerCapabilities (null , // experimental
73+ : new McpSchema .ServerCapabilities (null , // completions
74+ null , // experimental
7175 new McpSchema .ServerCapabilities .LoggingCapabilities (), // Enable
7276 // logging
7377 // by
@@ -81,6 +85,7 @@ record Async(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities s
8185 this .resources = (resources != null ) ? resources : Map .of ();
8286 this .resourceTemplates = (resourceTemplates != null ) ? resourceTemplates : List .of ();
8387 this .prompts = (prompts != null ) ? prompts : Map .of ();
88+ this .completions = (completions != null ) ? completions : Map .of ();
8489 this .rootsChangeConsumers = (rootsChangeConsumers != null ) ? rootsChangeConsumers : List .of ();
8590 this .instructions = instructions ;
8691 }
@@ -109,6 +114,11 @@ static Async fromSync(Sync syncSpec) {
109114 prompts .put (key , AsyncPromptSpecification .fromSync (prompt ));
110115 });
111116
117+ Map <CompletionRefKey , McpServerFeatures .AsyncCompletionSpecification > completions = new HashMap <>();
118+ syncSpec .completions ().forEach ((key , completion ) -> {
119+ completions .put (key , AsyncCompletionSpecification .fromSync (completion ));
120+ });
121+
112122 List <BiFunction <McpAsyncServerExchange , List <McpSchema .Root >, Mono <Void >>> rootChangeConsumers = new ArrayList <>();
113123
114124 for (var rootChangeConsumer : syncSpec .rootsChangeConsumers ()) {
@@ -118,7 +128,7 @@ static Async fromSync(Sync syncSpec) {
118128 }
119129
120130 return new Async (syncSpec .serverInfo (), syncSpec .serverCapabilities (), tools , resources ,
121- syncSpec .resourceTemplates (), prompts , rootChangeConsumers , syncSpec .instructions ());
131+ syncSpec .resourceTemplates (), prompts , completions , rootChangeConsumers , syncSpec .instructions ());
122132 }
123133 }
124134
@@ -140,6 +150,7 @@ record Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities se
140150 Map <String , McpServerFeatures .SyncResourceSpecification > resources ,
141151 List <McpSchema .ResourceTemplate > resourceTemplates ,
142152 Map <String , McpServerFeatures .SyncPromptSpecification > prompts ,
153+ Map <CompletionRefKey , McpServerFeatures .SyncCompletionSpecification > completions ,
143154 List <BiConsumer <McpSyncServerExchange , List <McpSchema .Root >>> rootsChangeConsumers , String instructions ) {
144155
145156 /**
@@ -159,14 +170,16 @@ record Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities se
159170 Map <String , McpServerFeatures .SyncResourceSpecification > resources ,
160171 List <McpSchema .ResourceTemplate > resourceTemplates ,
161172 Map <String , McpServerFeatures .SyncPromptSpecification > prompts ,
173+ Map <CompletionRefKey , McpServerFeatures .SyncCompletionSpecification > completions ,
162174 List <BiConsumer <McpSyncServerExchange , List <McpSchema .Root >>> rootsChangeConsumers ,
163175 String instructions ) {
164176
165177 Assert .notNull (serverInfo , "Server info must not be null" );
166178
167179 this .serverInfo = serverInfo ;
168180 this .serverCapabilities = (serverCapabilities != null ) ? serverCapabilities
169- : new McpSchema .ServerCapabilities (null , // experimental
181+ : new McpSchema .ServerCapabilities (null , // completions
182+ null , // experimental
170183 new McpSchema .ServerCapabilities .LoggingCapabilities (), // Enable
171184 // logging
172185 // by
@@ -180,6 +193,7 @@ record Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities se
180193 this .resources = (resources != null ) ? resources : new HashMap <>();
181194 this .resourceTemplates = (resourceTemplates != null ) ? resourceTemplates : new ArrayList <>();
182195 this .prompts = (prompts != null ) ? prompts : new HashMap <>();
196+ this .completions = (completions != null ) ? completions : new HashMap <>();
183197 this .rootsChangeConsumers = (rootsChangeConsumers != null ) ? rootsChangeConsumers : new ArrayList <>();
184198 this .instructions = instructions ;
185199 }
@@ -325,6 +339,19 @@ static AsyncPromptSpecification fromSync(SyncPromptSpecification prompt) {
325339 }
326340 }
327341
342+ public record AsyncCompletionSpecification (
343+ BiFunction <McpAsyncServerExchange , McpSchema .CompleteRequest , Mono <McpSchema .CompleteResult >> completionHandler ) {
344+
345+ static AsyncCompletionSpecification fromSync (SyncCompletionSpecification completion ) {
346+ if (completion == null ) {
347+ return null ;
348+ }
349+ return new AsyncCompletionSpecification ((exchange , request ) -> Mono
350+ .fromCallable (() -> completion .completionHandler ().apply (new McpSyncServerExchange (exchange ), request ))
351+ .subscribeOn (Schedulers .boundedElastic ()));
352+ }
353+ }
354+
328355 /**
329356 * Specification of a tool with its synchronous handler function. Tools are the
330357 * primary way for MCP servers to expose functionality to AI models. Each tool
@@ -431,4 +458,23 @@ public record SyncPromptSpecification(McpSchema.Prompt prompt,
431458 BiFunction <McpSyncServerExchange , McpSchema .GetPromptRequest , McpSchema .GetPromptResult > promptHandler ) {
432459 }
433460
461+ public record SyncCompletionSpecification (CompletionRefKey referenceKey ,
462+ BiFunction <McpSyncServerExchange , McpSchema .CompleteRequest , McpSchema .CompleteResult > completionHandler ) {
463+ }
464+
465+ public record CompletionRefKey (String type , String identifier ) {
466+ public static CompletionRefKey from (McpSchema .CompleteRequest request ) {
467+ var ref = request .ref ();
468+ if (ref instanceof McpSchema .CompleteRequest .PromptReference pr ) {
469+ return new CompletionRefKey (ref .type (), pr .name ());
470+ }
471+ else if (ref instanceof McpSchema .CompleteRequest .ResourceReference rr ) {
472+ return new CompletionRefKey (ref .type (), rr .uri ());
473+ }
474+ else {
475+ throw new IllegalArgumentException ("Unsupported reference type: " + ref );
476+ }
477+ }
478+ }
479+
434480}
0 commit comments