Skip to content

Commit d91acfd

Browse files
committed
chore: disable the connect tool
1 parent 7b9559c commit d91acfd

File tree

12 files changed

+136
-82
lines changed

12 files changed

+136
-82
lines changed

src/common/atlas/apiClient.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export interface ApiClientCredentials {
1515

1616
export interface ApiClientOptions {
1717
credentials?: ApiClientCredentials;
18-
baseUrl?: string;
18+
baseUrl: string;
1919
userAgent?: string;
2020
}
2121

@@ -63,12 +63,11 @@ export class ApiClient {
6363
},
6464
};
6565

66-
constructor(options?: ApiClientOptions) {
66+
constructor(options: ApiClientOptions) {
6767
this.options = {
6868
...options,
69-
baseUrl: options?.baseUrl || "https://cloud.mongodb.com/",
7069
userAgent:
71-
options?.userAgent ||
70+
options.userAgent ||
7271
`AtlasMCP/${packageInfo.version} (${process.platform}; ${process.arch}; ${process.env.HOSTNAME || "unknown"})`,
7372
};
7473

src/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ReadConcernLevel, ReadPreferenceMode, W } from "mongodb";
77
// If we decide to support non-string config options, we'll need to extend the mechanism for parsing
88
// env variables.
99
export interface UserConfig {
10-
apiBaseUrl?: string;
10+
apiBaseUrl: string;
1111
apiClientId?: string;
1212
apiClientSecret?: string;
1313
telemetry?: "enabled" | "disabled";
@@ -24,6 +24,7 @@ export interface UserConfig {
2424
}
2525

2626
const defaults: UserConfig = {
27+
apiBaseUrl: "https://cloud.mongodb.com/",
2728
logPath: getLogPath(),
2829
connectOptions: {
2930
readConcern: "local",

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ try {
1818
name: packageInfo.mcpServerName,
1919
version: packageInfo.version,
2020
});
21+
2122
const server = new Server({
2223
mcpServer,
2324
session,

src/server.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { type ServerEvent } from "./telemetry/types.js";
1111
import { type ServerCommand } from "./telemetry/types.js";
1212
import { CallToolRequestSchema, CallToolResult } from "@modelcontextprotocol/sdk/types.js";
1313
import assert from "assert";
14+
import { connectToMongoDB } from "./tools/mongodb/mongodbTool.js";
1415

1516
export interface ServerOptions {
1617
session: Session;
@@ -33,7 +34,7 @@ export class Server {
3334
this.userConfig = userConfig;
3435
}
3536

36-
async connect(transport: Transport) {
37+
async connect(transport: Transport): Promise<void> {
3738
this.mcpServer.server.registerCapabilities({ logging: {} });
3839

3940
this.registerTools();
@@ -88,6 +89,8 @@ export class Server {
8889
const closeTime = Date.now();
8990
this.emitServerEvent("stop", Date.now() - closeTime, error);
9091
};
92+
93+
await this.validateConfig();
9194
}
9295

9396
async close(): Promise<void> {
@@ -183,4 +186,29 @@ export class Server {
183186
);
184187
}
185188
}
189+
190+
private async validateConfig(): Promise<void> {
191+
const isAtlasConfigured = this.userConfig.apiClientId && this.userConfig.apiClientSecret;
192+
const isMongoDbConfigured = this.userConfig.connectionString;
193+
if (!isAtlasConfigured && !isMongoDbConfigured) {
194+
console.error(
195+
"Either Atlas Client Id or a MongoDB connection string must be configured - you can provide them as environment variables or as startup arguments. \n" +
196+
"Provide the Atlas credentials as `MDB_MCP_API_CLIENT_ID` and `MDB_MCP_API_CLIENT_SECRET` environment variables or as `--apiClientId` and `--apiClientSecret` startup arguments. \n" +
197+
"Provide the MongoDB connection string as `MDB_MCP_CONNECTION_STRING` environment variable or as `--connectionString` startup argument."
198+
);
199+
throw new Error("Either Atlas Client Id or a MongoDB connection string must be configured");
200+
}
201+
202+
if (this.userConfig.connectionString) {
203+
try {
204+
await connectToMongoDB(this.userConfig.connectionString, this.userConfig, this.session);
205+
} catch (error) {
206+
console.error(
207+
"Failed to connect to MongoDB instance using the connection string from the config: ",
208+
error
209+
);
210+
throw new Error("Failed to connect to MongoDB instance using the connection string from the config");
211+
}
212+
}
213+
}
186214
}

src/session.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Implementation } from "@modelcontextprotocol/sdk/types.js";
44
import EventEmitter from "events";
55

66
export interface SessionOptions {
7-
apiBaseUrl?: string;
7+
apiBaseUrl: string;
88
apiClientId?: string;
99
apiClientSecret?: string;
1010
}
@@ -20,7 +20,7 @@ export class Session extends EventEmitter<{
2020
version: string;
2121
};
2222

23-
constructor({ apiBaseUrl, apiClientId, apiClientSecret }: SessionOptions = {}) {
23+
constructor({ apiBaseUrl, apiClientId, apiClientSecret }: SessionOptions) {
2424
super();
2525

2626
const credentials: ApiClientCredentials | undefined =

src/tools/mongodb/mongodbTool.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,31 @@ import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver
44
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
55
import { ErrorCodes, MongoDBError } from "../../errors.js";
66
import logger, { LogId } from "../../logger.js";
7+
import { UserConfig } from "../../config.js";
8+
import { Session } from "../../session.js";
79

810
export const DbOperationArgs = {
911
database: z.string().describe("Database name"),
1012
collection: z.string().describe("Collection name"),
1113
};
1214

15+
export async function connectToMongoDB(connectionString: string, config: UserConfig, session: Session): Promise<void> {
16+
const provider = await NodeDriverServiceProvider.connect(connectionString, {
17+
productDocsLink: "https://docs.mongodb.com/todo-mcp",
18+
productName: "MongoDB MCP",
19+
readConcern: {
20+
level: config.connectOptions.readConcern,
21+
},
22+
readPreference: config.connectOptions.readPreference,
23+
writeConcern: {
24+
w: config.connectOptions.writeConcern,
25+
},
26+
timeoutMS: config.connectOptions.timeoutMS,
27+
});
28+
29+
session.serviceProvider = provider;
30+
}
31+
1332
export abstract class MongoDBToolBase extends ToolBase {
1433
protected category: ToolCategory = "mongodb";
1534

@@ -70,20 +89,7 @@ export abstract class MongoDBToolBase extends ToolBase {
7089
return super.handleError(error, args);
7190
}
7291

73-
protected async connectToMongoDB(connectionString: string): Promise<void> {
74-
const provider = await NodeDriverServiceProvider.connect(connectionString, {
75-
productDocsLink: "https://docs.mongodb.com/todo-mcp",
76-
productName: "MongoDB MCP",
77-
readConcern: {
78-
level: this.config.connectOptions.readConcern,
79-
},
80-
readPreference: this.config.connectOptions.readPreference,
81-
writeConcern: {
82-
w: this.config.connectOptions.writeConcern,
83-
},
84-
timeoutMS: this.config.connectOptions.timeoutMS,
85-
});
86-
87-
this.session.serviceProvider = provider;
92+
protected connectToMongoDB(connectionString: string): Promise<void> {
93+
return connectToMongoDB(connectionString, this.config, this.session);
8894
}
8995
}

src/tools/mongodb/tools.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ConnectTool } from "./metadata/connect.js";
1+
// TODO: https://github.com/mongodb-js/mongodb-mcp-server/issues/141 - reenable when the connect tool is reenabled
2+
// import { ConnectTool } from "./metadata/connect.js";
23
import { ListCollectionsTool } from "./metadata/listCollections.js";
34
import { CollectionIndexesTool } from "./read/collectionIndexes.js";
45
import { ListDatabasesTool } from "./metadata/listDatabases.js";
@@ -20,7 +21,8 @@ import { CreateCollectionTool } from "./create/createCollection.js";
2021
import { LogsTool } from "./metadata/logs.js";
2122

2223
export const MongoDbTools = [
23-
ConnectTool,
24+
// TODO: https://github.com/mongodb-js/mongodb-mcp-server/issues/141 - reenable when the connect tool is reenabled
25+
// ConnectTool,
2426
ListCollectionsTool,
2527
ListDatabasesTool,
2628
CollectionIndexesTool,

tests/integration/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface IntegrationTest {
2020
mcpServer: () => Server;
2121
}
2222

23-
export function setupIntegrationTest(getUserConfig: () => UserConfig = () => config): IntegrationTest {
23+
export function setupIntegrationTest(getUserConfig: () => UserConfig): IntegrationTest {
2424
let mcpClient: Client | undefined;
2525
let mcpServer: Server | undefined;
2626

tests/integration/server.test.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { expectDefined, setupIntegrationTest } from "./helpers.js";
22
import { config } from "../../src/config.js";
3+
import { describeWithMongoDB } from "./tools/mongodb/mongodbHelpers.js";
34

45
describe("Server integration test", () => {
5-
describe("without atlas", () => {
6-
const integration = setupIntegrationTest(() => ({
7-
...config,
8-
apiClientId: undefined,
9-
apiClientSecret: undefined,
10-
}));
11-
6+
describeWithMongoDB("without atlas", (integration) => {
127
it("should return positive number of tools and have no atlas tools", async () => {
138
const tools = await integration.mcpClient().listTools();
149
expectDefined(tools);
@@ -18,6 +13,7 @@ describe("Server integration test", () => {
1813
expect(atlasTools.length).toBeLessThanOrEqual(0);
1914
});
2015
});
16+
2117
describe("with atlas", () => {
2218
const integration = setupIntegrationTest(() => ({
2319
...config,

tests/integration/tools/atlas/atlasHelpers.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ObjectId } from "mongodb";
22
import { Group } from "../../../../src/common/atlas/openapi.js";
33
import { ApiClient } from "../../../../src/common/atlas/apiClient.js";
44
import { setupIntegrationTest, IntegrationTest } from "../../helpers.js";
5+
import { config } from "../../../../src/config.js";
56

67
export type IntegrationTestFunction = (integration: IntegrationTest) => void;
78

@@ -11,7 +12,12 @@ export function sleep(ms: number) {
1112

1213
export function describeWithAtlas(name: string, fn: IntegrationTestFunction) {
1314
const testDefinition = () => {
14-
const integration = setupIntegrationTest();
15+
const integration = setupIntegrationTest(() => ({
16+
...config,
17+
apiClientId: process.env.MDB_MCP_API_CLIENT_ID,
18+
apiClientSecret: process.env.MDB_MCP_API_CLIENT_SECRET,
19+
}));
20+
1521
describe(name, () => {
1622
fn(integration);
1723
});

0 commit comments

Comments
 (0)