@@ -9,6 +9,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
9
import { MongoClient , ObjectId } from "mongodb" ;
10
10
import { toIncludeAllMembers } from "jest-extended" ;
11
11
import config from "../../src/config.js" ;
12
+ import { McpError } from "@modelcontextprotocol/sdk/types.js" ;
12
13
13
14
interface ParameterInfo {
14
15
name : string ;
@@ -226,10 +227,93 @@ export const dbOperationParameters: ParameterInfo[] = [
226
227
{ name : "collection" , type : "string" , description : "Collection name" , required : true } ,
227
228
] ;
228
229
229
- export function validateParameters ( tool : ToolInfo , parameters : ParameterInfo [ ] ) : void {
230
- const toolParameters = getParameters ( tool ) ;
231
- expect ( toolParameters ) . toHaveLength ( parameters . length ) ;
232
- expect ( toolParameters ) . toIncludeAllMembers ( parameters ) ;
230
+ export const dbOperationInvalidArgTests = [ { } , { database : 123 } , { foo : "bar" , database : "test" } , { database : [ ] } ] ;
231
+
232
+ export function validateToolMetadata (
233
+ integration : IntegrationTest ,
234
+ name : string ,
235
+ description : string ,
236
+ parameters : ParameterInfo [ ]
237
+ ) : void {
238
+ it ( "should have correct metadata" , async ( ) => {
239
+ const { tools } = await integration . mcpClient ( ) . listTools ( ) ;
240
+ const tool = tools . find ( ( tool ) => tool . name === name ) ! ;
241
+ expect ( tool ) . toBeDefined ( ) ;
242
+ expect ( tool . description ) . toBe ( description ) ;
243
+
244
+ const toolParameters = getParameters ( tool ) ;
245
+ expect ( toolParameters ) . toHaveLength ( parameters . length ) ;
246
+ expect ( toolParameters ) . toIncludeAllMembers ( parameters ) ;
247
+ } ) ;
248
+ }
249
+
250
+ export function validateAutoConnectBehavior (
251
+ integration : IntegrationTest ,
252
+ name : string ,
253
+ validation : ( ) => {
254
+ args : { [ x : string ] : unknown } ;
255
+ expectedResponse ?: string ;
256
+ validate ?: ( content : unknown ) => void ;
257
+ } ,
258
+ beforeEachImpl ?: ( ) => Promise < void >
259
+ ) : void {
260
+ describe ( "when not connected" , ( ) => {
261
+ if ( beforeEachImpl ) {
262
+ beforeEach ( ( ) => beforeEachImpl ( ) ) ;
263
+ }
264
+
265
+ it ( "connects automatically if connection string is configured" , async ( ) => {
266
+ config . connectionString = integration . connectionString ( ) ;
267
+
268
+ const validationInfo = validation ( ) ;
269
+
270
+ const response = await integration . mcpClient ( ) . callTool ( {
271
+ name,
272
+ arguments : validationInfo . args ,
273
+ } ) ;
274
+
275
+ if ( validationInfo . expectedResponse ) {
276
+ const content = getResponseContent ( response . content ) ;
277
+ expect ( content ) . toContain ( validationInfo . expectedResponse ) ;
278
+ }
279
+
280
+ if ( validationInfo . validate ) {
281
+ validationInfo . validate ( response . content ) ;
282
+ }
283
+ } ) ;
284
+
285
+ it ( "throws an error if connection string is not configured" , async ( ) => {
286
+ const response = await integration . mcpClient ( ) . callTool ( {
287
+ name,
288
+ arguments : validation ( ) . args ,
289
+ } ) ;
290
+ const content = getResponseContent ( response . content ) ;
291
+ expect ( content ) . toContain ( "You need to connect to a MongoDB instance before you can access its data." ) ;
292
+ } ) ;
293
+ } ) ;
294
+ }
295
+
296
+ export function validateThrowsForInvalidArguments (
297
+ integration : IntegrationTest ,
298
+ name : string ,
299
+ args : { [ x : string ] : unknown } [ ]
300
+ ) : void {
301
+ describe ( "with invalid arguments" , ( ) => {
302
+ for ( const arg of args ) {
303
+ it ( `throws a schema error for: ${ JSON . stringify ( arg ) } ` , async ( ) => {
304
+ await integration . connectMcpClient ( ) ;
305
+ try {
306
+ await integration . mcpClient ( ) . callTool ( { name, arguments : arg } ) ;
307
+ expect . fail ( "Expected an error to be thrown" ) ;
308
+ } catch ( error ) {
309
+ expect ( error ) . toBeInstanceOf ( McpError ) ;
310
+ const mcpError = error as McpError ;
311
+ expect ( mcpError . code ) . toEqual ( - 32602 ) ;
312
+ expect ( mcpError . message ) . toContain ( `Invalid arguments for tool ${ name } ` ) ;
313
+ }
314
+ } ) ;
315
+ }
316
+ } ) ;
233
317
}
234
318
235
319
export function describeAtlas ( name : number | string | Function | jest . FunctionLike , fn : jest . EmptyFunction ) {
0 commit comments