Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
import io.modelcontextprotocol.server.McpServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncPromptSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncResourceSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.McpSyncServerExchange;
Expand Down Expand Up @@ -111,6 +113,7 @@ public McpSyncServer mcpSyncServer(McpServerTransportProviderBase transportProvi
McpServerChangeNotificationProperties changeNotificationProperties,
ObjectProvider<List<SyncToolSpecification>> tools,
ObjectProvider<List<SyncResourceSpecification>> resources,
ObjectProvider<List<SyncResourceTemplateSpecification>> resourceTemplates,
ObjectProvider<List<SyncPromptSpecification>> prompts,
ObjectProvider<List<SyncCompletionSpecification>> completions,
ObjectProvider<BiConsumer<McpSyncServerExchange, List<McpSchema.Root>>> rootsChangeConsumers,
Expand Down Expand Up @@ -157,6 +160,21 @@ public McpSyncServer mcpSyncServer(McpServerTransportProviderBase transportProvi
}
}

// Resources Templates
if (serverProperties.getCapabilities().isResource()) {
logger.info("Enable resources templates capabilities, notification: "
+ changeNotificationProperties.isResourceChangeNotification());
capabilitiesBuilder.resources(false, changeNotificationProperties.isResourceChangeNotification());

List<SyncResourceTemplateSpecification> resourceTemplateSpecifications = resourceTemplates.stream()
.flatMap(List::stream)
.toList();
if (!CollectionUtils.isEmpty(resourceTemplateSpecifications)) {
serverBuilder.resourceTemplates(resourceTemplateSpecifications);
logger.info("Registered resource templates: " + resourceTemplateSpecifications.size());
}
}

// Prompts
if (serverProperties.getCapabilities().isPrompt()) {
logger.info("Enable prompts capabilities, notification: "
Expand Down Expand Up @@ -210,6 +228,7 @@ public McpAsyncServer mcpAsyncServer(McpServerTransportProviderBase transportPro
McpServerChangeNotificationProperties changeNotificationProperties,
ObjectProvider<List<AsyncToolSpecification>> tools,
ObjectProvider<List<AsyncResourceSpecification>> resources,
ObjectProvider<List<AsyncResourceTemplateSpecification>> resourceTemplates,
ObjectProvider<List<AsyncPromptSpecification>> prompts,
ObjectProvider<List<AsyncCompletionSpecification>> completions,
ObjectProvider<BiConsumer<McpAsyncServerExchange, List<McpSchema.Root>>> rootsChangeConsumer) {
Expand Down Expand Up @@ -255,6 +274,21 @@ public McpAsyncServer mcpAsyncServer(McpServerTransportProviderBase transportPro
}
}

// Resources Templates
if (serverProperties.getCapabilities().isResource()) {
logger.info("Enable resources templates capabilities, notification: "
+ changeNotificationProperties.isResourceChangeNotification());
capabilitiesBuilder.resources(false, changeNotificationProperties.isResourceChangeNotification());

List<AsyncResourceTemplateSpecification> resourceTemplateSpecifications = resourceTemplates.stream()
.flatMap(List::stream)
.toList();
if (!CollectionUtils.isEmpty(resourceTemplateSpecifications)) {
serverBuilder.resourceTemplates(resourceTemplateSpecifications);
logger.info("Registered resources templates: " + resourceTemplateSpecifications.size());
}
}

// Prompts
if (serverProperties.getCapabilities().isPrompt()) {
logger.info("Enable prompts capabilities, notification: "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncCompletionSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncPromptSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessSyncServer;
import io.modelcontextprotocol.spec.McpSchema;
Expand Down Expand Up @@ -80,6 +82,7 @@ public McpStatelessSyncServer mcpStatelessSyncServer(McpStatelessServerTransport
McpSchema.ServerCapabilities.Builder capabilitiesBuilder, McpServerProperties serverProperties,
ObjectProvider<List<SyncToolSpecification>> tools,
ObjectProvider<List<SyncResourceSpecification>> resources,
ObjectProvider<List<SyncResourceTemplateSpecification>> resourceTemplates,
ObjectProvider<List<SyncPromptSpecification>> prompts,
ObjectProvider<List<SyncCompletionSpecification>> completions, Environment environment) {

Expand Down Expand Up @@ -113,6 +116,19 @@ public McpStatelessSyncServer mcpStatelessSyncServer(McpStatelessServerTransport
}
}

// Resources Templates
if (serverProperties.getCapabilities().isResource()) {
capabilitiesBuilder.resources(false, false);

List<SyncResourceTemplateSpecification> resourceSpecifications = resourceTemplates.stream()
.flatMap(List::stream)
.toList();
if (!CollectionUtils.isEmpty(resourceSpecifications)) {
serverBuilder.resourceTemplates(resourceSpecifications);
logger.info("Registered resource templates: " + resourceSpecifications.size());
}
}

// Prompts
if (serverProperties.getCapabilities().isPrompt()) {
capabilitiesBuilder.prompts(false);
Expand Down Expand Up @@ -156,6 +172,7 @@ public McpStatelessAsyncServer mcpStatelessAsyncServer(McpStatelessServerTranspo
McpSchema.ServerCapabilities.Builder capabilitiesBuilder, McpServerProperties serverProperties,
ObjectProvider<List<AsyncToolSpecification>> tools,
ObjectProvider<List<AsyncResourceSpecification>> resources,
ObjectProvider<List<AsyncResourceTemplateSpecification>> resourceTemplates,
ObjectProvider<List<AsyncPromptSpecification>> prompts,
ObjectProvider<List<AsyncCompletionSpecification>> completions) {

Expand Down Expand Up @@ -189,6 +206,19 @@ public McpStatelessAsyncServer mcpStatelessAsyncServer(McpStatelessServerTranspo
}
}

// Resources Templates
if (serverProperties.getCapabilities().isResource()) {
capabilitiesBuilder.resources(false, false);

List<AsyncResourceTemplateSpecification> resourceSpecifications = resourceTemplates.stream()
.flatMap(List::stream)
.toList();
if (!CollectionUtils.isEmpty(resourceSpecifications)) {
serverBuilder.resourceTemplates(resourceSpecifications);
logger.info("Registered resource templates: " + resourceSpecifications.size());
}
}

// Prompts
if (serverProperties.getCapabilities().isPrompt()) {
capabilitiesBuilder.prompts(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public List<McpServerFeatures.SyncResourceSpecification> resourceSpecs(
return syncResourceSpecifications;
}

@Bean
public List<McpServerFeatures.SyncResourceTemplateSpecification> resourceTemplateSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {

List<McpServerFeatures.SyncResourceTemplateSpecification> syncResourceSpecifications = SyncMcpAnnotationProviders
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can rename syncResourceSpecifications to syncResourceTemplateSpecifications. will fix when merging.

.resourceTemplateSpecifications(beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
return syncResourceSpecifications;
}

@Bean
public List<McpServerFeatures.SyncPromptSpecification> promptSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
Expand Down Expand Up @@ -96,6 +105,14 @@ public List<McpServerFeatures.AsyncResourceSpecification> resourceSpecs(
.resourceSpecifications(beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpServerFeatures.AsyncResourceTemplateSpecification> resourceTemplateSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {

return AsyncMcpAnnotationProviders
.resourceTemplateSpecifications(beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpServerFeatures.AsyncPromptSpecification> promptSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ public List<McpStatelessServerFeatures.SyncResourceSpecification> resourceSpecs(
.statelessResourceSpecifications(beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpStatelessServerFeatures.SyncResourceTemplateSpecification> resourceTemplateSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
return SyncMcpAnnotationProviders.statelessResourceTemplateSpecifications(
beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpStatelessServerFeatures.SyncPromptSpecification> promptSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
Expand Down Expand Up @@ -96,6 +103,13 @@ public List<McpStatelessServerFeatures.AsyncResourceSpecification> resourceSpecs
.statelessResourceSpecifications(beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpStatelessServerFeatures.AsyncResourceTemplateSpecification> resourceTemplateSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
return AsyncMcpAnnotationProviders.statelessResourceTemplateSpecifications(
beansWithMcpMethodAnnotations.getBeansByAnnotation(McpResource.class));
}

@Bean
public List<McpStatelessServerFeatures.AsyncPromptSpecification> promptSpecs(
ServerMcpAnnotatedBeans beansWithMcpMethodAnnotations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.modelcontextprotocol.server.McpServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.SyncPromptSpecification;
Expand Down Expand Up @@ -379,7 +380,12 @@ void syncServerSpecificationConfiguration() {
ConcurrentHashMap<String, AsyncResourceSpecification> resources = (ConcurrentHashMap<String, AsyncResourceSpecification>) ReflectionTestUtils
.getField(asyncServer, "resources");
assertThat(resources).hasSize(1);
assertThat(resources.get("config://{key}")).isNotNull();
assertThat(resources.get("simple://static")).isNotNull();

ConcurrentHashMap<String, AsyncResourceTemplateSpecification> resourceTemplatess = (ConcurrentHashMap<String, AsyncResourceTemplateSpecification>) ReflectionTestUtils
.getField(asyncServer, "resourceTemplates");
assertThat(resourceTemplatess).hasSize(1);
assertThat(resourceTemplatess.get("config://{key}")).isNotNull();

ConcurrentHashMap<String, AsyncPromptSpecification> prompts = (ConcurrentHashMap<String, AsyncPromptSpecification>) ReflectionTestUtils
.getField(asyncServer, "prompts");
Expand Down Expand Up @@ -412,7 +418,12 @@ void asyncServerSpecificationConfiguration() {
ConcurrentHashMap<String, AsyncResourceSpecification> resources = (ConcurrentHashMap<String, AsyncResourceSpecification>) ReflectionTestUtils
.getField(asyncServer, "resources");
assertThat(resources).hasSize(1);
assertThat(resources.get("config://{key}")).isNotNull();
assertThat(resources.get("simple://static")).isNotNull();

ConcurrentHashMap<String, AsyncResourceTemplateSpecification> resourceTemplatess = (ConcurrentHashMap<String, AsyncResourceTemplateSpecification>) ReflectionTestUtils
.getField(asyncServer, "resourceTemplates");
assertThat(resourceTemplatess).hasSize(1);
assertThat(resourceTemplatess.get("config://{key}")).isNotNull();

ConcurrentHashMap<String, AsyncPromptSpecification> prompts = (ConcurrentHashMap<String, AsyncPromptSpecification>) ReflectionTestUtils
.getField(asyncServer, "prompts");
Expand Down Expand Up @@ -608,6 +619,11 @@ public int add(@McpToolParam(description = "First number", required = true) int
return a + b;
}

@McpResource(uri = "simple://static", name = "Configuration", description = "Provides configuration data")
public String getSimple() {
return "Hi there!";
}

@McpResource(uri = "config://{key}", name = "Configuration", description = "Provides configuration data")
public String getConfig(String key) {
return "config value";
Expand Down Expand Up @@ -644,6 +660,11 @@ public Mono<Integer> add(@McpToolParam(description = "First number", required =
return Mono.just(a + b);
}

@McpResource(uri = "simple://static", name = "Configuration", description = "Provides configuration data")
public Mono<String> getSimple() {
return Mono.just("Hi there!");
}

@McpResource(uri = "config://{key}", name = "Configuration", description = "Provides configuration data")
public Mono<String> getConfig(String key) {
return Mono.just("config value");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncCompletionSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncPromptSpecification;
Expand Down Expand Up @@ -330,7 +331,12 @@ void syncStatelessServerSpecificationConfiguration() {
ConcurrentHashMap<String, AsyncResourceSpecification> resources = (ConcurrentHashMap<String, AsyncResourceSpecification>) ReflectionTestUtils
.getField(asyncServer, "resources");
assertThat(resources).hasSize(1);
assertThat(resources.get("config://{key}")).isNotNull();
assertThat(resources.get("simple://static")).isNotNull();

ConcurrentHashMap<String, AsyncResourceTemplateSpecification> resourceTemplates = (ConcurrentHashMap<String, AsyncResourceTemplateSpecification>) ReflectionTestUtils
.getField(asyncServer, "resourceTemplates");
assertThat(resourceTemplates).hasSize(1);
assertThat(resourceTemplates.get("config://{key}")).isNotNull();

ConcurrentHashMap<String, AsyncPromptSpecification> prompts = (ConcurrentHashMap<String, AsyncPromptSpecification>) ReflectionTestUtils
.getField(asyncServer, "prompts");
Expand Down Expand Up @@ -363,7 +369,12 @@ void asyncStatelessServerSpecificationConfiguration() {
ConcurrentHashMap<String, AsyncResourceSpecification> resources = (ConcurrentHashMap<String, AsyncResourceSpecification>) ReflectionTestUtils
.getField(asyncServer, "resources");
assertThat(resources).hasSize(1);
assertThat(resources.get("config://{key}")).isNotNull();
assertThat(resources.get("simple://static")).isNotNull();

ConcurrentHashMap<String, AsyncResourceTemplateSpecification> resourceTemplates = (ConcurrentHashMap<String, AsyncResourceTemplateSpecification>) ReflectionTestUtils
.getField(asyncServer, "resourceTemplates");
assertThat(resourceTemplates).hasSize(1);
assertThat(resourceTemplates.get("config://{key}")).isNotNull();

ConcurrentHashMap<String, AsyncPromptSpecification> prompts = (ConcurrentHashMap<String, AsyncPromptSpecification>) ReflectionTestUtils
.getField(asyncServer, "prompts");
Expand Down Expand Up @@ -530,6 +541,11 @@ public int add(@McpToolParam(description = "First number", required = true) int
return a + b;
}

@McpResource(uri = "simple://static", name = "Configuration", description = "Provides configuration data")
public String getSimple() {
return "Hi there!";
}

@McpResource(uri = "config://{key}", name = "Configuration", description = "Provides configuration data")
public String getConfig(String key) {
return "config value";
Expand Down Expand Up @@ -566,6 +582,11 @@ public Mono<Integer> add(@McpToolParam(description = "First number", required =
return Mono.just(a + b);
}

@McpResource(uri = "simple://static", name = "Configuration", description = "Provides configuration data")
public Mono<String> getSimple() {
return Mono.just("Hi there!");
}

@McpResource(uri = "config://{key}", name = "Configuration", description = "Provides configuration data")
public Mono<String> getConfig(String key) {
return Mono.just("config value");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.modelcontextprotocol.server.McpServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceTemplateSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures;
import org.springaicommunity.mcp.method.changed.prompt.AsyncPromptListChangedSpecification;
Expand Down Expand Up @@ -119,6 +120,17 @@ public static List<McpStatelessServerFeatures.AsyncResourceSpecification> statel
return new SpringAiAsyncStatelessResourceProvider(resourceObjects).getResourceSpecifications();
}

// RESOURCE TEMPLATE
public static List<AsyncResourceTemplateSpecification> resourceTemplateSpecifications(
List<Object> resourceObjects) {
return new SpringAiAsyncResourceProvider(resourceObjects).getResourceTemplateSpecifications();
}

public static List<McpStatelessServerFeatures.AsyncResourceTemplateSpecification> statelessResourceTemplateSpecifications(
List<Object> resourceObjects) {
return new SpringAiAsyncStatelessResourceProvider(resourceObjects).getResourceTemplateSpecifications();
}

// RESOURCE LIST CHANGED
public static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(
List<Object> resourceListChangedObjects) {
Expand Down
Loading