1414import java .util .concurrent .CopyOnWriteArrayList ;
1515import java .util .function .BiFunction ;
1616import java .util .function .Function ;
17- import java .util .stream .Collectors ;
1817
1918import com .fasterxml .jackson .core .type .TypeReference ;
2019import com .fasterxml .jackson .databind .ObjectMapper ;
@@ -333,13 +332,13 @@ private static class AsyncServerImpl extends McpAsyncServer {
333332 /**
334333 * Thread-safe list of tool handlers that can be modified at runtime.
335334 */
336- private final CopyOnWriteArrayList <McpServerFeatures .AsyncToolRegistration > tools = new CopyOnWriteArrayList <>();
335+ private final CopyOnWriteArrayList <McpServerFeatures .AsyncToolSpecification > tools = new CopyOnWriteArrayList <>();
337336
338337 private final CopyOnWriteArrayList <McpSchema .ResourceTemplate > resourceTemplates = new CopyOnWriteArrayList <>();
339338
340- private final ConcurrentHashMap <String , McpServerFeatures .AsyncResourceRegistration > resources = new ConcurrentHashMap <>();
339+ private final ConcurrentHashMap <String , McpServerFeatures .AsyncResourceSpecification > resources = new ConcurrentHashMap <>();
341340
342- private final ConcurrentHashMap <String , McpServerFeatures .AsyncPromptRegistration > prompts = new ConcurrentHashMap <>();
341+ private final ConcurrentHashMap <String , McpServerFeatures .AsyncPromptSpecification > prompts = new ConcurrentHashMap <>();
343342
344343 private LoggingLevel minLoggingLevel = LoggingLevel .DEBUG ;
345344
@@ -540,15 +539,27 @@ private McpServerSession.NotificationHandler asyncRootsListChangedNotificationHa
540539 * Add a new tool registration at runtime.
541540 * @param toolRegistration The tool registration to add
542541 * @return Mono that completes when clients have been notified of the change
542+ * @deprecated This method will be removed in 0.9.0. Use
543+ * {@link #addTool(McpServerFeatures.AsyncToolSpecification)}.
543544 */
545+ @ Deprecated
544546 public Mono <Void > addTool (McpServerFeatures .AsyncToolRegistration toolRegistration ) {
545- if (toolRegistration == null ) {
546- return Mono .error (new McpError ("Tool registration must not be null" ));
547+ return this .addTool (toolRegistration .toSpecification ());
548+ }
549+
550+ /**
551+ * Add a new tool registration at runtime.
552+ * @param toolSpecification The tool registration to add
553+ * @return Mono that completes when clients have been notified of the change
554+ */
555+ public Mono <Void > addTool (McpServerFeatures .AsyncToolSpecification toolSpecification ) {
556+ if (toolSpecification == null ) {
557+ return Mono .error (new McpError ("Tool specification must not be null" ));
547558 }
548- if (toolRegistration .tool () == null ) {
559+ if (toolSpecification .tool () == null ) {
549560 return Mono .error (new McpError ("Tool must not be null" ));
550561 }
551- if (toolRegistration .call () == null ) {
562+ if (toolSpecification .call () == null ) {
552563 return Mono .error (new McpError ("Tool call handler must not be null" ));
553564 }
554565 if (this .serverCapabilities .tools () == null ) {
@@ -557,13 +568,13 @@ public Mono<Void> addTool(McpServerFeatures.AsyncToolRegistration toolRegistrati
557568
558569 return Mono .defer (() -> {
559570 // Check for duplicate tool names
560- if (this .tools .stream ().anyMatch (th -> th .tool ().name ().equals (toolRegistration .tool ().name ()))) {
571+ if (this .tools .stream ().anyMatch (th -> th .tool ().name ().equals (toolSpecification .tool ().name ()))) {
561572 return Mono
562- .error (new McpError ("Tool with name '" + toolRegistration .tool ().name () + "' already exists" ));
573+ .error (new McpError ("Tool with name '" + toolSpecification .tool ().name () + "' already exists" ));
563574 }
564575
565- this .tools .add (toolRegistration );
566- logger .debug ("Added tool handler: {}" , toolRegistration .tool ().name ());
576+ this .tools .add (toolSpecification );
577+ logger .debug ("Added tool handler: {}" , toolSpecification .tool ().name ());
567578
568579 if (this .serverCapabilities .tools ().listChanged ()) {
569580 return notifyToolsListChanged ();
@@ -609,7 +620,7 @@ public Mono<Void> notifyToolsListChanged() {
609620
610621 private McpServerSession .RequestHandler <McpSchema .ListToolsResult > toolsListRequestHandler () {
611622 return (exchange , params ) -> {
612- List <Tool > tools = this .tools .stream ().map (McpServerFeatures .AsyncToolRegistration ::tool ).toList ();
623+ List <Tool > tools = this .tools .stream ().map (McpServerFeatures .AsyncToolSpecification ::tool ).toList ();
613624
614625 return Mono .just (new McpSchema .ListToolsResult (tools , null ));
615626 };
@@ -621,15 +632,15 @@ private McpServerSession.RequestHandler<CallToolResult> toolsCallRequestHandler(
621632 new TypeReference <McpSchema .CallToolRequest >() {
622633 });
623634
624- Optional <McpServerFeatures .AsyncToolRegistration > toolRegistration = this .tools .stream ()
635+ Optional <McpServerFeatures .AsyncToolSpecification > toolSpecification = this .tools .stream ()
625636 .filter (tr -> callToolRequest .name ().equals (tr .tool ().name ()))
626637 .findAny ();
627638
628- if (toolRegistration .isEmpty ()) {
639+ if (toolSpecification .isEmpty ()) {
629640 return Mono .error (new McpError ("Tool not found: " + callToolRequest .name ()));
630641 }
631642
632- return toolRegistration .map (tool -> tool .call ().apply (callToolRequest .arguments ()))
643+ return toolSpecification .map (tool -> tool .call ().apply (exchange , callToolRequest .arguments ()))
633644 .orElse (Mono .error (new McpError ("Tool not found: " + callToolRequest .name ())));
634645 };
635646 }
@@ -642,9 +653,21 @@ private McpServerSession.RequestHandler<CallToolResult> toolsCallRequestHandler(
642653 * Add a new resource handler at runtime.
643654 * @param resourceHandler The resource handler to add
644655 * @return Mono that completes when clients have been notified of the change
656+ * @deprecated This method will be removed in 0.9.0. Use
657+ * {@link #addResource(McpServerFeatures.AsyncResourceSpecification)}.
645658 */
659+ @ Deprecated
646660 public Mono <Void > addResource (McpServerFeatures .AsyncResourceRegistration resourceHandler ) {
647- if (resourceHandler == null || resourceHandler .resource () == null ) {
661+ return this .addResource (resourceHandler .toSpecification ());
662+ }
663+
664+ /**
665+ * Add a new resource handler at runtime.
666+ * @param resourceSpecification The resource handler to add
667+ * @return Mono that completes when clients have been notified of the change
668+ */
669+ public Mono <Void > addResource (McpServerFeatures .AsyncResourceSpecification resourceSpecification ) {
670+ if (resourceSpecification == null || resourceSpecification .resource () == null ) {
648671 return Mono .error (new McpError ("Resource must not be null" ));
649672 }
650673
@@ -653,11 +676,11 @@ public Mono<Void> addResource(McpServerFeatures.AsyncResourceRegistration resour
653676 }
654677
655678 return Mono .defer (() -> {
656- if (this .resources .putIfAbsent (resourceHandler .resource ().uri (), resourceHandler ) != null ) {
679+ if (this .resources .putIfAbsent (resourceSpecification .resource ().uri (), resourceSpecification ) != null ) {
657680 return Mono .error (new McpError (
658- "Resource with URI '" + resourceHandler .resource ().uri () + "' already exists" ));
681+ "Resource with URI '" + resourceSpecification .resource ().uri () + "' already exists" ));
659682 }
660- logger .debug ("Added resource handler: {}" , resourceHandler .resource ().uri ());
683+ logger .debug ("Added resource handler: {}" , resourceSpecification .resource ().uri ());
661684 if (this .serverCapabilities .resources ().listChanged ()) {
662685 return notifyResourcesListChanged ();
663686 }
@@ -679,7 +702,7 @@ public Mono<Void> removeResource(String resourceUri) {
679702 }
680703
681704 return Mono .defer (() -> {
682- McpServerFeatures .AsyncResourceRegistration removed = this .resources .remove (resourceUri );
705+ McpServerFeatures .AsyncResourceSpecification removed = this .resources .remove (resourceUri );
683706 if (removed != null ) {
684707 logger .debug ("Removed resource handler: {}" , resourceUri );
685708 if (this .serverCapabilities .resources ().listChanged ()) {
@@ -696,16 +719,14 @@ public Mono<Void> removeResource(String resourceUri) {
696719 * @return A Mono that completes when all clients have been notified
697720 */
698721 public Mono <Void > notifyResourcesListChanged () {
699- McpSchema .JSONRPCNotification jsonrpcNotification = new McpSchema .JSONRPCNotification (
700- McpSchema .JSONRPC_VERSION , McpSchema .METHOD_NOTIFICATION_RESOURCES_LIST_CHANGED , null );
701722 return this .mcpTransportProvider .notifyClients (McpSchema .METHOD_NOTIFICATION_RESOURCES_LIST_CHANGED , null );
702723 }
703724
704725 private McpServerSession .RequestHandler <McpSchema .ListResourcesResult > resourcesListRequestHandler () {
705726 return (exchange , params ) -> {
706727 var resourceList = this .resources .values ()
707728 .stream ()
708- .map (McpServerFeatures .AsyncResourceRegistration ::resource )
729+ .map (McpServerFeatures .AsyncResourceSpecification ::resource )
709730 .toList ();
710731 return Mono .just (new McpSchema .ListResourcesResult (resourceList , null ));
711732 };
@@ -723,9 +744,9 @@ private McpServerSession.RequestHandler<McpSchema.ReadResourceResult> resourcesR
723744 new TypeReference <McpSchema .ReadResourceRequest >() {
724745 });
725746 var resourceUri = resourceRequest .uri ();
726- McpServerFeatures .AsyncResourceRegistration registration = this .resources .get (resourceUri );
747+ McpServerFeatures .AsyncResourceSpecification registration = this .resources .get (resourceUri );
727748 if (registration != null ) {
728- return registration .readHandler ().apply (resourceRequest );
749+ return registration .readHandler ().apply (exchange , resourceRequest );
729750 }
730751 return Mono .error (new McpError ("Resource not found: " + resourceUri ));
731752 };
@@ -739,24 +760,36 @@ private McpServerSession.RequestHandler<McpSchema.ReadResourceResult> resourcesR
739760 * Add a new prompt handler at runtime.
740761 * @param promptRegistration The prompt handler to add
741762 * @return Mono that completes when clients have been notified of the change
763+ * @deprecated This method will be removed in 0.9.0. Use
764+ * {@link #addPrompt(McpServerFeatures.AsyncPromptSpecification)}.
742765 */
766+ @ Deprecated
743767 public Mono <Void > addPrompt (McpServerFeatures .AsyncPromptRegistration promptRegistration ) {
744- if (promptRegistration == null ) {
768+ return this .addPrompt (promptRegistration .toSpecification ());
769+ }
770+
771+ /**
772+ * Add a new prompt handler at runtime.
773+ * @param promptSpecification The prompt handler to add
774+ * @return Mono that completes when clients have been notified of the change
775+ */
776+ public Mono <Void > addPrompt (McpServerFeatures .AsyncPromptSpecification promptSpecification ) {
777+ if (promptSpecification == null ) {
745778 return Mono .error (new McpError ("Prompt registration must not be null" ));
746779 }
747780 if (this .serverCapabilities .prompts () == null ) {
748781 return Mono .error (new McpError ("Server must be configured with prompt capabilities" ));
749782 }
750783
751784 return Mono .defer (() -> {
752- McpServerFeatures .AsyncPromptRegistration registration = this .prompts
753- .putIfAbsent (promptRegistration .prompt ().name (), promptRegistration );
754- if (registration != null ) {
785+ McpServerFeatures .AsyncPromptSpecification specification = this .prompts
786+ .putIfAbsent (promptSpecification .prompt ().name (), promptSpecification );
787+ if (specification != null ) {
755788 return Mono .error (new McpError (
756- "Prompt with name '" + promptRegistration .prompt ().name () + "' already exists" ));
789+ "Prompt with name '" + promptSpecification .prompt ().name () + "' already exists" ));
757790 }
758791
759- logger .debug ("Added prompt handler: {}" , promptRegistration .prompt ().name ());
792+ logger .debug ("Added prompt handler: {}" , promptSpecification .prompt ().name ());
760793
761794 // Servers that declared the listChanged capability SHOULD send a
762795 // notification,
@@ -782,7 +815,7 @@ public Mono<Void> removePrompt(String promptName) {
782815 }
783816
784817 return Mono .defer (() -> {
785- McpServerFeatures .AsyncPromptRegistration removed = this .prompts .remove (promptName );
818+ McpServerFeatures .AsyncPromptSpecification removed = this .prompts .remove (promptName );
786819
787820 if (removed != null ) {
788821 logger .debug ("Removed prompt handler: {}" , promptName );
@@ -814,7 +847,7 @@ private McpServerSession.RequestHandler<McpSchema.ListPromptsResult> promptsList
814847
815848 var promptList = this .prompts .values ()
816849 .stream ()
817- .map (McpServerFeatures .AsyncPromptRegistration ::prompt )
850+ .map (McpServerFeatures .AsyncPromptSpecification ::prompt )
818851 .toList ();
819852
820853 return Mono .just (new McpSchema .ListPromptsResult (promptList , null ));
@@ -828,12 +861,12 @@ private McpServerSession.RequestHandler<McpSchema.GetPromptResult> promptsGetReq
828861 });
829862
830863 // Implement prompt retrieval logic here
831- McpServerFeatures .AsyncPromptRegistration registration = this .prompts .get (promptRequest .name ());
832- if (registration == null ) {
864+ McpServerFeatures .AsyncPromptSpecification specification = this .prompts .get (promptRequest .name ());
865+ if (specification == null ) {
833866 return Mono .error (new McpError ("Prompt not found: " + promptRequest .name ()));
834867 }
835868
836- return registration .promptHandler ().apply (promptRequest );
869+ return specification .promptHandler ().apply (exchange , promptRequest );
837870 };
838871 }
839872
@@ -938,13 +971,13 @@ private static final class LegacyAsyncServer extends McpAsyncServer {
938971 /**
939972 * Thread-safe list of tool handlers that can be modified at runtime.
940973 */
941- private final CopyOnWriteArrayList <McpServerFeatures .AsyncToolRegistration > tools = new CopyOnWriteArrayList <>();
974+ private final CopyOnWriteArrayList <McpServerFeatures .AsyncToolSpecification > tools = new CopyOnWriteArrayList <>();
942975
943976 private final CopyOnWriteArrayList <McpSchema .ResourceTemplate > resourceTemplates = new CopyOnWriteArrayList <>();
944977
945- private final ConcurrentHashMap <String , McpServerFeatures .AsyncResourceRegistration > resources = new ConcurrentHashMap <>();
978+ private final ConcurrentHashMap <String , McpServerFeatures .AsyncResourceSpecification > resources = new ConcurrentHashMap <>();
946979
947- private final ConcurrentHashMap <String , McpServerFeatures .AsyncPromptRegistration > prompts = new ConcurrentHashMap <>();
980+ private final ConcurrentHashMap <String , McpServerFeatures .AsyncPromptSpecification > prompts = new ConcurrentHashMap <>();
948981
949982 private LoggingLevel minLoggingLevel = LoggingLevel .DEBUG ;
950983
@@ -1170,7 +1203,7 @@ public Mono<Void> addTool(McpServerFeatures.AsyncToolRegistration toolRegistrati
11701203 .error (new McpError ("Tool with name '" + toolRegistration .tool ().name () + "' already exists" ));
11711204 }
11721205
1173- this .tools .add (toolRegistration );
1206+ this .tools .add (toolRegistration . toSpecification () );
11741207 logger .debug ("Added tool handler: {}" , toolRegistration .tool ().name ());
11751208
11761209 if (this .serverCapabilities .tools ().listChanged ()) {
@@ -1217,7 +1250,7 @@ public Mono<Void> notifyToolsListChanged() {
12171250
12181251 private DefaultMcpSession .RequestHandler <McpSchema .ListToolsResult > toolsListRequestHandler () {
12191252 return params -> {
1220- List <Tool > tools = this .tools .stream ().map (McpServerFeatures .AsyncToolRegistration ::tool ).toList ();
1253+ List <Tool > tools = this .tools .stream ().map (McpServerFeatures .AsyncToolSpecification ::tool ).toList ();
12211254
12221255 return Mono .just (new McpSchema .ListToolsResult (tools , null ));
12231256 };
@@ -1229,15 +1262,15 @@ private DefaultMcpSession.RequestHandler<CallToolResult> toolsCallRequestHandler
12291262 new TypeReference <McpSchema .CallToolRequest >() {
12301263 });
12311264
1232- Optional <McpServerFeatures .AsyncToolRegistration > toolRegistration = this .tools .stream ()
1265+ Optional <McpServerFeatures .AsyncToolSpecification > toolRegistration = this .tools .stream ()
12331266 .filter (tr -> callToolRequest .name ().equals (tr .tool ().name ()))
12341267 .findAny ();
12351268
12361269 if (toolRegistration .isEmpty ()) {
12371270 return Mono .error (new McpError ("Tool not found: " + callToolRequest .name ()));
12381271 }
12391272
1240- return toolRegistration .map (tool -> tool .call ().apply (callToolRequest .arguments ()))
1273+ return toolRegistration .map (tool -> tool .call ().apply (null , callToolRequest .arguments ()))
12411274 .orElse (Mono .error (new McpError ("Tool not found: " + callToolRequest .name ())));
12421275 };
12431276 }
@@ -1261,7 +1294,8 @@ public Mono<Void> addResource(McpServerFeatures.AsyncResourceRegistration resour
12611294 }
12621295
12631296 return Mono .defer (() -> {
1264- if (this .resources .putIfAbsent (resourceHandler .resource ().uri (), resourceHandler ) != null ) {
1297+ if (this .resources .putIfAbsent (resourceHandler .resource ().uri (),
1298+ resourceHandler .toSpecification ()) != null ) {
12651299 return Mono .error (new McpError (
12661300 "Resource with URI '" + resourceHandler .resource ().uri () + "' already exists" ));
12671301 }
@@ -1287,7 +1321,7 @@ public Mono<Void> removeResource(String resourceUri) {
12871321 }
12881322
12891323 return Mono .defer (() -> {
1290- McpServerFeatures .AsyncResourceRegistration removed = this .resources .remove (resourceUri );
1324+ McpServerFeatures .AsyncResourceSpecification removed = this .resources .remove (resourceUri );
12911325 if (removed != null ) {
12921326 logger .debug ("Removed resource handler: {}" , resourceUri );
12931327 if (this .serverCapabilities .resources ().listChanged ()) {
@@ -1311,7 +1345,7 @@ private DefaultMcpSession.RequestHandler<McpSchema.ListResourcesResult> resource
13111345 return params -> {
13121346 var resourceList = this .resources .values ()
13131347 .stream ()
1314- .map (McpServerFeatures .AsyncResourceRegistration ::resource )
1348+ .map (McpServerFeatures .AsyncResourceSpecification ::resource )
13151349 .toList ();
13161350 return Mono .just (new McpSchema .ListResourcesResult (resourceList , null ));
13171351 };
@@ -1328,9 +1362,9 @@ private DefaultMcpSession.RequestHandler<McpSchema.ReadResourceResult> resources
13281362 new TypeReference <McpSchema .ReadResourceRequest >() {
13291363 });
13301364 var resourceUri = resourceRequest .uri ();
1331- McpServerFeatures .AsyncResourceRegistration registration = this .resources .get (resourceUri );
1365+ McpServerFeatures .AsyncResourceSpecification registration = this .resources .get (resourceUri );
13321366 if (registration != null ) {
1333- return registration .readHandler ().apply (resourceRequest );
1367+ return registration .readHandler ().apply (null , resourceRequest );
13341368 }
13351369 return Mono .error (new McpError ("Resource not found: " + resourceUri ));
13361370 };
@@ -1354,8 +1388,8 @@ public Mono<Void> addPrompt(McpServerFeatures.AsyncPromptRegistration promptRegi
13541388 }
13551389
13561390 return Mono .defer (() -> {
1357- McpServerFeatures .AsyncPromptRegistration registration = this .prompts
1358- .putIfAbsent (promptRegistration .prompt ().name (), promptRegistration );
1391+ McpServerFeatures .AsyncPromptSpecification registration = this .prompts
1392+ .putIfAbsent (promptRegistration .prompt ().name (), promptRegistration . toSpecification () );
13591393 if (registration != null ) {
13601394 return Mono .error (new McpError (
13611395 "Prompt with name '" + promptRegistration .prompt ().name () + "' already exists" ));
@@ -1387,7 +1421,7 @@ public Mono<Void> removePrompt(String promptName) {
13871421 }
13881422
13891423 return Mono .defer (() -> {
1390- McpServerFeatures .AsyncPromptRegistration removed = this .prompts .remove (promptName );
1424+ McpServerFeatures .AsyncPromptSpecification removed = this .prompts .remove (promptName );
13911425
13921426 if (removed != null ) {
13931427 logger .debug ("Removed prompt handler: {}" , promptName );
@@ -1419,7 +1453,7 @@ private DefaultMcpSession.RequestHandler<McpSchema.ListPromptsResult> promptsLis
14191453
14201454 var promptList = this .prompts .values ()
14211455 .stream ()
1422- .map (McpServerFeatures .AsyncPromptRegistration ::prompt )
1456+ .map (McpServerFeatures .AsyncPromptSpecification ::prompt )
14231457 .toList ();
14241458
14251459 return Mono .just (new McpSchema .ListPromptsResult (promptList , null ));
@@ -1433,12 +1467,12 @@ private DefaultMcpSession.RequestHandler<McpSchema.GetPromptResult> promptsGetRe
14331467 });
14341468
14351469 // Implement prompt retrieval logic here
1436- McpServerFeatures .AsyncPromptRegistration registration = this .prompts .get (promptRequest .name ());
1470+ McpServerFeatures .AsyncPromptSpecification registration = this .prompts .get (promptRequest .name ());
14371471 if (registration == null ) {
14381472 return Mono .error (new McpError ("Prompt not found: " + promptRequest .name ()));
14391473 }
14401474
1441- return registration .promptHandler ().apply (promptRequest );
1475+ return registration .promptHandler ().apply (null , promptRequest );
14421476 };
14431477 }
14441478
0 commit comments