Bug description
The resources/list endpoint currently returns all registered resources, including those with templated URIs (e.g., user://{userId}). This behavior is inconsistent with the protocol's design, which separates static resources from templates.
According to convention, resources/list should only expose static, directly addressable resources. Templated resources should be discoverable exclusively through the resources/templates/list endpoint. This incorrect exposure can lead to confusion and improper handling on the client side.
Additionally, a related cleanup task is to fix a typo in a utility class name: DeafaultMcpUriTemplateManagerFactory should be DefaultMcpUriTemplateManagerFactory.
Environment
- Library:
io.modelcontextprotocol.sdk:mcp
- Version:
0.11.0-SNAPSHOT and prior.
- Java version: N/A (Affects all supported Java versions).
- Vector store: N/A.
Steps to reproduce
- Create an
McpAsyncServer instance.
- Register a mix of static and templated resources using the
.resources() builder method. For example:
McpServer.async(transportProvider)
.resources(
new McpServerFeatures.AsyncResourceSpecification(
new McpSchema.Resource("file:///static.txt", "Static File", "text/plain", null),
(exchange, req) -> Mono.empty()
),
new McpServerFeatures.AsyncResourceSpecification(
new McpSchema.Resource("user://{userId}", "User Profile", "application/json", null),
(exchange, req) -> Mono.empty()
)
)
.build();
- Start the server and connect a client.
- The client sends a
resources/list request to the server.
- Observe the
ListResourcesResult: the response contains both "file:///static.txt" and "user://{userId}".
Expected behavior
The response from the resources/list request should only contain the static resource. The templated resource should be filtered out.
resources/list response: Should contain only file:///static.txt.
resources/templates/list response: Should contain user://{userId} (as it is correctly inferred from the URI pattern).
Minimal Complete Reproducible example
The issue can be demonstrated and verified with a unit test that simulates the server's filtering logic. The current implementation in McpAsyncServer.java lacks the necessary filter.
Failing Test (Illustrates the Bug)
A test case that directly checks the current logic would look like this:
// In a test class like ResourceTemplateListingTest.java
@Test
void testResourceListingWithMixedResources() {
// Given a list of mixed resource types
List<McpSchema.Resource> allResources = List.of(
new McpSchema.Resource("file:///doc1.txt", "Doc 1", "text/plain", null, null),
new McpSchema.Resource("user://{userId}", "User Profile", "text/plain", null, null)
);
// When applying the server's filtering logic (currently none)
// This simulates the logic in McpAsyncServer.resourcesListRequestHandler()
List<McpSchema.Resource> filteredResources = allResources.stream()
// .filter(resource -> !resource.uri().contains("{")) // This line is missing
.collect(Collectors.toList());
// Then the assertion fails because the template is included
// Expected size: 1, Actual size: 2
assertThat(filteredResources).hasSize(1);
assertThat(filteredResources).extracting(McpSchema.Resource::uri)
.containsExactly("file:///doc1.txt");
}
Proposed Fix
The fix involves adding a filter to the resourcesListRequestHandler in McpAsyncServer.java:
// File: mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java
private McpServerSession.RequestHandler<McpSchema.ListResourcesResult> resourcesListRequestHandler() {
return (exchange, params) -> {
var resourceList = this.resources.values()
.stream()
.map(McpServerFeatures.AsyncResourceSpecification::resource)
// Add this filter to exclude templates
.filter(resource -> !resource.uri().contains("{"))
.toList();
return Mono.just(new McpSchema.ListResourcesResult(resourceList, null));
};
}
With this change, the reproducible example test case will pass, and the server will behave as expected.
Bug description
The
resources/listendpoint currently returns all registered resources, including those with templated URIs (e.g.,user://{userId}). This behavior is inconsistent with the protocol's design, which separates static resources from templates.According to convention,
resources/listshould only expose static, directly addressable resources. Templated resources should be discoverable exclusively through theresources/templates/listendpoint. This incorrect exposure can lead to confusion and improper handling on the client side.Additionally, a related cleanup task is to fix a typo in a utility class name:
DeafaultMcpUriTemplateManagerFactoryshould beDefaultMcpUriTemplateManagerFactory.Environment
io.modelcontextprotocol.sdk:mcp0.11.0-SNAPSHOTand prior.Steps to reproduce
McpAsyncServerinstance..resources()builder method. For example:resources/listrequest to the server.ListResourcesResult: the response contains both"file:///static.txt"and"user://{userId}".Expected behavior
The response from the
resources/listrequest should only contain the static resource. The templated resource should be filtered out.resources/listresponse: Should contain onlyfile:///static.txt.resources/templates/listresponse: Should containuser://{userId}(as it is correctly inferred from the URI pattern).Minimal Complete Reproducible example
The issue can be demonstrated and verified with a unit test that simulates the server's filtering logic. The current implementation in
McpAsyncServer.javalacks the necessary filter.Failing Test (Illustrates the Bug)
A test case that directly checks the current logic would look like this:
Proposed Fix
The fix involves adding a filter to the
resourcesListRequestHandlerinMcpAsyncServer.java:With this change, the reproducible example test case will pass, and the server will behave as expected.