Skip to content

Commit 7e885e6

Browse files
committed
add tests for automatic connections
1 parent eb1dbc7 commit 7e885e6

File tree

8 files changed

+200
-71
lines changed

8 files changed

+200
-71
lines changed

src/tools/mongodb/metadata/connect.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,21 @@ export class ConnectTool extends MongoDBToolBase {
3737

3838
let connectionString: string;
3939

40-
if (typeof connectionStringOrClusterName === "string") {
41-
if (
42-
connectionStringOrClusterName.startsWith("mongodb://") ||
43-
connectionStringOrClusterName.startsWith("mongodb+srv://")
44-
) {
45-
connectionString = connectionStringOrClusterName;
46-
} else {
47-
// TODO:
48-
return {
49-
content: [
50-
{
51-
type: "text",
52-
text: `Connecting via cluster name not supported yet. Please provide a connection string.`,
53-
},
54-
],
55-
};
56-
}
40+
if (
41+
connectionStringOrClusterName.startsWith("mongodb://") ||
42+
connectionStringOrClusterName.startsWith("mongodb+srv://")
43+
) {
44+
connectionString = connectionStringOrClusterName;
5745
} else {
58-
throw new MongoDBError(ErrorCodes.InvalidParams, "Invalid connection options");
46+
// TODO:
47+
return {
48+
content: [
49+
{
50+
type: "text",
51+
text: `Connecting via cluster name not supported yet. Please provide a connection string.`,
52+
},
53+
],
54+
};
5955
}
6056

6157
try {

src/tools/mongodb/mongodbTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ export abstract class MongoDBToolBase extends ToolBase {
1919
protected category: ToolCategory = "mongodb";
2020

2121
protected async ensureConnected(): Promise<NodeDriverServiceProvider> {
22-
const provider = this.session.serviceProvider;
22+
let provider = this.session.serviceProvider;
2323
if (!provider && config.connectionString) {
2424
await this.connectToMongoDB(config.connectionString);
25+
provider = this.session.serviceProvider;
2526
}
2627

2728
if (!provider) {

tests/integration/helpers.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import path from "path";
66
import fs from "fs/promises";
77
import { Session } from "../../src/session.js";
88
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9-
import { MongoClient } from "mongodb";
9+
import { MongoClient, ObjectId } from "mongodb";
1010
import { toIncludeAllMembers } from "jest-extended";
11+
import config from "../../src/config.js";
1112

1213
interface ParameterInfo {
1314
name: string;
@@ -23,13 +24,16 @@ export function setupIntegrationTest(): {
2324
mongoClient: () => MongoClient;
2425
connectionString: () => string;
2526
connectMcpClient: () => Promise<void>;
27+
randomDbName: () => string;
2628
} {
2729
let mongoCluster: runner.MongoCluster | undefined;
2830
let mongoClient: MongoClient | undefined;
2931

3032
let mcpClient: Client | undefined;
3133
let mcpServer: Server | undefined;
3234

35+
let randomDbName: string;
36+
3337
beforeEach(async () => {
3438
const clientTransport = new InMemoryTransport();
3539
const serverTransport = new InMemoryTransport();
@@ -59,6 +63,7 @@ export function setupIntegrationTest(): {
5963
});
6064
await mcpServer.connect(serverTransport);
6165
await mcpClient.connect(clientTransport);
66+
randomDbName = new ObjectId().toString();
6267
});
6368

6469
afterEach(async () => {
@@ -70,6 +75,8 @@ export function setupIntegrationTest(): {
7075

7176
await mongoClient?.close();
7277
mongoClient = undefined;
78+
79+
config.connectionString = undefined;
7380
});
7481

7582
beforeAll(async function () {
@@ -144,6 +151,7 @@ export function setupIntegrationTest(): {
144151
arguments: { connectionStringOrClusterName: getConnectionString() },
145152
});
146153
},
154+
randomDbName: () => randomDbName,
147155
};
148156
}
149157

tests/integration/tools/mongodb/create/createCollection.test.ts

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { toIncludeSameMembers } from "jest-extended";
88
import { McpError } from "@modelcontextprotocol/sdk/types.js";
99
import { ObjectId } from "bson";
10+
import config from "../../../../../src/config.js";
1011

1112
describe("createCollection tool", () => {
1213
const integration = setupIntegrationTest();
@@ -48,69 +49,90 @@ describe("createCollection tool", () => {
4849
describe("with non-existent database", () => {
4950
it("creates a new collection", async () => {
5051
const mongoClient = integration.mongoClient();
51-
let collections = await mongoClient.db("foo").listCollections().toArray();
52+
let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
5253
expect(collections).toHaveLength(0);
5354

5455
await integration.connectMcpClient();
5556
const response = await integration.mcpClient().callTool({
5657
name: "create-collection",
57-
arguments: { database: "foo", collection: "bar" },
58+
arguments: { database: integration.randomDbName(), collection: "bar" },
5859
});
5960
const content = getResponseContent(response.content);
60-
expect(content).toEqual('Collection "bar" created in database "foo".');
61+
expect(content).toEqual(`Collection "bar" created in database "${integration.randomDbName()}".`);
6162

62-
collections = await mongoClient.db("foo").listCollections().toArray();
63+
collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
6364
expect(collections).toHaveLength(1);
6465
expect(collections[0].name).toEqual("bar");
6566
});
6667
});
6768

6869
describe("with existing database", () => {
69-
let dbName: string;
70-
beforeEach(() => {
71-
dbName = new ObjectId().toString();
72-
});
73-
7470
it("creates new collection", async () => {
7571
const mongoClient = integration.mongoClient();
76-
await mongoClient.db(dbName).createCollection("collection1");
77-
let collections = await mongoClient.db(dbName).listCollections().toArray();
72+
await mongoClient.db(integration.randomDbName()).createCollection("collection1");
73+
let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
7874
expect(collections).toHaveLength(1);
7975

8076
await integration.connectMcpClient();
8177
const response = await integration.mcpClient().callTool({
8278
name: "create-collection",
83-
arguments: { database: dbName, collection: "collection2" },
79+
arguments: { database: integration.randomDbName(), collection: "collection2" },
8480
});
8581
const content = getResponseContent(response.content);
86-
expect(content).toEqual(`Collection "collection2" created in database "${dbName}".`);
87-
collections = await mongoClient.db(dbName).listCollections().toArray();
82+
expect(content).toEqual(`Collection "collection2" created in database "${integration.randomDbName()}".`);
83+
collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
8884
expect(collections).toHaveLength(2);
8985
expect(collections.map((c) => c.name)).toIncludeSameMembers(["collection1", "collection2"]);
9086
});
9187

9288
it("does nothing if collection already exists", async () => {
9389
const mongoClient = integration.mongoClient();
94-
await mongoClient.db(dbName).collection("collection1").insertOne({});
95-
let collections = await mongoClient.db(dbName).listCollections().toArray();
90+
await mongoClient.db(integration.randomDbName()).collection("collection1").insertOne({});
91+
let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
9692
expect(collections).toHaveLength(1);
97-
let documents = await mongoClient.db(dbName).collection("collection1").find({}).toArray();
93+
let documents = await mongoClient
94+
.db(integration.randomDbName())
95+
.collection("collection1")
96+
.find({})
97+
.toArray();
9898
expect(documents).toHaveLength(1);
9999

100100
await integration.connectMcpClient();
101101
const response = await integration.mcpClient().callTool({
102102
name: "create-collection",
103-
arguments: { database: dbName, collection: "collection1" },
103+
arguments: { database: integration.randomDbName(), collection: "collection1" },
104104
});
105105
const content = getResponseContent(response.content);
106-
expect(content).toEqual(`Collection "collection1" created in database "${dbName}".`);
107-
collections = await mongoClient.db(dbName).listCollections().toArray();
106+
expect(content).toEqual(`Collection "collection1" created in database "${integration.randomDbName()}".`);
107+
collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray();
108108
expect(collections).toHaveLength(1);
109109
expect(collections[0].name).toEqual("collection1");
110110

111111
// Make sure we didn't drop the existing collection
112-
documents = await mongoClient.db(dbName).collection("collection1").find({}).toArray();
112+
documents = await mongoClient.db(integration.randomDbName()).collection("collection1").find({}).toArray();
113113
expect(documents).toHaveLength(1);
114114
});
115115
});
116+
117+
describe("when not connected", () => {
118+
it("connects automatically if connection string is configured", async () => {
119+
config.connectionString = integration.connectionString();
120+
121+
const response = await integration.mcpClient().callTool({
122+
name: "create-collection",
123+
arguments: { database: integration.randomDbName(), collection: "new-collection" },
124+
});
125+
const content = getResponseContent(response.content);
126+
expect(content).toEqual(`Collection "new-collection" created in database "${integration.randomDbName()}".`);
127+
});
128+
129+
it("throw an error if connection string is not configured", async () => {
130+
const response = await integration.mcpClient().callTool({
131+
name: "create-collection",
132+
arguments: { database: integration.randomDbName(), collection: "new-collection" },
133+
});
134+
const content = getResponseContent(response.content);
135+
expect(content).toContain("You need to connect to a MongoDB instance before you can access its data.");
136+
});
137+
});
116138
});

0 commit comments

Comments
 (0)