• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mongodb-js / mongodb-mcp-server / 17429932259

03 Sep 2025 09:59AM UTC coverage: 81.125% (+0.2%) from 80.965%
17429932259

Pull #502

github

web-flow
Merge ed6adc6d6 into 47c0a09e0
Pull Request #502: chore: extend library interfaces to allow injecting a custom connection error handler MCP-132

901 of 1199 branches covered (75.15%)

Branch coverage included in aggregate %.

92 of 106 new or added lines in 9 files covered. (86.79%)

2 existing lines in 2 files now uncovered.

4579 of 5556 relevant lines covered (82.42%)

44.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.26
/src/tools/mongodb/mongodbTool.ts
1
import { z } from "zod";
2✔
2
import type { ToolArgs, ToolCategory, TelemetryToolMetadata } from "../tool.js";
3
import { ToolBase } from "../tool.js";
2✔
4
import type { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver";
5
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
6
import { ErrorCodes, MongoDBError } from "../../common/errors.js";
2✔
7
import { LogId } from "../../common/logger.js";
2✔
8
import type { Server } from "../../server.js";
9

10
export const DbOperationArgs = {
2✔
11
    database: z.string().describe("Database name"),
2✔
12
    collection: z.string().describe("Collection name"),
2✔
13
};
2✔
14

15
export abstract class MongoDBToolBase extends ToolBase {
2✔
16
    private server?: Server;
17
    public category: ToolCategory = "mongodb";
1,294✔
18

19
    protected async ensureConnected(): Promise<NodeDriverServiceProvider> {
2✔
20
        if (!this.session.isConnectedToMongoDB) {
175✔
21
            if (this.session.connectedAtlasCluster) {
47!
22
                throw new MongoDBError(
×
23
                    ErrorCodes.NotConnectedToMongoDB,
×
24
                    `Attempting to connect to Atlas cluster "${this.session.connectedAtlasCluster.clusterName}", try again in a few seconds.`
×
25
                );
×
26
            }
×
27

28
            if (this.config.connectionString) {
47!
29
                try {
23✔
30
                    await this.connectToMongoDB(this.config.connectionString);
23✔
31
                } catch (error) {
21✔
32
                    this.session.logger.error({
2✔
33
                        id: LogId.mongodbConnectFailure,
2✔
34
                        context: "mongodbTool",
2✔
35
                        message: `Failed to connect to MongoDB instance using the connection string from the config: ${error as string}`,
2✔
36
                    });
2✔
37
                    throw new MongoDBError(ErrorCodes.MisconfiguredConnectionString, "Not connected to MongoDB.");
2✔
38
                }
2✔
39
            }
23✔
40
        }
47✔
41

42
        if (!this.session.isConnectedToMongoDB) {
175✔
43
            throw new MongoDBError(ErrorCodes.NotConnectedToMongoDB, "Not connected to MongoDB");
24✔
44
        }
24!
45

46
        return this.session.serviceProvider;
149✔
47
    }
175✔
48

49
    public register(server: Server): boolean {
2✔
50
        this.server = server;
1,294✔
51
        return super.register(server);
1,294✔
52
    }
1,294✔
53

54
    protected handleError(
2✔
55
        error: unknown,
37✔
56
        args: ToolArgs<typeof this.argsShape>
37✔
57
    ): Promise<CallToolResult> | CallToolResult {
37✔
58
        if (error instanceof MongoDBError) {
37✔
59
            switch (error.code) {
35✔
60
                case ErrorCodes.NotConnectedToMongoDB:
35✔
61
                case ErrorCodes.MisconfiguredConnectionString: {
35✔
62
                    const connectionError = error as MongoDBError<
28✔
63
                        ErrorCodes.NotConnectedToMongoDB | ErrorCodes.MisconfiguredConnectionString
64
                    >;
65
                    const outcome = this.server?.connectionErrorHandler(connectionError, {
28✔
66
                        availableTools: this.server?.tools ?? [],
28!
67
                        connectionState: this.session.connectionManager.currentConnectionState,
28✔
68
                    });
28✔
69
                    if (outcome?.errorHandled) {
28✔
70
                        return outcome.result;
28✔
71
                    }
28!
72

NEW
73
                    return super.handleError(error, args);
×
NEW
74
                }
×
75
                case ErrorCodes.ForbiddenCollscan:
35!
76
                    return {
7✔
77
                        content: [
7✔
78
                            {
7✔
79
                                type: "text",
7✔
80
                                text: error.message,
7✔
81
                            },
7✔
82
                        ],
7✔
83
                        isError: true,
7✔
84
                    };
7✔
85
            }
35✔
86
        }
35!
87

88
        return super.handleError(error, args);
2✔
89
    }
37✔
90

91
    protected connectToMongoDB(connectionString: string): Promise<void> {
2✔
92
        return this.session.connectToMongoDB({ connectionString });
177✔
93
    }
177✔
94

95
    protected resolveTelemetryMetadata(
2✔
96
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
97
        args: ToolArgs<typeof this.argsShape>
×
98
    ): TelemetryToolMetadata {
×
99
        const metadata: TelemetryToolMetadata = {};
×
100

101
        // Add projectId to the metadata if running a MongoDB operation to an Atlas cluster
102
        if (this.session.connectedAtlasCluster?.projectId) {
×
103
            metadata.projectId = this.session.connectedAtlasCluster.projectId;
×
104
        }
×
105

106
        return metadata;
×
107
    }
×
108
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc