1
+ /*
2
+ * Copyright 2024-2024 the original author or authors.
3
+ */
4
+
5
+ package io .modelcontextprotocol .server ;
6
+
7
+ import io .modelcontextprotocol .spec .McpSchema ;
8
+ import org .junit .jupiter .api .Test ;
9
+
10
+ import java .util .List ;
11
+ import java .util .stream .Collectors ;
12
+
13
+ import static org .assertj .core .api .Assertions .assertThat ;
14
+
15
+ /**
16
+ * Test to verify the separation of regular resources and resource templates. Regular
17
+ * resources (without template parameters) should only appear in resources/list. Template
18
+ * resources (containing {}) should only appear in resources/templates/list.
19
+ */
20
+ public class ResourceTemplateListingTest {
21
+
22
+ @ Test
23
+ void testTemplateResourcesFilteredFromRegularListing () {
24
+ // The change we made filters resources containing "{" from the regular listing
25
+ // This test verifies that behavior is working correctly
26
+
27
+ // Given a string with template parameter
28
+ String templateUri = "file:///test/{userId}/profile.txt" ;
29
+ assertThat (templateUri .contains ("{" )).isTrue ();
30
+
31
+ // And a regular URI
32
+ String regularUri = "file:///test/regular.txt" ;
33
+ assertThat (regularUri .contains ("{" )).isFalse ();
34
+
35
+ // The filter should exclude template URIs
36
+ assertThat (!templateUri .contains ("{" )).isFalse ();
37
+ assertThat (!regularUri .contains ("{" )).isTrue ();
38
+ }
39
+
40
+ @ Test
41
+ void testResourceListingWithMixedResources () {
42
+ // Create resource list with both regular and template resources
43
+ List <McpSchema .Resource > allResources = List .of (
44
+ new McpSchema .Resource ("file:///test/doc1.txt" , "Document 1" , "text/plain" , null , null ),
45
+ new McpSchema .Resource ("file:///test/doc2.txt" , "Document 2" , "text/plain" , null , null ),
46
+ new McpSchema .Resource ("file:///test/{type}/document.txt" , "Typed Document" , "text/plain" , null , null ),
47
+ new McpSchema .Resource ("file:///users/{userId}/files/{fileId}" , "User File" , "text/plain" , null , null ));
48
+
49
+ // Apply the filter logic from McpAsyncServer line 438
50
+ List <McpSchema .Resource > filteredResources = allResources .stream ()
51
+ .filter (resource -> !resource .uri ().contains ("{" ))
52
+ .collect (Collectors .toList ());
53
+
54
+ // Verify only regular resources are included
55
+ assertThat (filteredResources ).hasSize (2 );
56
+ assertThat (filteredResources ).extracting (McpSchema .Resource ::uri )
57
+ .containsExactlyInAnyOrder ("file:///test/doc1.txt" , "file:///test/doc2.txt" );
58
+ }
59
+
60
+ @ Test
61
+ void testResourceTemplatesListedSeparately () {
62
+ // Create mixed resources
63
+ List <McpSchema .Resource > resources = List .of (
64
+ new McpSchema .Resource ("file:///test/regular.txt" , "Regular Resource" , "text/plain" , null , null ),
65
+ new McpSchema .Resource ("file:///test/user/{userId}/profile.txt" , "User Profile" , "text/plain" , null ,
66
+ null ));
67
+
68
+ // Create explicit resource template
69
+ McpSchema .ResourceTemplate explicitTemplate = new McpSchema .ResourceTemplate (
70
+ "file:///test/document/{docId}/content.txt" , "Document Template" , null , "text/plain" , null );
71
+
72
+ // Filter regular resources (those without template parameters)
73
+ List <McpSchema .Resource > regularResources = resources .stream ()
74
+ .filter (resource -> !resource .uri ().contains ("{" ))
75
+ .collect (Collectors .toList ());
76
+
77
+ // Extract template resources (those with template parameters)
78
+ List <McpSchema .ResourceTemplate > templateResources = resources .stream ()
79
+ .filter (resource -> resource .uri ().contains ("{" ))
80
+ .map (resource -> new McpSchema .ResourceTemplate (resource .uri (), resource .name (), resource .description (),
81
+ resource .mimeType (), resource .annotations ()))
82
+ .collect (Collectors .toList ());
83
+
84
+ // Verify regular resources list
85
+ assertThat (regularResources ).hasSize (1 );
86
+ assertThat (regularResources .get (0 ).uri ()).isEqualTo ("file:///test/regular.txt" );
87
+
88
+ // Verify template resources list includes both extracted and explicit templates
89
+ assertThat (templateResources ).hasSize (1 );
90
+ assertThat (templateResources .get (0 ).uriTemplate ()).isEqualTo ("file:///test/user/{userId}/profile.txt" );
91
+
92
+ // In the actual implementation, both would be combined
93
+ List <McpSchema .ResourceTemplate > allTemplates = List .of (templateResources .get (0 ), explicitTemplate );
94
+ assertThat (allTemplates ).hasSize (2 );
95
+ assertThat (allTemplates ).extracting (McpSchema .ResourceTemplate ::uriTemplate )
96
+ .containsExactlyInAnyOrder ("file:///test/user/{userId}/profile.txt" ,
97
+ "file:///test/document/{docId}/content.txt" );
98
+ }
99
+
100
+ }
0 commit comments