Skip to content

Commit 9eb0c1a

Browse files
refactor: Move all lookupDeploymentId calls to resolveTelemetryMetadata
1 parent c4a44e0 commit 9eb0c1a

File tree

5 files changed

+60
-29
lines changed

5 files changed

+60
-29
lines changed

src/tools/atlasLocal/atlasLocalTool.ts

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import type { TelemetryToolMetadata, ToolArgs, ToolCategory } from "../tool.js";
33
import { ToolBase } from "../tool.js";
44
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
55
import type { Client } from "@mongodb-js-preview/atlas-local";
6+
import { LogId } from "../../common/logger.js";
7+
import { z } from "zod";
68

79
export abstract class AtlasLocalToolBase extends ToolBase {
810
public category: ToolCategory = "atlas-local";
9-
protected deploymentId?: string;
1011

1112
protected verifyAllowed(): boolean {
1213
return this.session.atlasLocalClient !== undefined && super.verifyAllowed();
@@ -38,16 +39,10 @@ please log a ticket here: https://github.com/mongodb-js/mongodb-mcp-server/issue
3839
return this.executeWithAtlasLocalClient(client, ...args);
3940
}
4041

41-
protected async lookupDeploymentId(client: Client, containerId: string): Promise<void> {
42-
// Don't run if telemetry is disabled
43-
if (this.telemetry.isTelemetryEnabled()) {
44-
return;
45-
}
46-
47-
// Lookup the deployment id and save it to the deploymentId property.
48-
// This property will be added to the telemetry metadata when resolveTelemetryMetadata is called.
42+
protected async lookupDeploymentId(client: Client, containerId: string): Promise<string> {
43+
// Lookup and return the deployment id for telemetry metadata.
4944
const deploymentId = await client.getDeploymentId(containerId);
50-
this.deploymentId = deploymentId;
45+
return deploymentId;
5146
}
5247

5348
protected abstract executeWithAtlasLocalClient(
@@ -79,9 +74,37 @@ please log a ticket here: https://github.com/mongodb-js/mongodb-mcp-server/issue
7974
return super.handleError(error, args);
8075
}
8176

82-
protected resolveTelemetryMetadata(): TelemetryToolMetadata {
83-
return {
84-
atlasLocaldeploymentId: this.deploymentId,
85-
};
77+
protected async resolveTelemetryMetadata(
78+
...args: Parameters<ToolCallback<typeof this.argsShape>>
79+
): Promise<TelemetryToolMetadata> {
80+
const toolMetadata: TelemetryToolMetadata = {};
81+
82+
const client = this.session.atlasLocalClient;
83+
if (!args.length || !client) {
84+
return toolMetadata;
85+
}
86+
87+
// Create a typed parser for the exact shape we expect
88+
const argsShape = z.object(this.argsShape);
89+
const parsedResult = argsShape.safeParse(args[0]);
90+
91+
if (!parsedResult.success) {
92+
this.session.logger.debug({
93+
id: LogId.telemetryMetadataError,
94+
context: "tool",
95+
message: `Error parsing tool arguments: ${parsedResult.error.message}`,
96+
});
97+
return toolMetadata;
98+
}
99+
100+
const data = parsedResult.data;
101+
102+
// Extract deploymentName using type guard and lookup deployment ID
103+
if ("deploymentName" in data && typeof data.deploymentName === "string" && data.deploymentName.trim() !== "") {
104+
const deploymentId = await this.lookupDeploymentId(client, data.deploymentName);
105+
toolMetadata.atlasLocaldeploymentId = deploymentId;
106+
}
107+
108+
return toolMetadata;
86109
}
87110
}

src/tools/atlasLocal/connect/connectDeployment.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ export class ConnectDeploymentTool extends AtlasLocalToolBase {
2222
// Connect to the deployment
2323
await this.session.connectToMongoDB({ connectionString });
2424

25-
// Lookup the deployment id and add it to the telemetry metadata
26-
await this.lookupDeploymentId(client, deploymentName);
27-
2825
return {
2926
content: [
3027
{

src/tools/atlasLocal/create/createDeployment.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
22
import { AtlasLocalToolBase } from "../atlasLocalTool.js";
3-
import type { OperationType, ToolArgs } from "../../tool.js";
3+
import type { OperationType, ToolArgs, TelemetryToolMetadata } from "../../tool.js";
44
import type { Client, CreateDeploymentOptions, CreationSourceType } from "@mongodb-js-preview/atlas-local";
55
import { CommonArgs } from "../../args.js";
6+
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
67

78
export class CreateDeploymentTool extends AtlasLocalToolBase {
89
public name = "atlas-local-create-deployment";
@@ -12,6 +13,8 @@ export class CreateDeploymentTool extends AtlasLocalToolBase {
1213
deploymentName: CommonArgs.string().describe("Name of the deployment to create").optional(),
1314
};
1415

16+
private createdDeploymentId?: string;
17+
1518
protected async executeWithAtlasLocalClient(
1619
client: Client,
1720
{ deploymentName }: ToolArgs<typeof this.argsShape>
@@ -27,8 +30,8 @@ export class CreateDeploymentTool extends AtlasLocalToolBase {
2730
// Create the deployment
2831
const deployment = await client.createDeployment(deploymentOptions);
2932

30-
// Lookup the deployment id and add it to the telemetry metadata
31-
await this.lookupDeploymentId(client, deployment.containerId);
33+
// Capture deployment ID for telemetry
34+
this.createdDeploymentId = await this.lookupDeploymentId(client, deployment.containerId);
3235

3336
return {
3437
content: [
@@ -39,4 +42,15 @@ export class CreateDeploymentTool extends AtlasLocalToolBase {
3942
],
4043
};
4144
}
45+
46+
// Create tool needs to override resolveTelemetryMetadata because it doesn't
47+
// have the deployment name in the arguments, but rather in the response.
48+
protected resolveTelemetryMetadata(
49+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
50+
...args: Parameters<ToolCallback<typeof this.argsShape>>
51+
): Promise<TelemetryToolMetadata> {
52+
return Promise.resolve({
53+
atlasLocaldeploymentId: this.createdDeploymentId,
54+
});
55+
}
4256
}

src/tools/atlasLocal/delete/deleteDeployment.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ export class DeleteDeploymentTool extends AtlasLocalToolBase {
1616
client: Client,
1717
{ deploymentName }: ToolArgs<typeof this.argsShape>
1818
): Promise<CallToolResult> {
19-
// Lookup the deployment id and add it to the telemetry metadata
20-
await this.lookupDeploymentId(client, deploymentName);
21-
2219
// Delete the deployment
2320
await client.deleteDeployment(deploymentName);
2421

src/tools/tool.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export abstract class ToolBase {
158158
});
159159

160160
const result = await this.execute(...args);
161-
this.emitToolEvent(startTime, result, ...args);
161+
await this.emitToolEvent(startTime, result, ...args);
162162

163163
this.session.logger.debug({
164164
id: LogId.toolExecute,
@@ -174,7 +174,7 @@ export abstract class ToolBase {
174174
message: `Error executing ${this.name}: ${error as string}`,
175175
});
176176
const toolResult = await this.handleError(error, args[0] as ToolArgs<typeof this.argsShape>);
177-
this.emitToolEvent(startTime, toolResult, ...args);
177+
await this.emitToolEvent(startTime, toolResult, ...args);
178178
return toolResult;
179179
}
180180
};
@@ -275,24 +275,24 @@ export abstract class ToolBase {
275275

276276
protected abstract resolveTelemetryMetadata(
277277
...args: Parameters<ToolCallback<typeof this.argsShape>>
278-
): TelemetryToolMetadata;
278+
): TelemetryToolMetadata | Promise<TelemetryToolMetadata>;
279279

280280
/**
281281
* Creates and emits a tool telemetry event
282282
* @param startTime - Start time in milliseconds
283283
* @param result - Whether the command succeeded or failed
284284
* @param args - The arguments passed to the tool
285285
*/
286-
private emitToolEvent(
286+
private async emitToolEvent(
287287
startTime: number,
288288
result: CallToolResult,
289289
...args: Parameters<ToolCallback<typeof this.argsShape>>
290-
): void {
290+
): Promise<void> {
291291
if (!this.telemetry.isTelemetryEnabled()) {
292292
return;
293293
}
294294
const duration = Date.now() - startTime;
295-
const metadata = this.resolveTelemetryMetadata(...args);
295+
const metadata = await this.resolveTelemetryMetadata(...args);
296296
const event: ToolEvent = {
297297
timestamp: new Date().toISOString(),
298298
source: "mdbmcp",

0 commit comments

Comments
 (0)