4
4
5
5
package io .modelcontextprotocol .server ;
6
6
7
+ import static org .assertj .core .api .Assertions .assertThat ;
8
+ import static org .assertj .core .api .Assertions .assertThatCode ;
9
+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
10
+
7
11
import java .util .List ;
8
12
13
+ import org .junit .jupiter .api .AfterEach ;
14
+ import org .junit .jupiter .api .BeforeEach ;
15
+ import org .junit .jupiter .api .Test ;
16
+
9
17
import io .modelcontextprotocol .spec .McpError ;
10
18
import io .modelcontextprotocol .spec .McpSchema ;
11
19
import io .modelcontextprotocol .spec .McpSchema .CallToolResult ;
17
25
import io .modelcontextprotocol .spec .McpSchema .ServerCapabilities ;
18
26
import io .modelcontextprotocol .spec .McpSchema .Tool ;
19
27
import io .modelcontextprotocol .spec .McpServerTransportProvider ;
20
- import org .junit .jupiter .api .AfterEach ;
21
- import org .junit .jupiter .api .BeforeEach ;
22
- import org .junit .jupiter .api .Test ;
23
-
24
- import static org .assertj .core .api .Assertions .assertThat ;
25
- import static org .assertj .core .api .Assertions .assertThatCode ;
26
- import static org .assertj .core .api .Assertions .assertThatThrownBy ;
27
28
28
29
/**
29
30
* Test suite for the {@link McpSyncServer} that can be used with different
30
- * {@link io.modelcontextprotocol.spec.McpServerTransportProvider } implementations.
31
+ * {@link McpTransportProvider } implementations.
31
32
*
32
33
* @author Christian Tzolov
33
34
*/
34
- // KEEP IN SYNC with the class in mcp-test module
35
35
public abstract class AbstractMcpSyncServerTests {
36
36
37
37
private static final String TEST_TOOL_NAME = "test-tool" ;
@@ -109,6 +109,7 @@ void testGetAsyncServer() {
109
109
""" ;
110
110
111
111
@ Test
112
+ @ Deprecated
112
113
void testAddTool () {
113
114
var mcpSyncServer = McpServer .sync (createMcpTransportProvider ())
114
115
.serverInfo ("test-server" , "1.0.0" )
@@ -124,6 +125,23 @@ void testAddTool() {
124
125
}
125
126
126
127
@ Test
128
+ void testAddToolCall () {
129
+ var mcpSyncServer = McpServer .sync (createMcpTransportProvider ())
130
+ .serverInfo ("test-server" , "1.0.0" )
131
+ .capabilities (ServerCapabilities .builder ().tools (true ).build ())
132
+ .build ();
133
+
134
+ Tool newTool = new McpSchema .Tool ("new-tool" , "New test tool" , emptyJsonSchema );
135
+ assertThatCode (() -> mcpSyncServer .addTool (McpServerFeatures .SyncToolSpecification .builder ()
136
+ .tool (newTool )
137
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
138
+ .build ())).doesNotThrowAnyException ();
139
+
140
+ assertThatCode (() -> mcpSyncServer .closeGracefully ()).doesNotThrowAnyException ();
141
+ }
142
+
143
+ @ Test
144
+ @ Deprecated
127
145
void testAddDuplicateTool () {
128
146
Tool duplicateTool = new McpSchema .Tool (TEST_TOOL_NAME , "Duplicate tool" , emptyJsonSchema );
129
147
@@ -141,14 +159,89 @@ void testAddDuplicateTool() {
141
159
assertThatCode (() -> mcpSyncServer .closeGracefully ()).doesNotThrowAnyException ();
142
160
}
143
161
162
+ @ Test
163
+ void testAddDuplicateToolCall () {
164
+ Tool duplicateTool = new McpSchema .Tool (TEST_TOOL_NAME , "Duplicate tool" , emptyJsonSchema );
165
+
166
+ var mcpSyncServer = McpServer .sync (createMcpTransportProvider ())
167
+ .serverInfo ("test-server" , "1.0.0" )
168
+ .capabilities (ServerCapabilities .builder ().tools (true ).build ())
169
+ .toolCall (duplicateTool , (exchange , request ) -> new CallToolResult (List .of (), false ))
170
+ .build ();
171
+
172
+ assertThatThrownBy (() -> mcpSyncServer .addTool (McpServerFeatures .SyncToolSpecification .builder ()
173
+ .tool (duplicateTool )
174
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
175
+ .build ())).isInstanceOf (McpError .class )
176
+ .hasMessage ("Tool with name '" + TEST_TOOL_NAME + "' already exists" );
177
+
178
+ assertThatCode (() -> mcpSyncServer .closeGracefully ()).doesNotThrowAnyException ();
179
+ }
180
+
181
+ @ Test
182
+ void testDuplicateToolCallDuringBuilding () {
183
+ Tool duplicateTool = new Tool ("duplicate-build-toolcall" , "Duplicate toolcall during building" ,
184
+ emptyJsonSchema );
185
+
186
+ assertThatThrownBy (() -> McpServer .sync (createMcpTransportProvider ())
187
+ .serverInfo ("test-server" , "1.0.0" )
188
+ .capabilities (ServerCapabilities .builder ().tools (true ).build ())
189
+ .toolCall (duplicateTool , (exchange , request ) -> new CallToolResult (List .of (), false ))
190
+ .toolCall (duplicateTool , (exchange , request ) -> new CallToolResult (List .of (), false )) // Duplicate!
191
+ .build ()).isInstanceOf (IllegalArgumentException .class )
192
+ .hasMessage ("Tool with name 'duplicate-build-toolcall' is already registered." );
193
+ }
194
+
195
+ @ Test
196
+ void testDuplicateToolsInBatchListRegistration () {
197
+ Tool duplicateTool = new Tool ("batch-list-tool" , "Duplicate tool in batch list" , emptyJsonSchema );
198
+ List <McpServerFeatures .SyncToolSpecification > specs = List .of (
199
+ McpServerFeatures .SyncToolSpecification .builder ()
200
+ .tool (duplicateTool )
201
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
202
+ .build (),
203
+ McpServerFeatures .SyncToolSpecification .builder ()
204
+ .tool (duplicateTool )
205
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
206
+ .build () // Duplicate!
207
+ );
208
+
209
+ assertThatThrownBy (() -> McpServer .sync (createMcpTransportProvider ())
210
+ .serverInfo ("test-server" , "1.0.0" )
211
+ .capabilities (ServerCapabilities .builder ().tools (true ).build ())
212
+ .tools (specs )
213
+ .build ()).isInstanceOf (IllegalArgumentException .class )
214
+ .hasMessage ("Tool with name 'batch-list-tool' is already registered." );
215
+ }
216
+
217
+ @ Test
218
+ void testDuplicateToolsInBatchVarargsRegistration () {
219
+ Tool duplicateTool = new Tool ("batch-varargs-tool" , "Duplicate tool in batch varargs" , emptyJsonSchema );
220
+
221
+ assertThatThrownBy (() -> McpServer .sync (createMcpTransportProvider ())
222
+ .serverInfo ("test-server" , "1.0.0" )
223
+ .capabilities (ServerCapabilities .builder ().tools (true ).build ())
224
+ .tools (McpServerFeatures .SyncToolSpecification .builder ()
225
+ .tool (duplicateTool )
226
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
227
+ .build (),
228
+ McpServerFeatures .SyncToolSpecification .builder ()
229
+ .tool (duplicateTool )
230
+ .callHandler ((exchange , request ) -> new CallToolResult (List .of (), false ))
231
+ .build () // Duplicate!
232
+ )
233
+ .build ()).isInstanceOf (IllegalArgumentException .class )
234
+ .hasMessage ("Tool with name 'batch-varargs-tool' is already registered." );
235
+ }
236
+
144
237
@ Test
145
238
void testRemoveTool () {
146
239
Tool tool = new McpSchema .Tool (TEST_TOOL_NAME , "Test tool" , emptyJsonSchema );
147
240
148
241
var mcpSyncServer = McpServer .sync (createMcpTransportProvider ())
149
242
.serverInfo ("test-server" , "1.0.0" )
150
243
.capabilities (ServerCapabilities .builder ().tools (true ).build ())
151
- .tool (tool , (exchange , args ) -> new CallToolResult (List .of (), false ))
244
+ .toolCall (tool , (exchange , args ) -> new CallToolResult (List .of (), false ))
152
245
.build ();
153
246
154
247
assertThatCode (() -> mcpSyncServer .removeTool (TEST_TOOL_NAME )).doesNotThrowAnyException ();
0 commit comments