2020import java .util .HashMap ;
2121import java .util .List ;
2222import java .util .Map ;
23+ import java .util .function .Consumer ;
2324import java .util .function .Function ;
2425
2526import org .springframework .ai .mcp .spec .McpSchema ;
@@ -206,9 +207,12 @@ public static Builder using(McpTransport transport) {
206207 */
207208 public static class Builder {
208209
210+ private final static McpSchema .Implementation DEFAULT_SERVER_INFO = new McpSchema .Implementation ("mcp-server" ,
211+ "1.0.0" );
212+
209213 private final McpTransport transport ;
210214
211- private McpSchema .Implementation serverInfo ;
215+ private McpSchema .Implementation serverInfo = DEFAULT_SERVER_INFO ;
212216
213217 private McpSchema .ServerCapabilities serverCapabilities ;
214218
@@ -241,6 +245,8 @@ public static class Builder {
241245 */
242246 private Map <String , PromptRegistration > prompts = new HashMap <>();
243247
248+ private List <Consumer <List <McpSchema .Root >>> rootsChangeConsumers = new ArrayList <>();
249+
244250 private Builder (McpTransport transport ) {
245251 Assert .notNull (transport , "Transport must not be null" );
246252 this .transport = transport ;
@@ -255,22 +261,23 @@ private Builder(McpTransport transport) {
255261 * @return This builder instance for method chaining
256262 * @throws IllegalArgumentException if serverInfo is null
257263 */
258- public Builder info (McpSchema .Implementation serverInfo ) {
264+ public Builder serverInfo (McpSchema .Implementation serverInfo ) {
259265 Assert .notNull (serverInfo , "Server info must not be null" );
260266 this .serverInfo = serverInfo ;
261267 return this ;
262268 }
263269
264270 /**
265271 * Sets the server implementation information using name and version strings. This
266- * is a convenience method alternative to {@link #info(McpSchema.Implementation)}.
272+ * is a convenience method alternative to
273+ * {@link #serverInfo(McpSchema.Implementation)}.
267274 * @param name The server name. Must not be null or empty.
268275 * @param version The server version. Must not be null or empty.
269276 * @return This builder instance for method chaining
270277 * @throws IllegalArgumentException if name or version is null or empty
271- * @see #info (McpSchema.Implementation)
278+ * @see #serverInfo (McpSchema.Implementation)
272279 */
273- public Builder info (String name , String version ) {
280+ public Builder serverInfo (String name , String version ) {
274281 Assert .hasText (name , "Name must not be null or empty" );
275282 Assert .hasText (version , "Version must not be null or empty" );
276283 this .serverInfo = new McpSchema .Implementation (name , version );
@@ -518,6 +525,49 @@ public Builder prompts(PromptRegistration... prompts) {
518525 return this ;
519526 }
520527
528+ /**
529+ * Registers a consumer that will be notified when the list of roots changes. This
530+ * is useful for updating resource availability dynamically, such as when new
531+ * files are added or removed.
532+ * @param consumer The consumer to register. Must not be null.
533+ * @return This builder instance for method chaining
534+ * @throws IllegalArgumentException if consumer is null
535+ */
536+ public Builder rootsChangeConsumer (Consumer <List <McpSchema .Root >> consumer ) {
537+ Assert .notNull (consumer , "Consumer must not be null" );
538+ this .rootsChangeConsumers .add (consumer );
539+ return this ;
540+ }
541+
542+ /**
543+ * Registers multiple consumers that will be notified when the list of roots
544+ * changes. This method is useful when multiple consumers need to be registered at
545+ * once.
546+ * @param consumers The list of consumers to register. Must not be null.
547+ * @return This builder instance for method chaining
548+ * @throws IllegalArgumentException if consumers is null
549+ */
550+ public Builder rootsChangeConsumers (List <Consumer <List <McpSchema .Root >>> consumers ) {
551+ Assert .notNull (consumers , "Consumers list must not be null" );
552+ this .rootsChangeConsumers .addAll (consumers );
553+ return this ;
554+ }
555+
556+ /**
557+ * Registers multiple consumers that will be notified when the list of roots
558+ * changes using varargs. This method provides a convenient way to register
559+ * multiple consumers inline.
560+ * @param consumers The consumers to register. Must not be null.
561+ * @return This builder instance for method chaining
562+ * @throws IllegalArgumentException if consumers is null
563+ */
564+ public Builder rootsChangeConsumers (Consumer <List <McpSchema .Root >>... consumers ) {
565+ for (Consumer <List <McpSchema .Root >> consumer : consumers ) {
566+ this .rootsChangeConsumers .add (consumer );
567+ }
568+ return this ;
569+ }
570+
521571 /**
522572 * Builds a synchronous MCP server that provides blocking operations. Synchronous
523573 * servers process each request to completion before handling the next one, making
@@ -539,12 +589,9 @@ public McpSyncServer sync() {
539589 * settings
540590 */
541591 public McpAsyncServer async () {
542- if (serverInfo == null ) {
543- serverInfo = new McpSchema .Implementation ("mcp-server" , "1.0.0" );
544- }
545592
546593 return new McpAsyncServer (transport , serverInfo , serverCapabilities , tools , resources , resourceTemplates ,
547- prompts );
594+ prompts , rootsChangeConsumers );
548595 }
549596
550597 }
0 commit comments