Skip to content

Commit da63baf

Browse files
Load atlas-local tools async
1 parent 50637ea commit da63baf

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

src/server.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
UnsubscribeRequestSchema,
2020
} from "@modelcontextprotocol/sdk/types.js";
2121
import assert from "assert";
22-
import type { ToolBase } from "./tools/tool.js";
22+
import type { ToolBase, ToolConstructor } from "./tools/tool.js";
2323
import { validateConnectionString } from "./helpers/connectionOptions.js";
2424

2525
export interface ServerOptions {
@@ -61,11 +61,12 @@ export class Server {
6161

6262
this.mcpServer.server.registerCapabilities({ logging: {}, resources: { listChanged: true, subscribe: true } });
6363

64-
await this.tryInitializeAtlasLocalClient();
65-
6664
// TODO: Eventually we might want to make tools reactive too instead of relying on custom logic.
6765
this.registerTools();
6866

67+
// Atlas Local tools are optional and require async initialization
68+
void this.registerAtlasLocalTools();
69+
6970
// This is a workaround for an issue we've seen with some models, where they'll see that everything in the `arguments`
7071
// object is optional, and then not pass it at all. However, the MCP server expects the `arguments` object to be if
7172
// the tool accepts any arguments, even if they're all optional.
@@ -195,13 +196,27 @@ export class Server {
195196
this.telemetry.emitEvents([event]).catch(() => {});
196197
}
197198

198-
private async tryInitializeAtlasLocalClient(): Promise<void> {
199+
private async registerAtlasLocalTools(): Promise<void> {
199200
try {
201+
// Import Atlas Local client asyncronously
202+
// This will fail on unsupported platforms
200203
const { Client: AtlasLocalClient } = await import("@mongodb-js-preview/atlas-local");
201204

205+
// Connect to Atlas Local client
206+
// This will fail if docker is not running
202207
const client = AtlasLocalClient.connect();
208+
209+
// Set Atlas Local client
203210
this.session.setAtlasLocalClient(client);
211+
212+
// Register Atlas Local tools
213+
this.registerToolInstances(AtlasLocalTools);
204214
} catch (error) {
215+
// If Atlas Local tools are disabled, don't log an error
216+
if (this.userConfig.disabledTools.includes("atlas-local")) {
217+
return;
218+
}
219+
205220
console.warn(
206221
"Failed to initialize Atlas Local client, atlas-local tools will be disabled (error: ",
207222
error,
@@ -211,7 +226,11 @@ export class Server {
211226
}
212227

213228
private registerTools(): void {
214-
for (const toolConstructor of [...AtlasTools, ...AtlasLocalTools, ...MongoDbTools]) {
229+
this.registerToolInstances([...AtlasTools, ...MongoDbTools]);
230+
}
231+
232+
private registerToolInstances(tools: Array<ToolConstructor>): void {
233+
for (const toolConstructor of tools) {
215234
const tool = new toolConstructor(this.session, this.userConfig, this.telemetry);
216235
if (tool.register(this)) {
217236
this.tools.push(tool);

src/tools/tool.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export type TelemetryToolMetadata = {
1818
orgId?: string;
1919
};
2020

21+
export type ToolConstructor = new (session: Session, config: UserConfig, telemetry: Telemetry) => ToolBase;
22+
2123
export abstract class ToolBase {
2224
public abstract name: string;
2325

0 commit comments

Comments
 (0)