Skip to content

Commit e33df95

Browse files
move atlas local client initialization to 'TransportRunnerBase'
1 parent eb488ff commit e33df95

File tree

4 files changed

+49
-52
lines changed

4 files changed

+49
-52
lines changed

src/common/atlasLocal.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { Client } from "@mongodb-js-preview/atlas-local";
2+
3+
export type AtlasLocalClientFactoryFn = () => Promise<Client | undefined>;
4+
5+
export const defaultCreateAtlasLocalClient: AtlasLocalClientFactoryFn = async () => {
6+
console.log("defaultCreateAtlasLocalClient");
7+
try {
8+
// Import Atlas Local client asyncronously
9+
// This will fail on unsupported platforms
10+
// also measure the time it takes to import the client
11+
const { Client: AtlasLocalClient } = await import("@mongodb-js-preview/atlas-local");
12+
13+
try {
14+
// Connect to Atlas Local client
15+
// This will fail if docker is not running
16+
const client = AtlasLocalClient.connect();
17+
18+
// Set Atlas Local client
19+
return client;
20+
} catch (dockerError) {
21+
console.warn(
22+
"Failed to connect to Atlas Local client (Docker not available or not running), atlas-local tools will be disabled (error: ",
23+
dockerError,
24+
")"
25+
);
26+
}
27+
} catch (importError) {
28+
console.warn(
29+
"Failed to import Atlas Local client (platform not supported), atlas-local tools will be disabled (error: ",
30+
importError,
31+
")"
32+
);
33+
}
34+
35+
return undefined;
36+
};

src/common/session.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface SessionOptions {
2626
exportsManager: ExportsManager;
2727
connectionManager: ConnectionManager;
2828
keychain: Keychain;
29+
atlasLocalClient?: Client;
2930
}
3031

3132
export type SessionEvents = {
@@ -40,14 +41,14 @@ export class Session extends EventEmitter<SessionEvents> {
4041
readonly exportsManager: ExportsManager;
4142
readonly connectionManager: ConnectionManager;
4243
readonly apiClient: ApiClient;
44+
readonly atlasLocalClient?: Client;
4345
readonly keychain: Keychain;
4446

4547
mcpClient?: {
4648
name?: string;
4749
version?: string;
4850
title?: string;
4951
};
50-
atlasLocalClient?: Client;
5152

5253
public logger: CompositeLogger;
5354

@@ -59,6 +60,7 @@ export class Session extends EventEmitter<SessionEvents> {
5960
connectionManager,
6061
exportsManager,
6162
keychain,
63+
atlasLocalClient,
6264
}: SessionOptions) {
6365
super();
6466

@@ -73,6 +75,7 @@ export class Session extends EventEmitter<SessionEvents> {
7375
: undefined;
7476

7577
this.apiClient = new ApiClient({ baseUrl: apiBaseUrl, credentials }, logger);
78+
this.atlasLocalClient = atlasLocalClient;
7679
this.exportsManager = exportsManager;
7780
this.connectionManager = connectionManager;
7881
this.connectionManager.events.on("connection-success", () => this.emit("connect"));

src/server.ts

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ export class Server {
8787
// TODO: Eventually we might want to make tools reactive too instead of relying on custom logic.
8888
this.registerTools();
8989

90-
// Atlas Local tools are optional and require async initialization
91-
void this.registerAtlasLocalTools();
92-
9390
// This is a workaround for an issue we've seen with some models, where they'll see that everything in the `arguments`
9491
// object is optional, and then not pass it at all. However, the MCP server expects the `arguments` object to be if
9592
// the tool accepts any arguments, even if they're all optional.
@@ -220,55 +217,8 @@ export class Server {
220217
this.telemetry.emitEvents([event]);
221218
}
222219

223-
private async registerAtlasLocalTools(): Promise<void> {
224-
// If Atlas Local tools are disabled, don't attempt to connect to the client
225-
if (this.userConfig.disabledTools.includes("atlas-local")) {
226-
return;
227-
}
228-
229-
try {
230-
// Import Atlas Local client asyncronously
231-
// This will fail on unsupported platforms
232-
const { Client: AtlasLocalClient } = await import("@mongodb-js-preview/atlas-local");
233-
234-
try {
235-
// Connect to Atlas Local client
236-
// This will fail if docker is not running
237-
const client = AtlasLocalClient.connect();
238-
239-
// Set Atlas Local client
240-
this.session.atlasLocalClient = client;
241-
242-
// Register Atlas Local tools
243-
for (const toolConstructor of AtlasLocalTools) {
244-
const tool = new toolConstructor({
245-
session: this.session,
246-
config: this.userConfig,
247-
telemetry: this.telemetry,
248-
elicitation: this.elicitation,
249-
});
250-
if (tool.register(this)) {
251-
this.tools.push(tool);
252-
}
253-
}
254-
} catch (dockerError) {
255-
console.warn(
256-
"Failed to connect to Atlas Local client (Docker not available or not running), atlas-local tools will be disabled (error: ",
257-
dockerError,
258-
")"
259-
);
260-
}
261-
} catch (importError) {
262-
console.warn(
263-
"Failed to import Atlas Local client (platform not supported), atlas-local tools will be disabled (error: ",
264-
importError,
265-
")"
266-
);
267-
}
268-
}
269-
270220
private registerTools(): void {
271-
for (const toolConstructor of this.toolConstructors) {
221+
for (const toolConstructor of [...this.toolConstructors, ...AtlasLocalTools]) {
272222
const tool = new toolConstructor({
273223
session: this.session,
274224
config: this.userConfig,

src/transports/base.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ import {
1616
} from "../common/connectionErrorHandler.js";
1717
import type { CommonProperties } from "../telemetry/types.js";
1818
import { Elicitation } from "../elicitation.js";
19+
import type { AtlasLocalClientFactoryFn } from "../common/atlasLocal.js";
20+
import { defaultCreateAtlasLocalClient } from "../common/atlasLocal.js";
21+
import type { Client } from "@mongodb-js-preview/atlas-local";
1922

2023
export type TransportRunnerConfig = {
2124
userConfig: UserConfig;
2225
createConnectionManager?: ConnectionManagerFactoryFn;
2326
connectionErrorHandler?: ConnectionErrorHandler;
27+
createAtlasLocalClient?: AtlasLocalClientFactoryFn;
2428
additionalLoggers?: LoggerBase[];
2529
telemetryProperties?: Partial<CommonProperties>;
2630
};
@@ -31,18 +35,21 @@ export abstract class TransportRunnerBase {
3135
protected readonly userConfig: UserConfig;
3236
private readonly createConnectionManager: ConnectionManagerFactoryFn;
3337
private readonly connectionErrorHandler: ConnectionErrorHandler;
38+
private readonly atlasLocalClient: Promise<Client | undefined>;
3439
private readonly telemetryProperties: Partial<CommonProperties>;
3540

3641
protected constructor({
3742
userConfig,
3843
createConnectionManager = createMCPConnectionManager,
3944
connectionErrorHandler = defaultConnectionErrorHandler,
45+
createAtlasLocalClient = defaultCreateAtlasLocalClient,
4046
additionalLoggers = [],
4147
telemetryProperties = {},
4248
}: TransportRunnerConfig) {
4349
this.userConfig = userConfig;
4450
this.createConnectionManager = createConnectionManager;
4551
this.connectionErrorHandler = connectionErrorHandler;
52+
this.atlasLocalClient = createAtlasLocalClient();
4653
this.telemetryProperties = telemetryProperties;
4754
const loggers: LoggerBase[] = [...additionalLoggers];
4855
if (this.userConfig.loggers.includes("stderr")) {
@@ -85,6 +92,7 @@ export abstract class TransportRunnerBase {
8592
apiBaseUrl: this.userConfig.apiBaseUrl,
8693
apiClientId: this.userConfig.apiClientId,
8794
apiClientSecret: this.userConfig.apiClientSecret,
95+
atlasLocalClient: await this.atlasLocalClient,
8896
logger,
8997
exportsManager,
9098
connectionManager,

0 commit comments

Comments
 (0)