1
- import { vi , it , describe , beforeEach , afterEach , type MockedFunction , afterAll , expect } from "vitest" ;
1
+ import { vi , it , describe , beforeEach , afterEach , afterAll , expect } from "vitest" ;
2
2
import { type CallToolResult } from "@modelcontextprotocol/sdk/types.js" ;
3
3
import { Client } from "@modelcontextprotocol/sdk/client/index.js" ;
4
4
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
5
5
import { MongoDBToolBase } from "../../../../src/tools/mongodb/mongodbTool.js" ;
6
- import { type OperationType } from "../../../../src/tools/tool.js" ;
6
+ import { type ToolBase , type ToolConstructorParams , type OperationType } from "../../../../src/tools/tool.js" ;
7
7
import { defaultDriverOptions , type UserConfig } from "../../../../src/common/config.js" ;
8
8
import { MCPConnectionManager } from "../../../../src/common/connectionManager.js" ;
9
9
import { Session } from "../../../../src/common/session.js" ;
@@ -19,6 +19,7 @@ import { setupMongoDBIntegrationTest } from "./mongodbHelpers.js";
19
19
import { ErrorCodes } from "../../../../src/common/errors.js" ;
20
20
import { Keychain } from "../../../../src/common/keychain.js" ;
21
21
import { Elicitation } from "../../../../src/elicitation.js" ;
22
+ import { MongoDbTools } from "../../../../src/tools/mongodb/tools.js" ;
22
23
23
24
const injectedErrorHandler : ConnectionErrorHandler = ( error ) => {
24
25
switch ( error . code ) {
@@ -51,29 +52,45 @@ const injectedErrorHandler: ConnectionErrorHandler = (error) => {
51
52
}
52
53
} ;
53
54
54
- describe ( "MongoDBTool implementations" , ( ) => {
55
- const mdbIntegration = setupMongoDBIntegrationTest ( { enterprise : false } , [ ] ) ;
56
- const executeStub : MockedFunction < ( ) => Promise < CallToolResult > > = vi
57
- . fn ( )
58
- . mockResolvedValue ( { content : [ { type : "text" , text : "Something" } ] } ) ;
59
- class RandomTool extends MongoDBToolBase {
60
- name = "Random" ;
61
- operationType : OperationType = "read" ;
62
- protected description = "This is a tool." ;
63
- protected argsShape = { } ;
64
- public async execute ( ) : Promise < CallToolResult > {
65
- await this . ensureConnected ( ) ;
66
- return executeStub ( ) ;
55
+ class RandomTool extends MongoDBToolBase {
56
+ name = "Random" ;
57
+ operationType : OperationType = "read" ;
58
+ protected description = "This is a tool." ;
59
+ protected argsShape = { } ;
60
+ public async execute ( ) : Promise < CallToolResult > {
61
+ await this . ensureConnected ( ) ;
62
+ return { content : [ { type : "text" , text : "Something" } ] } ;
63
+ }
64
+ }
65
+
66
+ class UnusableVoyageTool extends MongoDBToolBase {
67
+ name = "UnusableVoyageTool" ;
68
+ operationType : OperationType = "read" ;
69
+ protected description = "This is a Voyage tool." ;
70
+ protected argsShape = { } ;
71
+
72
+ override verifyAllowed ( ) : boolean {
73
+ if ( this . config . voyageApiKey . trim ( ) ) {
74
+ return super . verifyAllowed ( ) ;
67
75
}
76
+ return false ;
77
+ }
78
+ public async execute ( ) : Promise < CallToolResult > {
79
+ await this . ensureConnected ( ) ;
80
+ return { content : [ { type : "text" , text : "Something" } ] } ;
68
81
}
82
+ }
83
+
84
+ describe ( "MongoDBTool implementations" , ( ) => {
85
+ const mdbIntegration = setupMongoDBIntegrationTest ( { enterprise : false } , [ ] ) ;
69
86
70
- let tool : RandomTool | undefined ;
71
87
let mcpClient : Client | undefined ;
72
88
let mcpServer : Server | undefined ;
73
89
let deviceId : DeviceId | undefined ;
74
90
75
91
async function cleanupAndStartServer (
76
92
config : Partial < UserConfig > | undefined = { } ,
93
+ toolConstructors : ( new ( params : ToolConstructorParams ) => ToolBase ) [ ] = [ ...MongoDbTools , RandomTool ] ,
77
94
errorHandler : ConnectionErrorHandler | undefined = connectionErrorHandler
78
95
) : Promise < void > {
79
96
await cleanup ( ) ;
@@ -126,16 +143,9 @@ describe("MongoDBTool implementations", () => {
126
143
mcpServer : internalMcpServer ,
127
144
connectionErrorHandler : errorHandler ,
128
145
elicitation,
146
+ toolConstructors,
129
147
} ) ;
130
148
131
- tool = new RandomTool ( {
132
- session,
133
- config : userConfig ,
134
- telemetry,
135
- elicitation,
136
- } ) ;
137
- tool . register ( mcpServer ) ;
138
-
139
149
await mcpServer . connect ( serverTransport ) ;
140
150
await mcpClient . connect ( clientTransport ) ;
141
151
}
@@ -150,8 +160,6 @@ describe("MongoDBTool implementations", () => {
150
160
151
161
deviceId ?. close ( ) ;
152
162
deviceId = undefined ;
153
-
154
- tool = undefined ;
155
163
}
156
164
157
165
beforeEach ( async ( ) => {
@@ -232,7 +240,7 @@ describe("MongoDBTool implementations", () => {
232
240
233
241
describe ( "when MCP is using injected connection error handler" , ( ) => {
234
242
beforeEach ( async ( ) => {
235
- await cleanupAndStartServer ( defaultTestConfig , injectedErrorHandler ) ;
243
+ await cleanupAndStartServer ( defaultTestConfig , [ ... MongoDbTools , RandomTool ] , injectedErrorHandler ) ;
236
244
} ) ;
237
245
238
246
describe ( "and comes across a MongoDB Error - NotConnectedToMongoDB" , ( ) => {
@@ -256,7 +264,11 @@ describe("MongoDBTool implementations", () => {
256
264
describe ( "and comes across a MongoDB Error - MisconfiguredConnectionString" , ( ) => {
257
265
it ( "should handle the error" , async ( ) => {
258
266
// This is a misconfigured connection string
259
- await cleanupAndStartServer ( { connectionString : "mongodb://localhost:1234" } , injectedErrorHandler ) ;
267
+ await cleanupAndStartServer (
268
+ { connectionString : "mongodb://localhost:1234" } ,
269
+ [ ...MongoDbTools , RandomTool ] ,
270
+ injectedErrorHandler
271
+ ) ;
260
272
const toolResponse = await mcpClient ?. callTool ( {
261
273
name : "Random" ,
262
274
arguments : { } ,
@@ -278,6 +290,7 @@ describe("MongoDBTool implementations", () => {
278
290
// This is a misconfigured connection string
279
291
await cleanupAndStartServer (
280
292
{ connectionString : mdbIntegration . connectionString ( ) , indexCheck : true } ,
293
+ [ ...MongoDbTools , RandomTool ] ,
281
294
injectedErrorHandler
282
295
) ;
283
296
const toolResponse = await mcpClient ?. callTool ( {
@@ -299,4 +312,17 @@ describe("MongoDBTool implementations", () => {
299
312
} ) ;
300
313
} ) ;
301
314
} ) ;
315
+
316
+ describe ( "when a tool is not usable" , ( ) => {
317
+ it ( "should not even be registered" , async ( ) => {
318
+ await cleanupAndStartServer (
319
+ { connectionString : mdbIntegration . connectionString ( ) , indexCheck : true } ,
320
+ [ RandomTool , UnusableVoyageTool ] ,
321
+ injectedErrorHandler
322
+ ) ;
323
+ const tools = await mcpClient ?. listTools ( { } ) ;
324
+ expect ( tools ?. tools ) . toHaveLength ( 1 ) ;
325
+ expect ( tools ?. tools . find ( ( tool ) => tool . name === "UnusableVoyageTool" ) ) . toBeUndefined ( ) ;
326
+ } ) ;
327
+ } ) ;
302
328
} ) ;
0 commit comments