-
Notifications
You must be signed in to change notification settings - Fork 675
Description
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 onlyfile:///static.txt
.resources/templates/list
response: 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.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.