1- import { vi , it , describe , beforeEach , afterEach , type MockedFunction , afterAll , expect } from "vitest" ;
1+ import { vi , it , describe , beforeEach , afterEach , afterAll , expect } from "vitest" ;
22import { type CallToolResult } from "@modelcontextprotocol/sdk/types.js" ;
33import { Client } from "@modelcontextprotocol/sdk/client/index.js" ;
44import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
55import { 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" ;
77import { defaultDriverOptions , type UserConfig } from "../../../../src/common/config.js" ;
88import { MCPConnectionManager } from "../../../../src/common/connectionManager.js" ;
99import { Session } from "../../../../src/common/session.js" ;
@@ -19,6 +19,7 @@ import { setupMongoDBIntegrationTest } from "./mongodbHelpers.js";
1919import { ErrorCodes } from "../../../../src/common/errors.js" ;
2020import { Keychain } from "../../../../src/common/keychain.js" ;
2121import { Elicitation } from "../../../../src/elicitation.js" ;
22+ import { MongoDbTools } from "../../../../src/tools/mongodb/tools.js" ;
2223
2324const injectedErrorHandler : ConnectionErrorHandler = ( error ) => {
2425 switch ( error . code ) {
@@ -51,29 +52,45 @@ const injectedErrorHandler: ConnectionErrorHandler = (error) => {
5152 }
5253} ;
5354
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 ( ) ;
6775 }
76+ return false ;
77+ }
78+ public async execute ( ) : Promise < CallToolResult > {
79+ await this . ensureConnected ( ) ;
80+ return { content : [ { type : "text" , text : "Something" } ] } ;
6881 }
82+ }
83+
84+ describe ( "MongoDBTool implementations" , ( ) => {
85+ const mdbIntegration = setupMongoDBIntegrationTest ( { enterprise : false } , [ ] ) ;
6986
70- let tool : RandomTool | undefined ;
7187 let mcpClient : Client | undefined ;
7288 let mcpServer : Server | undefined ;
7389 let deviceId : DeviceId | undefined ;
7490
7591 async function cleanupAndStartServer (
7692 config : Partial < UserConfig > | undefined = { } ,
93+ toolConstructors : ( new ( params : ToolConstructorParams ) => ToolBase ) [ ] = [ ...MongoDbTools , RandomTool ] ,
7794 errorHandler : ConnectionErrorHandler | undefined = connectionErrorHandler
7895 ) : Promise < void > {
7996 await cleanup ( ) ;
@@ -126,16 +143,9 @@ describe("MongoDBTool implementations", () => {
126143 mcpServer : internalMcpServer ,
127144 connectionErrorHandler : errorHandler ,
128145 elicitation,
146+ toolConstructors,
129147 } ) ;
130148
131- tool = new RandomTool ( {
132- session,
133- config : userConfig ,
134- telemetry,
135- elicitation,
136- } ) ;
137- tool . register ( mcpServer ) ;
138-
139149 await mcpServer . connect ( serverTransport ) ;
140150 await mcpClient . connect ( clientTransport ) ;
141151 }
@@ -150,8 +160,6 @@ describe("MongoDBTool implementations", () => {
150160
151161 deviceId ?. close ( ) ;
152162 deviceId = undefined ;
153-
154- tool = undefined ;
155163 }
156164
157165 beforeEach ( async ( ) => {
@@ -232,7 +240,7 @@ describe("MongoDBTool implementations", () => {
232240
233241 describe ( "when MCP is using injected connection error handler" , ( ) => {
234242 beforeEach ( async ( ) => {
235- await cleanupAndStartServer ( defaultTestConfig , injectedErrorHandler ) ;
243+ await cleanupAndStartServer ( defaultTestConfig , [ ... MongoDbTools , RandomTool ] , injectedErrorHandler ) ;
236244 } ) ;
237245
238246 describe ( "and comes across a MongoDB Error - NotConnectedToMongoDB" , ( ) => {
@@ -256,7 +264,11 @@ describe("MongoDBTool implementations", () => {
256264 describe ( "and comes across a MongoDB Error - MisconfiguredConnectionString" , ( ) => {
257265 it ( "should handle the error" , async ( ) => {
258266 // 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+ ) ;
260272 const toolResponse = await mcpClient ?. callTool ( {
261273 name : "Random" ,
262274 arguments : { } ,
@@ -278,6 +290,7 @@ describe("MongoDBTool implementations", () => {
278290 // This is a misconfigured connection string
279291 await cleanupAndStartServer (
280292 { connectionString : mdbIntegration . connectionString ( ) , indexCheck : true } ,
293+ [ ...MongoDbTools , RandomTool ] ,
281294 injectedErrorHandler
282295 ) ;
283296 const toolResponse = await mcpClient ?. callTool ( {
@@ -299,4 +312,17 @@ describe("MongoDBTool implementations", () => {
299312 } ) ;
300313 } ) ;
301314 } ) ;
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+ } ) ;
302328} ) ;
0 commit comments